fix: 修复附件上传字段名不匹配及下载接口问题

- 修复前端附件字段名 filePath -> fileUrl(管理后台expense/requirement)
- 修复移动端附件上传字段名及预览逻辑(base64->URL)
- 修复后端FileController下载接口支持COS文件重定向
- 修复其他前端API路径问题
This commit is contained in:
zhangjf 2026-03-03 23:42:14 +08:00
parent cc6577b3df
commit d613eae423
16 changed files with 224 additions and 254 deletions

View File

@ -19,6 +19,7 @@ CREATE TABLE IF NOT EXISTS project (
project_code VARCHAR(64) NOT NULL COMMENT '项目编码', project_code VARCHAR(64) NOT NULL COMMENT '项目编码',
project_name VARCHAR(128) NOT NULL COMMENT '项目名称', project_name VARCHAR(128) NOT NULL COMMENT '项目名称',
customer_id VARCHAR(32) NOT NULL COMMENT '客户ID', customer_id VARCHAR(32) NOT NULL COMMENT '客户ID',
customer_name VARCHAR(128) COMMENT '客户名称',
project_type VARCHAR(32) NOT NULL COMMENT '项目类型', project_type VARCHAR(32) NOT NULL COMMENT '项目类型',
budget_amount DECIMAL(18,2) COMMENT '预算金额', budget_amount DECIMAL(18,2) COMMENT '预算金额',
start_date DATE COMMENT '开始日期', start_date DATE COMMENT '开始日期',

View File

@ -13,20 +13,20 @@ export function createExpenseType(data: any) {
return request.post('/exp/expense-type', data) return request.post('/exp/expense-type', data)
} }
export function updateExpenseType(id: number, data: any) { export function updateExpenseType(id: string, data: any) {
return request.put(`/exp/expense-type/${id}`, data) return request.put(`/exp/expense-type/${id}`, data)
} }
export function deleteExpenseType(id: number) { export function deleteExpenseType(id: string) {
return request.delete(`/exp/expense-type/${id}`) return request.delete(`/exp/expense-type/${id}`)
} }
// 支出管理 // 支出管理
export function getExpenseList(params: { pageNum: number; pageSize: number; title?: string; expenseType?: number; approvalStatus?: number; payStatus?: number }) { export function getExpenseList(params: { pageNum: number; pageSize: number; title?: string; expenseType?: string; approvalStatus?: number; payStatus?: number }) {
return request.get('/exp/expense/page', { params }) return request.get('/exp/expense/page', { params })
} }
export function getExpenseById(id: number) { export function getExpenseById(id: string) {
return request.get(`/exp/expense/${id}`) return request.get(`/exp/expense/${id}`)
} }
@ -34,49 +34,49 @@ export function createExpense(data: any) {
return request.post('/exp/expense', data) return request.post('/exp/expense', data)
} }
export function updateExpense(id: number, data: any) { export function updateExpense(id: string, data: any) {
return request.put(`/exp/expense/${id}`, data) return request.put(`/exp/expense/${id}`, data)
} }
export function deleteExpense(id: number) { export function deleteExpense(id: string) {
return request.delete(`/exp/expense/${id}`) return request.delete(`/exp/expense/${id}`)
} }
// 审批流程 // 审批流程
export function submitExpense(id: number) { export function submitExpense(id: string) {
return request.post(`/exp/expense/${id}/submit`) return request.post(`/exp/expense/${id}/submit`)
} }
export function withdrawExpense(id: number) { export function withdrawExpense(id: string) {
return request.post(`/exp/expense/${id}/withdraw`) return request.post(`/exp/expense/${id}/withdraw`)
} }
export function approveExpense(id: number, comment: string) { export function approveExpense(id: string, comment: string) {
return request.put(`/exp/expense/${id}/approve?comment=${encodeURIComponent(comment)}`) return request.put(`/exp/expense/${id}/approve?comment=${encodeURIComponent(comment)}`)
} }
export function rejectExpense(id: number, comment: string) { export function rejectExpense(id: string, comment: string) {
return request.put(`/exp/expense/${id}/reject?comment=${encodeURIComponent(comment)}`) return request.put(`/exp/expense/${id}/reject?comment=${encodeURIComponent(comment)}`)
} }
export function confirmPayExpense(id: number, payChannel: string, payVoucher?: string) { export function confirmPayExpense(id: string, payChannel: string, payVoucher?: string) {
return request.put(`/exp/expense/${id}/confirm-pay?payChannel=${payChannel}&payVoucher=${payVoucher || ''}`) return request.put(`/exp/expense/${id}/confirm-pay?payChannel=${payChannel}&payVoucher=${payVoucher || ''}`)
} }
// 导出支出明细 // 导出支出明细
export function exportExpense(params?: { title?: string; expenseType?: number; approvalStatus?: number; payStatus?: number }) { export function exportExpense(params?: { title?: string; expenseType?: string; approvalStatus?: number; payStatus?: number }) {
const baseUrl = import.meta.env.VITE_API_URL || '' const baseUrl = import.meta.env.VITE_API_URL || ''
const token = localStorage.getItem('token') const token = localStorage.getItem('token')
const tenantId = localStorage.getItem('tenantId') || '1' const tenantId = localStorage.getItem('tenantId') || '1'
const queryParams = new URLSearchParams() const queryParams = new URLSearchParams()
if (params?.title) queryParams.append('title', params.title) if (params?.title) queryParams.append('title', params.title)
if (params?.expenseType) queryParams.append('expenseType', String(params.expenseType)) if (params?.expenseType) queryParams.append('expenseType', params.expenseType)
if (params?.approvalStatus !== undefined) queryParams.append('approvalStatus', String(params.approvalStatus)) if (params?.approvalStatus !== undefined) queryParams.append('approvalStatus', String(params.approvalStatus))
if (params?.payStatus !== undefined) queryParams.append('payStatus', String(params.payStatus)) if (params?.payStatus !== undefined) queryParams.append('payStatus', String(params.payStatus))
const queryString = queryParams.toString() const queryString = queryParams.toString()
const url = `${baseUrl}/exp/expense/export${queryString ? '?' + queryString : ''}` const url = `${baseUrl}/fund/exp/expense/export${queryString ? '?' + queryString : ''}`
return fetch(url, { return fetch(url, {
headers: { headers: {

View File

@ -1,11 +1,11 @@
import { request } from './request' import { request } from './request'
// 文件上传 // 文件上传
export function uploadFile(file: File, businessType?: string, businessId?: number, description?: string) { export function uploadFile(file: File, businessType?: string, businessId?: string, description?: string) {
const formData = new FormData() const formData = new FormData()
formData.append('file', file) formData.append('file', file)
if (businessType) formData.append('businessType', businessType) if (businessType) formData.append('businessType', businessType)
if (businessId) formData.append('businessId', String(businessId)) if (businessId) formData.append('businessId', businessId)
if (description) formData.append('description', description) if (description) formData.append('description', description)
return request.post('/file/upload', formData, { return request.post('/file/upload', formData, {
@ -16,26 +16,26 @@ export function uploadFile(file: File, businessType?: string, businessId?: numbe
} }
// 获取文件列表 // 获取文件列表
export function getFileList(params: { pageNum: number; pageSize: number; businessType?: string; businessId?: number; fileType?: string }) { export function getFileList(params: { pageNum: number; pageSize: number; businessType?: string; businessId?: string; fileType?: string }) {
return request.get('/file/page', { params }) return request.get('/file/page', { params })
} }
// 根据业务查询文件 // 根据业务查询文件
export function getFilesByBusiness(businessType: string, businessId: number) { export function getFilesByBusiness(businessType: string, businessId: string) {
return request.get('/file/list', { params: { businessType, businessId } }) return request.get('/file/list', { params: { businessType, businessId } })
} }
// 获取文件详情 // 获取文件详情
export function getFileById(id: number) { export function getFileById(id: string) {
return request.get(`/file/${id}`) return request.get(`/file/${id}`)
} }
// 删除文件 // 删除文件
export function deleteFile(id: number) { export function deleteFile(id: string) {
return request.delete(`/file/${id}`) return request.delete(`/file/${id}`)
} }
// 获取文件下载URL // 获取文件下载URL
export function getFileDownloadUrl(filePath: string) { export function getFileDownloadUrl(filePath: string) {
return `/file/download/${filePath}` return `/fund/file/download/${filePath}`
} }

View File

@ -4,7 +4,7 @@ export function getProjectList(params: { pageNum: number; pageSize: number; proj
return request.get('/project/page', { params }) return request.get('/project/page', { params })
} }
export function getProjectById(id: number) { export function getProjectById(id: string) {
return request.get(`/project/${id}`) return request.get(`/project/${id}`)
} }
@ -12,11 +12,11 @@ export function createProject(data: any) {
return request.post('/project', data) return request.post('/project', data)
} }
export function updateProject(id: number, data: any) { export function updateProject(id: string, data: any) {
return request.put(`/project/${id}`, data) return request.put(`/project/${id}`, data)
} }
export function deleteProject(id: number) { export function deleteProject(id: string) {
return request.delete(`/project/${id}`) return request.delete(`/project/${id}`)
} }
@ -25,7 +25,7 @@ export function getRequirementList(params: { pageNum: number; pageSize: number;
return request.get('/requirement/page', { params }) return request.get('/requirement/page', { params })
} }
export function getRequirementById(id: number) { export function getRequirementById(id: string) {
return request.get(`/requirement/${id}`) return request.get(`/requirement/${id}`)
} }
@ -33,10 +33,10 @@ export function createRequirement(data: any) {
return request.post('/requirement', data) return request.post('/requirement', data)
} }
export function updateRequirement(id: number, data: any) { export function updateRequirement(id: string, data: any) {
return request.put(`/requirement/${id}`, data) return request.put(`/requirement/${id}`, data)
} }
export function deleteRequirement(id: number) { export function deleteRequirement(id: string) {
return request.delete(`/requirement/${id}`) return request.delete(`/requirement/${id}`)
} }

View File

@ -70,22 +70,18 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="微信" prop="wechat"> <el-form-item label="邮箱" prop="email">
<el-input v-model="form.wechat" placeholder="请输入微信号" /> <el-input v-model="form.email" placeholder="请输入邮箱" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item label="主联系人" prop="isPrimary"> <el-form-item label="主联系人" prop="isPrimary">
<el-switch v-model="form.isPrimary" /> <el-switch v-model="form.isPrimary" :active-value="1" :inactive-value="0" />
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remarks"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remarks" type="textarea" :rows="3" placeholder="请输入备注" /> <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -126,15 +122,15 @@ const dialogTitle = ref('新增联系人')
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive({ const form = reactive({
contactId: null as number | null, id: null as string | null,
customerId: customerId.value, customerId: customerId.value,
contactName: '', contactName: '',
position: '', position: '',
phone: '', phone: '',
email: '', email: '',
wechat: '', isPrimary: 0,
isPrimary: false, status: 1,
remarks: '' remark: ''
}) })
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
@ -210,8 +206,8 @@ const handleSubmit = async () => {
submitLoading.value = true submitLoading.value = true
try { try {
if (form.contactId) { if (form.id) {
await updateContact(form.contactId, form) await updateContact(form.id, form)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} else { } else {
await createContact(form) await createContact(form)
@ -228,15 +224,15 @@ const handleSubmit = async () => {
} }
const resetForm = () => { const resetForm = () => {
form.contactId = null form.id = null
form.customerId = customerId.value form.customerId = customerId.value
form.contactName = '' form.contactName = ''
form.position = '' form.position = ''
form.phone = '' form.phone = ''
form.email = '' form.email = ''
form.wechat = '' form.isPrimary = 0
form.isPrimary = false form.status = 1
form.remarks = '' form.remark = ''
formRef.value?.clearValidate() formRef.value?.clearValidate()
} }

View File

@ -6,12 +6,12 @@
<el-input v-model="queryParams.title" placeholder="请输入支出标题" clearable style="width: 200px" /> <el-input v-model="queryParams.title" placeholder="请输入支出标题" clearable style="width: 200px" />
</el-form-item> </el-form-item>
<el-form-item label="支出类型"> <el-form-item label="支出类型">
<el-select v-model="queryParams.expenseTypeId" placeholder="请选择" clearable filterable style="width: 150px"> <el-select v-model="queryParams.expenseType" placeholder="请选择" clearable filterable style="width: 150px">
<el-option <el-option
v-for="item in expenseTypeList" v-for="item in expenseTypeList"
:key="item.typeId" :key="item.id"
:label="item.typeName" :label="item.typeName"
:value="item.typeId" :value="item.id"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -44,7 +44,7 @@
</div> </div>
<el-table :data="tableData" v-loading="loading" border stripe> <el-table :data="tableData" v-loading="loading" border stripe>
<el-table-column prop="expenseId" label="支出ID" width="80" /> <el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="支出标题" min-width="180" show-overflow-tooltip /> <el-table-column prop="title" label="支出标题" min-width="180" show-overflow-tooltip />
<el-table-column prop="expenseTypeName" label="支出类型" width="120" /> <el-table-column prop="expenseTypeName" label="支出类型" width="120" />
<el-table-column prop="projectName" label="关联项目" width="140" show-overflow-tooltip /> <el-table-column prop="projectName" label="关联项目" width="140" show-overflow-tooltip />
@ -57,20 +57,20 @@
<el-table-column prop="expenseDate" label="支出日期" width="120" /> <el-table-column prop="expenseDate" label="支出日期" width="120" />
<el-table-column prop="approvalStatus" label="审批状态" width="100"> <el-table-column prop="approvalStatus" label="审批状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.approvalStatus === 'DRAFT'" type="info">草稿</el-tag> <el-tag v-if="row.approvalStatus === 0" type="info">待审批</el-tag>
<el-tag v-else-if="row.approvalStatus === 'PENDING'" type="warning">审批</el-tag> <el-tag v-else-if="row.approvalStatus === 1" type="warning">审批</el-tag>
<el-tag v-else-if="row.approvalStatus === 'APPROVED'" type="success">已通过</el-tag> <el-tag v-else-if="row.approvalStatus === 2" type="success">已通过</el-tag>
<el-tag v-else-if="row.approvalStatus === 'REJECTED'" type="danger">已拒绝</el-tag> <el-tag v-else-if="row.approvalStatus === 3" type="danger">已拒绝</el-tag>
<el-tag v-else type="info">已撤回</el-tag> <el-tag v-else type="info">已撤回</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="payStatus" label="支付状态" width="100"> <el-table-column prop="payStatus" label="支付状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.payStatus === 'UNPAID'" type="warning">未支付</el-tag> <el-tag v-if="row.payStatus === 0" type="warning">未支付</el-tag>
<el-tag v-else type="success">已支付</el-tag> <el-tag v-else type="success">已支付</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="applicant" label="申请人" width="100" /> <el-table-column prop="createdBy" label="申请人" width="100" />
<el-table-column label="附件" width="80"> <el-table-column label="附件" width="80">
<template #default="{ row }"> <template #default="{ row }">
<el-icon v-if="row.attachments" style="color: #409EFF;"><Document /></el-icon> <el-icon v-if="row.attachments" style="color: #409EFF;"><Document /></el-icon>
@ -80,10 +80,10 @@
<el-table-column label="操作" width="320" fixed="right"> <el-table-column label="操作" width="320" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" :icon="View" @click="handleView(row)">详情</el-button> <el-button link type="primary" :icon="View" @click="handleView(row)">详情</el-button>
<el-button link type="primary" :icon="Edit" v-if="row.approvalStatus === 'DRAFT'" @click="handleEdit(row)">编辑</el-button> <el-button link type="primary" :icon="Edit" v-if="row.approvalStatus === 0" @click="handleEdit(row)">编辑</el-button>
<el-button link type="success" :icon="Check" v-if="row.approvalStatus === 'DRAFT'" @click="handleSubmit(row)">提交</el-button> <el-button link type="success" :icon="Check" v-if="row.approvalStatus === 0" @click="handleSubmit(row)">提交</el-button>
<el-button link type="warning" v-if="row.approvalStatus === 'PENDING'" @click="handleApprove(row)">审批</el-button> <el-button link type="warning" v-if="row.approvalStatus === 1" @click="handleApprove(row)">审批</el-button>
<el-button link type="danger" :icon="Delete" v-if="row.approvalStatus === 'DRAFT'" @click="handleDelete(row)">删除</el-button> <el-button link type="danger" :icon="Delete" v-if="row.approvalStatus === 0" @click="handleDelete(row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -115,13 +115,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="支出类型" prop="expenseTypeId"> <el-form-item label="支出类型" prop="expenseType">
<el-select v-model="form.expenseTypeId" placeholder="请选择" filterable style="width: 100%"> <el-select v-model="form.expenseType" placeholder="请选择" filterable style="width: 100%">
<el-option <el-option
v-for="item in expenseTypeList" v-for="item in expenseTypeList"
:key="item.typeId" :key="item.id"
:label="item.typeName" :label="item.typeName"
:value="item.typeId" :value="item.id"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -134,9 +134,9 @@
<el-select v-model="form.projectId" placeholder="请选择项目" filterable clearable style="width: 100%"> <el-select v-model="form.projectId" placeholder="请选择项目" filterable clearable style="width: 100%">
<el-option <el-option
v-for="item in projectList" v-for="item in projectList"
:key="item.projectId" :key="item.id"
:label="item.projectName" :label="item.projectName"
:value="item.projectId" :value="item.id"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -156,22 +156,29 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="支出日期" prop="expenseDate"> <el-form-item label="支出日期" prop="expenseDate">
<el-date-picker v-model="form.expenseDate" type="date" placeholder="请选择支出日期" style="width: 100%" /> <el-date-picker v-model="form.expenseDate" type="date" placeholder="请选择支出日期" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="申请人" prop="applicant"> <el-form-item label="关联项目">
<el-input v-model="form.applicant" placeholder="请输入申请人" /> <el-select v-model="form.projectId" placeholder="请选择项目" filterable clearable style="width: 100%">
<el-option
v-for="item in projectList"
:key="item.id"
:label="item.projectName"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="支出描述" prop="description"> <el-form-item label="支出描述" prop="purpose">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入支出描述" /> <el-input v-model="form.purpose" type="textarea" :rows="3" placeholder="请输入支出描述" />
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remarks"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" /> <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item> </el-form-item>
<el-form-item label="附件"> <el-form-item label="附件">
@ -286,7 +293,7 @@ import { getExpenseTypeTree } from '@/api/expense'
import { getProjectList } from '@/api/project' import { getProjectList } from '@/api/project'
// //
const uploadUrl = '/file/api/v1/file/upload' const uploadUrl = '/fund/file/upload'
const uploadHeaders = { const uploadHeaders = {
Authorization: `Bearer ${localStorage.getItem('token') || ''}`, Authorization: `Bearer ${localStorage.getItem('token') || ''}`,
'X-Tenant-Id': localStorage.getItem('tenantId') || '1' 'X-Tenant-Id': localStorage.getItem('tenantId') || '1'
@ -305,7 +312,7 @@ const queryParams = reactive({
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
title: '', title: '',
expenseTypeId: null as number | null, expenseType: null as string | null,
approvalStatus: '', approvalStatus: '',
payStatus: '' payStatus: ''
}) })
@ -315,32 +322,30 @@ const dialogTitle = ref('新增支出')
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive({ const form = reactive({
expenseId: null as number | null, id: null as string | null,
title: '', title: '',
expenseTypeId: null as number | null, expenseType: null as string | null,
projectId: null as number | null, projectId: null as string | null,
amount: 0, amount: 0,
payeeName: '', payeeName: '',
expenseDate: '', expenseDate: '',
applicant: '', purpose: '',
description: '', remark: '',
remarks: '',
attachments: '' attachments: ''
}) })
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
title: [{ required: true, message: '请输入支出标题', trigger: 'blur' }], title: [{ required: true, message: '请输入支出标题', trigger: 'blur' }],
expenseTypeId: [{ required: true, message: '请选择支出类型', trigger: 'change' }], expenseType: [{ required: true, message: '请选择支出类型', trigger: 'change' }],
amount: [{ required: true, message: '请输入支出金额', trigger: 'blur' }], amount: [{ required: true, message: '请输入支出金额', trigger: 'blur' }],
payeeName: [{ required: true, message: '请输入收款单位', trigger: 'blur' }], payeeName: [{ required: true, message: '请输入收款单位', trigger: 'blur' }],
expenseDate: [{ required: true, message: '请选择支出日期', trigger: 'change' }], expenseDate: [{ required: true, message: '请选择支出日期', trigger: 'change' }]
applicant: [{ required: true, message: '请输入申请人', trigger: 'blur' }]
}) })
const approvalVisible = ref(false) const approvalVisible = ref(false)
const approvalData = ref<any>({}) const approvalData = ref<any>({})
const approvalForm = reactive({ const approvalForm = reactive({
expenseId: null as number | null, expenseId: null as string | null,
comment: '' comment: ''
}) })
@ -351,8 +356,8 @@ const detailData = ref<any>({})
const handleUploadSuccess = (response: any, _file: any, fileListVal: any[]) => { const handleUploadSuccess = (response: any, _file: any, fileListVal: any[]) => {
if (response.code === 200 || response.code === 0) { if (response.code === 200 || response.code === 0) {
const urls = fileListVal const urls = fileListVal
.filter(f => f.response?.data?.filePath || f.url) .filter(f => f.response?.data?.fileUrl || f.url)
.map(f => f.response?.data?.filePath || f.url) .map(f => f.response?.data?.fileUrl || f.url)
form.attachments = urls.join(',') form.attachments = urls.join(',')
ElMessage.success('上传成功') ElMessage.success('上传成功')
} else { } else {
@ -368,8 +373,8 @@ const handleUploadError = () => {
// //
const handleUploadRemove = (_file: any, fileListVal: any[]) => { const handleUploadRemove = (_file: any, fileListVal: any[]) => {
const urls = fileListVal const urls = fileListVal
.filter(f => f.response?.data?.filePath || f.url) .filter(f => f.response?.data?.fileUrl || f.url)
.map(f => f.response?.data?.filePath || f.url) .map(f => f.response?.data?.fileUrl || f.url)
form.attachments = urls.join(',') form.attachments = urls.join(',')
} }
@ -377,7 +382,7 @@ const handleUploadRemove = (_file: any, fileListVal: any[]) => {
const getFileUrl = (path: string) => { const getFileUrl = (path: string) => {
if (!path) return '#' if (!path) return '#'
if (path.startsWith('http')) return path if (path.startsWith('http')) return path
return `/file/api/v1/file/download/${path}` return `/fund/file/download/${path}`
} }
// //
@ -434,7 +439,7 @@ const handleSearch = () => {
const handleReset = () => { const handleReset = () => {
queryParams.title = '' queryParams.title = ''
queryParams.expenseTypeId = null queryParams.expenseType = null
queryParams.approvalStatus = '' queryParams.approvalStatus = ''
queryParams.payStatus = '' queryParams.payStatus = ''
queryParams.pageNum = 1 queryParams.pageNum = 1
@ -474,7 +479,7 @@ const handleSubmit = (row: any) => {
type: 'warning' type: 'warning'
}).then(async () => { }).then(async () => {
try { try {
await submitExpense(row.expenseId) await submitExpense(row.id)
ElMessage.success('提交成功') ElMessage.success('提交成功')
fetchData() fetchData()
} catch (e) { } catch (e) {
@ -485,7 +490,7 @@ const handleSubmit = (row: any) => {
const handleApprove = (row: any) => { const handleApprove = (row: any) => {
approvalData.value = row approvalData.value = row
approvalForm.expenseId = row.expenseId approvalForm.expenseId = row.id
approvalForm.comment = '' approvalForm.comment = ''
approvalVisible.value = true approvalVisible.value = true
} }
@ -523,7 +528,7 @@ const handleDelete = (row: any) => {
type: 'warning' type: 'warning'
}).then(async () => { }).then(async () => {
try { try {
await deleteExpense(row.expenseId) await deleteExpense(row.id)
ElMessage.success('删除成功') ElMessage.success('删除成功')
fetchData() fetchData()
} catch (e) { } catch (e) {
@ -539,8 +544,8 @@ const handleSaveExpense = async () => {
submitLoading.value = true submitLoading.value = true
try { try {
if (form.expenseId) { if (form.id) {
await updateExpense(form.expenseId, form) await updateExpense(form.id, form)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} else { } else {
await createExpense(form) await createExpense(form)
@ -557,16 +562,15 @@ const handleSaveExpense = async () => {
} }
const resetForm = () => { const resetForm = () => {
form.expenseId = null form.id = null
form.title = '' form.title = ''
form.expenseTypeId = null form.expenseType = null
form.projectId = null form.projectId = null
form.amount = 0 form.amount = 0
form.payeeName = '' form.payeeName = ''
form.expenseDate = '' form.expenseDate = ''
form.applicant = '' form.purpose = ''
form.description = '' form.remark = ''
form.remarks = ''
form.attachments = '' form.attachments = ''
fileList.value = [] fileList.value = []
formRef.value?.clearValidate() formRef.value?.clearValidate()
@ -578,7 +582,7 @@ const handleExport = async () => {
try { try {
const params: any = {} const params: any = {}
if (queryParams.title) params.title = queryParams.title if (queryParams.title) params.title = queryParams.title
if (queryParams.expenseTypeId) params.expenseType = queryParams.expenseTypeId if (queryParams.expenseType) params.expenseType = queryParams.expenseType
if (queryParams.approvalStatus) params.approvalStatus = parseInt(queryParams.approvalStatus) if (queryParams.approvalStatus) params.approvalStatus = parseInt(queryParams.approvalStatus)
if (queryParams.payStatus) params.payStatus = parseInt(queryParams.payStatus) if (queryParams.payStatus) params.payStatus = parseInt(queryParams.payStatus)

View File

@ -105,8 +105,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="合同金额" prop="contractAmount"> <el-form-item label="项目类型" prop="projectType">
<el-input-number v-model="form.contractAmount" :precision="2" :min="0" style="width: 100%" /> <el-select v-model="form.projectType" placeholder="请选择" style="width: 100%">
<el-option label="开发项目" value="开发项目" />
<el-option label="运维项目" value="运维项目" />
<el-option label="咨询项目" value="咨询项目" />
<el-option label="集成项目" value="集成项目" />
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -131,23 +136,14 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="项目状态" prop="projectStatus"> <el-form-item label="预算金额" prop="budgetAmount">
<el-select v-model="form.projectStatus" placeholder="请选择" style="width: 100%"> <el-input-number v-model="form.budgetAmount" :precision="2" :min="0" style="width: 100%" />
<el-option label="待启动" value="PENDING" />
<el-option label="进行中" value="IN_PROGRESS" />
<el-option label="已完成" value="COMPLETED" />
<el-option label="已取消" value="CANCELLED" />
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="项目描述" prop="description"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入项目描述" /> <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -210,26 +206,23 @@ const dialogTitle = ref('新增项目')
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive({ const form = reactive({
projectId: null as number | null, id: null as string | null,
projectCode: '', projectCode: '',
projectName: '', projectName: '',
customerId: null as number | null, customerId: null as string | null,
contractAmount: 0, projectType: '',
budgetAmount: 0,
startDate: '', startDate: '',
endDate: '', endDate: '',
projectManager: '', projectManager: '',
projectStatus: 'PENDING', remark: ''
description: '',
remarks: ''
}) })
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
projectCode: [{ required: true, message: '请输入项目编号', trigger: 'blur' }], projectCode: [{ required: true, message: '请输入项目编号', trigger: 'blur' }],
projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }], projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
customerId: [{ required: true, message: '请选择客户', trigger: 'change' }], customerId: [{ required: true, message: '请选择客户', trigger: 'change' }],
contractAmount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }], projectType: [{ required: true, message: '请选择项目类型', trigger: 'change' }]
startDate: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
projectStatus: [{ required: true, message: '请选择项目状态', trigger: 'change' }]
}) })
const detailVisible = ref(false) const detailVisible = ref(false)
@ -310,8 +303,8 @@ const handleSubmit = async () => {
submitLoading.value = true submitLoading.value = true
try { try {
if (form.projectId) { if (form.id) {
await updateProject(form.projectId, form) await updateProject(form.id, form)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} else { } else {
await createProject(form) await createProject(form)
@ -328,17 +321,16 @@ const handleSubmit = async () => {
} }
const resetForm = () => { const resetForm = () => {
form.projectId = null form.id = null
form.projectCode = '' form.projectCode = ''
form.projectName = '' form.projectName = ''
form.customerId = null form.customerId = null
form.contractAmount = 0 form.projectType = ''
form.budgetAmount = 0
form.startDate = '' form.startDate = ''
form.endDate = '' form.endDate = ''
form.projectManager = '' form.projectManager = ''
form.projectStatus = 'PENDING' form.remark = ''
form.description = ''
form.remarks = ''
formRef.value?.clearValidate() formRef.value?.clearValidate()
} }

View File

@ -312,7 +312,7 @@ import { getProjectList } from '@/api/project'
import { getCustomerList } from '@/api/customer' import { getCustomerList } from '@/api/customer'
// //
const uploadUrl = '/file/api/v1/file/upload' const uploadUrl = '/fund/file/upload'
const uploadHeaders = { const uploadHeaders = {
Authorization: `Bearer ${localStorage.getItem('token') || ''}`, Authorization: `Bearer ${localStorage.getItem('token') || ''}`,
'X-Tenant-Id': localStorage.getItem('tenantId') || '1' 'X-Tenant-Id': localStorage.getItem('tenantId') || '1'
@ -380,8 +380,8 @@ const handleUploadSuccess = (response: any, _file: any, fileListVal: any[]) => {
if (response.code === 200 || response.code === 0) { if (response.code === 200 || response.code === 0) {
// URL // URL
const urls = fileListVal const urls = fileListVal
.filter(f => f.response?.data?.filePath || f.url) .filter(f => f.response?.data?.fileUrl || f.url)
.map(f => f.response?.data?.filePath || f.url) .map(f => f.response?.data?.fileUrl || f.url)
form.attachmentUrl = urls.join(',') form.attachmentUrl = urls.join(',')
ElMessage.success('上传成功') ElMessage.success('上传成功')
} else { } else {
@ -397,8 +397,8 @@ const handleUploadError = () => {
// //
const handleUploadRemove = (_file: any, fileListVal: any[]) => { const handleUploadRemove = (_file: any, fileListVal: any[]) => {
const urls = fileListVal const urls = fileListVal
.filter(f => f.response?.data?.filePath || f.url) .filter(f => f.response?.data?.fileUrl || f.url)
.map(f => f.response?.data?.filePath || f.url) .map(f => f.response?.data?.fileUrl || f.url)
form.attachmentUrl = urls.join(',') form.attachmentUrl = urls.join(',')
} }
@ -406,7 +406,7 @@ const handleUploadRemove = (_file: any, fileListVal: any[]) => {
const getFileUrl = (path: string) => { const getFileUrl = (path: string) => {
if (!path) return '#' if (!path) return '#'
if (path.startsWith('http')) return path if (path.startsWith('http')) return path
return `/file/api/v1/file/download/${path}` return `/fund/file/download/${path}`
} }
const fetchCustomers = async () => { const fetchCustomers = async () => {

View File

@ -92,8 +92,8 @@
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="应收款编号" prop="receivableCode"> <el-form-item label="应收金额" prop="receivableAmount">
<el-input v-model="form.receivableCode" placeholder="请输入应收款编号" /> <el-input-number v-model="form.receivableAmount" :precision="2" :min="0" style="width: 100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -124,35 +124,19 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="应收金额" prop="totalAmount"> <el-form-item label="应收日期" prop="receivableDate">
<el-input-number v-model="form.totalAmount" :precision="2" :min="0" style="width: 100%" /> <el-date-picker v-model="form.receivableDate" type="date" placeholder="请选择应收日期" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="到期日期" prop="paymentDueDate">
<el-date-picker v-model="form.paymentDueDate" type="date" placeholder="请选择到期日期" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-form-item label="备注" prop="remark">
<el-col :span="12"> <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" />
<el-form-item label="应收日期" prop="dueDate">
<el-date-picker v-model="form.dueDate" type="date" placeholder="请选择应收日期" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收款状态" prop="receiptStatus">
<el-select v-model="form.receiptStatus" placeholder="请选择" style="width: 100%">
<el-option label="未收款" value="UNPAID" />
<el-option label="部分收款" value="PARTIAL" />
<el-option label="已收款" value="PAID" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="账单描述" prop="description">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入账单描述" />
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -298,23 +282,22 @@ const dialogTitle = ref('新增应收款')
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive({ const form = reactive({
receivableId: null as number | null, id: null as string | null,
receivableCode: '', projectId: null as string | null,
projectId: null as number | null, customerId: null as string | null,
customerId: null as number | null, receivableAmount: 0,
totalAmount: 0, receivableDate: '',
dueDate: '', paymentDueDate: '',
receiptStatus: 'UNPAID', paymentMethod: '',
description: '', bankAccount: '',
remarks: '' remark: ''
}) })
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
receivableCode: [{ required: true, message: '请输入应收款编号', trigger: 'blur' }],
projectId: [{ required: true, message: '请选择关联项目', trigger: 'change' }], projectId: [{ required: true, message: '请选择关联项目', trigger: 'change' }],
customerId: [{ required: true, message: '请选择客户', trigger: 'change' }], customerId: [{ required: true, message: '请选择客户', trigger: 'change' }],
totalAmount: [{ required: true, message: '请输入应收金额', trigger: 'blur' }], receivableAmount: [{ required: true, message: '请输入应收金额', trigger: 'blur' }],
dueDate: [{ required: true, message: '请选择应收日期', trigger: 'change' }] receivableDate: [{ required: true, message: '请选择应收日期', trigger: 'change' }]
}) })
const receiptVisible = ref(false) const receiptVisible = ref(false)
@ -473,8 +456,8 @@ const handleSubmit = async () => {
submitLoading.value = true submitLoading.value = true
try { try {
if (form.receivableId) { if (form.id) {
await updateReceivable(form.receivableId, form) await updateReceivable(form.id, form)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} else { } else {
await createReceivable(form) await createReceivable(form)
@ -491,15 +474,15 @@ const handleSubmit = async () => {
} }
const resetForm = () => { const resetForm = () => {
form.receivableId = null form.id = null
form.receivableCode = ''
form.projectId = null form.projectId = null
form.customerId = null form.customerId = null
form.totalAmount = 0 form.receivableAmount = 0
form.dueDate = '' form.receivableDate = ''
form.receiptStatus = 'UNPAID' form.paymentDueDate = ''
form.description = '' form.paymentMethod = ''
form.remarks = '' form.bankAccount = ''
form.remark = ''
formRef.value?.clearValidate() formRef.value?.clearValidate()
} }

View File

@ -20,41 +20,11 @@ export default defineConfig(({ mode }) => {
server: { server: {
port: 3000, port: 3000,
proxy: { proxy: {
'/auth/': { // 所有 /fund/ 请求代理到网关,去掉 /fund 前缀
target: 'http://localhost:8100', '/fund/': {
changeOrigin: true
},
'/sys/': {
target: 'http://localhost:8000', target: 'http://localhost:8000',
changeOrigin: true changeOrigin: true,
}, rewrite: (path) => path.replace(/^\/fund/, '')
'/cust/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/proj/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/req/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/exp/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/receipt/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/file/': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/report/': {
target: 'http://localhost:8000',
changeOrigin: true
} }
} }
} }

View File

@ -6,6 +6,7 @@ import com.fundplatform.file.data.entity.FileRecord;
import com.fundplatform.file.data.service.FileRecordService; import com.fundplatform.file.data.service.FileRecordService;
import com.fundplatform.file.service.CosStorageService; import com.fundplatform.file.service.CosStorageService;
import com.fundplatform.file.vo.FileRecordVO; import com.fundplatform.file.vo.FileRecordVO;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -151,25 +152,43 @@ public class FileController {
/** /**
* 下载文件 * 下载文件
* 支持本地文件和COS文件下载
*/ */
@GetMapping("/download/**") @GetMapping("/download/**")
public void download(HttpServletResponse response, public void download(HttpServletResponse response,
HttpServletRequest httpRequest,
@RequestHeader(value = "X-Tenant-Id", required = false) String tenantId) throws IOException { @RequestHeader(value = "X-Tenant-Id", required = false) String tenantId) throws IOException {
String requestUri = request.getRequestURI(); String requestUri = httpRequest.getRequestURI();
String filePath = requestUri.substring(requestUri.indexOf("/download/") + 10); String filePath = requestUri.substring(requestUri.indexOf("/download/") + 10);
log.info("文件下载请求: filePath={}", filePath);
// 检查是否是COS路径
if (filePath.startsWith("cos:")) {
// COS文件重定向到COS URL
String cosUrl = filePath.substring(4);
response.sendRedirect(cosUrl);
return;
}
// 检查是否已经是完整URL
if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
response.sendRedirect(filePath);
return;
}
// 本地文件
String fullPath = uploadPath + "/" + filePath; String fullPath = uploadPath + "/" + filePath;
File file = new File(fullPath); File file = new File(fullPath);
if (!file.exists()) { if (!file.exists()) {
log.warn("文件不存在: {}", fullPath);
response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":404,\"message\":\"文件不存在\"}");
return; return;
} }
// 查找文件记录
// 简化处理直接下载
String fileName = file.getName(); String fileName = file.getName();
// 尝试还原原始文件名如果有扩展名的话
response.setContentType("application/octet-stream"); response.setContentType("application/octet-stream");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + "\""); "attachment; filename=\"" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + "\"");
@ -186,10 +205,6 @@ public class FileController {
} }
} }
// 注入HttpServletRequest
@jakarta.annotation.Resource
private jakarta.servlet.http.HttpServletRequest request;
/** /**
* 根据ID获取文件信息 * 根据ID获取文件信息
*/ */

View File

@ -132,7 +132,7 @@ const onAfterRead = async (file: any) => {
const res: any = await uploadFile(file.file, 'expense', undefined, '支出附件') const res: any = await uploadFile(file.file, 'expense', undefined, '支出附件')
// //
const filePath = res.data?.filePath || res.data?.url const filePath = res.data?.fileUrl || res.data?.url
if (filePath) { if (filePath) {
uploadedAttachments.value.push(filePath) uploadedAttachments.value.push(filePath)
console.log('文件上传成功:', filePath) console.log('文件上传成功:', filePath)

View File

@ -104,9 +104,18 @@ const getAttachmentCount = (attachments: string) => {
const previewAttachments = (item: any) => { const previewAttachments = (item: any) => {
if (!item.attachments) return if (!item.attachments) return
// base64 URL // URL
const attachmentList = item.attachments.split(',') const attachmentList = item.attachments.split(',').filter((s: string) => s.trim())
const imageUrls = attachmentList.map((b64: string) => `data:image/jpeg;base64,${b64}`)
// URL
const imageUrls = attachmentList.map((url: string) => {
// URL使
if (url.startsWith('http')) return url
// COS
if (url.startsWith('cos:')) return url.substring(4)
// 使
return `/fund/file/download/${url}`
})
ImagePreview.show({ ImagePreview.show({
images: imageUrls, images: imageUrls,

View File

@ -189,7 +189,7 @@ const onSubmit = async () => {
projectId: form.value.projectId, projectId: form.value.projectId,
receivableAmount: parseFloat(form.value.receivableAmount), receivableAmount: parseFloat(form.value.receivableAmount),
receivableDate: form.value.receivableDate, receivableDate: form.value.receivableDate,
description: form.value.description remark: form.value.description
}) })
showSuccessToast('提交成功') showSuccessToast('提交成功')
router.back() router.back()

View File

@ -19,7 +19,7 @@ public class FundReceiptController {
} }
@PostMapping @PostMapping
public Result<Long> create(@Valid @RequestBody FundReceiptDTO dto) { public Result<String> create(@Valid @RequestBody FundReceiptDTO dto) {
return Result.success(receiptService.createReceipt(dto)); return Result.success(receiptService.createReceipt(dto));
} }
@ -29,7 +29,7 @@ public class FundReceiptController {
} }
@GetMapping("/{id}") @GetMapping("/{id}")
public Result<FundReceiptVO> getById(@PathVariable Long id) { public Result<FundReceiptVO> getById(@PathVariable String id) {
return Result.success(receiptService.getReceiptById(id)); return Result.success(receiptService.getReceiptById(id));
} }
@ -44,17 +44,17 @@ public class FundReceiptController {
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public Result<Boolean> delete(@PathVariable Long id) { public Result<Boolean> delete(@PathVariable String id) {
return Result.success(receiptService.deleteReceipt(id)); return Result.success(receiptService.deleteReceipt(id));
} }
@PutMapping("/{id}/confirm") @PutMapping("/{id}/confirm")
public Result<Boolean> confirm(@PathVariable Long id) { public Result<Boolean> confirm(@PathVariable String id) {
return Result.success(receiptService.confirm(id)); return Result.success(receiptService.confirm(id));
} }
@PutMapping("/{id}/write-off") @PutMapping("/{id}/write-off")
public Result<Boolean> writeOff(@PathVariable Long id) { public Result<Boolean> writeOff(@PathVariable String id) {
return Result.success(receiptService.writeOff(id)); return Result.success(receiptService.writeOff(id));
} }
} }

View File

@ -39,7 +39,7 @@ public class ReceivableController {
* 创建应收款 * 创建应收款
*/ */
@PostMapping @PostMapping
public Result<Long> create(@Valid @RequestBody ReceivableDTO dto) { public Result<String> create(@Valid @RequestBody ReceivableDTO dto) {
return Result.success(receivableService.createReceivable(dto)); return Result.success(receivableService.createReceivable(dto));
} }
@ -47,7 +47,7 @@ public class ReceivableController {
* 更新应收款仅待确认状态可修改 * 更新应收款仅待确认状态可修改
*/ */
@PutMapping("/{id}") @PutMapping("/{id}")
public Result<Boolean> update(@PathVariable Long id, @Valid @RequestBody ReceivableDTO dto) { public Result<Boolean> update(@PathVariable String id, @Valid @RequestBody ReceivableDTO dto) {
dto.setId(id); dto.setId(id);
return Result.success(receivableService.updateReceivable(dto)); return Result.success(receivableService.updateReceivable(dto));
} }
@ -56,7 +56,7 @@ public class ReceivableController {
* 根据ID查询应收款 * 根据ID查询应收款
*/ */
@GetMapping("/{id}") @GetMapping("/{id}")
public Result<ReceivableVO> getById(@PathVariable Long id) { public Result<ReceivableVO> getById(@PathVariable String id) {
return Result.success(receivableService.getReceivableById(id)); return Result.success(receivableService.getReceivableById(id));
} }
@ -67,8 +67,8 @@ public class ReceivableController {
public Result<Page<ReceivableVO>> page( public Result<Page<ReceivableVO>> page(
@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize, @RequestParam(defaultValue = "10") int pageSize,
@RequestParam(required = false) Long projectId, @RequestParam(required = false) String projectId,
@RequestParam(required = false) Long customerId, @RequestParam(required = false) String customerId,
@RequestParam(required = false) String status, @RequestParam(required = false) String status,
@RequestParam(required = false) Integer confirmStatus) { @RequestParam(required = false) Integer confirmStatus) {
return Result.success(receivableService.pageReceivables(pageNum, pageSize, projectId, customerId, status, confirmStatus)); return Result.success(receivableService.pageReceivables(pageNum, pageSize, projectId, customerId, status, confirmStatus));
@ -79,8 +79,8 @@ public class ReceivableController {
*/ */
@PutMapping("/{id}/confirm") @PutMapping("/{id}/confirm")
public Result<Boolean> confirm( public Result<Boolean> confirm(
@PathVariable Long id, @PathVariable String id,
@RequestHeader(value = "X-User-Id", required = false) Long confirmBy) { @RequestHeader(value = "X-User-Id", required = false) String confirmBy) {
return Result.success(receivableService.confirmReceivable(id, confirmBy)); return Result.success(receivableService.confirmReceivable(id, confirmBy));
} }
@ -88,7 +88,7 @@ public class ReceivableController {
* 取消确认 * 取消确认
*/ */
@PutMapping("/{id}/cancel-confirm") @PutMapping("/{id}/cancel-confirm")
public Result<Boolean> cancelConfirm(@PathVariable Long id) { public Result<Boolean> cancelConfirm(@PathVariable String id) {
return Result.success(receivableService.cancelConfirm(id)); return Result.success(receivableService.cancelConfirm(id));
} }
@ -96,7 +96,7 @@ public class ReceivableController {
* 记录收款 * 记录收款
*/ */
@PostMapping("/{id}/receipt") @PostMapping("/{id}/receipt")
public Result<Boolean> recordReceipt(@PathVariable Long id, @RequestParam BigDecimal amount) { public Result<Boolean> recordReceipt(@PathVariable String id, @RequestParam BigDecimal amount) {
return Result.success(receivableService.recordReceipt(id, amount)); return Result.success(receivableService.recordReceipt(id, amount));
} }
@ -104,7 +104,7 @@ public class ReceivableController {
* 获取应收款的收款记录列表 * 获取应收款的收款记录列表
*/ */
@GetMapping("/{id}/receipts") @GetMapping("/{id}/receipts")
public Result<List<FundReceiptVO>> getReceipts(@PathVariable Long id) { public Result<List<FundReceiptVO>> getReceipts(@PathVariable String id) {
return Result.success(receivableService.getReceiptsByReceivableId(id)); return Result.success(receivableService.getReceiptsByReceivableId(id));
} }
@ -121,7 +121,7 @@ public class ReceivableController {
* 删除应收款仅待确认状态可删除 * 删除应收款仅待确认状态可删除
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public Result<Boolean> delete(@PathVariable Long id) { public Result<Boolean> delete(@PathVariable String id) {
return Result.success(receivableService.deleteReceivable(id)); return Result.success(receivableService.deleteReceivable(id));
} }
@ -166,8 +166,8 @@ public class ReceivableController {
*/ */
@GetMapping("/export") @GetMapping("/export")
public void exportExcel( public void exportExcel(
@RequestParam(required = false) Long projectId, @RequestParam(required = false) String projectId,
@RequestParam(required = false) Long customerId, @RequestParam(required = false) String customerId,
@RequestParam(required = false) String status, @RequestParam(required = false) String status,
@RequestParam(required = false) Integer confirmStatus, @RequestParam(required = false) Integer confirmStatus,
HttpServletResponse response) { HttpServletResponse response) {