fix: 合同页面的日期优化,然后合同结算的时候也进行了优化

This commit is contained in:
Maple 2025-08-12 17:28:17 +08:00
parent 3fb4cc0950
commit cc525c45b7
4 changed files with 259 additions and 57 deletions

View File

@ -35,11 +35,11 @@
<a-col :span="12">
<a-form-item field="contractStatus" label="合同状态">
<a-select v-model="contractData.contractStatus">
<a-option value="未确认">未确认</a-option>
<a-option value="待审批">待审批</a-option>
<a-option value="已签署">已签署</a-option>
<a-option value="未执行">未执行</a-option>
<a-option value="执行中">执行中</a-option>
<a-option value="已完成">已完成</a-option>
<a-option value="验收中">验收中</a-option>
<a-option value="结算中">结算中</a-option>
<a-option value="已结算">已结算</a-option>
<a-option value="已终止">已终止</a-option>
</a-select>
</a-form-item>

View File

@ -48,18 +48,23 @@
<span class="font-medium text-green-600">{{ (record.amount || 0).toLocaleString() }}</span>
</template>
<!-- 收款金额 -->
<template #receivedAmount="{ record }">
<span class="font-medium text-blue-600">{{ (record.receivedAmount || 0).toLocaleString() }}</span>
<!-- 结算金额支出合同 -->
<template #settlementAmount="{ record }">
<span class="font-medium text-blue-600">{{ (record.settlementAmount || record.receivedAmount || 0).toLocaleString() }}</span>
</template>
<template #action="{ record }">
<a-space>
<a-link @click="viewDetail(record)">查看</a-link>
<a-link @click="editRecord(record)">编辑</a-link>
<a-link :disabled="record.contractStatus === '已结算'" @click="!(record.contractStatus === '已结算') && openSettlement(record)">结算</a-link>
<a-link status="danger" @click="deleteContract(record)">删除</a-link>
</a-space>
</template>
<!-- 日期展示仅年月日放在 action 模板之外作为独立列插槽 -->
<template #signDate="{ record }">{{ (record.signDate || '').slice(0,10) }}</template>
<template #performanceDeadline="{ record }">{{ (record.performanceDeadline || '').slice(0,10) }}</template>
<template #paymentDate="{ record }">{{ (record.paymentDate || '').slice(0,10) }}</template>
</GiTable>
<!-- 合同详情弹窗 -->
@ -102,6 +107,15 @@
@update:contract-data="handleNewContractDataUpdate"
/>
</a-modal>
<!-- 合同结算弹窗 -->
<a-modal v-model:visible="showSettlementModal" title="合同结算" :width="520" @before-ok="submitSettlement">
<a-form :model="settlementForm" layout="vertical">
<a-form-item field="amount" label="结算金额"><a-input-number v-model="settlementForm.amount" style="width:100%" /></a-form-item>
<a-form-item field="paymentDate" label="付款日期"><a-date-picker v-model="settlementForm.paymentDate" show-time value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/></a-form-item>
<a-form-item field="paymentPeriod" label="账期"><a-date-picker v-model="settlementForm.paymentPeriod" show-time value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/></a-form-item>
<a-form-item field="notes" label="备注"><a-textarea v-model="settlementForm.notes" /></a-form-item>
</a-form>
</a-modal>
</GiPageLayout>
</template>
@ -173,11 +187,11 @@ const queryFormColumns = [
props: {
placeholder: '请选择合同状态',
options: [
{ label: '未确认', value: '未确认' },
{ label: '待审批', value: '待审批' },
{ label: '已签署', value: '已签署' },
{ label: '未执行', value: '未执行' },
{ label: '执行中', value: '执行中' },
{ label: '已完成', value: '已完成' },
{ label: '验收中', value: '验收中' },
{ label: '结算中', value: '结算中' },
{ label: '已结算', value: '已结算' },
{ label: '已终止', value: '已终止' },
],
},
@ -187,9 +201,8 @@ const queryFormColumns = [
label: '签署时间',
type: 'range-picker' as const,
props: {
placeholder: ['开始时间', '结束时间'],
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
placeholder: ['开始日期', '结束日期'],
format: 'YYYY-MM-DD',
},
},
]
@ -200,11 +213,11 @@ const tableColumns: TableColumnData[] = [
{ title: '项目名称', dataIndex: 'projectName', width: 250, ellipsis: true, tooltip: true },
{ title: '客户名称', dataIndex: 'customer', width: 200, ellipsis: true, tooltip: true },
{ title: '合同金额', dataIndex: 'amount', slotName: 'contractAmount', width: 120 },
{ title: '已收款金额', dataIndex: 'receivedAmount', slotName: 'receivedAmount', width: 120 },
{ title: '未收款金额', dataIndex: 'pendingAmount', width: 120 },
{ title: '签署日期', dataIndex: 'signDate', width: 120 },
{ title: '履约期限', dataIndex: 'performanceDeadline', width: 120 },
{ title: '付款日期', dataIndex: 'paymentDate', width: 120 },
{ title: '已结算金额', dataIndex: 'settlementAmount', slotName: 'settlementAmount', width: 120 },
{ title: '未结算金额', dataIndex: 'pendingAmount', width: 120 },
{ title: '签署日期', dataIndex: 'signDate', slotName: 'signDate', width: 120 },
{ title: '履约期限', dataIndex: 'performanceDeadline', slotName: 'performanceDeadline', width: 120 },
{ title: '付款日期', dataIndex: 'paymentDate', slotName: 'paymentDate', width: 120 },
{ title: '合同状态', dataIndex: 'contractStatus', slotName: 'status', width: 100 },
{ title: '销售人员', dataIndex: 'salespersonName', width: 100 },
{ title: '销售部门', dataIndex: 'salespersonDeptName', width: 100 },
@ -252,10 +265,10 @@ const fetchContractList = async () => {
}
}
//
//
dataList.value = filtered.map((item: ContractItem) => ({
...item,
pendingAmount: (item.amount || 0) - (item.receivedAmount || 0),
pendingAmount: (item.amount || 0) - ((item.settlementAmount || item.receivedAmount || 0)),
}))
//
@ -284,11 +297,11 @@ const pagination = reactive({
//
const getStatusColor = (status: string) => {
const colorMap: Record<string, string> = {
未确认: 'gray',
待审批: 'orange',
已签署: 'blue',
未执行: 'gray',
执行中: 'cyan',
已完成: 'green',
验收中: 'arcoblue',
结算中: 'orange',
已结算: 'green',
已终止: 'red',
}
return colorMap[status] || 'gray'
@ -381,7 +394,7 @@ const openAddModal = () => {
amount: 0,
accountNumber: '',
notes: '',
contractStatus: '未确认',
contractStatus: '未执行',
contractText: '',
projectName: '',
salespersonName: null,
@ -477,8 +490,8 @@ const editRecord = (record: ContractItem) => {
...record,
amount: record.amount || 0,
projectId: record.projectId || '',
type: record.type || '收入合同',
contractStatus: record.contractStatus || '未确认',
type: record.type || '支出合同',
contractStatus: record.contractStatus || '未执行',
}
selectedContractData.value = completeRecord
@ -548,6 +561,91 @@ const handleEditSubmit = async () => {
}
}
//
const showSettlementModal = ref(false)
const settlementForm = reactive({
//
contractId: '',
amount: 0,
paymentDate: '',
paymentPeriod: '',
notes: '',
//
accountNumber: '',
code: '',
customer: '',
departmentId: '',
duration: '',
productService: '',
projectId: '',
salespersonId: '',
settlementId: '',
settlementStatus: '',
})
const settlementRecord = ref<ContractItem | null>(null)
const openSettlement = (record: ContractItem) => {
if (record.contractStatus === '已结算') return
settlementRecord.value = record
Object.assign(settlementForm, {
//
contractId: record.contractId,
amount: record.amount || 0,
paymentDate: record.paymentDate || '',
paymentPeriod: '',
notes: '',
// 便
accountNumber: (record as any).accountNumber || '',
code: (record as any).code || '',
customer: (record as any).customer || '',
departmentId: (record as any).departmentId || '',
duration: (record as any).duration || '',
productService: (record as any).productService || '',
projectId: (record as any).projectId || '',
salespersonId: (record as any).salespersonId || '',
settlementId: (record as any).settlementId || '',
settlementStatus: (record as any).settlementStatus || '',
})
showSettlementModal.value = true
}
const submitSettlement = async () => {
try {
const payload:any = {
accountNumber: settlementForm.accountNumber || '',
amount: settlementForm.amount,
code: settlementForm.code || '',
contractId: settlementForm.contractId,
customer: settlementForm.customer || '',
departmentId: settlementForm.departmentId || '',
duration: settlementForm.duration || '',
notes: settlementForm.notes || '',
paymentDate: settlementForm.paymentDate || null,
paymentPeriod: settlementForm.paymentPeriod || '',
productService: settlementForm.productService || '',
projectId: settlementForm.projectId || '',
salespersonId: settlementForm.salespersonId || '',
settlementId: settlementForm.settlementId || '',
settlementStatus: settlementForm.settlementStatus || '',
}
const res = await http.post('/contract-settlement', payload)
if (res.code === 200 || (res as any).status === 200) {
Message.success('合同结算成功')
// 0 0 => /
const origin = settlementRecord.value
const settledAmount = (origin?.settlementAmount ?? origin?.receivedAmount ?? 0) + (settlementForm.amount || 0)
const pendingAfter = Math.max((origin?.amount || 0) - settledAmount, 0)
const targetStatus = pendingAfter === 0 ? '已结算' : '结算中'
await http.put('/contract', { contractId: settlementForm.contractId, contractStatus: targetStatus, type: origin?.type || '支出合同' })
showSettlementModal.value = false
search()
return true
}
Message.error(res.msg || '合同结算失败')
return false
} catch (e:any) {
Message.error(e?.message || '合同结算失败')
return false
}
}
//
const deleteContract = (record: ContractItem) => {

View File

@ -35,11 +35,11 @@
<a-col :span="12">
<a-form-item field="contractStatus" label="合同状态">
<a-select v-model="contractData.contractStatus">
<a-option value="未确认">未确认</a-option>
<a-option value="待审批">待审批</a-option>
<a-option value="已签署">已签署</a-option>
<a-option value="未执行">未执行</a-option>
<a-option value="执行中">执行中</a-option>
<a-option value="已完成">已完成</a-option>
<a-option value="验收中">验收中</a-option>
<a-option value="结算中">结算中</a-option>
<a-option value="已结算">已结算</a-option>
<a-option value="已终止">已终止</a-option>
</a-select>
</a-form-item>

View File

@ -48,18 +48,24 @@
<span class="font-medium text-green-600">{{ (record.amount || 0).toLocaleString() }}</span>
</template>
<!-- 收款金额 -->
<!-- 回款金额收入合同 -->
<template #receivedAmount="{ record }">
<span class="font-medium text-blue-600">{{ (record.receivedAmount || 0).toLocaleString() }}</span>
<span class="font-medium text-blue-600">{{ (record.receivedAmount || record.settlementAmount || 0).toLocaleString() }}</span>
</template>
<template #action="{ record }">
<a-space>
<a-link @click="viewDetail(record)">查看</a-link>
<a-link @click="editRecord(record)">编辑</a-link>
<a-link :disabled="record.contractStatus === '已结算'" @click="!(record.contractStatus === '已结算') && openSettlement(record)">结算</a-link>
<a-link status="danger" @click="deleteContract(record)">删除</a-link>
</a-space>
</template>
<!-- 日期展示仅年月日放在 action 模板之外作为独立列插槽 -->
<template #signDate="{ record }">{{ (record.signDate || '').slice(0,10) }}</template>
<template #performanceDeadline="{ record }">{{ (record.performanceDeadline || '').slice(0,10) }}</template>
<template #paymentDate="{ record }">{{ (record.paymentDate || '').slice(0,10) }}</template>
</GiTable>
<!-- 合同详情弹窗 -->
@ -87,8 +93,6 @@
@update:contract-data="handleContractDataUpdate"
/>
</a-modal>
</GiPageLayout>
<!-- 新建合同弹窗 -->
<a-modal
v-model:visible="showAddModal"
@ -102,7 +106,18 @@
:contract-data="newContractData"
@update:contract-data="handleNewContractDataUpdate"
/>
</a-modal>
<!-- 合同结算弹窗 -->
<a-modal v-model:visible="showSettlementModal" title="合同结算" :width="520" @before-ok="submitSettlement">
<a-form :model="settlementForm" layout="vertical">
<a-form-item field="amount" label="结算金额"><a-input-number v-model="settlementForm.amount" style="width:100%" /></a-form-item>
<a-form-item field="paymentDate" label="付款日期"><a-date-picker v-model="settlementForm.paymentDate" show-time value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/></a-form-item>
<a-form-item field="paymentPeriod" label="账期"><a-date-picker v-model="settlementForm.paymentPeriod" show-time value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/></a-form-item>
<a-form-item field="notes" label="备注"><a-textarea v-model="settlementForm.notes" /></a-form-item>
</a-form>
</a-modal>
</GiPageLayout>
</template>
<script setup lang="ts">
@ -162,17 +177,17 @@ const queryFormColumns = [
{ field: 'status', label: '合同状态', type: 'select' as const, props: {
placeholder: '请选择合同状态',
options: [
{ label: '未确认', value: '未确认' },
{ label: '待审批', value: '待审批' },
{ label: '已签署', value: '已签署' },
{ label: '未执行', value: '未执行' },
{ label: '执行中', value: '执行中' },
{ label: '已完成', value: '已完成' },
{ label: '验收中', value: '验收中' },
{ label: '结算中', value: '结算中' },
{ label: '已结算', value: '已结算' },
{ label: '已终止', value: '已终止' },
],
},
},
{ field: 'signDateRange', label: '签署时间', type: 'range-picker' as const, props: {
placeholder: ['开始时间', '结束时间'], showTime: true, format: 'YYYY-MM-DD HH:mm:ss',
placeholder: ['开始日期', '结束日期'], format: 'YYYY-MM-DD',
}
},
]
@ -185,16 +200,105 @@ const tableColumns: TableColumnData[] = [
{ title: '合同金额', dataIndex: 'amount', slotName: 'contractAmount', width: 120 },
{ title: '已收款金额', dataIndex: 'receivedAmount', slotName: 'receivedAmount', width: 120 },
{ title: '未收款金额', dataIndex: 'pendingAmount', width: 120 },
{ title: '签署日期', dataIndex: 'signDate', width: 120 },
{ title: '履约期限', dataIndex: 'performanceDeadline', width: 120 },
{ title: '付款日期', dataIndex: 'paymentDate', width: 120 },
{ title: '合同状态', dataIndex: 'contractStatus', slotName: 'status', width: 100 },
{ title: '签署日期', dataIndex: 'signDate', slotName: 'signDate', width: 120 },
{ title: '履约期限', dataIndex: 'performanceDeadline', slotName: 'performanceDeadline', width: 120 },
{ title: '付款日期', dataIndex: 'paymentDate', slotName: 'paymentDate', width: 120 },
{ title: '合同状态', dataIndex: 'contractStatus', slotName: 'status', width: 120 },
{ title: '销售人员', dataIndex: 'salespersonName', width: 100 },
{ title: '销售部门', dataIndex: 'salespersonDeptName', width: 100 },
{ title: '产品服务', dataIndex: 'productService', width: 120, ellipsis: true, tooltip: true },
{ title: '备注', dataIndex: 'notes', width: 200, ellipsis: true, tooltip: true },
{ title: '操作', slotName: 'action', width: 200, fixed: 'right' },
{ title: '备注', dataIndex: 'notes', width: 220, ellipsis: true, tooltip: true },
{ title: '操作', slotName: 'action', width: 240, fixed: 'right' },
]
//
const showSettlementModal = ref(false)
const settlementForm = reactive({
//
contractId: '',
amount: 0,
paymentDate: '',
paymentPeriod: '',
notes: '',
//
accountNumber: '',
code: '',
customer: '',
departmentId: '',
duration: '',
productService: '',
projectId: '',
salespersonId: '',
settlementId: '',
settlementStatus: '',
})
const settlementRecord = ref<ContractItem | null>(null)
const openSettlement = (record: ContractItem) => {
if (record.contractStatus === '已结算') return
settlementRecord.value = record
Object.assign(settlementForm, {
//
contractId: record.contractId,
amount: record.amount || 0,
paymentDate: record.paymentDate || '',
paymentPeriod: '',
notes: '',
// 便
accountNumber: (record as any).accountNumber || '',
code: (record as any).code || '',
customer: (record as any).customer || '',
departmentId: (record as any).departmentId || '',
duration: (record as any).duration || '',
productService: (record as any).productService || '',
projectId: (record as any).projectId || '',
salespersonId: (record as any).salespersonId || '',
settlementId: (record as any).settlementId || '',
settlementStatus: (record as any).settlementStatus || '',
})
showSettlementModal.value = true
}
const submitSettlement = async () => {
try {
const payload:any = {
accountNumber: settlementForm.accountNumber || '',
amount: settlementForm.amount,
code: settlementForm.code || '',
contractId: settlementForm.contractId,
customer: settlementForm.customer || '',
departmentId: settlementForm.departmentId || '',
duration: settlementForm.duration || '',
notes: settlementForm.notes || '',
paymentDate: settlementForm.paymentDate || null,
paymentPeriod: settlementForm.paymentPeriod || '',
productService: settlementForm.productService || '',
projectId: settlementForm.projectId || '',
salespersonId: settlementForm.salespersonId || '',
settlementId: settlementForm.settlementId || '',
settlementStatus: settlementForm.settlementStatus || '',
}
const res = await http.post('/contract-settlement', payload)
if (res.code === 200 || (res as any).status === 200) {
Message.success('合同结算成功')
// 0 0 =>
const origin = settlementRecord.value
const settledAmount = (origin?.settlementAmount ?? origin?.receivedAmount ?? 0) + (settlementForm.amount || 0)
const pendingAfter = Math.max((origin?.amount || 0) - settledAmount, 0)
const targetStatus = pendingAfter === 0 ? '已结算' : '结算中'
await http.put('/contract', { contractId: settlementForm.contractId, contractStatus: targetStatus, type: origin?.type || '收入合同' })
showSettlementModal.value = false
search()
return true
}
Message.error(res.msg || '合同结算失败')
return false
} catch (e:any) {
Message.error(e?.message || '合同结算失败')
return false
}
}
//
const loading = ref(false)
const dataList = ref<ContractItem[]>([])
@ -235,7 +339,7 @@ const fetchContractList = async () => {
dataList.value = revenueContracts.map((item: ContractItem) => ({
...item,
pendingAmount: (item.amount || 0) - (item.receivedAmount || 0),
pendingAmount: (item.amount || 0) - ((item.receivedAmount || item.settlementAmount || 0)),
}))
pagination.total = dataList.value.length
@ -263,11 +367,11 @@ const pagination = reactive({
//
const getStatusColor = (status: string) => {
const colorMap: Record<string, string> = {
未确认: 'gray',
待审批: 'orange',
已签署: 'blue',
未执行: 'gray',
执行中: 'cyan',
已完成: 'green',
验收中: 'arcoblue',
结算中: 'orange',
已结算: 'green',
已终止: 'red',
}
return colorMap[status] || 'gray'
@ -318,7 +422,7 @@ const newContractData = ref<ContractItem>({
contractId: '', customer: '', code: '', projectId: '', type: '收入合同',
productService: '', paymentDate: null, performanceDeadline: null,
paymentAddress: '', amount: 0, accountNumber: '', notes: '',
contractStatus: '未确认', contractText: '', projectName: '',
contractStatus: '未执行', contractText: '', projectName: '',
salespersonName: null, salespersonDeptName: '', settlementAmount: null,
receivedAmount: null, contractStatusLabel: null, createBy: null, updateBy: null,
createTime: '', updateTime: '', page: 1, pageSize: 10, signDate: '', duration: '',
@ -329,7 +433,7 @@ const openAddModal = () => {
contractId: '', customer: '', code: '', projectId: '', type: '收入合同',
productService: '', paymentDate: null, performanceDeadline: null,
paymentAddress: '', amount: 0, accountNumber: '', notes: '',
contractStatus: '未确认', contractText: '', projectName: '',
contractStatus: '未执行', contractText: '', projectName: '',
salespersonName: null, salespersonDeptName: '', settlementAmount: null,
receivedAmount: null, contractStatusLabel: null, createBy: null, updateBy: null,
createTime: '', updateTime: '', page: 1, pageSize: 10, signDate: '', duration: '',
@ -347,7 +451,7 @@ const handleAddSubmit = async () => {
accountNumber: newContractData.value.accountNumber || '',
amount: newContractData.value.amount || 0,
code: newContractData.value.code || '',
contractStatus: newContractData.value.contractStatus || '',
contractStatus: newContractData.value.contractStatus || '未执行',
contractText: newContractData.value.contractText || '',
customer: newContractData.value.customer || '',
departmentId: (newContractData.value as any).departmentId || '',
@ -391,7 +495,7 @@ const editRecord = (record: ContractItem) => {
amount: record.amount || 0,
projectId: record.projectId || '',
type: record.type || '收入合同',
contractStatus: record.contractStatus || '未确认',
contractStatus: record.contractStatus || '未执行',
}
selectedContractData.value = completeRecord
@ -418,7 +522,7 @@ const handleEditSubmit = async () => {
amount: editedContractData.value.amount || 0,
code: editedContractData.value.code || '',
contractId: editedContractData.value.contractId,
contractStatus: editedContractData.value.contractStatus || '',
contractStatus: editedContractData.value.contractStatus || '未执行',
contractText: editedContractData.value.contractText || '',
customer: editedContractData.value.customer || '',
departmentId: editedContractData.value.departmentId || '',