1.3.3前端:

feat(应收款):完成财务应收款功能
dev
xs 1 week ago
parent bbf40dc056
commit 3337b24c9d

@ -93,9 +93,9 @@ export function getErpProjectInfoList(query) {
* @param query * @param query
* @returns {*} * @returns {*}
*/ */
export function getErpProjectWithProjectList(query) { export function getErpProjectWithContractList(query) {
return request({ return request({
url: '/oa/erp/projectInfo/getErpProjectWithProjectList', url: '/oa/erp/projectInfo/getErpProjectWithContractList',
method: 'get', method: 'get',
params: query params: query
}); });

@ -33,6 +33,7 @@
:row-class-name="tableRowClassName" :row-class-name="tableRowClassName"
@row-click="handleRowClick" @row-click="handleRowClick"
@expand-change="handleExpandChange" @expand-change="handleExpandChange"
default-expand-all
> >
<el-table-column type="expand" width="50"> <el-table-column type="expand" width="50">
<template #default="props"> <template #default="props">
@ -87,14 +88,16 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="projectCode" label="项目号" width="150" /> <el-table-column prop="projectCode" label="项目号" width="130" />
<el-table-column prop="projectName" label="项目名称" min-width="160" /> <el-table-column prop="projectName" label="项目名称" min-width="150" />
<el-table-column prop="businessDirection" label="业务方向" width="120"> <el-table-column prop="amount" label="项目金额" width="110" />
<el-table-column prop="managerName" label="项目经理" width="110" />
<el-table-column prop="businessDirection" label="业务方向" width="110">
<template #default="scope"> <template #default="scope">
<dict-tag :options="business_direction" :value="scope.row.businessDirection" /> <dict-tag :options="business_direction" :value="scope.row.businessDirection" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="contractFlag" label="有无合同" min-width="120"> <el-table-column prop="contractFlag" label="有无合同" width="100">
<template #default="scope"> <template #default="scope">
<dict-tag :options="contract_flag" :value="scope.row.contractFlag" /> <dict-tag :options="contract_flag" :value="scope.row.contractFlag" />
</template> </template>
@ -128,7 +131,7 @@
<script setup lang="ts" name="ProjectSelectDialog"> <script setup lang="ts" name="ProjectSelectDialog">
import { ref, reactive, toRefs, onMounted } from 'vue'; import { ref, reactive, toRefs, onMounted } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { getErpProjectWithProjectList } from '@/api/oa/erp/projectInfo'; import { getErpProjectWithContractList } from '@/api/oa/erp/projectInfo';
import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types'; import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types';
const props = defineProps({ const props = defineProps({
@ -231,7 +234,7 @@ const resetQuery = () => {
const getProjectList = async () => { const getProjectList = async () => {
projectLoading.value = true; projectLoading.value = true;
try { try {
const res = await getErpProjectWithProjectList(queryParams.value); const res = await getErpProjectWithContractList(queryParams.value);
console.log(res) console.log(res)
projectList.value = res.rows; projectList.value = res.rows;
projectTotal.value = res.total; projectTotal.value = res.total;

@ -7,16 +7,16 @@
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
</div> </div>
<div class="header-right"> <div class="header-right">
<el-button type="primary" @click="submitForm" :loading="buttonLoading">保存</el-button> <el-button type="primary" @click="submitForm" :loading="buttonLoading" v-if="!isFormDisabled"></el-button>
<el-button @click="resetForm"></el-button> <el-button @click="resetForm" v-if="!isFormDisabled"></el-button>
<!-- <el-button @click="handleCalculate" v-if="formData.id"></el-button>--> <!-- <el-button @click="handleCalculate" v-if="formData.id"></el-button>-->
</div> </div>
</div> </div>
<el-divider /> <el-divider />
<!-- 表单内容 --> <!-- 表单内容 -->
<el-form ref="receivableFormRef" :model="formData" :rules="formRules" label-width="160px" class="receivable-form"> <el-form ref="receivableFormRef" :model="formData" :rules="formRules" :disabled="isFormDisabled" label-width="160px" class="receivable-form">
<!-- 合同信息区域 - 可折叠 --> <!-- 合同信息区域 - 可折叠 -->
<div class="form-section" v-loading="loading"> <div class="form-section" v-loading="loading">
<div class="section-header" @click="toggleSection('contract')"> <div class="section-header" @click="toggleSection('contract')">
@ -39,11 +39,7 @@
@click="showProjectSelectDialog" @click="showProjectSelectDialog"
suffix-icon="Search" suffix-icon="Search"
/> />
<el-input <el-input v-if="formData.accountReceivableId" v-model="formData.projectCode" readonly />
v-if="formData.accountReceivableId"
v-model="formData.projectCode"
readonly
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -61,12 +57,7 @@
@click="showContractSelectDialog" @click="showContractSelectDialog"
suffix-icon="Search" suffix-icon="Search"
/> />
<el-input <el-input v-else v-model="formData.contractCode" readonly />
v-else
v-model="formData.contractCode"
readonly
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -75,8 +66,8 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="签单月份" prop="contractMonth"> <el-form-item label="签单月份" prop="contractDate">
<el-date-picker v-model="formData.contractMonth" type="month" readonly style="width: 100%" format="YYYY-MM" /> <el-date-picker v-model="formData.contractDate" type="month" readonly style="width: 100%" format="YYYY-MM" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -95,13 +86,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="客户名称" prop="customerName"> <el-form-item label="客户名称" prop="oneCustomerName">
<el-input v-model="formData.customerName" readonly /> <el-input v-model="formData.oneCustomerName" readonly />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="签订主体" prop="contractingEntity"> <el-form-item label="签订主体" prop="twoCustomerName">
<el-input v-model="formData.contractingEntity" readonly /> <el-input v-model="formData.twoCustomerName" readonly />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -115,18 +106,18 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="客户经理" prop="customerManager"> <el-form-item label="客户经理" prop="managerName">
<el-input v-model="formData.customerManager" readonly /> <el-input v-model="formData.managerName" readonly />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="软控-订单号" prop="mesnacOrderNo"> <el-form-item label="软控-订单号" prop="mesnacOrderNo">
<el-input v-model="formData.mesnacOrderNo" /> <el-input v-model="formData.mesnacOrderNo" readonly />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="软控-项目号" prop="mesnacProjectCode"> <el-form-item label="软控-项目号" prop="mesnacProjectCode">
<el-input v-model="formData.mesnacProjectCode" /> <el-input v-model="formData.mesnacProjectCode" readonly />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -315,8 +306,7 @@
</el-col> </el-col>
<el-col :span="6" v-if="finAccountReceivableStage.paymentStageId === PAYMENT_STAGE_ID.WARRANTY"> <el-col :span="6" v-if="finAccountReceivableStage.paymentStageId === PAYMENT_STAGE_ID.WARRANTY">
<el-form-item label="质保条款" prop="paymentDeadline" label-width="90px"> <el-form-item label="质保条款" prop="paymentDeadline" label-width="90px">
<el-input v-model="finAccountReceivableStage.paymentDeadline" placeholder="质保条款" readonly> <el-input v-model="finAccountReceivableStage.paymentDeadline" placeholder="质保条款" readonly> </el-input>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -334,17 +324,16 @@
<!-- 基准日期字段 - 根据节点类型显示不同标签 --> <!-- 基准日期字段 - 根据节点类型显示不同标签 -->
<el-col :span="6" v-if="finAccountReceivableStage.paymentStageId === PAYMENT_STAGE_ID.DELIVERY"> <el-col :span="6" v-if="finAccountReceivableStage.paymentStageId === PAYMENT_STAGE_ID.DELIVERY">
<el-form-item label="合同交货期" prop="stageRequiredDate" label-width="90px"> <el-form-item label="合同交货期" prop="stageRequiredDate" label-width="90px">
<el-date-picker <el-date-picker v-model="finAccountReceivableStage.stageRequiredDate" type="date" placeholder="选择日期" style="width: 100%" />
v-model="finAccountReceivableStage.stageRequiredDate"
type="date"
placeholder="选择日期"
style="width: 100%"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6" v-if="getStageConfig(finAccountReceivableStage.paymentStageId).showStageRealDate"> <el-col :span="6" v-if="getStageConfig(finAccountReceivableStage.paymentStageId).showStageRealDate">
<el-form-item :label="getStageConfig(finAccountReceivableStage.paymentStageId).stageRealDateLabel" prop="stageRealDate" label-width="90px"> <el-form-item
:label="getStageConfig(finAccountReceivableStage.paymentStageId).stageRealDateLabel"
prop="stageRealDate"
label-width="90px"
>
<el-date-picker <el-date-picker
v-model="finAccountReceivableStage.stageRealDate" v-model="finAccountReceivableStage.stageRealDate"
type="date" type="date"
@ -355,7 +344,6 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 到期日显示 --> <!-- 到期日显示 -->
<el-col :span="6" v-if="finAccountReceivableStage.paymentStageId !== PAYMENT_STAGE_ID.WARRANTY"> <el-col :span="6" v-if="finAccountReceivableStage.paymentStageId !== PAYMENT_STAGE_ID.WARRANTY">
<el-form-item label="到期日" prop="dueDate" label-width="90px"> <el-form-item label="到期日" prop="dueDate" label-width="90px">
@ -635,7 +623,6 @@
<!-- 合同选择弹窗组件 --> <!-- 合同选择弹窗组件 -->
<ContractSelectDialog v-model:visible="contractSelectDialogVisible" @contract-selected="handleContractSelected" /> <ContractSelectDialog v-model:visible="contractSelectDialogVisible" @contract-selected="handleContractSelected" />
</div> </div>
</template> </template>
@ -675,9 +662,9 @@ const buttonLoading = ref(false);
const title = ref('新增应收款项目'); const title = ref('新增应收款项目');
const CONTRACT_FLAG = { const CONTRACT_FLAG = {
YES:'1', YES: '1',
NO:'2' NO: '2'
} };
// //
const collapsed = ref({ const collapsed = ref({
@ -703,6 +690,10 @@ const PAYMENT_STAGE_ID = {
WARRANTY: 8 // WARRANTY: 8 //
}; };
const isFormDisabled = computed(() => {
return routeParams.value.type === 'view' || routeParams.value.type === 'approval';
});
const finAccountReceivableStageList = ref<FinAccountReceivableStageVO[]>([]); const finAccountReceivableStageList = ref<FinAccountReceivableStageVO[]>([]);
// //
@ -714,34 +705,42 @@ const showProjectSelectDialog = () => {
}; };
// //
const handleProjectSelected = (project: any) => { const handleProjectSelected = (result: any) => {
const project = result.project;
const erpContractInfoList = project.erpContractInfoVoList;
let totalPrice = project.amount;
if (erpContractInfoList && erpContractInfoList.length > 1) {
totalPrice = result.contract?.totalPrice;
}
console.log(result.project);
console.log(result.contract)
Object.assign(formData.value, { Object.assign(formData.value, {
contractId: project.contractId,
contractFlag: project.contractFlag, contractFlag: project.contractFlag,
projectId: project.projectId, projectId: project.projectId,
projectName: project.projectName, projectName: project.projectName,
projectCode: project.projectCode, projectCode: project.projectCode,
contractCode: project.contractCode,
contractName: project.contractName,
contractMonth: project.contractDate,
contractDate: project.contractDate,
externalContractCode: project.externalContractCode,
internalContractCode: project.internalContractCode,
customerName: project.customerName,
contractingEntity: project.contractingEntity,
businessDirection: project.businessDirection,
customerManager: project.customerManager,
deptName: project.deptName, deptName: project.deptName,
orderContractCode: project.orderContractCode, managerName: project.managerName,
projectStatus: project.projectStatus, projectStatus: project.projectStatus,
totalPrice: project.totalPrice, contractId: result.contract?.contractId,
totalPriceHighway: project.totalPrice, contractCode: result.contract?.contractCode,
totalPriceOri: project.totalPrice contractName: result.contract?.contractName,
contractDate: result.contract?.contractDate,
externalContractCode: result.contract?.externalContractCode,
internalContractCode: result.contract?.internalContractCode,
oneCustomerName: result.contract?.oneCustomerName,
twoCustomerName: result.contract?.twoCustomerName,
businessDirection: result.contract?.businessDirection,
orderContractCode: project.projectCode,
mesnacOrderNo: result.contract?.orderContractCode,
mesnacProjectCode: result.contract?.projectContractCode,
totalPrice: totalPrice,
totalPriceHighway: totalPrice,
totalPriceOri: totalPrice
}); });
getErpFinAccountReceivableStages(); getErpFinAccountReceivableStages();
}; };
// //
const contractSelectDialogVisible = ref(false); const contractSelectDialogVisible = ref(false);
@ -756,24 +755,18 @@ const handleContractSelected = (contract: any) => {
contractId: contract.contractId, contractId: contract.contractId,
contractCode: contract.contractCode, contractCode: contract.contractCode,
contractName: contract.contractName, contractName: contract.contractName,
contractMonth: contract.contractDate,
contractDate: contract.contractDate, contractDate: contract.contractDate,
externalContractCode: contract.externalContractCode, externalContractCode: contract.externalContractCode,
internalContractCode: contract.internalContractCode, internalContractCode: contract.internalContractCode,
// customerName: contract.customerName, oneCustomerName: contract.oneCustomerName,
// contractingEntity: project.contractingEntity, twoCustomerName: contract.twoCustomerName,
businessDirection: contract.businessDirection, businessDirection: contract.businessDirection,
// customerManager: project.customerManager, mesnacOrderNo: contract.orderContractCode,
// deptName: project.deptName, mesnacProjectCode: contract.projectContractCode,
orderContractCode: contract.orderContractCode,
totalPrice: contract.totalPrice,
totalPriceHighway: contract.totalPrice,
totalPriceOri: contract.totalPrice,
}); });
getErpFinAccountReceivableStages(); getErpFinAccountReceivableStages();
}; };
/** 新增时查询应收款节点信息列表 */ /** 新增时查询应收款节点信息列表 */
const getErpFinAccountReceivableStages = async () => { const getErpFinAccountReceivableStages = async () => {
if (formData.value.contractId && formData.value.contractId !== '') { if (formData.value.contractId && formData.value.contractId !== '') {
@ -800,6 +793,7 @@ const initializeStageCalculations = () => {
stage.receivedAmount = '0'; stage.receivedAmount = '0';
} }
stage.paymentAmount = formData.value.totalPrice*stage.paymentPercentage/100;
// //
switch (stage.paymentStageId) { switch (stage.paymentStageId) {
case PAYMENT_STAGE_ID.WARRANTY: case PAYMENT_STAGE_ID.WARRANTY:
@ -968,8 +962,7 @@ const agingData = computed(() => {
baseDate: getBaseDateForAging(stage), baseDate: getBaseDateForAging(stage),
aging: calculateStageAging(stage), aging: calculateStageAging(stage),
paymentStageId: stage.paymentStageId paymentStageId: stage.paymentStageId
})) })); //
.filter((item) => item.owedAmount > 0); //
}); });
// //
@ -1310,18 +1303,17 @@ const formData = ref<any>({
projectCode: '', projectCode: '',
projectCategory: '', projectCategory: '',
projectType: '', projectType: '',
contractMonth: '',
contractDate: '', contractDate: '',
externalContractCode: '', externalContractCode: '',
internalContractCode: '', internalContractCode: '',
generalContractor: '', generalContractor: '',
customerAbbreviation: '', customerAbbreviation: '',
contractParties: '', contractParties: '',
customerName: '', oneCustomerName: '',
contractingEntity: '', twoCustomerName: '',
businessDirection: '', businessDirection: '',
deptName: '', deptName: '',
customerManager: '', managerName: '',
mesnacOrderNo: '', mesnacOrderNo: '',
mesnacProjectCode: '', mesnacProjectCode: '',
orderContractCode: '', orderContractCode: '',
@ -1385,10 +1377,8 @@ const paymentRate = computed(() => {
}); });
const paymentDescription = computed(() => { const paymentDescription = computed(() => {
return finAccountReceivableStageList.value return finAccountReceivableStageList.value.map((item) => `${item.paymentDescription}`).join('\n'); // 使
.map(item => `${item.paymentDescription}`) });
.join('\n') // 使
})
// //
const toggleSection = (section: string) => { const toggleSection = (section: string) => {
@ -1419,18 +1409,17 @@ const resetForm = () => {
projectCode: '', projectCode: '',
projectCategory: '', projectCategory: '',
projectType: '', projectType: '',
contractMonth: '',
contractDate: '', contractDate: '',
externalContractCode: '', externalContractCode: '',
internalContractCode: '', internalContractCode: '',
generalContractor: '', generalContractor: '',
customerAbbreviation: '', customerAbbreviation: '',
contractParties: '', contractParties: '',
customerName: '', oneCustomerName: '',
contractingEntity: '', twoCustomerName: '',
businessDirection: '', businessDirection: '',
deptName: '', deptName: '',
customerManager: '', managerName: '',
mesnacOrderNo: '', mesnacOrderNo: '',
mesnacProjectCode: '', mesnacProjectCode: '',
orderContractCode: '', orderContractCode: '',
@ -1461,18 +1450,17 @@ const loadData = async (accountReceivableId: string) => {
stageLoading.value = true; stageLoading.value = true;
try { try {
const res = await getFinAccountReceivable(accountReceivableId); const res = await getFinAccountReceivable(accountReceivableId);
console.log(res.data) console.log(res.data);
const erpProjectInfo = res.data.erpProjectInfoVo; const erpProjectInfo = res.data.erpProjectInfoVo;
Object.assign(formData.value, res.data, erpProjectInfo); const erpContractInfo = res.data.erpContractInfoVo;
console.log("--")
Object.assign(formData.value, res.data, erpProjectInfo,erpContractInfo);
Object.assign(formData.value, { Object.assign(formData.value, {
projectCategory: res.data.projectCategory, projectCategory: res.data.projectCategory,
oneCustomerName: res.data.oneCustomerName,
twoCustomerName: res.data.twoCustomerName,
managerName: res.data.managerName,
remark: res.data.remark, remark: res.data.remark,
contractMonth: erpProjectInfo.contractDate,
orderContractCode: erpProjectInfo.orderContractCode,
totalPrice: erpProjectInfo.totalPrice,
totalPriceHighway: erpProjectInfo.totalPrice,
totalPriceOri: erpProjectInfo.totalPrice,
paymentMethod: erpProjectInfo.paymentMethod
}); });
await getEditErpFinAccountReceivableStages(); await getEditErpFinAccountReceivableStages();
@ -1496,7 +1484,7 @@ const submitForm = () => {
finAccountReceivableStageList: finAccountReceivableStageList.value finAccountReceivableStageList: finAccountReceivableStageList.value
}; };
console.log(finAccountReceivableForm) console.log(finAccountReceivableForm);
if (formData.value.accountReceivableId) { if (formData.value.accountReceivableId) {
await updateFinAccountReceivable(finAccountReceivableForm); await updateFinAccountReceivable(finAccountReceivableForm);
} else { } else {

@ -1,32 +1,123 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 搜索表单 --> <!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch"> <el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="130px">
<el-form-item label="项目编号" prop="projectNo"> <el-form-item label="项目编号" prop="receivableProjectCode">
<el-input <el-input
v-model="queryParams.projectNo" v-model="queryParams.receivableProjectCode"
placeholder="请输入项目编号" placeholder="请输入项目编号"
clearable clearable
style="width: 200px" style="width: 200px"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="客户名称" prop="clientName"> <el-form-item label="项目名称" prop="receivableProjectName">
<el-input <el-input
v-model="queryParams.clientName" v-model="queryParams.receivableProjectName"
placeholder="请输入客户名称" placeholder="请输入项目名称"
clearable clearable
style="width: 200px" style="width: 200px"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="项目状态" prop="projectStatus">
<el-select v-model="queryParams.projectStatus" placeholder="项目状态" clearable style="width: 200px"> <el-form-item label="集团应收模板编号" prop="invoiceCode">
<el-option label="已结算" value="已结算" /> <el-input
<el-option label="进行中" value="进行中" /> v-model="queryParams.invoiceCode"
<el-option label="已终止" value="已终止" /> placeholder="请输入集团应收模板编号"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目大类" prop="projectCategory">
<el-input
v-model="queryParams.projectCategory"
placeholder="请输入项目大类"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目小类" prop="projectType">
<el-input
v-model="queryParams.projectType"
placeholder="请输入项目小类"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总包" prop="generalContractor">
<el-input
v-model="queryParams.generalContractor"
placeholder="请输入总包"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="客户简称" prop="customerAbbreviation">
<el-input
v-model="queryParams.customerAbbreviation"
placeholder="请输入客户简称"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="合同签订方" prop="contractParties">
<el-input
v-model="queryParams.contractParties"
placeholder="请输入合同签订方"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="WBS.元素" prop="wbsElement">
<el-input
v-model="queryParams.wbsElement"
placeholder="请输入WBS.元素"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="行项目" prop="lineItem">
<el-input
v-model="queryParams.lineItem"
placeholder="请输入行项目"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目状态" prop="finProjectStatus">
<el-input
v-model="queryParams.finProjectStatus"
placeholder="请输入项目状态"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="业务项目状态" prop="receivableProjectStatus">
<el-select v-model="queryParams.receivableProjectStatus" placeholder="请选择业务项目状态" clearable @keyup.enter="handleQuery">
<el-option v-for="dict in project_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button> <el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button> <el-button icon="Refresh" @click="resetQuery"></el-button>
@ -87,12 +178,12 @@
:span-method="objectSpanMethod" :span-method="objectSpanMethod"
> >
<!-- 项目编号列 - 也是合并显示列 --> <!-- 项目编号列 - 也是合并显示列 -->
<el-table-column prop="projectNo" label="项目编号" width="200"> <el-table-column prop="receivableProjectCode" label="项目编号" width="200">
<template #default="scope"> <template #default="scope">
<!-- 项目行显示项目编号 --> <!-- 项目行显示项目编号 -->
<div v-if="scope.row.type === 'project'" class="project-cell"> <div v-if="scope.row.type === 'project'" class="project-cell">
<el-icon class="project-folder-icon"><Folder /></el-icon> <el-icon class="project-folder-icon"><Folder /></el-icon>
<span>{{ scope.row.projectCode }}</span> <span>{{ scope.row.receivableProjectCode }}</span>
</div> </div>
<!-- 汇总信息卡片 - 第一行 --> <!-- 汇总信息卡片 - 第一行 -->
@ -256,34 +347,148 @@
</el-table-column> </el-table-column>
<!-- 海威项目编号列 --> <!-- 海威项目编号列 -->
<el-table-column prop="invoiceCode" label="集团应收模板编号" width="150"> <el-table-column prop="receivableProjectName" label="项目名称" width="150">
<template #default="scope">
<span v-if="scope.row.type === 'project'">{{ scope.row.receivableProjectName }}</span>
</template>
</el-table-column>
<el-table-column prop="invoiceCode" label="集团应收模板编号" width="130">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.type === 'project'">{{ scope.row.invoiceCode || scope.row.invoiceCode }}</span> <span v-if="scope.row.type === 'project'">{{ scope.row.invoiceCode || scope.row.invoiceCode }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="projectCategory" label="项目大类" width="120">
<template #default="scope">
<span v-if="scope.row.type === 'project'">{{ scope.row.projectCategory }}</span>
</template>
</el-table-column>
<el-table-column prop="projectType" label="项目小类" width="120">
<template #default="scope">
<span v-if="scope.row.type === 'project'">{{ scope.row.projectType }}</span>
</template>
</el-table-column>
<el-table-column prop="generalContractor" label="总包" min-width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="client-cell">
<!-- <el-icon class="client-icon"><User /></el-icon>-->
<span>{{ scope.row.generalContractor }}</span>
</div>
</template>
</el-table-column>
<!-- 客户名称列 --> <!-- 客户名称列 -->
<el-table-column prop="clientName" label="客户名称" min-width="180"> <el-table-column prop="customerAbbreviation" label="客户简称" min-width="120">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.type === 'project'" class="client-cell"> <div v-if="scope.row.type === 'project'" class="client-cell">
<el-icon class="client-icon"><User /></el-icon> <el-icon class="client-icon"><User /></el-icon>
<span>{{ scope.row.clientName }}</span> <span>{{ scope.row.customerAbbreviation }}</span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<!-- 合同编号列 --> <!-- 合同编号列 -->
<el-table-column prop="contractNo" label="合同编号" width="180"> <el-table-column prop="contractParties" label="合同签订方" width="150">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell"> <div v-if="scope.row.type === 'project'" class="contract-cell">
<el-icon class="contract-icon"><Document /></el-icon> <!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.contractNo || scope.row.projectNo }}</span> <span>{{ scope.row.contractParties }}</span>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="wbsElement" label="WBS.元素" width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.wbsElement }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="lineItem" label="行项目" width="100">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.lineItem }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="finProjectStatus" label="项目状态" width="100">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.finProjectStatus }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="receivableProjectStatus" label="业务项目状态" width="110">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<dict-tag :options="project_status" :value="scope.row.receivableProjectStatus" />
</div>
</template>
</el-table-column>
<el-table-column prop="settlementMonth" label="结算月份" width="100">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ formatToMonth(scope.row.settlementMonth) }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="totalPrice" label="合同金额" width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.totalPrice }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="income" label="收入" width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.income }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="invoiceAmount" label="开票金额" width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.invoiceAmount }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="managerName" label="项目经理" width="120">
<template #default="scope">
<div v-if="scope.row.type === 'project'" class="contract-cell">
<!-- <el-icon class="contract-icon"><Document /></el-icon>-->
<span>{{ scope.row.managerName }}</span>
</div>
</template>
</el-table-column>
<!-- 操作列 --> <!-- 操作列 -->
<el-table-column label="操作" align="center" fixed="right" width="180"> <el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.type === 'project'" class="action-buttons"> <div v-if="scope.row.type === 'project'" class="action-buttons">
<el-button link type="primary" size="small" @click="handleUpdate(scope.row)"> <el-button link type="primary" size="small" @click="handleUpdate(scope.row)">
@ -292,6 +497,9 @@
<el-button link type="primary" size="small" @click="handleDetail(scope.row)"> <el-button link type="primary" size="small" @click="handleDetail(scope.row)">
<el-icon><Document /></el-icon> <el-icon><Document /></el-icon>
</el-button> </el-button>
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">
<el-icon><Delete /></el-icon>
</el-button>
</div> </div>
<div v-else class="action-buttons"> <div v-else class="action-buttons">
<el-button v-if="scope.row.type === 'summary'" link type="primary" size="small" @click="handleAddNode(scope.row)"> <el-button v-if="scope.row.type === 'summary'" link type="primary" size="small" @click="handleAddNode(scope.row)">
@ -321,7 +529,7 @@
</div> </div>
</template> </template>
<script setup name="ReceivableTreeList"> <script setup name="ReceivableTreeList" lang="ts">
import { ref, reactive, getCurrentInstance, nextTick } from 'vue' import { ref, reactive, getCurrentInstance, nextTick } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
@ -331,11 +539,17 @@ import {
Plus Plus
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { import {
listFinAccountReceivable listFinAccountReceivable,delFinAccountReceivable
} from '@/api/oa/erp/finAccountReceivable'; } from '@/api/oa/erp/finAccountReceivable';
import Default from 'vue-json-pretty';
import { FinAccountReceivableVO } from '@/api/oa/erp/finAccountReceivable/types';
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const router = useRouter() const router = useRouter()
const { project_status } = toRefs<any>(
proxy?.useDict('project_status')
);
// //
const treeData = ref([]) const treeData = ref([])
const total = ref(0) const total = ref(0)
@ -344,6 +558,8 @@ const showSearch = ref(true)
const expandAll = ref(false) const expandAll = ref(false)
const treeTable = ref(null) const treeTable = ref(null)
const queryFormRef = ref<ElFormInstance>();
// ID // ID
const expandedProjectIds = ref(new Set()) const expandedProjectIds = ref(new Set())
@ -357,6 +573,16 @@ const queryParams = ref({
}) })
const formatToMonth = (date) => {
if (!date) return ''
const d = new Date(date)
if (isNaN(d.getTime())) return date //
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
return `${year}-${month}` // 2024-01
}
// Mock // Mock
let mockProjects = [ let mockProjects = [
@ -419,7 +645,7 @@ const getList = async () => {
treeData.value = mockProjects.map(p => ({ treeData.value = mockProjects.map(p => ({
...p, ...p,
hasChildren:true, hasChildren:false,
type:'project', type:'project',
children: [] // children: [] //
})) }))
@ -478,11 +704,11 @@ const getNodeChildren = (row, treeNode, resolve) => {
// //
setTimeout(() => { setTimeout(() => {
let children = [] let children = []
const summary = getProjectSummary(row.id) const summary = getProjectSummary(row.accountReceivableId)
// //
children.push({ children.push({
id: `summary-${row.id}`, accountReceivableId: `summary-${row.id}`,
parentId: row.id, parentId: row.id,
type: 'summary', type: 'summary',
name: '项目汇总', name: '项目汇总',
@ -494,7 +720,7 @@ const getNodeChildren = (row, treeNode, resolve) => {
}) })
// //
if (row.id === 1) { if (row.accountReceivableId === 4) {
children.push( children.push(
{ {
id: 101, id: 101,
@ -538,7 +764,7 @@ const getNodeChildren = (row, treeNode, resolve) => {
startDate: '2025-05-25', startDate: '2025-05-25',
dueDate: '2025-06-25', dueDate: '2025-06-25',
period: '30天', period: '30天',
overdueDays: calculateOverdueDays('2025-06-25'), overdueDays: calculateOverdueDays('2023-06-25'),
hasChildren: false hasChildren: false
}, },
{ {
@ -866,8 +1092,8 @@ function handleQuery() {
/** 重置按钮操作 */ /** 重置按钮操作 */
function resetQuery() { function resetQuery() {
proxy.resetForm("queryRef") queryFormRef.value?.resetFields();
handleQuery() handleQuery();
} }
/** 新增项目 */ /** 新增项目 */
@ -897,9 +1123,27 @@ function handleUpdate(row) {
/** 查看详情 */ /** 查看详情 */
function handleDetail(row) { function handleDetail(row) {
router.push(`/receivable/form?id=${row.id}&view=1`) router.push({
path: '/fin/finAccountReceivable/add',
query: {
type: 'view',
accountReceivableId: row.accountReceivableId,
pageNum: queryParams.value.pageNum
}
});
} }
/** 删除按钮操作 */
const handleDelete = async (row?: FinAccountReceivableVO) => {
const _receivableIds = row?.accountReceivableId;
const receivableProjectCode = row?.receivableProjectCode;
await proxy?.$modal.confirm('是否确认删除项目编号为"' + receivableProjectCode + '"的数据项?').finally(() => (loading.value = false));
await delFinAccountReceivable(_receivableIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 添加节点 */ /** 添加节点 */
function handleAddNode(row) { function handleAddNode(row) {
const projectId = row.parentId const projectId = row.parentId
@ -1005,7 +1249,7 @@ onActivated(() => {
/* 操作按钮 */ /* 操作按钮 */
.action-buttons { .action-buttons {
display: flex; display: flex;
gap: 8px; gap: 1px;
justify-content: center; justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
} }

Loading…
Cancel
Save