Files
klp-oa/klp-ui/src/views/crm/contract/fin_sta/index.vue
砂糖 af6eb19952 fix(crm): 修正应收表格合同编号绑定字段错误
将合同编号列的prop从contractCode改为orderCode,匹配实际数据源字段
2026-05-23 18:13:13 +08:00

396 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<div class="app-container">
<!-- 筛选区域 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="80px" v-show="showSearch">
<el-form-item label="客户" prop="customerId">
<CustomerSelect v-model="queryParams.customerId" bindField="customerId" @change="handleCustomerChange"
:style="{ width: '240px' }" />
</el-form-item>
<el-form-item label="合同编号" prop="contractCode">
<el-select v-model="queryParams.contractCode" placeholder="请选择合同编号" filterable clearable style="width: 240px;">
<el-option v-for="item in contractOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 收款明细标题 -->
<el-descriptions title="收款明细"></el-descriptions>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-if="searchable" :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 收款明细表格 -->
<KLPTable v-loading="loading" :data="receivableList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column label="合同编号" align="center" prop="orderCode" />
<el-table-column label="收款日期" align="center" prop="dueDate" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.dueDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="应收金额" align="center" prop="amount" />
<el-table-column label="已收款" align="center" prop="paidAmount" />
<el-table-column label="未收款" align="center" prop="balanceAmount" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</KLPTable>
<!-- 分页 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改应收款对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="客户" prop="customerId">
<CustomerSelect v-model="form.customerId" bindField="customerId" @change="handleFormCustomerChange"
:style="{ width: '100%' }" />
</el-form-item>
<el-form-item label="合同编号" prop="contractCode">
<el-select v-model="form.contractCode" placeholder="请选择合同编号" filterable clearable style="width: 100%;">
<el-option v-for="item in formContractOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="收款日期" prop="dueDate">
<el-date-picker clearable v-model="form.dueDate" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择收款日期">
</el-date-picker>
</el-form-item>
<el-form-item label="收款金额" prop="amount">
<el-input-number :controls=false v-model="form.amount" :step="1.00"
:precision="2" placeholder="请输入应收金额" :min="0" style="width: 100%;"/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listReceivable, getReceivable, delReceivable, addReceivable, updateReceivable } from "@/api/finance/receivable";
import { listOrder } from "@/api/crm/order";
import CustomerSelect from "@/components/KLPService/CustomerSelect/index.vue";
export default {
components: {
CustomerSelect
},
name: "FinanceStatus",
data() {
return {
buttonLoading: false,
loading: true,
ids: [],
single: true,
multiple: true,
showSearch: true,
searchable: true,
total: 0,
receivableList: [],
title: "",
open: false,
queryParams: {
pageNum: 1,
pageSize: 20,
customerId: undefined,
contractCode: undefined,
orderId: undefined,
orderCode: undefined,
dueDate: undefined,
amount: undefined,
paidAmount: undefined,
balanceAmount: undefined,
status: undefined,
},
contractOptions: [],
formContractOptions: [],
form: {},
rules: {}
};
},
computed: {
totalAmount() {
return this.receivableList.reduce((total, item) => total + parseFloat(item.amount || 0), 0);
},
receivedAmount() {
return this.receivableList.reduce((total, item) => total + parseFloat(item.paidAmount || 0), 0);
},
unreceivedAmount() {
return this.totalAmount - this.receivedAmount;
}
},
created() {
this.getList();
this.loadContracts(); // 加载所有合同编号,支持独立查询
},
methods: {
getList() {
this.loading = true;
listReceivable(this.queryParams).then(response => {
this.receivableList = response.rows || [];
this.total = response.total || 0;
}).catch(error => {
console.error('数据加载失败:', error);
this.$message.error('数据加载失败,请稍后重试');
this.receivableList = [];
this.total = 0;
}).finally(() => {
this.loading = false;
});
},
cancel() {
this.open = false;
this.reset();
},
handleCustomerChange(customer) {
// 根据客户ID获取合同列表可选
if (customer && customer.customerId) {
this.loadContracts(customer.customerId);
} else {
// 不传客户ID加载所有合同
this.loadContracts();
}
},
loadContracts(customerId) {
listOrder({ customerId: customerId || undefined, pageNum: 1, pageSize: 100 }).then(res => {
this.contractOptions = (res.rows || []).map(item => ({
value: item.contractCode,
label: item.contractCode
}));
});
},
handleFormCustomerChange(customer) {
// 清空合同选择
this.form.contractCode = undefined;
// 根据客户ID获取合同列表
if (customer && customer.customerId) {
listOrder({ customerId: customer.customerId, pageNum: 1, pageSize: 100 }).then(res => {
this.formContractOptions = (res.rows || []).map(item => ({
value: item.contractCode,
label: item.contractCode
}));
});
} else {
this.formContractOptions = [];
}
},
reset() {
this.form = {
receivableId: undefined,
customerId: undefined,
orderId: undefined,
dueDate: undefined,
amount: undefined,
paidAmount: 0,
balanceAmount: undefined,
status: undefined,
delFlag: undefined,
remark: undefined,
createTime: undefined,
createBy: undefined,
updateTime: undefined,
updateBy: undefined
};
this.resetForm("form");
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.receivableId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
handleAdd() {
this.reset();
this.open = true;
this.title = "添加应收款管理";
},
handleUpdate(row) {
this.loading = true;
this.reset();
const receivableId = row.receivableId || this.ids;
getReceivable(receivableId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改应收款管理";
}).catch(error => {
this.loading = false;
this.$message.error('获取数据失败');
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.receivableId != null) {
const { balanceAmount, ...payload } = this.form;
updateReceivable(payload).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addReceivable(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
handleDelete(row) {
const receivableIds = row.receivableId || this.ids;
this.$modal.confirm('是否确认删除应收款管理编号为"' + receivableIds + '"的数据项?').then(() => {
this.loading = true;
return delReceivable(receivableIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
handleExport() {
this.download('klp/receivable/export', {
...this.queryParams
}, `receivable_${new Date().getTime()}.xlsx`);
},
parseTime(time, pattern) {
if (!time) return '';
const d = new Date(time);
const year = d.getFullYear();
const month = (d.getMonth() + 1).toString().padStart(2, '0');
const day = d.getDate().toString().padStart(2, '0');
return pattern.replace('{y}', year).replace('{m}', month).replace('{d}', day);
}
}
};
</script>
<style scoped>
.stats-card {
display: flex;
gap: 16px;
margin-bottom: 16px;
}
.stat-item {
flex: 1;
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
text-align: center;
}
.stat-value {
font-size: 28px;
font-weight: 700;
color: #303133;
margin-bottom: 8px;
}
.stat-value.success {
color: #67c23a;
}
.stat-value.danger {
color: #f56c6c;
}
.stat-value.warning {
color: #e6a23c;
}
.stat-label {
font-size: 13px;
color: #909399;
}
.quick-filter {
display: flex;
gap: 16px;
margin-bottom: 16px;
padding-left: 8px;
}
.quick-filter .el-button.active {
color: #409eff;
font-weight: 500;
}
.expiring-tag,
.expired-tag {
display: inline-block;
margin-left: 4px;
padding: 2px 6px;
font-size: 10px;
border-radius: 4px;
}
.expiring-tag {
background: #fffbe6;
color: #e6a23c;
}
.expired-tag {
background: #fff2f0;
color: #f56c6c;
}
.text-danger {
color: #f56c6c !important;
}
.text-warning {
color: #e6a23c !important;
}
.detail-content {
padding: 8px;
}
</style>