Merge branch 'master' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory_web
This commit is contained in:
commit
dc58a447f3
|
|
@ -1,6 +1,108 @@
|
|||
import config from "@/config"
|
||||
import http from "@/utils/request"
|
||||
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: {
|
||||
list: {
|
||||
|
|
@ -348,4 +450,4 @@ export default {
|
|||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
list: {
|
||||
|
|
@ -187,4 +237,4 @@ export default {
|
|||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2191,6 +2191,24 @@ const routes = [
|
|||
},
|
||||
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",
|
||||
path: "/pum/order",
|
||||
|
|
@ -2245,6 +2263,15 @@ const routes = [
|
|||
},
|
||||
component: "sam/contract",
|
||||
},
|
||||
{
|
||||
name: "contractRecord",
|
||||
path: "/sam/contract_record",
|
||||
meta: {
|
||||
title: "到款流水查询",
|
||||
perms: ["contract"],
|
||||
},
|
||||
component: "sam/contract_record",
|
||||
},
|
||||
{
|
||||
name: "samOrder",
|
||||
path: "/sam/samOrder",
|
||||
|
|
|
|||
|
|
@ -14,10 +14,27 @@
|
|||
<dv-capsule-chart :config="config_left1" class="leftChartBlock1"/>
|
||||
</dv-border-box-1>
|
||||
</div>
|
||||
<div style="height: 40vh;">
|
||||
<div style="height: 40vh;" class="mat-panel-wrap">
|
||||
<dv-border-box-1>
|
||||
<div class="chartBlockTitle">产品占比</div>
|
||||
<dv-active-ring-chart :config="config_left2" class="leftChartBlock2"/>
|
||||
<div class="mat-inner">
|
||||
<div class="mat-header">
|
||||
<div class="mat-title">
|
||||
<span class="mat-title-bar"></span>
|
||||
<span class="mat-title-icon">📦</span>
|
||||
产品统计
|
||||
</div>
|
||||
</div>
|
||||
<div class="mat-body">
|
||||
<div v-for="group in materialsList" :key="group.type" class="mat-group">
|
||||
<div class="mat-group-label" :style="{ borderLeftColor: group.color }">
|
||||
<span>{{ group.type }}</span>
|
||||
</div>
|
||||
<div class="mat-row" v-for="item in group.list" :key="item">
|
||||
<span class="mat-name">{{ item }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dv-border-box-1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -107,22 +124,21 @@
|
|||
<div class="perf-title">
|
||||
<span class="perf-title-bar"></span>
|
||||
<span class="perf-title-icon">👥</span>
|
||||
人员日产量 TOP5
|
||||
人员月产量
|
||||
</div>
|
||||
<div class="perf-unit">单位: 件</div>
|
||||
</div>
|
||||
<div class="perf-list" ref="perfList">
|
||||
<div class="perf-row" v-for="(item, idx) in scrollPerfItems" :key="idx">
|
||||
<div class="perf-avatar">{{ item.操作人 ? item.操作人.charAt(0) : '?' }}</div>
|
||||
<div class="perf-name">{{ item.操作人 }}</div>
|
||||
<div class="perf-avatar">{{ item.name ? item.name.charAt(0) : '?' }}</div>
|
||||
<div class="perf-name">{{ item.name }}</div>
|
||||
<div class="perf-count">
|
||||
<span class="perf-num">{{ item.生产数 }}</span>
|
||||
<span class="perf-num">{{ item.count }}</span>
|
||||
<span class="perf-unit-sm">件</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="perf-footer">
|
||||
平均效率 {{ avgEfficiency }}%
|
||||
<span class="perf-lightning">⚡</span>
|
||||
标兵: {{ topPerson }}
|
||||
</div>
|
||||
|
|
@ -396,9 +412,9 @@ export default {
|
|||
{name:'洗棒',value:0},
|
||||
{name:'捆棒',value:0},
|
||||
{name:'拉单丝',value:0},
|
||||
{name:'捆一次棒',value:0},
|
||||
{name:'排一次棒',value:0},
|
||||
{name:'一次复丝',value:0},
|
||||
{name:'捆二次棒',value:0},
|
||||
{name:'排二次棒',value:0},
|
||||
{name:'二次复丝',value:0},
|
||||
],
|
||||
showValue: true
|
||||
|
|
@ -423,6 +439,11 @@ export default {
|
|||
lastUpdateInterval: null,
|
||||
scrollTimer: null,
|
||||
performanceList: [],
|
||||
materialsList: [
|
||||
{type: '倒像器', color: '#53c6f3', list: [],img:'public/img/bx/dxq2.png'},
|
||||
{type: '直板', color: '#c8ff50', list: [],img:'public/img/bx/zb2.png'},
|
||||
{type: '光锥', color: '#ff9d3e', list: [],img:'public/img/bx/gz2.png'}
|
||||
],
|
||||
perfScrollTimer: null,
|
||||
currentTime: "",
|
||||
currentDay: "",
|
||||
|
|
@ -430,7 +451,7 @@ export default {
|
|||
end_time:'',
|
||||
start_time:'',
|
||||
deptName:"拉丝排板班组",
|
||||
mgroups:['洗棒','捆棒','拉单丝','捆一次棒','一次复丝','捆二次棒','二次复丝'],
|
||||
mgroups:['洗棒','捆棒','拉单丝','排一次棒','一次复丝','排二次棒','二次复丝'],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -445,34 +466,32 @@ export default {
|
|||
if (this.equipmentList.length === 0) return [];
|
||||
return [...this.equipmentList, ...this.equipmentList];
|
||||
},
|
||||
// 全员按生产数降序排列
|
||||
// 全员按 count 降序排列
|
||||
sortedPerfList() {
|
||||
return [...this.performanceList]
|
||||
.sort((a, b) => Number(b.生产数) - Number(a.生产数));
|
||||
.sort((a, b) => b.count - a.count);
|
||||
},
|
||||
// 渲染两份,用于无缝滚动
|
||||
scrollPerfItems() {
|
||||
if (!this.sortedPerfList.length) return [];
|
||||
return [...this.sortedPerfList, ...this.sortedPerfList];
|
||||
},
|
||||
// 平均效率 = 合格数之和 / 生产数之和
|
||||
avgEfficiency() {
|
||||
if (!this.performanceList.length) return 0;
|
||||
const totalProd = this.performanceList.reduce((s, i) => s + Number(i.生产数 || 0), 0);
|
||||
const totalOk = this.performanceList.reduce((s, i) => s + Number(i.合格数 || 0), 0);
|
||||
if (!totalProd) return 0;
|
||||
return Math.round(totalOk / totalProd * 100);
|
||||
},
|
||||
// 标兵 = 生产数最多的人
|
||||
// 标兵 = 产量最多的人
|
||||
topPerson() {
|
||||
if (!this.performanceList.length) return '-';
|
||||
return [...this.performanceList]
|
||||
.sort((a, b) => Number(b.生产数) - Number(a.生产数))[0]?.操作人 || '-';
|
||||
.sort((a, b) => b.count - a.count)[0]?.name || '-';
|
||||
},
|
||||
materialsGroups() {
|
||||
if (this.equipmentList.length === 0) return [];
|
||||
console.log(this.equipmentList);
|
||||
return [...this.equipmentList];
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
//洗棒、捆棒、拉丝 :洗棒、捆棒、拉单丝、捆一次棒、一次复丝、捆二次棒、二次复丝
|
||||
//洗棒、捆棒、拉丝 :洗棒、捆棒、拉单丝、排一次棒、一次复丝、排二次棒、二次复丝
|
||||
this.showTime();
|
||||
this.dayInterval = setInterval(() => {
|
||||
this.showTime();
|
||||
|
|
@ -481,10 +500,12 @@ export default {
|
|||
that.getEquipment();
|
||||
that.getMgroups();
|
||||
//每个人日生产量:个人绩效
|
||||
that.getEveryoneCount();
|
||||
// that.getEveryoneCount(that.deptName2);
|
||||
// that.getEveryoneCount(that.deptName3);
|
||||
// that.getEveryoneCount();
|
||||
that.materialAll();
|
||||
let date = new Date();
|
||||
let year = date.getFullYear();
|
||||
let month = date.getMonth() + 1;
|
||||
console.log(new Date(year, month, 0).getDate())
|
||||
},
|
||||
methods: {
|
||||
getMondayOfCurrentWeek() {
|
||||
|
|
@ -526,10 +547,17 @@ export default {
|
|||
let that = this;
|
||||
let params = {page: 0,query:" { id, name }"};
|
||||
that.$API.mtm.mgroup.list.req(params).then((res) => {
|
||||
that.performanceList = [];
|
||||
that.materialsList[0].list = [];
|
||||
that.materialsList[1].list = [];
|
||||
that.materialsList[2].list = [];
|
||||
res.forEach((item)=>{
|
||||
let index = that.mgroups.indexOf(item.name);
|
||||
if(index>-1){
|
||||
//车间库存
|
||||
that.getmgroupMaterial(item.id,item.name,index);
|
||||
//员工生产统计
|
||||
that.getEveryoneCount(item.id,item.name)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -637,16 +665,43 @@ export default {
|
|||
});
|
||||
},
|
||||
//每个人日产量
|
||||
getEveryoneCount(){
|
||||
getEveryoneCount(id,name){
|
||||
let that = this;
|
||||
that.performanceList = [];
|
||||
let date = that.$TOOL.dateFormat(new Date(), "yyyy-MM-dd");
|
||||
let date = new Date();
|
||||
let year = date.getFullYear();
|
||||
let month = date.getMonth() + 1;
|
||||
let days = new Date(year, month,0).getDate();
|
||||
let start_date = year + "-" + month + "-01";
|
||||
let end_date = year + "-" + month + "-" + days;
|
||||
let params = {
|
||||
query: {start_date:date,end_date:date,dept_name:that.deptName},
|
||||
query: {start_date:start_date,end_date:end_date,mgroup_name:name},
|
||||
};
|
||||
this.$API.bi.dataset.exec.req("performance", params).then((res) => {
|
||||
let exceStr = "";
|
||||
if(name=='拉单丝'){
|
||||
exceStr = "product_defect_lds";
|
||||
}else if(name=='排一次棒'||name=='一次复丝'||name=='排二次棒'||name=='二次复丝'){
|
||||
exceStr = "product_defect_jjcj";
|
||||
}
|
||||
this.$API.bi.dataset.exec.req(exceStr, params).then((res) => {
|
||||
if(res.data2.ds0.length > 0){
|
||||
that.performanceList = res.data2.ds0;
|
||||
res.data2.ds0.forEach(item => {
|
||||
const itemName = item.员工;
|
||||
const count = Number(item.总切片数) || 0;
|
||||
const existing = that.performanceList.find(p => p.name === itemName);
|
||||
if (existing) {
|
||||
existing.count += count;
|
||||
} else {
|
||||
that.performanceList.push({ name: itemName, count });
|
||||
}
|
||||
const matName = item.物料名;
|
||||
let index = matName.indexOf('倒像器') > -1 ? 0: matName.indexOf('直板') > -1 ?1 : 2;
|
||||
const matExisting = that.materialsList[index].list.find(m => m === matName);
|
||||
if (matExisting) {
|
||||
} else {
|
||||
that.materialsList[index].list.push(matName);
|
||||
}
|
||||
});
|
||||
console.log('that.materialsList',that.materialsList);
|
||||
}
|
||||
that.$nextTick(() => { that.startPerfScroll(); });
|
||||
});
|
||||
|
|
@ -760,9 +815,112 @@ export default {
|
|||
left: 5%;
|
||||
border-radius: 3vh;
|
||||
}
|
||||
.leftChartBlock2{
|
||||
width:100%;
|
||||
height: 35vh;
|
||||
/* ===== 产品统计面板 ===== */
|
||||
.mat-panel-wrap { position: relative; }
|
||||
|
||||
.mat-inner {
|
||||
position: absolute;
|
||||
inset: 2.5%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-header {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 4vh;
|
||||
padding: 0 1.2vh;
|
||||
border-bottom: 1px solid rgba(83, 198, 243, 0.25);
|
||||
}
|
||||
.mat-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4vh;
|
||||
font-size: 1.5vh;
|
||||
font-weight: 600;
|
||||
color: #e0f4ff;
|
||||
}
|
||||
.mat-title-bar {
|
||||
display: inline-block;
|
||||
width: 3px;
|
||||
height: 1.6vh;
|
||||
background: #00b4ff;
|
||||
border-radius: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.mat-title-icon { font-style: normal; font-size: 1.4vh; }
|
||||
|
||||
.mat-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0.5vh 0.8vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1vh;
|
||||
}
|
||||
.mat-body::-webkit-scrollbar { width: 2px; }
|
||||
.mat-body::-webkit-scrollbar-thumb { background: rgba(83, 198, 243, 0.3); border-radius: 2px; }
|
||||
|
||||
.mat-group { display: flex; flex-direction: column; gap: 0.35vh; }
|
||||
|
||||
.mat-group-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.25vh 0.6vh;
|
||||
margin-bottom: 0.15vh;
|
||||
border-left: 2.5px solid;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border-radius: 0 0.4vh 0.4vh 0;
|
||||
font-size: 1.25vh;
|
||||
font-weight: 600;
|
||||
color: rgba(220, 240, 255, 0.9);
|
||||
}
|
||||
.mat-group-total {
|
||||
font-size: 1.3vh;
|
||||
font-weight: 700;
|
||||
font-family: "myfont", "Microsoft Yahei";
|
||||
}
|
||||
|
||||
.mat-row {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 1.1vh;
|
||||
color: rgba(180, 215, 240, 0.75);
|
||||
padding: 0.1vh 1vw;
|
||||
|
||||
}
|
||||
.mat-name {
|
||||
width: 9vh;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.mat-bar-wrap {
|
||||
flex: 1;
|
||||
height: 0.7vh;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-radius: 1vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
.mat-bar {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: 1vh;
|
||||
opacity: 0.75;
|
||||
transition: width 0.6s ease;
|
||||
}
|
||||
.mat-count {
|
||||
flex-shrink: 0;
|
||||
width: 4vh;
|
||||
text-align: right;
|
||||
font-weight: 700;
|
||||
font-family: "myfont", "Microsoft Yahei";
|
||||
font-size: 1.3vh;
|
||||
color: #c8ff50;
|
||||
}
|
||||
.middleTableBlock1{
|
||||
width:94%;
|
||||
|
|
@ -1048,4 +1206,5 @@ export default {
|
|||
color: #ff9d3e;
|
||||
font-size: 1.4vh;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -40,6 +40,25 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</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-form-item label="截止到货日期">
|
||||
<el-date-picker
|
||||
|
|
@ -96,11 +115,13 @@ export default {
|
|||
visible: false,
|
||||
isSaveing: false,
|
||||
options: [],
|
||||
contractOptions: [],
|
||||
setFiltersVisible: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
this.getContracts();
|
||||
},
|
||||
methods: {
|
||||
//显示
|
||||
|
|
@ -114,6 +135,17 @@ export default {
|
|||
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() {
|
||||
this.$refs.dialogForm.validate(async (valid) => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -12,23 +12,58 @@
|
|||
<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="name">
|
||||
</el-table-column>
|
||||
<el-table-column label="合同编号" prop="number">
|
||||
</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">
|
||||
<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 label="签订日期" prop="sign_date">
|
||||
</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 label="创建人" prop="create_by_name">
|
||||
</el-table-column>
|
||||
<el-table-column label="描述">
|
||||
<template #default="scope">{{ scope.row.description }}</template>
|
||||
</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">
|
||||
<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>
|
||||
|
|
@ -43,18 +78,27 @@
|
|||
</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/ContractRecordDrawer.vue";
|
||||
export default {
|
||||
name: "rparty",
|
||||
components: {
|
||||
saveDialog,
|
||||
detailDrawer,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: {
|
||||
save: false,
|
||||
detail: false,
|
||||
},
|
||||
apiObj: this.$API.sam.contract.list,
|
||||
query: {
|
||||
|
|
@ -62,16 +106,40 @@ export default {
|
|||
page_size: 20,
|
||||
type: 10
|
||||
},
|
||||
contractId: "",
|
||||
selection: [],
|
||||
state_: {
|
||||
10: '完好',
|
||||
20: '限用',
|
||||
30: '在修',
|
||||
40: '禁用',
|
||||
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;
|
||||
|
|
@ -93,13 +161,21 @@ export default {
|
|||
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) {
|
||||
this.$confirm(`确定删除吗?`, "提示", {
|
||||
type: "warning",
|
||||
}).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.$refs.table.refresh();
|
||||
return res;
|
||||
}).catch((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>
|
||||
|
|
|
|||
|
|
@ -43,6 +43,35 @@
|
|||
</el-date-picker>
|
||||
</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="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-form-item label="关联客户" prop="customer">
|
||||
<el-select
|
||||
|
|
@ -98,6 +127,12 @@ export default {
|
|||
isSaveing: false,
|
||||
setFiltersVisible: false,
|
||||
options: [],
|
||||
statusOptions: [
|
||||
{ value: 10, label: "草稿" },
|
||||
{ value: 20, label: "执行中" },
|
||||
{ value: 30, label: "已完成" },
|
||||
{ value: 40, label: "已终止" },
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -114,6 +149,11 @@ export default {
|
|||
open(mode = "add",type) {
|
||||
this.mode = mode;
|
||||
this.visible = true;
|
||||
if (mode === "add") {
|
||||
this.form = {
|
||||
status: 10,
|
||||
};
|
||||
}
|
||||
return this;
|
||||
},
|
||||
//提交
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -3,15 +3,6 @@
|
|||
<el-aside>
|
||||
<el-container>
|
||||
<el-header style="height: 40px;">
|
||||
<!-- <el-select
|
||||
v-model="query.material_start__type"
|
||||
placeholder="请选择"
|
||||
style="width: 90px;"
|
||||
>
|
||||
<el-option label="原料" :value="30"></el-option>
|
||||
<el-option label="半成品" :value="20"></el-option>
|
||||
<el-option label="成品" :value="10"></el-option>
|
||||
</el-select> -->
|
||||
<el-input
|
||||
v-model="query.batch"
|
||||
placeholder="请输入批次号"
|
||||
|
|
@ -34,7 +25,6 @@
|
|||
:paginationLayout="'total, sizes, jumper'"
|
||||
>
|
||||
<el-table-column prop="batch" label="批次号"></el-table-column>
|
||||
<!-- <el-table-column prop="version" label="版本" width="60"></el-table-column> -->
|
||||
</scTable>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
|
@ -137,6 +127,7 @@
|
|||
<el-table-column type="expand">
|
||||
<template #default="props">
|
||||
<div style="padding-left: 50px">
|
||||
<p v-if="props.row.new_batch!==null" style="color: #5f9ea0;font-size: 16px;margin-bottom: 5px;">新批次号:{{ props.row.new_batch }}</p>
|
||||
<template v-for="item in props.row.handoverb" :key="item.id">
|
||||
<el-descriptions :column="3">
|
||||
<el-descriptions-item label="批次">
|
||||
|
|
|
|||
|
|
@ -295,7 +295,13 @@
|
|||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" class-name="colorheader6">
|
||||
<el-table-column label="开台人" align="center" class-name="colorheader6">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.data.喷码_一体刀_操作人">{{scope.row.data.喷码_一体刀_操作人}}</span>
|
||||
<span v-if="scope.row.data.喷码_磨床开台_操作人">{{scope.row.data.喷码_磨床开台_操作人}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" class-name="colorheader7">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.data.中检一_缺陷_备注 }}</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
@change="formWminChange(wm_in)"
|
||||
style="width: 300px;margin-left: 10px;"
|
||||
></el-input>
|
||||
<!-- <scScanner @scanResult="formWminChange"></scScanner> -->
|
||||
<scScanner @scanResult="codeTextChange" v-if="project_code!=='bxerp'"></scScanner>
|
||||
</el-form-item>
|
||||
<el-form-item label="总计:">
|
||||
{{ totalCount }}
|
||||
|
|
@ -373,6 +373,7 @@ export default {
|
|||
},
|
||||
wm_in:"",
|
||||
route_code: "",
|
||||
project_code:'',
|
||||
materials:[],
|
||||
totalCount: 0,
|
||||
deptID:'',
|
||||
|
|
@ -395,6 +396,8 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
let config_base = that.$TOOL.data.get("BASE_INFO").base;
|
||||
that.project_code = config_base.base_code;
|
||||
let arr = that.$route.path.split("/");
|
||||
that.route_code = arr[2];
|
||||
that.form.type = that.type;
|
||||
|
|
@ -642,6 +645,10 @@ export default {
|
|||
this.form.handoverb.splice(index,1);
|
||||
this.countChange();
|
||||
},
|
||||
codeTextChange(text){
|
||||
this.wm_in = text;
|
||||
this.formWminChange(text);
|
||||
},
|
||||
//显示
|
||||
open(mode = "add",data,mtype) {
|
||||
let that = this;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
style="padding: 0 10px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-col :span="project_code!=='bxerp'?22:24">
|
||||
<el-form-item label="扫码:">
|
||||
<el-input
|
||||
class="inputWrap"
|
||||
|
|
@ -26,11 +26,14 @@
|
|||
v-model="wm_in"
|
||||
clearable
|
||||
@change="formWminChange(wm_in)"
|
||||
style="width: 100%;top: -7px;ime-mode:active"
|
||||
style="width: 100%;ime-mode:active"
|
||||
></el-input>
|
||||
<span style="color: red;line-height: 12px;font-size: 14px;">*请扫同一批次的物料码</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2" v-if="project_code!=='bxerp'">
|
||||
<scScanner style="top: -7px" @scanResult="codeTextChange"></scScanner>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :md="12" :sm="12" :xs="24">
|
||||
|
|
@ -262,6 +265,7 @@ export default {
|
|||
route_code:"",
|
||||
imageUrl:'',
|
||||
test_file:'',
|
||||
project_code:'',
|
||||
visible: false,
|
||||
isSaveing: false,
|
||||
batchCountCando:0,
|
||||
|
|
@ -278,6 +282,8 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
let that = this;
|
||||
let config_base = that.$TOOL.data.get("BASE_INFO").base;
|
||||
that.project_code = config_base.base_code;
|
||||
this.route_code = this.$route.path.split("/")[2];
|
||||
this.form.handle_date = this.$TOOL.dateFormat2(new Date());
|
||||
// this.form.work_start_time = this.$TOOL.dateFormat(new Date());
|
||||
|
|
@ -341,6 +347,10 @@ export default {
|
|||
})
|
||||
});
|
||||
},
|
||||
codeTextChange(text){
|
||||
this.wm_in = text;
|
||||
this.formWminChange(text);
|
||||
},
|
||||
//显示
|
||||
open(mode = "add") {
|
||||
let that = this;
|
||||
|
|
|
|||
Loading…
Reference in New Issue