1.1.12 添加合同回款页面

dev
yinq 2 weeks ago
parent 681b574beb
commit 0e86a7758c

@ -1,6 +1,13 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ErpProjectPlanVO, ErpProjectPlanForm, ErpProjectPlanQuery } from '@/api/oa/erp/erpProjectPlan/types';
import {
ContractCollectionPageVO,
ContractCollectionStageDetailVO,
ErpProjectPlanVO,
ErpProjectPlanForm,
ErpProjectPlanQuery
} from '@/api/oa/erp/erpProjectPlan/types';
import { ErpProjectPlanStageForm, ErpProjectPlanStageVO } from '@/api/oa/erp/erpProjectPlanStage/types';
/**
*
@ -86,3 +93,45 @@ export const projectPlanSubmitAndFlowStart = (data: ErpProjectPlanForm): AxiosPr
data: data
});
};
/**
*
*/
export const collectionStageList = (projectPlanId: string | number): AxiosPromise<ErpProjectPlanStageVO[]> => {
return request({
url: '/oa/erp/erpProjectPlan/collectionStageList/' + projectPlanId,
method: 'get'
});
};
/**
*
*/
export const confirmCollectionStage = (data: ErpProjectPlanStageForm) => {
return request({
url: '/oa/erp/erpProjectPlan/confirmCollectionStage',
method: 'post',
data
});
};
/**
*
*/
export const contractCollectionPage = (query?: ErpProjectPlanQuery): AxiosPromise<ContractCollectionPageVO[]> => {
return request({
url: '/oa/erp/erpProjectPlan/contractCollectionPage',
method: 'get',
params: query
});
};
/**
*
*/
export const contractCollectionStageDetail = (projectPlanId: string | number): AxiosPromise<ContractCollectionStageDetailVO[]> => {
return request({
url: '/oa/erp/erpProjectPlan/contractCollectionStageDetail/' + projectPlanId,
method: 'get'
});
};

@ -276,6 +276,65 @@ export interface ErpProjectPlanQuery extends PageQuery {
*/
createName?: string;
/**
*
*/
contractName?: string;
/**
*
*/
contractNo?: string;
/**
*
*/
orderNo?: string;
/**
*
*/
orderName?: string;
/**
*
*/
deptName?: string;
}
export interface ContractCollectionPageVO {
projectPlanId: string | number;
projectId: string | number;
contractId: string | number;
orderNo: string;
contractName: string;
orderName: string;
contractNo: string;
businessDirection: string;
orderType: string;
deptName: string;
amount: number;
paymentRate: number;
}
export interface ContractCollectionStageDetailVO {
paymentMethodId: string | number;
contractId: string | number;
paymentStageId: string | number;
stageName: string;
collectionStage: string;
paymentPercentage: number;
paymentAmount: number;
paymentDeadline: number;
paymentDescription: string;
planStageId: string | number;
receivableDate: string;
actualRepaymentAmount: number;
collectionConfirmUserId: string | number;
collectionConfirmTime: string;
collectionConfirmStatus: string;
collectionConfirmRemark: string;
}

@ -94,6 +94,31 @@ export interface ErpProjectPlanStageVO {
*/
activeFlag: string;
/**
*
*/
actualRepaymentAmount: number;
/**
*
*/
collectionConfirmUserId: string | number;
/**
*
*/
collectionConfirmTime: string;
/**
* 0 1 2
*/
collectionConfirmStatus: string;
/**
*
*/
collectionConfirmRemark: string;
}
export interface ErpProjectPlanStageForm extends BaseEntity {
@ -192,6 +217,31 @@ export interface ErpProjectPlanStageForm extends BaseEntity {
*/
activeFlag?: string;
/**
*
*/
actualRepaymentAmount?: number;
/**
*
*/
collectionConfirmUserId?: string | number;
/**
*
*/
collectionConfirmTime?: string;
/**
* 0 1 2
*/
collectionConfirmStatus?: string;
/**
*
*/
collectionConfirmRemark?: string;
}
export interface ErpProjectPlanStageQuery extends PageQuery {
@ -281,6 +331,31 @@ export interface ErpProjectPlanStageQuery extends PageQuery {
*/
activeFlag?: string;
/**
*
*/
actualRepaymentAmount?: number;
/**
*
*/
collectionConfirmUserId?: string | number;
/**
*
*/
collectionConfirmTime?: string;
/**
* 0 1 2
*/
collectionConfirmStatus?: string;
/**
*
*/
collectionConfirmRemark?: string;
/**
*
*/

@ -0,0 +1,247 @@
<template>
<div class="app-container">
<el-form v-show="showSearch" :model="queryParams" :inline="true" label-width="90px">
<el-form-item label="部门">
<el-input v-model="queryParams.deptName" clearable placeholder="请输入部门" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="订单编号">
<el-input v-model="queryParams.orderNo" clearable placeholder="请输入订单编号" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同编号">
<el-input v-model="queryParams.contractNo" clearable placeholder="请输入合同编号" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同名称">
<el-input v-model="queryParams.contractName" clearable placeholder="请输入合同名称" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="订单名称">
<el-input v-model="queryParams.orderName" clearable placeholder="请输入订单名称" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar v-model:showSearch="showSearch" :columns="columns" @queryTable="getList" />
</el-row>
<el-table
v-loading="loading"
:data="list"
border
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }"
>
<el-table-column v-if="columns[0].visible" label="订单编号" prop="orderNo" min-width="140" />
<el-table-column v-if="columns[1].visible" label="订单名称" prop="orderName" min-width="180" show-overflow-tooltip />
<el-table-column v-if="columns[2].visible" label="合同编号" prop="contractNo" min-width="140" />
<el-table-column v-if="columns[3].visible" label="合同名称" prop="contractName" min-width="180" show-overflow-tooltip />
<el-table-column v-if="columns[4].visible" label="业务方向" min-width="100">
<template #default="scope">
<dict-tag :options="business_direction" :value="scope.row.businessDirection" />
</template>
</el-table-column>
<el-table-column v-if="columns[5].visible" label="部门" prop="deptName" min-width="140" show-overflow-tooltip />
<el-table-column v-if="columns[6].visible" label="合同金额" prop="amount" min-width="120" />
<el-table-column v-if="columns[7].visible" label="回款比例(%)" prop="paymentRate" min-width="100">
<template #default="scope">
{{ scope.row.paymentRate ?? 0 }}
</template>
</el-table-column>
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openStageDialog(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<el-dialog v-model="stageDialogVisible" title="合同回款阶段确认" width="1200px">
<el-table v-loading="stageLoading" :data="stageList" border>
<el-table-column label="合同订单阶段" prop="stageName" min-width="130" />
<el-table-column label="回款阶段标识" prop="collectionStage" min-width="120" />
<el-table-column label="预计回款比例(%)" prop="repaymentRate" width="130" />
<el-table-column label="合同阶段比例(%)" prop="paymentPercentage" width="130" />
<el-table-column label="合同阶段金额" prop="paymentAmount" width="130" />
<el-table-column label="实际回款金额" prop="actualRepaymentAmount" width="130" />
<el-table-column label="确认状态" width="110">
<template #default="scope">
<dict-tag :options="collection_confirm_status" :value="scope.row.collectionConfirmStatus || '0'" />
</template>
</el-table-column>
<el-table-column label="确认人" prop="collectionConfirmUserId" width="100" />
<el-table-column label="确认时间" width="160">
<template #default="scope">
{{ formatDate(scope.row.collectionConfirmTime) }}
</template>
</el-table-column>
<el-table-column label="确认备注" prop="collectionConfirmRemark" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" width="100" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openConfirmDialog(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-dialog v-model="confirmDialogVisible" title="阶段回款确认" width="500px">
<el-form :model="confirmForm" label-width="120px">
<el-form-item label="实际回款日期" required>
<el-date-picker v-model="confirmForm.receivableDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
</el-form-item>
<el-form-item label="实际回款金额" required>
<el-input-number v-model="confirmForm.actualRepaymentAmount" :precision="2" :min="0" style="width: 100%" />
</el-form-item>
<el-form-item label="确认状态">
<el-select v-model="confirmForm.collectionConfirmStatus" clearable style="width: 100%">
<el-option v-for="item in collection_confirm_status" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="确认备注">
<el-input v-model="confirmForm.collectionConfirmRemark" type="textarea" :rows="3" maxlength="500" show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="confirmDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="confirmLoading" @click="submitConfirm"></el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="ContractCollectionPage">
import { getCurrentInstance, reactive, ref, toRefs } from 'vue';
import { ElMessage } from 'element-plus';
import {
confirmCollectionStage,
contractCollectionPage,
contractCollectionStageDetail
} from '@/api/oa/erp/erpProjectPlan';
import { ContractCollectionPageVO, ContractCollectionStageDetailVO } from '@/api/oa/erp/erpProjectPlan/types';
import { ErpProjectPlanStageForm } from '@/api/oa/erp/erpProjectPlanStage/types';
const { proxy } = getCurrentInstance() as any;
const { collection_confirm_status, business_direction } = toRefs(
proxy?.useDict('collection_confirm_status', 'business_direction')
);
const loading = ref(false);
const showSearch = ref(true);
const total = ref(0);
const list = ref<ContractCollectionPageVO[]>([]);
const columns = ref([
{ key: 0, label: '订单编号', visible: true },
{ key: 1, label: '订单名称', visible: true },
{ key: 2, label: '合同编号', visible: true },
{ key: 3, label: '合同名称', visible: true },
{ key: 4, label: '业务方向', visible: true },
{ key: 5, label: '部门', visible: true },
{ key: 6, label: '金额', visible: true },
{ key: 7, label: '回款比例(%)', visible: true }
]);
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
deptName: '',
orderNo: '',
contractNo: '',
contractName: '',
orderName: ''
});
const stageDialogVisible = ref(false);
const stageLoading = ref(false);
const stageList = ref<ContractCollectionStageDetailVO[]>([]);
const confirmDialogVisible = ref(false);
const confirmLoading = ref(false);
const confirmForm = reactive<ErpProjectPlanStageForm>({
planStageId: undefined,
receivableDate: '',
actualRepaymentAmount: 0,
collectionConfirmStatus: '',
collectionConfirmRemark: ''
});
const currentPlanId = ref<string | number>();
const getList = async () => {
loading.value = true;
const res = await contractCollectionPage(queryParams);
list.value = res.rows || [];
total.value = res.total || 0;
loading.value = false;
};
const handleQuery = () => {
queryParams.pageNum = 1;
getList();
};
const resetQuery = () => {
queryParams.deptName = '';
queryParams.orderNo = '';
queryParams.contractNo = '';
queryParams.contractName = '';
queryParams.orderName = '';
handleQuery();
};
const openStageDialog = async (row: ContractCollectionPageVO) => {
if (!row.projectPlanId) {
ElMessage.warning('该记录未关联项目计划,无法进行阶段回款确认');
return;
}
currentPlanId.value = row.projectPlanId;
stageDialogVisible.value = true;
stageLoading.value = true;
const res = await contractCollectionStageDetail(row.projectPlanId);
stageList.value = res.data || [];
stageLoading.value = false;
};
const openConfirmDialog = (row: ContractCollectionStageDetailVO) => {
confirmForm.planStageId = row.planStageId;
confirmForm.receivableDate = '';
confirmForm.actualRepaymentAmount = row.actualRepaymentAmount || 0;
confirmForm.collectionConfirmStatus = row.collectionConfirmStatus || '';
confirmForm.collectionConfirmRemark = row.collectionConfirmRemark || '';
confirmDialogVisible.value = true;
};
const submitConfirm = async () => {
if (!confirmForm.planStageId) {
ElMessage.warning('缺少阶段ID');
return;
}
if (!confirmForm.receivableDate) {
ElMessage.warning('请选择实际回款日期');
return;
}
confirmLoading.value = true;
await confirmCollectionStage(confirmForm);
confirmLoading.value = false;
confirmDialogVisible.value = false;
ElMessage.success('确认成功');
if (currentPlanId.value) {
const res = await contractCollectionStageDetail(currentPlanId.value);
stageList.value = res.data || [];
}
};
const formatDate = (val?: string) => {
if (!val) return '';
return String(val).replace('T', ' ').slice(0, 19);
};
getList();
</script>
Loading…
Cancel
Save