Industrial-image-management.../src/views/project-management/contract/revenue-contract/index.vue

444 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<GiPageLayout>
<GiTable
row-key="id"
title="收入合同管理"
:data="dataList"
:columns="tableColumns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1600 }"
:pagination="pagination"
@page-change="onPageChange"
@page-size-change="onPageSizeChange"
@refresh="search"
>
<template #top>
<GiForm
v-model="searchForm"
search
:columns="queryFormColumns"
size="medium"
@search="search"
@reset="reset"
/>
</template>
<template #toolbar-left>
<a-space>
<a-button type="primary" @click="openAddModal">
<template #icon><icon-plus /></template>
<template #default>新建合同</template>
</a-button>
<a-button @click="exportContract">
<template #icon><icon-download /></template>
<template #default>导出合同</template>
</a-button>
</a-space>
</template>
<!-- 合同状态 -->
<template #status="{ record }">
<a-tag :color="getStatusColor(record.contractStatus)">
{{ getStatusText(record.contractStatusLabel || record.contractStatus) }}
</a-tag>
</template>
<!-- 合同金额 -->
<template #contractAmount="{ record }">
<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>
<template #action="{ record }">
<a-space>
<a-link @click="viewDetail(record)">详情</a-link>
<a-link v-if="record.contractStatus === '未确认'" @click="editRecord(record)">编辑</a-link>
<a-link v-if="record.contractStatus === '待审批'" @click="approveContract(record)">审批</a-link>
<a-link @click="viewPayment(record)">收款记录</a-link>
<a-link v-if="record.contractStatus !== '已签署' && record.contractStatus !== '已完成'" @click="deleteContract(record)">删除</a-link>
</a-space>
</template>
</GiTable>
<!-- 合同详情弹窗 -->
<a-modal
v-model:visible="showDetailModal"
title="合同详情"
:width="800"
:footer="false"
@cancel="closeDetailModal"
>
<ContractDetail v-if="showDetailModal" :contract-id="selectedContractId" />
</a-modal>
<!-- 合同编辑弹窗 -->
<a-modal
v-model:visible="showEditModal"
title="编辑合同"
:width="800"
@cancel="closeEditModal"
@before-ok="handleEditSubmit"
>
<ContractEdit
v-if="showEditModal"
:contract-data="selectedContractData"
@update:contract-data="handleContractDataUpdate"
/>
</a-modal>
</GiPageLayout>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import { Message, Modal } from '@arco-design/web-vue'
import type { TableColumnData } from '@arco-design/web-vue'
import ContractEdit from './ContractEdit.vue'
import ContractDetail from './ContractDetail.vue'
import http from '@/utils/http'
// 接口数据类型定义
interface ContractItem {
contractId: string
customer: string
code: string
projectId: string
type: string
productService: string
paymentDate: string | null
performanceDeadline: string | null
paymentAddress: string
amount: number
accountNumber: string
notes: string
contractStatus: string
contractText: string | null
projectName: string
salespersonName: string | null
salespersonDeptName: string
settlementAmount: number | null
receivedAmount: number | null
contractStatusLabel: string | null
createBy: string | null
updateBy: string | null
createTime: string
updateTime: string
page: number
pageSize: number
signDate: string
duration: string
}
// 搜索表单
const searchForm = reactive({
contractName: '',
contractCode: '',
client: '',
status: '',
signDate: '',
page: 1,
size: 10,
})
// 查询条件配置
const queryFormColumns = [
{
field: 'contractName',
label: '合同名称',
type: 'input' as const,
props: {
placeholder: '请输入合同名称',
},
},
{
field: 'client',
label: '客户',
type: 'input' as const,
props: {
placeholder: '请输入客户名称',
},
},
{
field: 'status',
label: '合同状态',
type: 'select' as const,
props: {
placeholder: '请选择合同状态',
options: [
{ label: '未确认', value: '未确认' },
{ label: '待审批', value: '待审批' },
{ label: '已签署', value: '已签署' },
{ label: '执行中', value: '执行中' },
{ label: '已完成', value: '已完成' },
{ label: '已终止', value: '已终止' },
],
},
},
]
// 表格列配置
const tableColumns: TableColumnData[] = [
{ title: '合同编号', dataIndex: 'code', width: 150 },
{ 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: 'contractStatus', slotName: 'status', width: 100 },
{ 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' },
]
// 数据状态
const loading = ref(false)
const dataList = ref<ContractItem[]>([])
// API调用函数
const fetchContractList = async () => {
try {
loading.value = true
const params = {
page: searchForm.page,
pageSize: searchForm.size,
contractName: searchForm.contractName,
code: searchForm.contractCode,
customer: searchForm.client,
contractStatus: searchForm.status,
signDate: searchForm.signDate,
}
const response = await http.get('/contract/list', params)
if (response.code === 200) {
// 过滤出类型为"收入合同"的数据
const allContracts = response.rows || []
const revenueContracts = allContracts.filter((item: ContractItem) => item.type === '收入合同')
// 计算未收款金额
dataList.value = revenueContracts.map((item: ContractItem) => ({
...item,
pendingAmount: (item.amount || 0) - (item.receivedAmount || 0),
}))
pagination.total = Number.parseInt(response.total) || 0
} else {
Message.error(response.msg || '获取合同列表失败')
dataList.value = []
}
} catch (error) {
console.error('获取合同列表失败:', error)
Message.error('获取合同列表失败')
dataList.value = []
} finally {
loading.value = false
}
}
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showTotal: true,
showPageSize: true,
})
// 获取状态颜色
const getStatusColor = (status: string) => {
const colorMap: Record<string, string> = {
未确认: 'gray',
待审批: 'orange',
已签署: 'blue',
执行中: 'cyan',
已完成: 'green',
已终止: 'red',
}
return colorMap[status] || 'gray'
}
// 获取状态文本
const getStatusText = (status: string) => {
// 直接返回后端返回的状态文本如果有contractStatusLabel则使用否则使用contractStatus
return status || '未知状态'
}
// 搜索和重置
const search = async () => {
await fetchContractList()
}
const reset = () => {
Object.assign(searchForm, {
contractName: '',
contractCode: '',
client: '',
status: '',
signDate: '',
page: 1,
size: 10,
})
pagination.current = 1
search()
}
// 分页处理
const onPageChange = (page: number) => {
searchForm.page = page
pagination.current = page
search()
}
const onPageSizeChange = (size: number) => {
searchForm.size = size
searchForm.page = 1
pagination.pageSize = size
pagination.current = 1
search()
}
// 操作方法
const openAddModal = () => {
Message.info('新建合同功能开发中...')
}
const exportContract = () => {
Message.info('导出合同功能开发中...')
}
// 显示合同编辑弹窗
const showEditModal = ref(false)
const selectedContractData = ref<ContractItem | null>(null)
const editedContractData = ref<ContractItem | null>(null)
const editRecord = (record: ContractItem) => {
// 确保所有必要的字段都存在
const completeRecord = {
...record,
amount: record.amount || 0,
projectId: record.projectId || '',
type: record.type || '收入合同',
contractStatus: record.contractStatus || '未确认',
}
selectedContractData.value = completeRecord
showEditModal.value = true
}
const closeEditModal = () => {
showEditModal.value = false
selectedContractData.value = null
editedContractData.value = null
}
const handleContractDataUpdate = (data: ContractItem) => {
editedContractData.value = data
}
const handleEditSubmit = async () => {
if (!editedContractData.value) return false;
try {
const requestData = {
...editedContractData.value,
accountNumber: editedContractData.value.accountNumber || '',
amount: editedContractData.value.amount || 0,
code: editedContractData.value.code || '',
contractId: editedContractData.value.contractId,
contractStatus: editedContractData.value.contractStatus || '',
contractText: editedContractData.value.contractText || '',
customer: editedContractData.value.customer || '',
departmentId: editedContractData.value.departmentId || '',
duration: editedContractData.value.duration || '',
notes: editedContractData.value.notes || '',
paymentAddress: editedContractData.value.paymentAddress || '',
paymentDate: editedContractData.value.paymentDate || null,
performanceDeadline: editedContractData.value.performanceDeadline || null,
productService: editedContractData.value.productService || '',
projectId: editedContractData.value.projectId || '',
salespersonId: editedContractData.value.salespersonId || '',
signDate: editedContractData.value.signDate || null,
type: editedContractData.value.type || '',
};
console.log('Edited Contract Data:', requestData); // 打印请求数据以便调试
// 修改此处,直接向 /contract 发送 PUT 请求
const response = await http.put('/contract', requestData);
// 检查响应状态
if (response.status === 200 && response.code === 200) {
Message.success('合同编辑成功');
closeEditModal();
search(); // 刷新列表
return true;
} else {
Message.error(response.msg || '合同编辑失败');
return false;
}
} catch (error) {
console.error('合同编辑失败:', error);
Message.error('合同编辑失败: ' + (error.message || '请稍后再试'));
return false;
}
}
// 删除合同
const deleteContract = async (record: ContractItem) => {
try {
await Modal.confirm({
title: '确认删除',
content: `确定要删除合同 "${record.projectName}" 吗?`,
})
const response = await http.delete(`/contract/${record.contractId}`)
if (response.code === 200) {
Message.success('合同删除成功')
search() // 刷新列表
} else {
Message.error(response.msg || '合同删除失败')
}
} catch (error) {
// 用户取消删除或请求失败
if (error !== 'cancel') {
console.error('合同删除失败:', error)
Message.error('合同删除失败')
}
}
}
// 显示合同详情弹窗
const showDetailModal = ref(false)
const selectedContractId = ref<string | null>(null)
const viewDetail = (record: ContractItem) => {
selectedContractId.value = record.contractId
showDetailModal.value = true
}
const closeDetailModal = () => {
showDetailModal.value = false
selectedContractId.value = null
}
const approveContract = (record: ContractItem) => {
Message.info(`审批合同: ${record.projectName}`)
}
const viewPayment = (record: ContractItem) => {
Message.info(`查看收款记录: ${record.projectName}`)
}
onMounted(() => {
fetchContractList()
})
</script>