zhangjf bc56bd672b revert: 恢复 expense API路径与 gateway 配置保持一致
架构说明:
- 前端 baseURL: /fund
- 网关路由:Path=/fund/exp/**
- StripPrefix=1: 去掉/fund 前缀
- PrefixPath=/api/v1: 自动添加/api/v1 前缀
- 后端 Controller: /api/v1/exp/expense-type

请求流程:
前端:GET /fund/exp/expense-type/page
网关:匹配 Path=/fund/exp/** → StripPrefix=1 → PrefixPath=/api/v1
后端:接收 /api/v1/exp/expense-type/page ✓

与其他模块保持一致:
- customer: GET /customer/page → /api/v1/customer/page
- project: GET /project/page → /api/v1/project/page
- expense: GET /exp/expense-type/page → /api/v1/exp/expense-type/page

设计原则:
- 前端不硬编码/api/v1,由网关统一处理
- 符合网关路由与 API路径分离的架构设计
2026-03-01 22:39:02 +08:00

101 lines
3.3 KiB
TypeScript

import { request } from './request'
// 支出类型
export function getExpenseTypeList(params: { pageNum: number; pageSize: number; typeName?: string; status?: string }) {
return request.get('/exp/expense-type/page', { params })
}
export function getExpenseTypeTree() {
return request.get('/exp/expense-type/tree')
}
export function createExpenseType(data: any) {
return request.post('/exp/expense-type', data)
}
export function updateExpenseType(id: number, data: any) {
return request.put(`/exp/expense-type/${id}`, data)
}
export function deleteExpenseType(id: number) {
return request.delete(`/exp/expense-type/${id}`)
}
// 支出管理
export function getExpenseList(params: { pageNum: number; pageSize: number; title?: string; expenseType?: number; approvalStatus?: number; payStatus?: number }) {
return request.get('/exp/expense/page', { params })
}
export function getExpenseById(id: number) {
return request.get(`/exp/expense/${id}`)
}
export function createExpense(data: any) {
return request.post('/exp/expense', data)
}
export function updateExpense(id: number, data: any) {
return request.put(`/exp/expense/${id}`, data)
}
export function deleteExpense(id: number) {
return request.delete(`/exp/expense/${id}`)
}
// 审批流程
export function submitExpense(id: number) {
return request.post(`/exp/expense/${id}/submit`)
}
export function withdrawExpense(id: number) {
return request.post(`/exp/expense/${id}/withdraw`)
}
export function approveExpense(id: number, comment: string) {
return request.put(`/exp/expense/${id}/approve?comment=${encodeURIComponent(comment)}`)
}
export function rejectExpense(id: number, comment: string) {
return request.put(`/exp/expense/${id}/reject?comment=${encodeURIComponent(comment)}`)
}
export function confirmPayExpense(id: number, payChannel: string, payVoucher?: string) {
return request.put(`/exp/expense/${id}/confirm-pay?payChannel=${payChannel}&payVoucher=${payVoucher || ''}`)
}
// 导出支出明细
export function exportExpense(params?: { title?: string; expenseType?: number; approvalStatus?: number; payStatus?: number }) {
const baseUrl = import.meta.env.VITE_API_URL || ''
const token = localStorage.getItem('token')
const tenantId = localStorage.getItem('tenantId') || '1'
const queryParams = new URLSearchParams()
if (params?.title) queryParams.append('title', params.title)
if (params?.expenseType) queryParams.append('expenseType', String(params.expenseType))
if (params?.approvalStatus !== undefined) queryParams.append('approvalStatus', String(params.approvalStatus))
if (params?.payStatus !== undefined) queryParams.append('payStatus', String(params.payStatus))
const queryString = queryParams.toString()
const url = `${baseUrl}/exp/expense/export${queryString ? '?' + queryString : ''}`
return fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
'X-Tenant-Id': tenantId
}
}).then(response => {
if (!response.ok) throw new Error('导出失败')
const contentDisposition = response.headers.get('Content-Disposition')
let filename = '支出明细.xlsx'
if (contentDisposition) {
const match = contentDisposition.match(/filename\*=utf-8''(.+)/i)
if (match && match[1]) {
filename = decodeURIComponent(match[1])
}
}
return response.blob().then(blob => ({ blob, filename }))
})
}