/** * 报销模块 API(REST,协议 code===0 / msg / data.rows) * 路径挂在 /api 下:/reimburses、/advances、/expense-items、/attachments */ import { request, parseResponseJson } from '@/utils/request' function unwrap(res) { const body = parseResponseJson(res) if (!body || typeof body !== 'object') { throw new Error('接口响应异常') } if (body.code != null && body.code !== 0) { throw new Error(body.msg || body.message || '请求失败') } return body.data != null ? body.data : body } async function get(url, params = {}) { const res = await request({ url, method: 'GET', data: params, params }) return unwrap(res) } async function post(url, data = {}) { const res = await request({ url, method: 'POST', data }) return unwrap(res) } async function put(url, data = {}, params = {}) { const res = await request({ url, method: 'PUT', data, params }) return unwrap(res) } function pageParams(query = {}) { const { pageNum, page, pageSize, ...rest } = query const params = { page: pageNum ?? page ?? 1, pageSize: pageSize ?? 20 } Object.keys(rest).forEach((k) => { if (rest[k] != null && rest[k] !== '') params[k] = rest[k] }) return params } function normalizeList(data) { if (Array.isArray(data)) return { rows: data, total: data.length } const d = data || {} return { rows: d.rows || d.list || [], total: d.total ?? 0 } } // ── 费用项目 ── export async function getExpenseItemTree() { const data = await get('/expense-items/tree') return Array.isArray(data) ? data : [] } /** 展平可选叶子费用项目(供 picker) */ export function flattenExpenseLeaves(tree, path = []) { const out = [] ;(tree || []).forEach((node) => { const name = node.itemName || node.item_name || '' const nextPath = path.concat(name) const children = node.children || [] if (children.length) { out.push(...flattenExpenseLeaves(children, nextPath)) } else { out.push({ id: String(node.id), name, pathLabel: nextPath.join(' / ') }) } }) return out } // ── 报销 ── export async function listMyReimburse(query = {}) { return normalizeList(await get('/reimburses/my', pageParams(query))) } export async function listPendingReimburse(query = {}) { return normalizeList(await get('/reimburses/pending-approval', pageParams(query))) } export async function listApprovedByMeReimburse(query = {}) { return normalizeList(await get('/reimburses/approved-by-me', pageParams(query))) } export async function getReimburse(id) { return get(`/reimburses/${String(id)}`) } export async function generateReimburseTitle(reimburseDate) { const params = {} if (reimburseDate) params.reimburseDate = reimburseDate return get('/reimburses/generate-title', params) } export function createReimburse(data) { return post('/reimburses/', data) } export function updateReimburse(id, data) { return put(`/reimburses/${String(id)}`, data) } export function submitReimburse(id) { return post(`/reimburses/${String(id)}/submit`) } export function approveReimburse(id, approvalOpinion = '') { return post(`/reimburses/${String(id)}/approve`, { approvalOpinion }) } export function rejectReimburse(id, approvalOpinion = '') { return post(`/reimburses/${String(id)}/reject`, { approvalOpinion }) } export async function getReimburseApprovalHistory(id) { const data = await get(`/reimburses/${String(id)}/approval-history`) return Array.isArray(data) ? data : [] } // ── 借款(备用金) ── export async function listMyAdvance(query = {}) { return normalizeList(await get('/advances/my', pageParams(query))) } export async function listPendingAdvance(query = {}) { return normalizeList(await get('/advances/pending-approval', pageParams(query))) } export async function listApprovedByMeAdvance(query = {}) { return normalizeList(await get('/advances/approved-by-me', pageParams(query))) } export async function getAdvance(id) { return get(`/advances/${String(id)}`) } export function createAdvance(data) { return post('/advances/', data) } export function submitAdvance(id) { return post(`/advances/${String(id)}/submit`) } export function approveAdvance(id, approvalOpinion = '') { return post(`/advances/${String(id)}/approve`, { approvalOpinion }) } export function rejectAdvance(id, approvalOpinion = '') { return post(`/advances/${String(id)}/reject`, { approvalOpinion }) } export async function getAdvanceApprovalHistory(id) { const data = await get(`/advances/${String(id)}/approval-history`) return Array.isArray(data) ? data : [] } // ── 附件 ── export async function listAttachments(bizType, bizId) { const data = await get('/attachments/list', { biz_type: bizType, biz_id: String(bizId) }) return Array.isArray(data) ? data : [] } export async function bindAttachments(ids, bizType, bizId) { if (!ids?.length) return 0 const q = [ `ids=${encodeURIComponent(ids.map(String).join(','))}`, `biz_type=${encodeURIComponent(bizType)}`, `biz_id=${encodeURIComponent(String(bizId))}` ].join('&') return put(`/attachments/bind-biz?${q}`, {}) } export async function previewAttachment(id) { return get(`/attachments/preview/${String(id)}`) }