feat: add contract settlement pages

This commit is contained in:
caoqianming 2026-04-20 16:56:44 +08:00
parent 80c20c222b
commit 4b3217e208
14 changed files with 1858 additions and 13 deletions

View File

@ -1,6 +1,108 @@
import config from "@/config" import config from "@/config"
import http from "@/utils/request" import http from "@/utils/request"
export default { export default {
// 采购合同
contract: {
list: {
name: "采购合同列表",
req: async function(data){
return await http.get(
`${config.API_URL}/pum/pu_contract/`,
data
);
}
},
create: {
name: "创建采购合同",
req: async function(data){
return await http.post(
`${config.API_URL}/pum/pu_contract/`,
data);
}
},
cquery: {
name: "复杂查询",
req: async function(data){
return await http.post(
`${config.API_URL}/pum/pu_contract/cquery/`,
data);
}
},
item: {
name: "获取采购合同详情",
req: async function(id){
return await http.get(
`${config.API_URL}/pum/pu_contract/${id}/`
);
}
},
update: {
name: "更新采购合同",
req: async function(id, data){
return await http.put(
`${config.API_URL}/pum/pu_contract/${id}/`,
data);
}
},
delete: {
name: "删除采购合同",
req: async function(id){
return await http.delete(
`${config.API_URL}/pum/pu_contract/${id}/`);
}
}
},
// 采购合同付款流水
contractRecord: {
list: {
name: "采购合同付款流水列表",
req: async function(data){
return await http.get(
`${config.API_URL}/pum/pu_contract_record/`,
data
);
}
},
create: {
name: "创建采购合同付款流水",
req: async function(data){
return await http.post(
`${config.API_URL}/pum/pu_contract_record/`,
data);
}
},
cquery: {
name: "复杂查询",
req: async function(data){
return await http.post(
`${config.API_URL}/pum/pu_contract_record/cquery/`,
data);
}
},
item: {
name: "获取采购合同付款流水详情",
req: async function(id){
return await http.get(
`${config.API_URL}/pum/pu_contract_record/${id}/`
);
}
},
update: {
name: "更新采购合同付款流水",
req: async function(id, data){
return await http.put(
`${config.API_URL}/pum/pu_contract_record/${id}/`,
data);
}
},
delete: {
name: "删除采购合同付款流水",
req: async function(id){
return await http.delete(
`${config.API_URL}/pum/pu_contract_record/${id}/`);
}
}
},
// 采购订单 // 采购订单
order: { order: {
list: { list: {
@ -348,4 +450,4 @@ export default {
} }
}, },
} }
} }

View File

@ -52,6 +52,56 @@ export default {
} }
} }
}, },
contractRecord: {
list: {
name: "合同流水列表",
req: async function(data){
return await http.get(
`${config.API_URL}/sam/contract_record/`,
data
);
}
},
create: {
name: "创建合同流水",
req: async function(data){
return await http.post(
`${config.API_URL}/sam/contract_record/`,
data);
}
},
cquery: {
name: "复杂查询",
req: async function(data){
return await http.post(
`${config.API_URL}/sam/contract_record/cquery/`,
data);
}
},
item: {
name: "获取合同流水详情",
req: async function(id){
return await http.get(
`${config.API_URL}/sam/contract_record/${id}/`
);
}
},
update: {
name: "更新合同流水",
req: async function(id, data){
return await http.put(
`${config.API_URL}/sam/contract_record/${id}/`,
data);
}
},
delete: {
name: "删除合同流水",
req: async function(id){
return await http.delete(
`${config.API_URL}/sam/contract_record/${id}/`);
}
}
},
// 客户信息 // 客户信息
customer: { customer: {
list: { list: {
@ -187,4 +237,4 @@ export default {
} }
}, },
} }
} }

View File

@ -2182,6 +2182,24 @@ const routes = [
}, },
component: "pum/planitem", component: "pum/planitem",
}, },
{
name: "puContract",
path: "/pum/contract",
meta: {
title: "采购合同",
perms: ["pu_contract"],
},
component: "pum/contract",
},
{
name: "puContractRecord",
path: "/pum/contract_record",
meta: {
title: "付款流水查询",
perms: ["pu_contract"],
},
component: "pum/contract_record",
},
{ {
name: "order", name: "order",
path: "/pum/order", path: "/pum/order",
@ -2236,6 +2254,15 @@ const routes = [
}, },
component: "sam/contract", component: "sam/contract",
}, },
{
name: "contractRecord",
path: "/sam/contract_record",
meta: {
title: "到款流水查询",
perms: ["contract"],
},
component: "sam/contract_record",
},
{ {
name: "samOrder", name: "samOrder",
path: "/sam/samOrder", path: "/sam/samOrder",

View File

@ -0,0 +1,275 @@
<template>
<el-drawer
v-model="visible"
title="采购合同详情 / 付款流水"
size="70%"
destroy-on-close
@closed="$emit('closed')"
>
<div v-loading="loading" class="drawer-wrap">
<el-card shadow="hover" header="合同信息">
<div class="contract-head">
<el-tag :type="statusTagType(contract.status)" effect="dark">
{{ statusMap[contract.status] || "-" }}
</el-tag>
<div class="contract-progress">
<el-progress
:percentage="progressNumber(contract.pay_progress)"
:stroke-width="16"
:color="progressColor(contract.status, contract.pay_progress)"
/>
</div>
</div>
<el-descriptions :column="3" border>
<el-descriptions-item label="合同编号">{{ contract.number }}</el-descriptions-item>
<el-descriptions-item label="合同名称">{{ contract.name }}</el-descriptions-item>
<el-descriptions-item label="供应商">{{ contract.supplier_name }}</el-descriptions-item>
<el-descriptions-item label="签订日期">{{ contract.sign_date }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ statusMap[contract.status] || "-" }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ contract.description || "-" }}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-alert
v-if="isTerminated"
title="当前合同已终止,流水已锁定,不可新增、编辑或删除。"
type="error"
show-icon
:closable="false"
class="contract-alert"
/>
<el-row :gutter="12" class="summary-row">
<el-col v-for="item in summaryCards" :key="item.label" :span="8">
<el-card shadow="never" class="summary-card">
<div class="summary-label">{{ item.label }}</div>
<div class="summary-value">{{ item.value }}</div>
</el-card>
</el-col>
</el-row>
<el-card shadow="hover">
<template #header>
<div class="card-header">
<span>付款流水</span>
<el-button type="primary" @click="handleAdd" :disabled="isTerminated" v-auth="'pu_contract.update'">新增流水</el-button>
</div>
</template>
<scTable
ref="table"
:data="records"
row-key="id"
stripe
hidePagination
hideDo
hideRefresh
>
<el-table-column type="index" width="50" />
<el-table-column label="付款日期" prop="record_date" />
<el-table-column label="付款金额" prop="amount" />
<el-table-column label="阶段类型">
<template #default="scope">
<el-tag size="small" effect="plain">{{ stageMap[scope.row.stage_type] || "-" }}</el-tag>
</template>
</el-table-column>
<el-table-column label="付款方式">
<template #default="scope">
<el-tag size="small" type="info" effect="plain">{{ payMethodMap[scope.row.pay_method] || "-" }}</el-tag>
</template>
</el-table-column>
<el-table-column label="凭证号" prop="voucher_no" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
<el-table-column label="创建人" prop="create_by_name" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" :disabled="isTerminated" @click="handleEdit(scope.row)" v-auth="'pu_contract.update'">编辑</el-button>
<el-button link type="danger" :disabled="isTerminated" @click="handleDelete(scope.row)" v-auth="'pu_contract.update'">删除</el-button>
</template>
</el-table-column>
</scTable>
</el-card>
</div>
</el-drawer>
<record-form
v-if="dialog.form"
ref="recordForm"
@success="handleFormSuccess"
@closed="dialog.form = false"
/>
</template>
<script>
import recordForm from "./PuContractRecordForm.vue";
export default {
components: {
recordForm,
},
emits: ["refresh", "closed"],
data() {
return {
visible: false,
loading: false,
contractId: "",
contract: {},
records: [],
dialog: {
form: false,
},
statusMap: {
10: "草稿",
20: "执行中",
30: "已完成",
40: "已终止",
},
stageMap: {
10: "首款",
20: "中间款",
30: "尾款",
40: "其他",
},
payMethodMap: {
10: "银行转账",
20: "现金",
30: "承兑",
40: "微信",
50: "支付宝",
60: "其他",
},
};
},
computed: {
isTerminated() {
return this.contract.status === 40;
},
summaryCards() {
return [
{ label: "合同金额", value: this.contract.contract_amount || 0 },
{ label: "已付款", value: this.contract.paid_amount || 0 },
{ label: "未付款", value: this.contract.unpaid_amount || 0 },
{ label: "付款进度", value: `${this.contract.pay_progress || 0}%` },
{ label: "首款合计", value: this.sumByStage(10) },
{ label: "中间款合计", value: this.sumByStage(20) },
{ label: "尾款合计", value: this.sumByStage(30) },
];
},
},
methods: {
progressNumber(value) {
return Number(value || 0);
},
progressColor(status, progress) {
if (status === 40) {
return "#f56c6c";
}
if (Number(progress || 0) >= 100) {
return "#67c23a";
}
return "#409eff";
},
statusTagType(status) {
return {
10: "info",
20: "primary",
30: "success",
40: "danger",
}[status] || "info";
},
open(contractId) {
this.contractId = contractId;
this.visible = true;
this.loadData();
return this;
},
async loadData() {
this.loading = true;
try {
const [contract, records] = await Promise.all([
this.$API.pum.contract.item.req(this.contractId),
this.$API.pum.contractRecord.list.req({ page: 0, contract: this.contractId }),
]);
this.contract = contract;
this.records = Array.isArray(records) ? records : records?.data || [];
} finally {
this.loading = false;
}
},
sumByStage(stageType) {
return this.records
.filter((item) => item.stage_type === stageType)
.reduce((total, item) => total + Number(item.amount || 0), 0)
.toFixed(2);
},
handleAdd() {
if (this.isTerminated) {
return;
}
this.dialog.form = true;
this.$nextTick(() => {
this.$refs.recordForm.open("add", this.contractId);
});
},
handleEdit(row) {
if (this.isTerminated) {
return;
}
this.dialog.form = true;
this.$nextTick(() => {
this.$refs.recordForm.open("edit", this.contractId).setData(row, this.contractId);
});
},
handleDelete(row) {
if (this.isTerminated) {
return;
}
this.$confirm("确定删除这条流水吗?", "提示", {
type: "warning",
}).then(async () => {
await this.$API.pum.contractRecord.delete.req(row.id);
this.$message.success("删除成功");
this.handleFormSuccess();
}).catch(() => {});
},
async handleFormSuccess() {
this.dialog.form = false;
await this.loadData();
this.$emit("refresh");
},
},
};
</script>
<style scoped>
.drawer-wrap {
padding: 8px;
}
.summary-row {
margin: 12px 0;
}
.contract-head {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 16px;
}
.contract-progress {
flex: 1;
}
.contract-alert {
margin-top: 12px;
}
.summary-card {
margin-bottom: 12px;
}
.summary-label {
font-size: 13px;
color: #909399;
}
.summary-value {
margin-top: 8px;
font-size: 20px;
font-weight: 600;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>

View File

@ -0,0 +1,191 @@
<template>
<el-dialog
:title="titleMap[mode]"
v-model="visible"
width="640px"
destroy-on-close
@closed="$emit('closed')"
>
<el-form
ref="dialogForm"
:model="form"
:rules="rules"
label-width="120px"
>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="付款日期" prop="record_date">
<el-date-picker
v-model="form.record_date"
type="date"
value-format="YYYY-MM-DD"
placeholder="付款日期"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="付款金额" prop="amount">
<el-input-number
v-model="form.amount"
:min="0"
:precision="2"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="阶段类型" prop="stage_type">
<el-select
v-model="form.stage_type"
placeholder="阶段类型"
style="width: 100%"
>
<el-option
v-for="item in stageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="付款方式" prop="pay_method">
<el-select
v-model="form.pay_method"
placeholder="付款方式"
style="width: 100%"
>
<el-option
v-for="item in payMethodOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="凭证号">
<el-input v-model="form.voucher_no" placeholder="凭证号" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
:rows="3"
placeholder="备注"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :loading="isSaving" @click="submit">
保存
</el-button>
</template>
</el-dialog>
</template>
<script>
export default {
emits: ["success", "closed"],
data() {
return {
visible: false,
mode: "add",
isSaving: false,
titleMap: {
add: "新增付款流水",
edit: "编辑付款流水",
},
form: {
contract: "",
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
},
stageOptions: [
{ value: 10, label: "首款" },
{ value: 20, label: "中间款" },
{ value: 30, label: "尾款" },
{ value: 40, label: "其他" },
],
payMethodOptions: [
{ value: 10, label: "银行转账" },
{ value: 20, label: "现金" },
{ value: 30, label: "承兑" },
{ value: 40, label: "微信" },
{ value: 50, label: "支付宝" },
{ value: 60, label: "其他" },
],
rules: {
record_date: [{ required: true, message: "请选择付款日期", trigger: "change" }],
amount: [{ required: true, message: "请输入付款金额", trigger: "blur" }],
stage_type: [{ required: true, message: "请选择阶段类型", trigger: "change" }],
pay_method: [{ required: true, message: "请选择付款方式", trigger: "change" }],
},
};
},
methods: {
open(mode = "add", contractId = "") {
this.mode = mode;
this.visible = true;
this.form = {
contract: contractId,
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
};
return this;
},
setData(data, contractId = "") {
this.form = Object.assign(
{
contract: contractId || data.contract,
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
},
data
);
return this;
},
submit() {
this.$refs.dialogForm.validate(async (valid) => {
if (!valid) {
return;
}
this.isSaving = true;
try {
if (this.mode === "add") {
await this.$API.pum.contractRecord.create.req(this.form);
} else {
await this.$API.pum.contractRecord.update.req(this.form.id, this.form);
}
this.$message.success("操作成功");
this.$emit("success");
this.visible = false;
} finally {
this.isSaving = false;
}
});
},
},
};
</script>

170
src/views/pum/contract.vue Normal file
View File

@ -0,0 +1,170 @@
<template>
<el-container>
<el-header>
<div class="left-panel">
<el-button type="primary" icon="el-icon-plus" @click="add" v-auth="'pu_contract.create'">新增</el-button>
</div>
<div class="right-panel">
<el-input v-model="query.search" placeholder="合同编号/合同名称/供应商" clearable style="margin-right: 5px;" />
<el-button type="primary" icon="el-icon-search" @click="handleQuery"></el-button>
</div>
</el-header>
<el-main class="nopadding">
<scTable ref="table" :apiObj="apiObj" row-key="id" stripe :params="query">
<el-table-column type="index" width="50" />
<el-table-column label="合同编号" prop="number" />
<el-table-column label="合同名称" prop="name" />
<el-table-column label="供应商" prop="supplier_name" />
<el-table-column label="合同金额" prop="contract_amount">
<template #default="scope">
<span class="amount-strong">{{ formatMoney(scope.row.contract_amount) }}</span>
</template>
</el-table-column>
<el-table-column label="已付款" prop="paid_amount">
<template #default="scope">
<span class="amount-success">{{ formatMoney(scope.row.paid_amount) }}</span>
</template>
</el-table-column>
<el-table-column label="未付款" prop="unpaid_amount">
<template #default="scope">
<span class="amount-warning">{{ formatMoney(scope.row.unpaid_amount) }}</span>
</template>
</el-table-column>
<el-table-column label="付款进度" min-width="180">
<template #default="scope">
<div class="progress-cell">
<el-progress
:percentage="progressNumber(scope.row.pay_progress)"
:stroke-width="14"
:color="progressColor(scope.row.status, scope.row.pay_progress)"
/>
</div>
</template>
</el-table-column>
<el-table-column label="签订日期" prop="sign_date" />
<el-table-column label="合同状态">
<template #default="scope">
<el-tag :type="statusTagType(scope.row.status)" effect="dark">
{{ statusMap[scope.row.status] || "-" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="table_detail(scope.row)">流水详情</el-button>
<el-button link type="primary" @click="table_edit(scope.row)" v-auth="'pu_contract.update'">编辑</el-button>
<el-button link type="danger" @click="table_del(scope.row)" v-auth="'pu_contract.delete'">删除</el-button>
</template>
</el-table-column>
</scTable>
</el-main>
</el-container>
<save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSaveSuccess" @closed="dialog.save = false"></save-dialog>
<detail-drawer v-if="dialog.detail" ref="detailDrawer" @refresh="handleSaveSuccess" @closed="dialog.detail = false"></detail-drawer>
</template>
<script>
import saveDialog from "./contract_form.vue";
import detailDrawer from "./components/PuContractRecordDrawer.vue";
export default {
components: {
saveDialog,
detailDrawer,
},
data() {
return {
dialog: {
save: false,
detail: false,
},
apiObj: this.$API.pum.contract.list,
query: {
page: 1,
page_size: 20,
},
statusMap: {
10: "草稿",
20: "执行中",
30: "已完成",
40: "已终止",
},
};
},
methods: {
formatMoney(value) {
return Number(value || 0).toFixed(2);
},
progressNumber(value) {
return Number(value || 0);
},
progressColor(status, progress) {
if (status === 40) {
return "#f56c6c";
}
if (Number(progress || 0) >= 100) {
return "#67c23a";
}
return "#409eff";
},
statusTagType(status) {
return {
10: "info",
20: "primary",
30: "success",
40: "danger",
}[status] || "info";
},
add() {
this.dialog.save = true;
this.$nextTick(() => {
this.$refs.saveDialog.open("add");
});
},
table_edit(row) {
this.dialog.save = true;
this.$nextTick(() => {
this.$refs.saveDialog.open("edit").setData(row);
});
},
table_detail(row) {
this.dialog.detail = true;
this.$nextTick(() => {
this.$refs.detailDrawer.open(row.id);
});
},
table_del(row) {
this.$confirm("确定删除吗?", "提示", {
type: "warning",
}).then(async () => {
await this.$API.pum.contract.delete.req(row.id);
this.$message.success("删除成功");
this.$refs.table.refresh();
}).catch(() => {});
},
handleSaveSuccess() {
this.$refs.table.refresh();
},
handleQuery() {
this.$refs.table.queryData(this.query);
},
},
};
</script>
<style scoped>
.amount-strong {
font-weight: 600;
color: #303133;
}
.amount-success {
font-weight: 600;
color: #67c23a;
}
.amount-warning {
font-weight: 600;
color: #e6a23c;
}
.progress-cell {
padding-right: 8px;
}
</style>

View File

@ -0,0 +1,179 @@
<template>
<el-dialog
:title="titleMap[mode]"
v-model="visible"
:size="1000"
destroy-on-close
@closed="$emit('closed')"
>
<el-container v-loading="loading">
<el-main style="padding: 0 20px 20px 20px">
<el-form ref="dialogForm" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :md="12" :sm="24">
<el-form-item label="合同名称" prop="name">
<el-input v-model="form.name" placeholder="合同名称" />
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="合同编号" prop="number">
<el-input v-model="form.number" placeholder="合同编号" />
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="合同金额" prop="contract_amount">
<el-input-number
v-model="form.contract_amount"
:precision="2"
:min="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="签订日期" prop="sign_date">
<el-date-picker
v-model="form.sign_date"
type="date"
placeholder="签订日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="生效日期">
<el-date-picker
v-model="form.effective_date"
type="date"
placeholder="生效日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="截止日期">
<el-date-picker
v-model="form.end_date"
type="date"
placeholder="截止日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="供应商" prop="supplier">
<el-select v-model="form.supplier" placeholder="供应商" clearable style="width: 100%">
<el-option
v-for="item in supplierOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="合同状态" prop="status">
<el-select v-model="form.status" placeholder="合同状态" clearable style="width: 100%">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :md="24" :sm="24">
<el-form-item label="描述">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="描述" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-main>
<el-footer>
<el-button type="primary" :loading="isSaving" @click="submit">保存</el-button>
<el-button @click="visible = false">取消</el-button>
</el-footer>
</el-container>
</el-dialog>
</template>
<script>
export default {
emits: ["success", "closed"],
data() {
return {
loading: false,
mode: "add",
visible: false,
isSaving: false,
form: {
status: 10,
},
titleMap: {
add: "新增采购合同",
edit: "编辑采购合同",
show: "查看采购合同",
},
supplierOptions: [],
statusOptions: [
{ value: 10, label: "草稿" },
{ value: 20, label: "执行中" },
{ value: 30, label: "已完成" },
{ value: 40, label: "已终止" },
],
rules: {
name: [{ required: true, message: "请输入合同名称", trigger: "blur" }],
number: [{ required: true, message: "请输入合同编号", trigger: "blur" }],
supplier: [{ required: true, message: "请选择供应商", trigger: "change" }],
sign_date: [{ required: true, message: "请选择签订日期", trigger: "change" }],
},
};
},
mounted() {
this.getSuppliers();
},
methods: {
getSuppliers() {
this.$API.pum.supplier.list.req({ page: 0 }).then((res) => {
this.supplierOptions = res;
});
},
open(mode = "add") {
this.mode = mode;
this.visible = true;
if (mode === "add") {
this.form = {
status: 10,
};
}
return this;
},
setData(data) {
this.form = Object.assign({}, data);
return this;
},
submit() {
this.$refs.dialogForm.validate(async (valid) => {
if (!valid) {
return;
}
this.isSaving = true;
try {
if (this.mode === "add") {
await this.$API.pum.contract.create.req(this.form);
} else {
await this.$API.pum.contract.update.req(this.form.id, this.form);
}
this.$message.success("操作成功");
this.$emit("success", this.form, this.mode);
this.visible = false;
} finally {
this.isSaving = false;
}
});
},
},
};
</script>

View File

@ -0,0 +1,110 @@
<template>
<el-container>
<el-header>
<div class="left-panel"></div>
<div class="right-panel">
<el-input
v-model="query.search"
placeholder="合同编号/合同名称/供应商"
clearable
style="margin-right: 5px"
/>
<el-select
v-model="query.stage_type"
clearable
placeholder="阶段类型"
style="width: 140px; margin-right: 5px"
>
<el-option v-for="item in stageOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button type="primary" icon="el-icon-search" @click="handleQuery"></el-button>
</div>
</el-header>
<el-main class="nopadding">
<scTable ref="table" :apiObj="apiObj" row-key="id" stripe :params="query">
<el-table-column type="index" width="50" />
<el-table-column label="付款日期" prop="record_date" />
<el-table-column label="付款金额" prop="amount" />
<el-table-column label="阶段类型">
<template #default="scope">{{ stageMap[scope.row.stage_type] || "-" }}</template>
</el-table-column>
<el-table-column label="付款方式">
<template #default="scope">{{ payMethodMap[scope.row.pay_method] || "-" }}</template>
</el-table-column>
<el-table-column label="合同编号" prop="contract_number" />
<el-table-column label="供应商" prop="supplier_name" />
<el-table-column label="凭证号" prop="voucher_no" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
<el-table-column label="操作" width="100" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openContract(scope.row.contract)">查看合同</el-button>
</template>
</el-table-column>
</scTable>
</el-main>
</el-container>
<detail-drawer
v-if="dialog.detail"
ref="detailDrawer"
@refresh="refreshTable"
@closed="dialog.detail = false"
/>
</template>
<script>
import detailDrawer from "./components/PuContractRecordDrawer.vue";
export default {
components: {
detailDrawer,
},
data() {
return {
apiObj: this.$API.pum.contractRecord.list,
query: {
page: 1,
page_size: 20,
search: "",
stage_type: "",
},
dialog: {
detail: false,
},
stageOptions: [
{ value: 10, label: "首款" },
{ value: 20, label: "中间款" },
{ value: 30, label: "尾款" },
{ value: 40, label: "其他" },
],
stageMap: {
10: "首款",
20: "中间款",
30: "尾款",
40: "其他",
},
payMethodMap: {
10: "银行转账",
20: "现金",
30: "承兑",
40: "微信",
50: "支付宝",
60: "其他",
},
};
},
methods: {
handleQuery() {
this.$refs.table.queryData(this.query);
},
openContract(contractId) {
this.dialog.detail = true;
this.$nextTick(() => {
this.$refs.detailDrawer.open(contractId);
});
},
refreshTable() {
this.$refs.table.refresh();
},
},
};
</script>

View File

@ -40,6 +40,25 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :md="12" :sm="24">
<el-form-item label="采购合同">
<el-select
v-model="form.contract"
placeholder="采购合同"
clearable
filterable
style="width: 100%"
@change="handleContractChange"
>
<el-option
v-for="item in contractOptions"
:key="item.id"
:label="`${item.number} - ${item.name}`"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24"> <el-col :md="12" :sm="24">
<el-form-item label="截止到货日期"> <el-form-item label="截止到货日期">
<el-date-picker <el-date-picker
@ -96,11 +115,13 @@ export default {
visible: false, visible: false,
isSaveing: false, isSaveing: false,
options: [], options: [],
contractOptions: [],
setFiltersVisible: false, setFiltersVisible: false,
}; };
}, },
mounted() { mounted() {
this.getList(); this.getList();
this.getContracts();
}, },
methods: { methods: {
// //
@ -114,6 +135,17 @@ export default {
this.options = res; this.options = res;
}); });
}, },
getContracts() {
this.$API.pum.contract.list.req({ page: 0 }).then((res) => {
this.contractOptions = res;
});
},
handleContractChange(value) {
const contract = this.contractOptions.find((item) => item.id === value);
if (contract) {
this.form.supplier = contract.supplier;
}
},
// //
submit() { submit() {
this.$refs.dialogForm.validate(async (valid) => { this.$refs.dialogForm.validate(async (valid) => {

View File

@ -0,0 +1,275 @@
<template>
<el-drawer
v-model="visible"
title="销售合同详情 / 到款流水"
size="70%"
destroy-on-close
@closed="$emit('closed')"
>
<div v-loading="loading" class="drawer-wrap">
<el-card shadow="hover" header="合同信息">
<div class="contract-head">
<el-tag :type="statusTagType(contract.status)" effect="dark">
{{ statusMap[contract.status] || "-" }}
</el-tag>
<div class="contract-progress">
<el-progress
:percentage="progressNumber(contract.receive_progress)"
:stroke-width="16"
:color="progressColor(contract.status, contract.receive_progress)"
/>
</div>
</div>
<el-descriptions :column="3" border>
<el-descriptions-item label="合同编号">{{ contract.number }}</el-descriptions-item>
<el-descriptions-item label="合同名称">{{ contract.name }}</el-descriptions-item>
<el-descriptions-item label="客户">{{ contract.customer_name }}</el-descriptions-item>
<el-descriptions-item label="签订日期">{{ contract.sign_date }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ statusMap[contract.status] || "-" }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ contract.description || "-" }}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-alert
v-if="isTerminated"
title="当前合同已终止,流水已锁定,不可新增、编辑或删除。"
type="error"
show-icon
:closable="false"
class="contract-alert"
/>
<el-row :gutter="12" class="summary-row">
<el-col v-for="item in summaryCards" :key="item.label" :span="8">
<el-card shadow="never" class="summary-card">
<div class="summary-label">{{ item.label }}</div>
<div class="summary-value">{{ item.value }}</div>
</el-card>
</el-col>
</el-row>
<el-card shadow="hover">
<template #header>
<div class="card-header">
<span>到款流水</span>
<el-button type="primary" @click="handleAdd" :disabled="isTerminated" v-auth="'contract.update'">新增流水</el-button>
</div>
</template>
<scTable
ref="table"
:data="records"
row-key="id"
stripe
hidePagination
hideDo
hideRefresh
>
<el-table-column type="index" width="50" />
<el-table-column label="到款日期" prop="record_date" />
<el-table-column label="到款金额" prop="amount" />
<el-table-column label="阶段类型">
<template #default="scope">
<el-tag size="small" effect="plain">{{ stageMap[scope.row.stage_type] || "-" }}</el-tag>
</template>
</el-table-column>
<el-table-column label="收款方式">
<template #default="scope">
<el-tag size="small" type="info" effect="plain">{{ payMethodMap[scope.row.pay_method] || "-" }}</el-tag>
</template>
</el-table-column>
<el-table-column label="凭证号" prop="voucher_no" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
<el-table-column label="创建人" prop="create_by_name" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<el-button link type="primary" :disabled="isTerminated" @click="handleEdit(scope.row)" v-auth="'contract.update'">编辑</el-button>
<el-button link type="danger" :disabled="isTerminated" @click="handleDelete(scope.row)" v-auth="'contract.update'">删除</el-button>
</template>
</el-table-column>
</scTable>
</el-card>
</div>
</el-drawer>
<record-form
v-if="dialog.form"
ref="recordForm"
@success="handleFormSuccess"
@closed="dialog.form = false"
/>
</template>
<script>
import recordForm from "./ContractRecordForm.vue";
export default {
components: {
recordForm,
},
emits: ["refresh", "closed"],
data() {
return {
visible: false,
loading: false,
contractId: "",
contract: {},
records: [],
dialog: {
form: false,
},
statusMap: {
10: "草稿",
20: "执行中",
30: "已完成",
40: "已终止",
},
stageMap: {
10: "首款",
20: "中间款",
30: "尾款",
40: "其他",
},
payMethodMap: {
10: "银行转账",
20: "现金",
30: "承兑",
40: "微信",
50: "支付宝",
60: "其他",
},
};
},
computed: {
isTerminated() {
return this.contract.status === 40;
},
summaryCards() {
return [
{ label: "合同金额", value: this.contract.amount || 0 },
{ label: "已到款", value: this.contract.received_amount || 0 },
{ label: "未到款", value: this.contract.unreceived_amount || 0 },
{ label: "到款进度", value: `${this.contract.receive_progress || 0}%` },
{ label: "首款合计", value: this.sumByStage(10) },
{ label: "中间款合计", value: this.sumByStage(20) },
{ label: "尾款合计", value: this.sumByStage(30) },
];
},
},
methods: {
progressNumber(value) {
return Number(value || 0);
},
progressColor(status, progress) {
if (status === 40) {
return "#f56c6c";
}
if (Number(progress || 0) >= 100) {
return "#67c23a";
}
return "#409eff";
},
statusTagType(status) {
return {
10: "info",
20: "primary",
30: "success",
40: "danger",
}[status] || "info";
},
open(contractId) {
this.contractId = contractId;
this.visible = true;
this.loadData();
return this;
},
async loadData() {
this.loading = true;
try {
const [contract, records] = await Promise.all([
this.$API.sam.contract.item.req(this.contractId),
this.$API.sam.contractRecord.list.req({ page: 0, contract: this.contractId }),
]);
this.contract = contract;
this.records = Array.isArray(records) ? records : records?.data || [];
} finally {
this.loading = false;
}
},
sumByStage(stageType) {
return this.records
.filter((item) => item.stage_type === stageType)
.reduce((total, item) => total + Number(item.amount || 0), 0)
.toFixed(2);
},
handleAdd() {
if (this.isTerminated) {
return;
}
this.dialog.form = true;
this.$nextTick(() => {
this.$refs.recordForm.open("add", this.contractId);
});
},
handleEdit(row) {
if (this.isTerminated) {
return;
}
this.dialog.form = true;
this.$nextTick(() => {
this.$refs.recordForm.open("edit", this.contractId).setData(row, this.contractId);
});
},
handleDelete(row) {
if (this.isTerminated) {
return;
}
this.$confirm("确定删除这条流水吗?", "提示", {
type: "warning",
}).then(async () => {
await this.$API.sam.contractRecord.delete.req(row.id);
this.$message.success("删除成功");
this.handleFormSuccess();
}).catch(() => {});
},
async handleFormSuccess() {
this.dialog.form = false;
await this.loadData();
this.$emit("refresh");
},
},
};
</script>
<style scoped>
.drawer-wrap {
padding: 8px;
}
.summary-row {
margin: 12px 0;
}
.contract-head {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 16px;
}
.contract-progress {
flex: 1;
}
.contract-alert {
margin-top: 12px;
}
.summary-card {
margin-bottom: 12px;
}
.summary-label {
font-size: 13px;
color: #909399;
}
.summary-value {
margin-top: 8px;
font-size: 20px;
font-weight: 600;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>

View File

@ -0,0 +1,191 @@
<template>
<el-dialog
:title="titleMap[mode]"
v-model="visible"
width="640px"
destroy-on-close
@closed="$emit('closed')"
>
<el-form
ref="dialogForm"
:model="form"
:rules="rules"
label-width="120px"
>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="到款日期" prop="record_date">
<el-date-picker
v-model="form.record_date"
type="date"
value-format="YYYY-MM-DD"
placeholder="到款日期"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="到款金额" prop="amount">
<el-input-number
v-model="form.amount"
:min="0"
:precision="2"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="阶段类型" prop="stage_type">
<el-select
v-model="form.stage_type"
placeholder="阶段类型"
style="width: 100%"
>
<el-option
v-for="item in stageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收款方式" prop="pay_method">
<el-select
v-model="form.pay_method"
placeholder="收款方式"
style="width: 100%"
>
<el-option
v-for="item in payMethodOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="凭证号">
<el-input v-model="form.voucher_no" placeholder="凭证号" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
:rows="3"
placeholder="备注"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" :loading="isSaving" @click="submit">
保存
</el-button>
</template>
</el-dialog>
</template>
<script>
export default {
emits: ["success", "closed"],
data() {
return {
visible: false,
mode: "add",
isSaving: false,
titleMap: {
add: "新增到款流水",
edit: "编辑到款流水",
},
form: {
contract: "",
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
},
stageOptions: [
{ value: 10, label: "首款" },
{ value: 20, label: "中间款" },
{ value: 30, label: "尾款" },
{ value: 40, label: "其他" },
],
payMethodOptions: [
{ value: 10, label: "银行转账" },
{ value: 20, label: "现金" },
{ value: 30, label: "承兑" },
{ value: 40, label: "微信" },
{ value: 50, label: "支付宝" },
{ value: 60, label: "其他" },
],
rules: {
record_date: [{ required: true, message: "请选择到款日期", trigger: "change" }],
amount: [{ required: true, message: "请输入到款金额", trigger: "blur" }],
stage_type: [{ required: true, message: "请选择阶段类型", trigger: "change" }],
pay_method: [{ required: true, message: "请选择收款方式", trigger: "change" }],
},
};
},
methods: {
open(mode = "add", contractId = "") {
this.mode = mode;
this.visible = true;
this.form = {
contract: contractId,
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
};
return this;
},
setData(data, contractId = "") {
this.form = Object.assign(
{
contract: contractId || data.contract,
record_date: "",
amount: undefined,
stage_type: 40,
pay_method: 10,
voucher_no: "",
remark: "",
},
data
);
return this;
},
submit() {
this.$refs.dialogForm.validate(async (valid) => {
if (!valid) {
return;
}
this.isSaving = true;
try {
if (this.mode === "add") {
await this.$API.sam.contractRecord.create.req(this.form);
} else {
await this.$API.sam.contractRecord.update.req(this.form.id, this.form);
}
this.$message.success("操作成功");
this.$emit("success");
this.visible = false;
} finally {
this.isSaving = false;
}
});
},
},
};
</script>

View File

@ -12,23 +12,58 @@
<el-main class="nopadding"> <el-main class="nopadding">
<scTable ref="table" :apiObj="apiObj" row-key="id" stripe :params="query"> <scTable ref="table" :apiObj="apiObj" row-key="id" stripe :params="query">
<el-table-column type="index" width="50" /> <el-table-column type="index" width="50" />
<el-table-column label="合同名称" prop="name">
</el-table-column>
<el-table-column label="合同编号" prop="number"> <el-table-column label="合同编号" prop="number">
</el-table-column> </el-table-column>
<el-table-column label="合同名称" prop="name">
</el-table-column>
<el-table-column label="关联客户" prop="customer_name">
</el-table-column>
<el-table-column label="合同金额" prop="amount"> <el-table-column label="合同金额" prop="amount">
<template #default="scope">
<span class="amount-strong">{{ formatMoney(scope.row.amount) }}</span>
</template>
</el-table-column>
<el-table-column label="已到款" prop="received_amount">
<template #default="scope">
<span class="amount-success">{{ formatMoney(scope.row.received_amount) }}</span>
</template>
</el-table-column>
<el-table-column label="未到款" prop="unreceived_amount">
<template #default="scope">
<span class="amount-warning">{{ formatMoney(scope.row.unreceived_amount) }}</span>
</template>
</el-table-column>
<el-table-column label="到款进度" min-width="180">
<template #default="scope">
<div class="progress-cell">
<el-progress
:percentage="progressNumber(scope.row.receive_progress)"
:stroke-width="14"
:color="progressColor(scope.row.status, scope.row.receive_progress)"
/>
</div>
</template>
</el-table-column> </el-table-column>
<el-table-column label="签订日期" prop="sign_date"> <el-table-column label="签订日期" prop="sign_date">
</el-table-column> </el-table-column>
<el-table-column label="关联客户" prop="customer_name"> <el-table-column label="合同状态">
<template #default="scope">
<el-tag :type="statusTagType(scope.row.status)" effect="dark">
{{ statusMap[scope.row.status] || "-" }}
</el-tag>
</template>
</el-table-column> </el-table-column>
<el-table-column label="创建人" prop="create_by_name"> <el-table-column label="创建人" prop="create_by_name">
</el-table-column> </el-table-column>
<el-table-column label="描述"> <el-table-column label="描述">
<template #default="scope">{{ scope.row.description }}</template> <template #default="scope">{{ scope.row.description }}</template>
</el-table-column> </el-table-column>
<el-table-column label="操作" fixed="right" align="left" width="120"> <el-table-column label="操作" fixed="right" align="left" width="180">
<template #default="scope"> <template #default="scope">
<el-link type="primary" @click="table_detail(scope.row)">
流水详情
</el-link>
<el-divider direction="vertical"></el-divider>
<el-link type="primary" @click="table_edit(scope.row)" v-auth="'contract.update'"> <el-link type="primary" @click="table_edit(scope.row)" v-auth="'contract.update'">
编辑 编辑
</el-link> </el-link>
@ -43,18 +78,27 @@
</el-container> </el-container>
<save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSaveSuccess" <save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSaveSuccess"
@closed="dialog.save = false"></save-dialog> @closed="dialog.save = false"></save-dialog>
<detail-drawer
v-if="dialog.detail"
ref="detailDrawer"
@refresh="handleSaveSuccess"
@closed="dialog.detail = false"
></detail-drawer>
</template> </template>
<script> <script>
import saveDialog from "./contract_form.vue"; import saveDialog from "./contract_form.vue";
import detailDrawer from "./components/ContractRecordDrawer.vue";
export default { export default {
name: "rparty", name: "rparty",
components: { components: {
saveDialog, saveDialog,
detailDrawer,
}, },
data() { data() {
return { return {
dialog: { dialog: {
save: false, save: false,
detail: false,
}, },
apiObj: this.$API.sam.contract.list, apiObj: this.$API.sam.contract.list,
query: { query: {
@ -62,16 +106,40 @@ export default {
page_size: 20, page_size: 20,
type: 10 type: 10
}, },
contractId: "",
selection: [], selection: [],
state_: { statusMap: {
10: '完好', 10: "草稿",
20: '限用', 20: "执行中",
30: '在修', 30: "已完成",
40: '禁用', 40: "已终止",
}, },
}; };
}, },
methods: { methods: {
formatMoney(value) {
return Number(value || 0).toFixed(2);
},
progressNumber(value) {
return Number(value || 0);
},
progressColor(status, progress) {
if (status === 40) {
return "#f56c6c";
}
if (Number(progress || 0) >= 100) {
return "#67c23a";
}
return "#409eff";
},
statusTagType(status) {
return {
10: "info",
20: "primary",
30: "success",
40: "danger",
}[status] || "info";
},
// //
add() { add() {
this.dialog.save = true; this.dialog.save = true;
@ -93,13 +161,21 @@ export default {
this.$refs.saveDialog.open("show").setData(row); this.$refs.saveDialog.open("show").setData(row);
}); });
}, },
table_detail(row) {
this.contractId = row.id;
this.dialog.detail = true;
this.$nextTick(() => {
this.$refs.detailDrawer.open(row.id);
});
},
// //
async table_del(row) { async table_del(row) {
this.$confirm(`确定删除吗?`, "提示", { this.$confirm(`确定删除吗?`, "提示", {
type: "warning", type: "warning",
}).then(() => { }).then(() => {
this.$API.pum.order.delete.req(row.id).then((res) => { this.$API.sam.contract.delete.req(row.id).then((res) => {
this.$message.success("删除成功"); this.$message.success("删除成功");
this.$refs.table.refresh();
return res; return res;
}).catch((err) => { }).catch((err) => {
return err; return err;
@ -123,4 +199,21 @@ export default {
}, },
}, },
}; };
</script> </script>
<style scoped>
.amount-strong {
font-weight: 600;
color: #303133;
}
.amount-success {
font-weight: 600;
color: #67c23a;
}
.amount-warning {
font-weight: 600;
color: #e6a23c;
}
.progress-cell {
padding-right: 8px;
}
</style>

View File

@ -43,6 +43,35 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :md="12" :sm="24">
<el-form-item label="生效日期">
<el-date-picker
v-model="form.effective_date"
type="date"
placeholder="生效日期"
value-format="YYYY-MM-DD"
style="width:100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="截止日期">
<el-date-picker
v-model="form.end_date"
type="date"
placeholder="截止日期"
value-format="YYYY-MM-DD"
style="width:100%"
/>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="合同状态" prop="status">
<el-select v-model="form.status" placeholder="合同状态" style="width:100%">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24"> <el-col :md="12" :sm="24">
<el-form-item label="关联客户" prop="customer"> <el-form-item label="关联客户" prop="customer">
<el-select <el-select
@ -98,6 +127,12 @@ export default {
isSaveing: false, isSaveing: false,
setFiltersVisible: false, setFiltersVisible: false,
options: [], options: [],
statusOptions: [
{ value: 10, label: "草稿" },
{ value: 20, label: "执行中" },
{ value: 30, label: "已完成" },
{ value: 40, label: "已终止" },
],
}; };
}, },
mounted() { mounted() {
@ -114,6 +149,11 @@ export default {
open(mode = "add",type) { open(mode = "add",type) {
this.mode = mode; this.mode = mode;
this.visible = true; this.visible = true;
if (mode === "add") {
this.form = {
status: 10,
};
}
return this; return this;
}, },
// //

View File

@ -0,0 +1,110 @@
<template>
<el-container>
<el-header>
<div class="left-panel"></div>
<div class="right-panel">
<el-input
v-model="query.search"
placeholder="合同编号/合同名称/客户"
clearable
style="margin-right: 5px"
/>
<el-select
v-model="query.stage_type"
clearable
placeholder="阶段类型"
style="width: 140px; margin-right: 5px"
>
<el-option v-for="item in stageOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button type="primary" icon="el-icon-search" @click="handleQuery"></el-button>
</div>
</el-header>
<el-main class="nopadding">
<scTable ref="table" :apiObj="apiObj" row-key="id" stripe :params="query">
<el-table-column type="index" width="50" />
<el-table-column label="到款日期" prop="record_date" />
<el-table-column label="到款金额" prop="amount" />
<el-table-column label="阶段类型">
<template #default="scope">{{ stageMap[scope.row.stage_type] || "-" }}</template>
</el-table-column>
<el-table-column label="收款方式">
<template #default="scope">{{ payMethodMap[scope.row.pay_method] || "-" }}</template>
</el-table-column>
<el-table-column label="合同编号" prop="contract_number" />
<el-table-column label="客户" prop="customer_name" />
<el-table-column label="凭证号" prop="voucher_no" show-overflow-tooltip />
<el-table-column label="备注" prop="remark" show-overflow-tooltip />
<el-table-column label="操作" width="100" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openContract(scope.row.contract)">查看合同</el-button>
</template>
</el-table-column>
</scTable>
</el-main>
</el-container>
<detail-drawer
v-if="dialog.detail"
ref="detailDrawer"
@refresh="refreshTable"
@closed="dialog.detail = false"
/>
</template>
<script>
import detailDrawer from "./components/ContractRecordDrawer.vue";
export default {
components: {
detailDrawer,
},
data() {
return {
apiObj: this.$API.sam.contractRecord.list,
query: {
page: 1,
page_size: 20,
search: "",
stage_type: "",
},
dialog: {
detail: false,
},
stageOptions: [
{ value: 10, label: "首款" },
{ value: 20, label: "中间款" },
{ value: 30, label: "尾款" },
{ value: 40, label: "其他" },
],
stageMap: {
10: "首款",
20: "中间款",
30: "尾款",
40: "其他",
},
payMethodMap: {
10: "银行转账",
20: "现金",
30: "承兑",
40: "微信",
50: "支付宝",
60: "其他",
},
};
},
methods: {
handleQuery() {
this.$refs.table.queryData(this.query);
},
openContract(contractId) {
this.dialog.detail = true;
this.$nextTick(() => {
this.$refs.detailDrawer.open(contractId);
});
},
refreshTable() {
this.$refs.table.refresh();
},
},
};
</script>