Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -30,9 +30,9 @@
|
||||
</span>
|
||||
</div>
|
||||
<!-- <el-alert :title="'已配置'+allCols.length+'个列'" type="info" :closable="false" show-icon style="margin-bottom:8px" /> -->
|
||||
<el-table v-loading="gridLoading" height="calc(100vh - 260px)" :data="gridRows" border stripe size="mini" style="width:100%" :header-cell-style="headerStyle" :key="'tbl-'+inputMode">
|
||||
<el-table v-loading="gridLoading" height="calc(100vh - 260px)" :data="tableData" border stripe size="mini" style="width:100%" :header-cell-style="headerStyle" :row-class-name="rowClassName" :key="'tbl-'+inputMode">
|
||||
<el-table-column label="日期" width="135" fixed>
|
||||
<template slot-scope="s"><el-date-picker v-model="s.row.detailDate" type="date" value-format="yyyy-MM-dd" size="mini" style="width:124px" @change="sortGrid" /></template>
|
||||
<template slot-scope="s"><span v-if="s.row.$isSummary" class="summary-label">{{ s.row.detailDate }}</span><el-date-picker v-else v-model="s.row.detailDate" type="date" value-format="yyyy-MM-dd" size="mini" style="width:124px" @change="sortGrid" /></template>
|
||||
</el-table-column>
|
||||
<template v-for="col in displayCols">
|
||||
<el-table-column v-if="col.$type==='detail' && !col.isShift" :key="'d'+col.itemId" align="center" width="130">
|
||||
@@ -40,7 +40,8 @@
|
||||
<div class="col-hd">{{ col.itemName }}{{ col.unit ? '('+col.unit+')' : '' }}</div>
|
||||
</template>
|
||||
<template slot-scope="s">
|
||||
<el-input v-model="s.row['q'+col.itemId]" size="mini" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<span v-if="s.row.$isSummary" class="summary-val">{{ s.row['q'+col.itemId] || '-' }}</span>
|
||||
<el-input v-else v-model="s.row['q'+col.itemId]" size="mini" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<!-- <span slot="suffix" v-if="col.queryCondition" class="input-suffix-actions">
|
||||
<i title="反填" v-if="col.category==='辅料'||col.category==='能耗'" :class="backfillLoading[col.itemId]?'el-icon-loading':'el-icon-upload2'" class="ica ica-backfill" @click.stop="backfillCell(col, s.row)" />
|
||||
<i title="自动获取" :class="autoLoading[col.itemId]?'el-icon-loading':'el-icon-refresh'" class="ica ica-fetch" @click.stop="fetchAutoData(col, s.row)" />
|
||||
@@ -53,27 +54,39 @@
|
||||
<div class="col-hd">{{ col.itemName }}{{ col.unit ? '('+col.unit+')' : '' }}</div>
|
||||
</template>
|
||||
<template slot-scope="s">
|
||||
<div class="shift-cell">
|
||||
<span class="shift-tag">甲</span>
|
||||
<el-input v-model="s.row['q'+col.itemId+'_1']" size="mini" class="shift-input" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<!-- <span slot="suffix" v-if="col.queryCondition" class="input-suffix-actions"><i v-if="col.category==='辅料'||col.category==='能耗'" :class="backfillLoading[col.itemId]?'el-icon-loading':'el-icon-upload2'" class="ica ica-backfill" @click.stop="backfillCell(col, s.row, '1')" /><i :class="autoLoading[col.itemId]?'el-icon-loading':'el-icon-refresh'" class="ica ica-fetch" @click.stop="fetchAutoData(col, s.row, '1')" /></span> -->
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="shift-cell">
|
||||
<span class="shift-tag">乙</span>
|
||||
<el-input v-model="s.row['q'+col.itemId+'_2']" size="mini" class="shift-input" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<!-- <span slot="suffix" v-if="col.queryCondition" class="input-suffix-actions"><i v-if="col.category==='辅料'||col.category==='能耗'" :class="backfillLoading[col.itemId]?'el-icon-loading':'el-icon-upload2'" class="ica ica-backfill" @click.stop="backfillCell(col, s.row, '2')" /><i :class="autoLoading[col.itemId]?'el-icon-loading':'el-icon-refresh'" class="ica ica-fetch" @click.stop="fetchAutoData(col, s.row, '2')" /></span> -->
|
||||
</el-input>
|
||||
</div>
|
||||
<template v-if="s.row.$isSummary">
|
||||
<div class="shift-cell"><span class="shift-tag">甲</span><span class="summary-val">{{ s.row['q'+col.itemId+'_1'] || '-' }}</span></div>
|
||||
<div class="shift-cell"><span class="shift-tag">乙</span><span class="summary-val">{{ s.row['q'+col.itemId+'_2'] || '-' }}</span></div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="shift-cell">
|
||||
<span class="shift-tag">甲</span>
|
||||
<el-input v-model="s.row['q'+col.itemId+'_1']" size="mini" class="shift-input" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<!-- <span slot="suffix" v-if="col.queryCondition" class="input-suffix-actions"><i v-if="col.category==='辅料'||col.category==='能耗'" :class="backfillLoading[col.itemId]?'el-icon-loading':'el-icon-upload2'" class="ica ica-backfill" @click.stop="backfillCell(col, s.row, '1')" /><i :class="autoLoading[col.itemId]?'el-icon-loading':'el-icon-refresh'" class="ica ica-fetch" @click.stop="fetchAutoData(col, s.row, '1')" /></span> -->
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="shift-cell">
|
||||
<span class="shift-tag">乙</span>
|
||||
<el-input v-model="s.row['q'+col.itemId+'_2']" size="mini" class="shift-input" @input="recalcAll" :class="{'anomaly-input': isAnomalyCell(s.row.detailDate, col.itemId)}">
|
||||
<!-- <span slot="suffix" v-if="col.queryCondition" class="input-suffix-actions"><i v-if="col.category==='辅料'||col.category==='能耗'" :class="backfillLoading[col.itemId]?'el-icon-loading':'el-icon-upload2'" class="ica ica-backfill" @click.stop="backfillCell(col, s.row, '2')" /><i :class="autoLoading[col.itemId]?'el-icon-loading':'el-icon-refresh'" class="ica ica-fetch" @click.stop="fetchAutoData(col, s.row, '2')" /></span> -->
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.$type==='metric' && !col.isShift" :key="'m'+col.mIdx" :label="col.metricName+(col.unit?'('+col.unit+')':'')" width="85" align="center">
|
||||
<template slot-scope="s">{{ s.row['mv'+col.mIdx]!=null ? s.row['mv'+col.mIdx] : '-' }}</template>
|
||||
<template slot-scope="s"><span v-if="s.row.$isSummary" class="summary-val">{{ s.row['mv'+col.mIdx]!=null ? s.row['mv'+col.mIdx] : '-' }}</span><template v-else>{{ s.row['mv'+col.mIdx]!=null ? s.row['mv'+col.mIdx] : '-' }}</template></template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.$type==='metric' && col.isShift" :key="'ms'+col.mIdx" :label="col.metricName+(col.unit?'('+col.unit+')':'')" width="95" align="center">
|
||||
<template slot-scope="s">
|
||||
<div class="shift-metric">甲 {{ s.row['mv'+col.mIdx+'_1']!=null ? s.row['mv'+col.mIdx+'_1'] : '-' }}</div>
|
||||
<div class="shift-metric">乙 {{ s.row['mv'+col.mIdx+'_2']!=null ? s.row['mv'+col.mIdx+'_2'] : '-' }}</div>
|
||||
<template v-if="s.row.$isSummary">
|
||||
<div class="shift-metric"><span class="summary-val">甲 {{ s.row['mv'+col.mIdx+'_1']!=null ? s.row['mv'+col.mIdx+'_1'] : '-' }}</span></div>
|
||||
<div class="shift-metric"><span class="summary-val">乙 {{ s.row['mv'+col.mIdx+'_2']!=null ? s.row['mv'+col.mIdx+'_2'] : '-' }}</span></div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="shift-metric">甲 {{ s.row['mv'+col.mIdx+'_1']!=null ? s.row['mv'+col.mIdx+'_1'] : '-' }}</div>
|
||||
<div class="shift-metric">乙 {{ s.row['mv'+col.mIdx+'_2']!=null ? s.row['mv'+col.mIdx+'_2'] : '-' }}</div>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
@@ -82,7 +95,7 @@
|
||||
<!-- <el-button size="mini" type="text" style="padding:0 2px;font-size:11px" @click="saveRow(s.row)">保存</el-button>
|
||||
<el-button size="mini" type="text" style="padding:0 2px;font-size:11px" @click="fetchRow(s.row)">抓取</el-button>
|
||||
<el-button size="mini" type="text" style="padding:0 2px;font-size:11px;color:#67c23a" @click="backfillRow(s.row)">反填</el-button> -->
|
||||
<el-button size="mini" type="text" style="padding:0 2px;font-size:11px;color:#f56c6c" @click="gridRows.splice(s.$index,1)">删除</el-button>
|
||||
<el-button v-if="!s.row.$isSummary" size="mini" type="text" style="padding:0 2px;font-size:11px;color:#f56c6c" @click="gridRows.splice(s.$index - summaryRows.length,1)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -494,6 +507,74 @@ export default {
|
||||
})
|
||||
return col && col.color ? { background: col.color, color: '#fff' } : {}
|
||||
}
|
||||
},
|
||||
summaryRows() {
|
||||
const rows = this.gridRows.filter(r => r.detailDate)
|
||||
if (!rows.length) return []
|
||||
const detailCols = this.allCols.filter(c => c.$type === 'detail')
|
||||
const metricCols = this.allCols.filter(c => c.$type === 'metric')
|
||||
const rp = this.activeReport || {}
|
||||
const esc = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
const evalF = (f) => { const s = f.replace(/[^0-9+\-*/.()\s]/g,''); if(!s) return null; try { const r = new Function('return ('+s+')')(); return isFinite(r)?(Math.round(r*100)/100).toFixed(2):null } catch(e){ return null } }
|
||||
const calc = (type) => {
|
||||
const row = { detailDate: type === 'sum' ? '总和' : '平均', $isSummary: true, $summaryType: type }
|
||||
const n = rows.length || 1
|
||||
detailCols.forEach(col => {
|
||||
if (col.isShift) {
|
||||
const s1 = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId + '_1']) || 0), 0)
|
||||
const s2 = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId + '_2']) || 0), 0)
|
||||
row['q' + col.itemId + '_1'] = type === 'sum' ? s1.toFixed(2) : (s1 / n).toFixed(2)
|
||||
row['q' + col.itemId + '_2'] = type === 'sum' ? s2.toFixed(2) : (s2 / n).toFixed(2)
|
||||
row['q' + col.itemId] = type === 'sum' ? (s1 + s2).toFixed(2) : ((s1 + s2) / n).toFixed(2)
|
||||
} else {
|
||||
const s = rows.reduce((a, r) => a + (parseFloat(r['q' + col.itemId]) || 0), 0)
|
||||
row['q' + col.itemId] = type === 'sum' ? s.toFixed(2) : (s / n).toFixed(2)
|
||||
}
|
||||
})
|
||||
metricCols.forEach((m, mi) => {
|
||||
if (!m.metricFormula) {
|
||||
if (m.isShift) { row['mv'+m.mIdx+'_1'] = null; row['mv'+m.mIdx+'_2'] = null }
|
||||
else row['mv'+m.mIdx] = null
|
||||
return
|
||||
}
|
||||
const ef = (shiftId) => {
|
||||
let f = m.metricFormula
|
||||
for (let pmi = 0; pmi < mi; pmi++) {
|
||||
const pm = metricCols[pmi]; if (!pm.metricName) continue
|
||||
const pn = esc(pm.metricName)
|
||||
if (pm.isShift) {
|
||||
const pv1 = row['mv'+pm.mIdx+'_1']; const pv2 = row['mv'+pm.mIdx+'_2']
|
||||
if (pv1 != null) f = f.replace(new RegExp('@\\{'+pn+'\\}\\.甲班','g'), pv1)
|
||||
if (pv2 != null) f = f.replace(new RegExp('@\\{'+pn+'\\}\\.乙班','g'), pv2)
|
||||
}
|
||||
const pv = pm.isShift ? (shiftId ? row['mv'+pm.mIdx+'_'+shiftId] : null) : row['mv'+pm.mIdx]
|
||||
if (pv != null) f = f.replace(new RegExp('@\\{'+pn+'\\}','g'), pv)
|
||||
}
|
||||
detailCols.forEach(c => {
|
||||
const item = this.allItems.find(i => String(i.itemId) === String(c.itemId))
|
||||
if (!item || !item.itemCode) return; const code = item.itemCode
|
||||
if (c.isShift) {
|
||||
const v1 = parseFloat(row['q'+c.itemId+'_1'])||0; const v2 = parseFloat(row['q'+c.itemId+'_2'])||0
|
||||
f = f.replace(new RegExp('@\\{'+code+'\\}\\.甲班','g'), v1).replace(new RegExp('@\\{'+code+'\\}\\.乙班','g'), v2)
|
||||
const v = shiftId ? (shiftId==='1'?v1:v2) : v1+v2
|
||||
f = f.replace(new RegExp('@\\{'+code+'\\}','g'), v)
|
||||
} else {
|
||||
const v = parseFloat(row['q'+c.itemId])||0
|
||||
f = f.replace(new RegExp('@\\{'+code+'\\}\\.甲班','g'), v).replace(new RegExp('@\\{'+code+'\\}\\.乙班','g'), v).replace(new RegExp('@\\{'+code+'\\}','g'), v)
|
||||
}
|
||||
})
|
||||
f = f.replace(/input_weight/g, rp.inputWeight||0).replace(/output_weight/g, rp.outputWeight||0).replace(/price/g, (m.usePrice == 1) ? (m.metricValue || 0) : 0)
|
||||
return evalF(f)
|
||||
}
|
||||
if (m.isShift) { row['mv'+m.mIdx+'_1']=ef('1'); row['mv'+m.mIdx+'_2']=ef('2') }
|
||||
else row['mv'+m.mIdx]=ef(null)
|
||||
})
|
||||
return row
|
||||
}
|
||||
return [calc('sum'), calc('avg')]
|
||||
},
|
||||
tableData() {
|
||||
return [...this.summaryRows, ...this.gridRows]
|
||||
}
|
||||
},
|
||||
watch: { configOpen(v) { if (!v) this.rpOpen = false } },
|
||||
@@ -509,6 +590,10 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rowClassName({ row }) {
|
||||
if (row.$isSummary) return 'summary-row'
|
||||
return ''
|
||||
},
|
||||
/* report */
|
||||
getList() {
|
||||
this.loading = true
|
||||
@@ -1142,4 +1227,8 @@ export default {
|
||||
.ica-backfill { color: #67c23a; margin-right: 1px; }
|
||||
.ica:hover { opacity: 0.7; }
|
||||
/deep/ .anomaly-input .el-input__inner { background: #fef0f0 !important; border-color: #f56c6c !important; }
|
||||
/deep/ .summary-row td { background: #f0f7ff !important; font-weight: bold; }
|
||||
/deep/ .summary-row td .cell { color: #303133; }
|
||||
.summary-label { font-weight: bold; color: #303133; padding: 0 5px; }
|
||||
.summary-val { font-weight: bold; color: #303133; }
|
||||
</style>
|
||||
|
||||
@@ -90,19 +90,19 @@
|
||||
</div>
|
||||
|
||||
<el-tabs v-model="activeTab" class="pd-tabs">
|
||||
<el-tab-pane label="采购要求" name="items">
|
||||
<el-table :data="current.items" border size="mini" max-height="420">
|
||||
<el-tab-pane label="采购与到货" name="all">
|
||||
<div class="pd-sec-title">采购要求</div>
|
||||
<el-table :data="current.items" border size="mini" max-height="300">
|
||||
<el-table-column label="#" type="index" width="44" align="center" />
|
||||
<el-table-column label="规格" prop="spec" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="总重量(T)" prop="weight" min-width="110" align="right" />
|
||||
<el-table-column label="厂商" prop="manufacturer" min-width="180" show-overflow-tooltip />
|
||||
<template slot="empty"><span>无采购要求</span></template>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="'到货明细(' + deliveryList.length + ')'" name="delivery">
|
||||
<div class="pd-sec-title" style="margin-top:16px">到货明细({{ deliveryList.length }})</div>
|
||||
<el-table
|
||||
:data="deliveryList" border stripe size="mini" max-height="420"
|
||||
:data="deliveryList" border stripe size="mini" max-height="300"
|
||||
v-loading="deliveryLoading" :row-class-name="rowClass"
|
||||
>
|
||||
<el-table-column label="日期" prop="arrivalDate" width="100" align="center" />
|
||||
@@ -121,6 +121,32 @@
|
||||
<template slot="empty"><span>暂无到货记录,点右上角「上传到货表格」</span></template>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="'关联合同(' + (current.contractInfos ? current.contractInfos.length : 0) + ')'" name="contracts">
|
||||
<el-table :data="current.contractInfos" border size="mini" max-height="420" style="width:100%">
|
||||
<el-table-column label="订单编号" prop="orderCode" width="150" show-overflow-tooltip fixed />
|
||||
<el-table-column label="合同号" prop="contractCode" width="140" show-overflow-tooltip />
|
||||
<el-table-column label="合同名称" prop="contractName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="客户(需方)" prop="customer" width="130" show-overflow-tooltip />
|
||||
<el-table-column label="供方" prop="supplier" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="金额" prop="orderAmount" width="110" align="right" />
|
||||
<el-table-column label="销售员" prop="salesman" width="80" />
|
||||
<el-table-column label="签订时间" prop="signTime" width="105" align="center" />
|
||||
<el-table-column label="签订地点" prop="signLocation" width="110" show-overflow-tooltip />
|
||||
<el-table-column label="交货日期" prop="deliveryDate" width="105" align="center" />
|
||||
<el-table-column label="合同状态" width="90" align="center">
|
||||
<template slot-scope="s">{{ contractStatusText(s.row.status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应付定金" prop="depositPayable" width="100" align="right" />
|
||||
<el-table-column label="已付定金" prop="depositPaid" width="100" align="right" />
|
||||
<el-table-column label="未结款" prop="unpaidAmount" width="100" align="right" />
|
||||
<el-table-column label="产品内容" prop="productContent" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="供方电话" prop="supplierPhone" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="需方电话" prop="customerPhone" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="备注" prop="remark" min-width="150" show-overflow-tooltip />
|
||||
<template slot="empty"><span>无关联合同</span></template>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</section>
|
||||
@@ -146,7 +172,7 @@ export default {
|
||||
planList: [],
|
||||
queryParams: { pageNum: 1, pageSize: 20, keyword: undefined },
|
||||
current: {},
|
||||
activeTab: 'items',
|
||||
activeTab: 'all',
|
||||
deliveryList: [],
|
||||
deliveryLoading: false,
|
||||
refreshing: false,
|
||||
@@ -180,10 +206,12 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
selectPlan(p) {
|
||||
this.activeTab = 'items'
|
||||
this.activeTab = 'all'
|
||||
this.current = { ...p }
|
||||
this.deliveryList = []
|
||||
// 打开即静默按钢卷表复核一次到货状态
|
||||
// 立即加载详情,不等待 WMS 刷新
|
||||
this.refreshDetail()
|
||||
// 后台静默按钢卷表复核一次到货状态
|
||||
const planId = p.planId
|
||||
refreshArrival(planId).catch(() => {}).finally(() => {
|
||||
if (this.current.planId === planId) this.refreshDetail()
|
||||
@@ -212,13 +240,11 @@ export default {
|
||||
},
|
||||
statusText(row) {
|
||||
if (row.arrived === 1) return '已到货'
|
||||
if (row.inTransit === 1) return '在途'
|
||||
return '未到'
|
||||
return '在途'
|
||||
},
|
||||
statusClass(row) {
|
||||
if (row.arrived === 1) return 'yes'
|
||||
if (row.inTransit === 1) return 'transit'
|
||||
return 'no'
|
||||
return 'transit'
|
||||
},
|
||||
handleUploadSuccess(res) {
|
||||
if (res.code === 200) {
|
||||
@@ -228,7 +254,7 @@ export default {
|
||||
} else {
|
||||
this.$modal.msgSuccess(res.msg || '导入成功')
|
||||
}
|
||||
this.activeTab = 'delivery'
|
||||
this.activeTab = 'all'
|
||||
this.refreshDetail()
|
||||
this.getList(true)
|
||||
} else {
|
||||
@@ -240,6 +266,9 @@ export default {
|
||||
},
|
||||
fmt(v) {
|
||||
return Number(v || 0).toLocaleString('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 3 })
|
||||
},
|
||||
contractStatusText(v) {
|
||||
return { 0: '草稿', 1: '生效', 2: '作废', 3: '已完成' }[v] || '—'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,6 +321,10 @@ $sub: #909399;
|
||||
&.wide { grid-column: span 2; }
|
||||
}
|
||||
.pd-tabs { padding: 0 18px 18px; }
|
||||
.pd-sec-title {
|
||||
font-size: 13px; font-weight: 600; color: $ink;
|
||||
border-left: 3px solid $accent; padding-left: 8px; margin-bottom: 10px;
|
||||
}
|
||||
.pd-mtag {
|
||||
font-size: 11px; line-height: 16px; padding: 0 6px; border-radius: 2px; border: 1px solid #dcdfe6; color: $sub;
|
||||
&.yes { color: #3a8a4d; border-color: #b7d9bf; background: #f0f9f1; }
|
||||
|
||||
@@ -218,6 +218,31 @@
|
||||
<template slot="empty"><span>无采购要求</span></template>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'关联合同(' + (current.contractInfos ? current.contractInfos.length : 0) + ')'" name="contracts">
|
||||
<el-table :data="current.contractInfos" border size="mini" max-height="340" style="width:100%">
|
||||
<el-table-column label="订单编号" prop="orderCode" width="150" show-overflow-tooltip fixed />
|
||||
<el-table-column label="合同号" prop="contractCode" width="140" show-overflow-tooltip />
|
||||
<el-table-column label="合同名称" prop="contractName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="客户(需方)" prop="customer" width="130" show-overflow-tooltip />
|
||||
<el-table-column label="供方" prop="supplier" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="金额" prop="orderAmount" width="110" align="right" />
|
||||
<el-table-column label="销售员" prop="salesman" width="80" />
|
||||
<el-table-column label="签订时间" prop="signTime" width="105" align="center" />
|
||||
<el-table-column label="签订地点" prop="signLocation" width="110" show-overflow-tooltip />
|
||||
<el-table-column label="交货日期" prop="deliveryDate" width="105" align="center" />
|
||||
<el-table-column label="合同状态" width="90" align="center">
|
||||
<template slot-scope="s">{{ contractStatusText(s.row.status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="应付定金" prop="depositPayable" width="100" align="right" />
|
||||
<el-table-column label="已付定金" prop="depositPaid" width="100" align="right" />
|
||||
<el-table-column label="未结款" prop="unpaidAmount" width="100" align="right" />
|
||||
<el-table-column label="产品内容" prop="productContent" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="供方电话" prop="supplierPhone" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="需方电话" prop="customerPhone" width="120" show-overflow-tooltip />
|
||||
<el-table-column label="备注" prop="remark" min-width="150" show-overflow-tooltip />
|
||||
<template slot="empty"><span>无关联合同</span></template>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</section>
|
||||
@@ -555,6 +580,9 @@ export default {
|
||||
},
|
||||
auditText(s) {
|
||||
return { '0': '待审核', '1': '已通过', '2': '已驳回', '3': '待送审' }[s] || '—'
|
||||
},
|
||||
contractStatusText(v) {
|
||||
return { 0: '草稿', 1: '生效', 2: '作废', 3: '已完成' }[v] || '—'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +69,8 @@
|
||||
<!-- 待提交:提交送审 -->
|
||||
<el-button v-if="currentRow.flowStatus === 1" size="mini" type="primary" plain icon="el-icon-s-promotion"
|
||||
@click="handleSubmit" v-hasPermi="['qc:qualityReview:submit']">提交送审</el-button>
|
||||
<!-- 待审批:审批/驳回 -->
|
||||
<el-button v-if="currentRow.flowStatus === 2" size="mini" type="success" plain icon="el-icon-check"
|
||||
@click="handleApprove" v-hasPermi="['qc:qualityReview:approve']">审批通过</el-button>
|
||||
<el-button v-if="currentRow.flowStatus === 2" size="mini" type="danger" plain icon="el-icon-close"
|
||||
@click="handleReject" v-hasPermi="['qc:qualityReview:approve']">驳回</el-button>
|
||||
<!-- 已通过:执行改判 -->
|
||||
<el-button v-if="currentRow.flowStatus === 3" size="mini" type="warning" plain icon="el-icon-setting"
|
||||
@click="handleExecute" v-hasPermi="['qc:qualityReview:execute']">执行改判</el-button>
|
||||
<!-- 待审批:审批/驳回表单在下方展示,顶部不再重复放置操作按钮 -->
|
||||
<!-- 已通过:审批通过时已直接执行改判,无需额外操作 -->
|
||||
<!-- 已驳回:重新提交 -->
|
||||
<el-button v-if="currentRow.flowStatus === 4" size="mini" type="primary" plain icon="el-icon-s-promotion"
|
||||
@click="handleReSubmit" v-hasPermi="['qc:qualityReview:submit']">重新提交</el-button>
|
||||
@@ -109,9 +103,6 @@
|
||||
<el-col :span="8">
|
||||
<el-form-item label="传递日期">{{ currentRow.transmitDate }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="生产日期">{{ currentRow.prodDateRange }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@@ -145,15 +136,7 @@
|
||||
<!-- ===== 品质部评审意见 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-edit-outline"></i> 品质部评审意见</span></div>
|
||||
<div v-if="currentRow.flowStatus === 1 || currentRow.flowStatus === 4" class="section-editor">
|
||||
<el-input type="textarea" :rows="3" v-model="opinionForm.deptOpinion" placeholder="请填写品质部评审意见..." />
|
||||
<div style="margin-top:8px; display:flex; gap:8px;">
|
||||
<el-input v-model="opinionForm.deptSign" placeholder="签字人" style="width:160px;" size="small" />
|
||||
<el-date-picker v-model="opinionForm.deptSignDate" type="date" placeholder="签字日期" size="small" />
|
||||
</div>
|
||||
<el-button size="small" type="primary" @click="saveOpinion" style="margin-top:8px;">保存意见</el-button>
|
||||
</div>
|
||||
<div v-else class="section-display">
|
||||
<div class="section-display">
|
||||
<div class="opinion-text">{{ currentRow.deptOpinion || '暂未填写' }}</div>
|
||||
<div class="opinion-footer" v-if="currentRow.deptOpinion">
|
||||
<span>签字:{{ currentRow.deptSign || '-' }}</span>
|
||||
@@ -165,34 +148,51 @@
|
||||
<!-- ===== 领导审批意见 ===== -->
|
||||
<el-card class="detail-section" shadow="never">
|
||||
<div slot="header"><span><i class="el-icon-s-check"></i> 领导审批意见</span></div>
|
||||
<!-- flowStatus=2时显示审批表单,权限由后端API控制,前端不做限制 -->
|
||||
<!-- flowStatus=2时显示审批表单(创建时已填好内容,领导仅确认/驳回) -->
|
||||
<div v-if="currentRow.flowStatus === 2" class="section-editor">
|
||||
<!-- 审批通过模式 -->
|
||||
<el-radio-group v-model="approveAction" style="margin-bottom:12px;">
|
||||
<el-radio-button label="approve">通过</el-radio-button>
|
||||
<el-radio-button label="reject">驳回</el-radio-button>
|
||||
</el-radio-group>
|
||||
<!-- 领导意见(只读展示) -->
|
||||
<div class="approve-opinion-box">
|
||||
<label>领导审批意见:</label>
|
||||
<div class="opinion-content">{{ currentRow.leaderOpinion || '暂未填写' }}</div>
|
||||
<div class="opinion-footer" v-if="currentRow.leaderOpinion">
|
||||
<span>签字:{{ currentRow.leaderSign || '-' }}</span>
|
||||
<span>日期:{{ currentRow.leaderSignDate || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="approveAction === 'approve'">
|
||||
<el-input type="textarea" :rows="3" v-model="approveForm.leaderOpinion" placeholder="请输入领导审批意见..." />
|
||||
<div style="margin:8px 0;">
|
||||
<el-input v-model="approveForm.leaderSign" placeholder="签字人" style="width:160px;" size="small" />
|
||||
<!-- 各钢卷改判后等级(只读展示) -->
|
||||
<div class="approve-coil-section">
|
||||
<div class="approve-coil-title">各钢卷改判后质量状态:</div>
|
||||
<el-table :data="coilList" size="small" border max-height="300">
|
||||
<el-table-column prop="currentCoilNo" label="产品卷号" width="140" />
|
||||
<el-table-column prop="spec" label="规格(mm)" width="100" />
|
||||
<el-table-column prop="defectDesc" label="缺陷描述" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="beforeQuality" label="当前等级" width="80" align="center">
|
||||
<template slot-scope="s"><el-tag size="mini" type="danger">{{ s.row.beforeQuality }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="regradeQuality" label="改判后等级" width="110" align="center">
|
||||
<template slot-scope="s"><el-tag size="mini" type="warning">{{ s.row.regradeQuality }}</el-tag></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="approve-actions">
|
||||
<el-radio-group v-model="approveAction" size="small">
|
||||
<el-radio-button label="approve">通过</el-radio-button>
|
||||
<el-radio-button label="reject">驳回</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="approve-action-body">
|
||||
<template v-if="approveAction === 'approve'">
|
||||
<p class="approve-hint">确认审批通过后将直接执行改判,钢卷质量状态和库区将同步更新</p>
|
||||
<el-button type="success" @click="doApprove" :size="'small'" icon="el-icon-check" round>确认通过</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input type="textarea" :rows="2" v-model="rejectReason" placeholder="请输入驳回原因..." style="margin-bottom:8px;" />
|
||||
<el-button type="danger" @click="doReject" :size="'small'" icon="el-icon-close" round>确认驳回</el-button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="approve-coil-section">
|
||||
<div class="approve-coil-title">请为每个钢卷指定改判后质量状态:</div>
|
||||
<div v-for="coil in coilList" :key="coil.detailId" class="approve-coil-row">
|
||||
<span class="approve-coil-label">{{ coil.currentCoilNo }}({{ coil.spec }})</span>
|
||||
<el-select v-model="approveCoilMap[coil.detailId]" placeholder="请选择改判后等级" size="small" style="width:180px;">
|
||||
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="small" type="success" @click="doApprove">确认通过</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input type="textarea" :rows="3" v-model="rejectReason" placeholder="请输入驳回原因..." />
|
||||
<el-button size="small" type="danger" @click="doReject" style="margin-top:8px;">确认驳回</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="section-display">
|
||||
<div class="opinion-text">{{ currentRow.leaderOpinion || '暂无审批意见' }}</div>
|
||||
@@ -228,8 +228,14 @@
|
||||
</div>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="900px" :close-on-click-modal="false" append-to-body>
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="960px" :close-on-click-modal="false" append-to-body class="review-dialog">
|
||||
<el-form ref="form" :model="editForm" :rules="rules" label-width="100px" size="small">
|
||||
<!-- ===== 基本信息 ===== -->
|
||||
<div class="dialog-section">
|
||||
<div class="dialog-section-header">
|
||||
<i class="el-icon-info"></i>
|
||||
<span>基本信息</span>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
@@ -243,23 +249,20 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="传递人" prop="transmitUser">
|
||||
<el-input v-model="editForm.transmitUser" />
|
||||
<el-input v-model="editForm.transmitUser" placeholder="填写传递人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="传递日期" prop="transmitDate">
|
||||
<el-date-picker v-model="editForm.transmitDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="生产日期" prop="prodDateRange">
|
||||
<el-input v-model="editForm.prodDateRange" placeholder="如:14-15" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ===== 钢卷选择 ===== -->
|
||||
<div class="dialog-section">
|
||||
<div class="dialog-section-header">
|
||||
@@ -276,13 +279,23 @@
|
||||
<el-input v-model="scope.row.defectDesc" size="mini" placeholder="输入缺陷描述" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="regradeQuality" label="改判后等级" min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.regradeQuality" placeholder="请选择" size="mini">
|
||||
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="60" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="editForm.coilList.splice(scope.$index, 1)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="editForm.coilList.length === 0" class="dialog-table-empty" style="cursor:pointer;" @click="showCoilSelector = true">请选择O级钢卷</div>
|
||||
<div v-if="editForm.coilList.length === 0" class="dialog-table-empty" @click="showCoilSelector = true">
|
||||
<i class="el-icon-circle-plus-outline"></i>
|
||||
<span>点击选择O级钢卷</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 钢卷选择器(嵌套在弹窗内) ===== -->
|
||||
@@ -292,31 +305,63 @@
|
||||
:filters="{ qualityStatusCsv: 'O', status: 0 }"
|
||||
@confirm="onDialogCoilConfirm" />
|
||||
|
||||
<el-divider />
|
||||
<!-- ===== 品质部评审 ===== -->
|
||||
<div class="dialog-section">
|
||||
<div class="dialog-section-header">
|
||||
<i class="el-icon-edit-outline"></i>
|
||||
<span>品质部评审意见</span>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="评审意见" prop="deptOpinion">
|
||||
<el-input type="textarea" :rows="3" v-model="editForm.deptOpinion" placeholder="请填写品质部评审意见" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="签字人">
|
||||
<el-input v-model="editForm.deptSign" placeholder="签字人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="签字日期">
|
||||
<el-date-picker v-model="editForm.deptSignDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- ===== 领导审批 ===== -->
|
||||
<div class="dialog-section">
|
||||
<div class="dialog-section-header">
|
||||
<i class="el-icon-s-check"></i>
|
||||
<span>领导审批意见</span>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="品质部意见" prop="deptOpinion">
|
||||
<el-input type="textarea" :rows="3" v-model="editForm.deptOpinion" placeholder="请填写品质部评审意见" />
|
||||
<el-form-item label="审批意见" prop="leaderOpinion">
|
||||
<el-input type="textarea" :rows="3" v-model="editForm.leaderOpinion" placeholder="请填写领导审批意见" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="签字人">
|
||||
<el-input v-model="editForm.deptSign" />
|
||||
<el-input v-model="editForm.leaderSign" placeholder="领导姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="签字日期">
|
||||
<el-date-picker v-model="editForm.deptSignDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
<el-date-picker v-model="editForm.leaderSignDate" type="date" placeholder="选择日期" style="width:100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveForm">确定</el-button>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false" icon="el-icon-close">取消</el-button>
|
||||
<el-button type="primary" @click="saveForm" icon="el-icon-check">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -354,12 +399,6 @@ export default {
|
||||
// 钢卷选择
|
||||
showCoilSelector: false,
|
||||
|
||||
// 品质部意见编辑(独立于editForm,避免串数据)
|
||||
opinionForm: {
|
||||
deptOpinion: '',
|
||||
deptSign: '',
|
||||
deptSignDate: undefined
|
||||
},
|
||||
// 编辑弹窗
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
@@ -374,6 +413,9 @@ export default {
|
||||
deptOpinion: '',
|
||||
deptSign: '',
|
||||
deptSignDate: undefined,
|
||||
leaderOpinion: '',
|
||||
leaderSign: '',
|
||||
leaderSignDate: undefined,
|
||||
coilList: []
|
||||
},
|
||||
rules: {
|
||||
@@ -427,13 +469,6 @@ export default {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
// 初始化品质部意见编辑(独立于editForm)
|
||||
this.opinionForm = {
|
||||
deptOpinion: data.deptOpinion || '',
|
||||
deptSign: data.deptSign || '',
|
||||
deptSignDate: data.deptSignDate || undefined
|
||||
}
|
||||
this.approveForm.reviewId = reviewId
|
||||
this.approveForm.leaderOpinion = ''
|
||||
this.approveForm.leaderSign = ''
|
||||
this.rejectReason = ''
|
||||
@@ -460,6 +495,9 @@ export default {
|
||||
deptOpinion: '',
|
||||
deptSign: '',
|
||||
deptSignDate: undefined,
|
||||
leaderOpinion: '',
|
||||
leaderSign: '',
|
||||
leaderSignDate: undefined,
|
||||
coilList: []
|
||||
}
|
||||
this.editing = true
|
||||
@@ -477,6 +515,9 @@ export default {
|
||||
deptOpinion: row.deptOpinion,
|
||||
deptSign: row.deptSign,
|
||||
deptSignDate: row.deptSignDate,
|
||||
leaderOpinion: row.leaderOpinion || '',
|
||||
leaderSign: row.leaderSign || '',
|
||||
leaderSignDate: row.leaderSignDate || undefined,
|
||||
coilList: this.coilList.map(c => ({ ...c }))
|
||||
}
|
||||
this.editing = true
|
||||
@@ -513,6 +554,7 @@ export default {
|
||||
spec: coil.specification, // CoilSelector返回的字段名为specification
|
||||
netWeight: coil.netWeight,
|
||||
defectDesc: '',
|
||||
regradeQuality: '', // 改判后等级,由创建者填写
|
||||
groupSeq: startIdx + idx + 1,
|
||||
beforeQuality: coil.qualityStatus || 'O'
|
||||
}))
|
||||
@@ -541,50 +583,14 @@ export default {
|
||||
},
|
||||
|
||||
// ===== 审批 =====
|
||||
handleApprove() {
|
||||
this.approveAction = 'approve'
|
||||
this.approveForm = {
|
||||
reviewId: this.currentRow.reviewId,
|
||||
leaderOpinion: '',
|
||||
leaderSign: ''
|
||||
}
|
||||
// 先构建完整对象再赋值
|
||||
const map = {}
|
||||
this.coilList.forEach(c => {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
},
|
||||
doApprove() {
|
||||
if (!this.approveForm.leaderOpinion) {
|
||||
this.$modal.msgError('请输入审批意见')
|
||||
return
|
||||
}
|
||||
const coilRegradeList = this.coilList.map(c => ({
|
||||
detailId: c.detailId,
|
||||
regradeQuality: this.approveCoilMap[c.detailId]
|
||||
}))
|
||||
const invalid = coilRegradeList.some(r => !r.regradeQuality)
|
||||
if (invalid) {
|
||||
this.$modal.msgError('请为每个钢卷指定改判后质量状态')
|
||||
return
|
||||
}
|
||||
this.$confirm('确认审批通过?', '提示', { type: 'success' }).then(() => {
|
||||
approveQualityReview({
|
||||
reviewId: this.currentRow.reviewId,
|
||||
leaderOpinion: this.approveForm.leaderOpinion,
|
||||
leaderSign: this.approveForm.leaderSign,
|
||||
coilRegradeList
|
||||
}).then(() => {
|
||||
this.$confirm('确认审批通过?审批后将直接执行改判,钢卷质量状态将同步更新。', '提示', { type: 'success' }).then(() => {
|
||||
approveQualityReview(this.currentRow.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('审批通过')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
handleReject() {
|
||||
this.approveAction = 'reject'
|
||||
this.rejectReason = ''
|
||||
},
|
||||
doReject() {
|
||||
if (!this.rejectReason) {
|
||||
this.$modal.msgError('请输入驳回原因')
|
||||
@@ -627,20 +633,8 @@ export default {
|
||||
hasPermi(permi) {
|
||||
return this.$store.getters.permissions && this.$store.getters.permissions.includes(permi)
|
||||
},
|
||||
saveOpinion() {
|
||||
if (!this.currentRow) return
|
||||
updateQualityReview({
|
||||
reviewId: this.currentRow.reviewId,
|
||||
deptOpinion: this.opinionForm.deptOpinion,
|
||||
deptSign: this.opinionForm.deptSign,
|
||||
deptSignDate: this.opinionForm.deptSignDate
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess('保存成功')
|
||||
this.handleRefreshDetail()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -804,6 +798,20 @@ export default {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.approve-actions {
|
||||
background: #fafafa;
|
||||
border-radius: 4px;
|
||||
padding: 16px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.approve-actions .approve-action-body {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.approve-actions .approve-hint {
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
}
|
||||
.text-muted { color: #c0c4cc; }
|
||||
.timeline-opinion {
|
||||
font-size: 13px;
|
||||
|
||||
@@ -44,22 +44,28 @@
|
||||
</el-radio-group>
|
||||
|
||||
<template v-if="approveAction === 'approve'">
|
||||
<el-input type="textarea" :rows="3" v-model="approveForm.leaderOpinion" placeholder="请输入领导审批意见..." style="margin-bottom:12px;" />
|
||||
<el-input v-model="approveForm.leaderSign" placeholder="签字人" style="width:160px; margin-bottom:12px;" size="small" />
|
||||
<!-- 领导意见(只读展示) -->
|
||||
<div class="approve-opinion-box">
|
||||
<label>领导审批意见:</label>
|
||||
<div class="opinion-content">{{ approveDialog.review.leaderOpinion || '暂未填写' }}</div>
|
||||
<div class="opinion-footer" v-if="approveDialog.review.leaderOpinion">
|
||||
<span>签字:{{ approveDialog.review.leaderSign || '-' }}</span>
|
||||
<span>日期:{{ approveDialog.review.leaderSignDate || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 各钢卷改判后等级(只读展示) -->
|
||||
<div class="coil-regrade-section">
|
||||
<div class="coil-regrade-title">请为以下钢卷指定改判后质量状态:</div>
|
||||
<div class="coil-regrade-title">各钢卷改判后质量状态:</div>
|
||||
<el-table :data="approveCoilList" size="small" border max-height="300">
|
||||
<el-table-column prop="currentCoilNo" label="产品卷号" width="140" />
|
||||
<el-table-column prop="spec" label="规格" width="100" />
|
||||
<el-table-column prop="beforeQuality" label="当前等级" width="80">
|
||||
<el-table-column prop="defectDesc" label="缺陷描述" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="beforeQuality" label="当前等级" width="80" align="center">
|
||||
<template slot-scope="s"><el-tag size="mini" type="danger">{{ s.row.beforeQuality }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="改判后状态" width="160">
|
||||
<template slot-scope="s">
|
||||
<el-select v-model="approveCoilMap[s.row.detailId]" placeholder="请选择" size="small">
|
||||
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
<el-table-column prop="regradeQuality" label="改判后等级" width="110" align="center">
|
||||
<template slot-scope="s"><el-tag size="mini" type="warning">{{ s.row.regradeQuality }}</el-tag></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
@@ -97,13 +103,7 @@ export default {
|
||||
review: null
|
||||
},
|
||||
approveAction: 'approve',
|
||||
approveForm: {
|
||||
reviewId: undefined,
|
||||
leaderOpinion: '',
|
||||
leaderSign: ''
|
||||
},
|
||||
approveCoilList: [],
|
||||
approveCoilMap: {},
|
||||
approveLoading: false,
|
||||
rejectReason: ''
|
||||
}
|
||||
@@ -126,19 +126,13 @@ export default {
|
||||
handleQuickApprove(row) {
|
||||
this.approveAction = 'approve'
|
||||
this.approveDialog.review = row
|
||||
this.approveForm = { reviewId: row.reviewId, leaderOpinion: '', leaderSign: '' }
|
||||
this.rejectReason = ''
|
||||
this.approveDialog.visible = true
|
||||
|
||||
// 加载明细
|
||||
// 加载明细(只读展示)
|
||||
getQualityReview(row.reviewId).then(res => {
|
||||
const data = res.data
|
||||
this.approveCoilList = data.coilList || []
|
||||
const map = {}
|
||||
;(data.coilList || []).forEach(c => {
|
||||
map[c.detailId] = c.regradeQuality || ''
|
||||
})
|
||||
this.approveCoilMap = map
|
||||
})
|
||||
},
|
||||
handleQuickReject(row) {
|
||||
@@ -150,25 +144,8 @@ export default {
|
||||
}).catch(() => {})
|
||||
},
|
||||
doApprove() {
|
||||
if (!this.approveForm.leaderOpinion) {
|
||||
this.$modal.msgError('请输入审批意见')
|
||||
return
|
||||
}
|
||||
const coilRegradeList = this.approveCoilList.map(c => ({
|
||||
detailId: c.detailId,
|
||||
regradeQuality: this.approveCoilMap[c.detailId]
|
||||
}))
|
||||
if (coilRegradeList.some(r => !r.regradeQuality)) {
|
||||
this.$modal.msgError('请为每个钢卷指定改判后质量状态')
|
||||
return
|
||||
}
|
||||
this.approveLoading = true
|
||||
approveQualityReview({
|
||||
reviewId: this.approveDialog.review.reviewId,
|
||||
leaderOpinion: this.approveForm.leaderOpinion,
|
||||
leaderSign: this.approveForm.leaderSign,
|
||||
coilRegradeList
|
||||
}).then(() => {
|
||||
approveQualityReview(this.approveDialog.review.reviewId).then(() => {
|
||||
this.$modal.msgSuccess('审批通过')
|
||||
this.approveDialog.visible = false
|
||||
this.approveLoading = false
|
||||
@@ -205,6 +182,13 @@ export default {
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.opinion-footer {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.coil-regrade-section {
|
||||
margin-top: 12px;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<template slot-scope="{ row }">{{ row.CREW || row.crew || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="钢种" min-width="80" show-overflow-tooltip>
|
||||
<template slot-scope="{ row }">{{ row.ORDER_QUALITY || row.order_quality || row.GRADE || row.grade || '—' }}</template>
|
||||
<template slot-scope="{ row }">{{ row.GRADE || row.grade || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="来料厚度" width="68" align="right">
|
||||
<template slot-scope="{ row }">{{ row.ENTRY_THICK || row.entry_thick || '—' }}</template>
|
||||
|
||||
@@ -197,7 +197,7 @@ export default {
|
||||
total: 0,
|
||||
coilList: [],
|
||||
statistics: {},
|
||||
overdueDays: 20,
|
||||
overdueDays: 60,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 50,
|
||||
|
||||
@@ -163,7 +163,10 @@
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 钢卷明细表格 -->
|
||||
<h4 style="margin-top: 20px">钢卷明细</h4>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 20px">
|
||||
<h4 style="margin: 0">钢卷明细</h4>
|
||||
<el-button type="primary" size="small" icon="el-icon-download" @click="handleExportDetail">导出</el-button>
|
||||
</div>
|
||||
<el-table :data="dialogList" border stripe max-height="500" style="width: 100%">
|
||||
<el-table-column prop="enterCoilNo" label="入场钢卷号" align="center" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="currentCoilNo" label="当前钢卷号" align="center" min-width="150" show-overflow-tooltip />
|
||||
@@ -518,6 +521,15 @@ export default {
|
||||
.finally(() => { this.dialogLoading = false; });
|
||||
},
|
||||
|
||||
handleExportDetail() {
|
||||
if (!this.currentWarehouse) return;
|
||||
this.download('wms/materialCoil/export', {
|
||||
warehouseId: this.currentWarehouse.warehouseId,
|
||||
dataType: 1,
|
||||
status: 0,
|
||||
}, `钢卷明细_${this.currentWarehouse.warehouseName}_${new Date().getTime()}.xlsx`);
|
||||
},
|
||||
|
||||
// ============ 弹窗数据透视图(班组 × 品质) ============
|
||||
getQualityGroup(qs) {
|
||||
if (!qs) return '未知';
|
||||
|
||||
589
klp-ui/src/views/wms/post/aps/processes.vue
Normal file
589
klp-ui/src/views/wms/post/aps/processes.vue
Normal file
@@ -0,0 +1,589 @@
|
||||
<template>
|
||||
<div class="app-container" style="height: calc(100vh - 84px); display: flex;">
|
||||
<!-- 左侧工艺列表 -->
|
||||
<div class="left-panel" v-loading="processLoading"
|
||||
style="width: 35%; border-right: 1px solid #e4e7ed; overflow-y: auto;">
|
||||
<!-- 筛选区 -->
|
||||
<div class="filter-section" style="padding: 10px; border-bottom: 1px solid #e4e7ed;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 4px; flex-wrap: wrap;">
|
||||
<el-input v-model="queryParams.processName" placeholder="工艺名称" clearable @keyup.enter.native="handleSearch"
|
||||
style="width: 160px;" />
|
||||
<el-button class="aps-btn-red" icon="el-icon-search" size="mini" @click="handleSearch">筛选</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" class="aps-btn-silver" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<el-button class="aps-btn-red" icon="el-icon-plus" size="mini" @click="handleAddProcess">新增工艺</el-button>
|
||||
<span style="font-size: 12px; color: #909399;">
|
||||
共 <span class="aps-total-count">{{ total }}</span> 条
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<div class="custom-list">
|
||||
<div class="list-body">
|
||||
<div v-for="item in processList" :key="item.processId" class="list-item"
|
||||
:class="{ 'list-item-active': currentProcess && currentProcess.processId === item.processId }"
|
||||
@click="handleProcessClick(item)">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
|
||||
<div style="font-weight: bold; font-size: 14px;">{{ item.processName }}</div>
|
||||
<div style="display: flex; gap: 4px;">
|
||||
<el-button type="text" icon="el-icon-edit" size="mini" @click.stop="handleUpdateProcess(item)"></el-button>
|
||||
<el-button type="text" icon="el-icon-delete" size="mini" style="color: #F56C6C;" @click.stop="handleDeleteProcess(item)"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #909399; margin-bottom: 4px;">
|
||||
{{ item.processDesc || '暂无描述' }}
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #909399;">
|
||||
备注: {{ item.remark || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="processList.length === 0 && !processLoading"
|
||||
style="padding: 40px; text-align: center; color: #909399;">
|
||||
暂无工艺数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getProcessList" style="padding: 10px; margin-bottom: 10px !important;" />
|
||||
</div>
|
||||
|
||||
<!-- 右侧工艺步骤区域 -->
|
||||
<div class="right-panel" v-if="currentProcess && currentProcess.processId"
|
||||
style="flex: 1; display: flex; flex-direction: column;" v-loading="stepLoading">
|
||||
<div class="detail-panel">
|
||||
<!-- 工艺基本信息卡片 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-header">
|
||||
<span>工艺基本信息</span>
|
||||
</div>
|
||||
<div class="detail-card-body">
|
||||
<div class="form-grid-2">
|
||||
<div class="form-field"><label>工艺名称</label>
|
||||
<div class="field-value">{{ currentProcess.processName }}</div>
|
||||
</div>
|
||||
<div class="form-field"><label>工艺描述</label>
|
||||
<div class="field-value">{{ currentProcess.processDesc || '-' }}</div>
|
||||
</div>
|
||||
<div class="form-field" style="grid-column:1/3;"><label>备注</label>
|
||||
<div class="field-value">{{ currentProcess.remark || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工艺步骤卡片 -->
|
||||
<div class="detail-card">
|
||||
<div class="detail-card-header">
|
||||
<span>工艺步骤({{ stepList.length }} 步)</span>
|
||||
<el-button type="text" icon="el-icon-plus" size="mini" style="color: white;" @click="handleAddStep">新增步骤</el-button>
|
||||
</div>
|
||||
<div class="detail-card-body">
|
||||
<div v-if="stepList.length > 0" class="process-timeline-wrap">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(step, index) in stepList"
|
||||
:key="step.stepId"
|
||||
:timestamp="'步骤 ' + step.stepOrder"
|
||||
placement="top"
|
||||
:type="index === stepList.length - 1 ? 'success' : 'primary'"
|
||||
:hollow="index !== stepList.length - 1"
|
||||
size="large"
|
||||
>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-header">
|
||||
<span class="step-name">{{ step.stepName }}</span>
|
||||
<div class="step-actions">
|
||||
<el-button type="text" icon="el-icon-edit" size="mini" @click="handleUpdateStep(step)"></el-button>
|
||||
<el-button type="text" icon="el-icon-delete" size="mini" style="color: #F56C6C;" @click="handleDeleteStep(step)"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="step.remark" class="step-remark">{{ step.remark }}</div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</div>
|
||||
<el-empty v-else description="暂无工艺步骤" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else style="flex: 1; display: flex; flex-direction: column;">
|
||||
<el-empty description="选择工艺后查看步骤" />
|
||||
</div>
|
||||
|
||||
<!-- 新增/编辑工艺弹窗 -->
|
||||
<el-dialog :title="processTitle" :visible.sync="processOpen" width="500px" append-to-body>
|
||||
<el-form ref="processForm" :model="processForm" :rules="processRules" label-width="80px">
|
||||
<el-form-item label="工艺名称" prop="processName">
|
||||
<el-input v-model="processForm.processName" placeholder="请输入工艺名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="工艺描述" prop="processDesc">
|
||||
<el-input v-model="processForm.processDesc" type="textarea" :rows="3" placeholder="请输入工艺描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="processForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitProcessForm">确 定</el-button>
|
||||
<el-button @click="cancelProcess">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增/编辑工艺步骤弹窗 -->
|
||||
<el-dialog :title="stepTitle" :visible.sync="stepOpen" width="500px" append-to-body>
|
||||
<el-form ref="stepForm" :model="stepForm" :rules="stepRules" label-width="80px">
|
||||
<el-form-item label="步骤顺序" prop="stepOrder">
|
||||
<el-input-number v-model="stepForm.stepOrder" :min="1" :max="99" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="步骤名称" prop="stepName">
|
||||
<el-input v-model="stepForm.stepName" placeholder="请输入步骤名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="stepForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitStepForm">确 定</el-button>
|
||||
<el-button @click="cancelStep">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProcess, getProcess, addProcess, updateProcess, delProcess } from '@/api/aps/process'
|
||||
import { listProcessStep, addProcessStep, updateProcessStep, delProcessStep } from '@/api/aps/processStep'
|
||||
|
||||
export default {
|
||||
name: 'ApsProcesses',
|
||||
data() {
|
||||
return {
|
||||
// 工艺相关
|
||||
processLoading: false,
|
||||
processList: [],
|
||||
total: 0,
|
||||
currentProcess: null,
|
||||
queryParams: {
|
||||
processName: '',
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
processTitle: '',
|
||||
processOpen: false,
|
||||
processForm: {},
|
||||
processRules: {
|
||||
processName: [
|
||||
{ required: true, message: '工艺名称不能为空', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
// 工艺步骤相关
|
||||
stepLoading: false,
|
||||
submitLoading: false,
|
||||
stepList: [],
|
||||
stepTitle: '',
|
||||
stepOpen: false,
|
||||
stepForm: {},
|
||||
stepRules: {
|
||||
stepOrder: [
|
||||
{ required: true, message: '步骤顺序不能为空', trigger: 'blur' }
|
||||
],
|
||||
stepName: [
|
||||
{ required: true, message: '步骤名称不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getProcessList()
|
||||
},
|
||||
methods: {
|
||||
/** 查询工艺列表 */
|
||||
getProcessList() {
|
||||
this.processLoading = true
|
||||
listProcess(this.queryParams).then(res => {
|
||||
this.processList = res.rows || []
|
||||
this.total = res.total || 0
|
||||
}).catch(() => {
|
||||
this.processList = []
|
||||
this.total = 0
|
||||
}).finally(() => {
|
||||
this.processLoading = false
|
||||
})
|
||||
},
|
||||
/** 搜索 */
|
||||
handleSearch() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getProcessList()
|
||||
},
|
||||
/** 重置 */
|
||||
resetQuery() {
|
||||
this.queryParams.processName = ''
|
||||
this.handleSearch()
|
||||
},
|
||||
/** 点击工艺 */
|
||||
handleProcessClick(process) {
|
||||
this.currentProcess = process
|
||||
this.getStepList(process.processId)
|
||||
},
|
||||
/** 查询工艺步骤列表 */
|
||||
getStepList(processId) {
|
||||
this.stepLoading = true
|
||||
listProcessStep({ processId }).then(res => {
|
||||
this.stepList = res.rows || []
|
||||
}).catch(() => {
|
||||
this.stepList = []
|
||||
}).finally(() => {
|
||||
this.stepLoading = false
|
||||
})
|
||||
},
|
||||
/** 新增工艺 */
|
||||
handleAddProcess() {
|
||||
this.resetProcessForm()
|
||||
this.processTitle = '新增工艺'
|
||||
this.processOpen = true
|
||||
},
|
||||
/** 修改工艺 */
|
||||
handleUpdateProcess(row) {
|
||||
this.resetProcessForm()
|
||||
const processId = row.processId || this.currentProcess.processId
|
||||
getProcess(processId).then(res => {
|
||||
this.processForm = res.data
|
||||
this.processTitle = '修改工艺'
|
||||
this.processOpen = true
|
||||
})
|
||||
},
|
||||
/** 提交工艺表单 */
|
||||
submitProcessForm() {
|
||||
this.$refs['processForm'].validate(valid => {
|
||||
if (valid) {
|
||||
this.submitLoading = true
|
||||
if (this.processForm.processId != undefined) {
|
||||
updateProcess(this.processForm).then(response => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.processOpen = false
|
||||
this.getProcessList()
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
} else {
|
||||
addProcess(this.processForm).then(response => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.processOpen = false
|
||||
this.getProcessList()
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除工艺 */
|
||||
handleDeleteProcess(row) {
|
||||
const processIds = row.processId || this.currentProcess.processId
|
||||
this.$modal.confirm('是否确认删除该工艺?').then(() => {
|
||||
return delProcess(processIds)
|
||||
}).then(() => {
|
||||
this.getProcessList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
this.currentProcess = null
|
||||
this.stepList = []
|
||||
}).catch(() => {})
|
||||
},
|
||||
/** 取消工艺弹窗 */
|
||||
cancelProcess() {
|
||||
this.processOpen = false
|
||||
this.resetProcessForm()
|
||||
},
|
||||
/** 重置工艺表单 */
|
||||
resetProcessForm() {
|
||||
this.processForm = {
|
||||
processId: undefined,
|
||||
processName: undefined,
|
||||
processDesc: undefined,
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('processForm')
|
||||
},
|
||||
/** 新增步骤 */
|
||||
handleAddStep() {
|
||||
this.resetStepForm()
|
||||
this.stepForm.processId = this.currentProcess.processId
|
||||
// 自动计算下一步骤顺序
|
||||
if (this.stepList.length > 0) {
|
||||
const maxOrder = Math.max(...this.stepList.map(s => s.stepOrder || 0))
|
||||
this.stepForm.stepOrder = maxOrder + 1
|
||||
} else {
|
||||
this.stepForm.stepOrder = 1
|
||||
}
|
||||
this.stepTitle = '新增工艺步骤'
|
||||
this.stepOpen = true
|
||||
},
|
||||
/** 修改步骤 */
|
||||
handleUpdateStep(row) {
|
||||
this.resetStepForm()
|
||||
this.stepForm = { ...row }
|
||||
this.stepTitle = '修改工艺步骤'
|
||||
this.stepOpen = true
|
||||
},
|
||||
/** 提交步骤表单 */
|
||||
submitStepForm() {
|
||||
this.$refs['stepForm'].validate(valid => {
|
||||
if (valid) {
|
||||
this.submitLoading = true
|
||||
if (this.stepForm.stepId != undefined) {
|
||||
updateProcessStep(this.stepForm).then(response => {
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.stepOpen = false
|
||||
this.getStepList(this.currentProcess.processId)
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
} else {
|
||||
addProcessStep(this.stepForm).then(response => {
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.stepOpen = false
|
||||
this.getStepList(this.currentProcess.processId)
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除步骤 */
|
||||
handleDeleteStep(row) {
|
||||
const stepIds = row.stepId
|
||||
this.$modal.confirm('是否确认删除该工艺步骤?').then(() => {
|
||||
return delProcessStep(stepIds)
|
||||
}).then(() => {
|
||||
this.getStepList(this.currentProcess.processId)
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
/** 取消步骤弹窗 */
|
||||
cancelStep() {
|
||||
this.stepOpen = false
|
||||
this.resetStepForm()
|
||||
},
|
||||
/** 重置步骤表单 */
|
||||
resetStepForm() {
|
||||
this.stepForm = {
|
||||
stepId: undefined,
|
||||
processId: undefined,
|
||||
stepOrder: undefined,
|
||||
stepName: undefined,
|
||||
remark: undefined
|
||||
}
|
||||
this.resetForm('stepForm')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './scss/aps-theme.scss';
|
||||
|
||||
.app-container {
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
height: calc(100vh - 84px);
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
height: calc(100vh - 84px);
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.custom-list {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
padding: 12px;
|
||||
border-bottom: 2px solid #dddddd;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.list-item:hover {
|
||||
background-color: $aps-silver-1;
|
||||
}
|
||||
|
||||
.list-item-active {
|
||||
background-color: $aps-red-1;
|
||||
border-left: 3px solid $aps-red-2;
|
||||
}
|
||||
|
||||
.aps-total-count {
|
||||
color: $aps-red-2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.aps-btn-red {
|
||||
@include aps-btn-red;
|
||||
}
|
||||
|
||||
.aps-btn-silver {
|
||||
@include aps-btn-silver;
|
||||
}
|
||||
|
||||
.detail-panel {
|
||||
flex: 1;
|
||||
overflow-y: scroll;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
background: $aps-bg;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: $aps-white;
|
||||
border: 1px solid $aps-border;
|
||||
border-radius: $aps-radius;
|
||||
box-shadow: $aps-shadow-sm;
|
||||
}
|
||||
|
||||
.detail-card-header {
|
||||
background: linear-gradient(to right, $aps-red-2, $aps-red-3);
|
||||
color: white;
|
||||
padding: 8px 14px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.detail-card-body {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.form-grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px 16px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.form-field label {
|
||||
font-size: 11px;
|
||||
color: $aps-text-muted;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-field .field-value {
|
||||
font-size: 13px;
|
||||
color: $aps-text;
|
||||
padding: 4px 0;
|
||||
border-bottom: 1px solid $aps-silver-mid;
|
||||
}
|
||||
|
||||
.aps-product-table {
|
||||
width: 100%;
|
||||
|
||||
::v-deep th {
|
||||
background: $aps-silver-1 !important;
|
||||
color: $aps-silver-5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ====== 工艺步骤时间线 ======
|
||||
.process-timeline-wrap {
|
||||
padding: 20px 10px;
|
||||
|
||||
::v-deep .el-timeline {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
::v-deep .el-timeline-item__wrapper {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
::v-deep .el-timeline-item__timestamp {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: $aps-text-muted;
|
||||
}
|
||||
|
||||
::v-deep .el-timeline-item__tail {
|
||||
border-left-color: $aps-silver-3;
|
||||
}
|
||||
|
||||
::v-deep .el-timeline-item__node--primary {
|
||||
background-color: $aps-red-2;
|
||||
border-color: $aps-red-2;
|
||||
}
|
||||
|
||||
::v-deep .el-timeline-item__node--success {
|
||||
background-color: #67C23A;
|
||||
border-color: #67C23A;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
background: $aps-white;
|
||||
border: 1px solid $aps-border;
|
||||
border-radius: $aps-radius;
|
||||
padding: 12px 16px;
|
||||
transition: box-shadow 0.2s, border-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
border-color: $aps-red-2;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.step-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $aps-text;
|
||||
}
|
||||
|
||||
.step-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
.timeline-content:hover & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.step-remark {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: $aps-text-muted;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed $aps-silver-3;
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="filter-section" style="padding: 10px; border-bottom: 1px solid #e4e7ed;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 4px; flex-wrap: wrap;">
|
||||
<el-input v-model="queryParams.scheduleNo" placeholder="排产单号" clearable @keyup.enter.native="handleSearch"
|
||||
<el-input v-model="queryParams.scheduleNo" placeholder="产需单号" clearable @keyup.enter.native="handleSearch"
|
||||
style="width: 130px;" size="small" />
|
||||
<el-input v-model="queryParams.customerName" placeholder="客户名" clearable
|
||||
@keyup.enter.native="handleSearch" style="width: 130px;" size="small" />
|
||||
@@ -58,15 +58,19 @@
|
||||
<div class="detail-card-header">
|
||||
<span>产需单信息</span>
|
||||
<div style="display:flex; gap:6px;">
|
||||
<button class="header-btn" :disabled="currentReq.scheduleStatus !== 0 && currentReq.scheduleStatus !== 3" @click="handleEdit(currentReq)">编辑</button>
|
||||
<button v-if="currentReq.scheduleStatus === 0 || currentReq.scheduleStatus === 3" class="header-btn" style="background:rgba(255,255,255,0.4);border-color:rgba(255,255,255,0.7);" @click="handleDispatch">{{ currentReq.scheduleStatus === 3 ? '重新下发' : '下发' }}</button>
|
||||
<button class="header-btn"
|
||||
:disabled="currentReq.scheduleStatus !== 0 && currentReq.scheduleStatus !== 3"
|
||||
@click="handleEdit(currentReq)">编辑</button>
|
||||
<button v-if="currentReq.scheduleStatus === 0 || currentReq.scheduleStatus === 3" class="header-btn"
|
||||
style="background:rgba(255,255,255,0.4);border-color:rgba(255,255,255,0.7);"
|
||||
@click="handleDispatch">{{ currentReq.scheduleStatus === 3 ? '重新下发' : '下发' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-card-body">
|
||||
<table class="req-info-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="req-td-label">排产单号</td>
|
||||
<td class="req-td-label">产需单号</td>
|
||||
<td class="req-td-value">{{ currentReq.scheduleNo }}</td>
|
||||
<td class="req-td-label">生产日期</td>
|
||||
<td class="req-td-value">{{ currentReq.prodDate }}</td>
|
||||
@@ -75,7 +79,7 @@
|
||||
<td class="req-td-label">排产状态</td>
|
||||
<td class="req-td-value"><span class="aps-status-tag"
|
||||
:class="'status-' + (currentReq.scheduleStatus || 0)">{{ statusMap[currentReq.scheduleStatus] ||
|
||||
'未知' }}</span></td>
|
||||
'未知' }}</span></td>
|
||||
<td class="req-td-label">业务员</td>
|
||||
<td class="req-td-value">{{ currentReq.businessUser }}</td>
|
||||
</tr>
|
||||
@@ -139,7 +143,8 @@
|
||||
</tr>
|
||||
<tr v-if="currentReq.returnReason">
|
||||
<td class="req-td-label" style="color:#e74c3c;">驳回原因</td>
|
||||
<td class="req-td-value" colspan="3" style="color:#e74c3c;background:#fdecea;">{{ currentReq.returnReason }}</td>
|
||||
<td class="req-td-value" colspan="3" style="color:#e74c3c;background:#fdecea;">{{
|
||||
currentReq.returnReason }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -190,8 +195,10 @@
|
||||
<el-table-column label="操作" width="130" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<span style="white-space:nowrap;">
|
||||
<el-button v-if="canEdit" type="text" size="small" style="color:#409EFF;" @click="handleDetailEdit(scope.row)">编辑</el-button>
|
||||
<el-button v-if="canEdit" type="text" size="small" style="color:#ff4d4f;" @click="handleDetailDelete(scope.row)">删除</el-button>
|
||||
<el-button v-if="canEdit" type="text" size="small" style="color:#409EFF;"
|
||||
@click="handleDetailEdit(scope.row)">编辑</el-button>
|
||||
<el-button v-if="canEdit" type="text" size="small" style="color:#ff4d4f;"
|
||||
@click="handleDetailDelete(scope.row)">删除</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -204,13 +211,15 @@
|
||||
</el-row>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="700px" append-to-body
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="900px" append-to-body
|
||||
:close-on-click-modal="false">
|
||||
<el-form ref="reqForm" :model="reqForm" :rules="reqRules" label-width="110px" size="small">
|
||||
<!-- 第一行:必填项 -->
|
||||
<div style="display: flex; gap: 16px;">
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<el-form ref="reqForm" :model="reqForm" :rules="reqRules" label-width="80px" size="small">
|
||||
<!-- 第一行:必填项 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排产单号" prop="scheduleNo">
|
||||
<el-form-item label="产需单号" prop="scheduleNo">
|
||||
<el-input v-model="reqForm.scheduleNo" placeholder="自动生成或手动填写" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -282,19 +291,42 @@
|
||||
<el-form-item label="交货重量偏差" prop="weightDeviation">
|
||||
<el-input v-model="reqForm.weightDeviation" />
|
||||
</el-form-item>
|
||||
<el-form-item label="其他技术要求" prop="otherTechReq">
|
||||
<el-input v-model="reqForm.otherTechReq" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="付款情况说明" prop="paymentDesc">
|
||||
<el-input v-model="reqForm.paymentDesc" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="其他技术要求" prop="otherTechReq">
|
||||
<el-input v-model="reqForm.otherTechReq" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="reqForm.remark" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 右侧:历史记录 -->
|
||||
<div style="width: 200px; flex-shrink: 0;" v-if="!reqForm.scheduleId && scheduleNoHistory.length > 0">
|
||||
<div style="font-size: 13px; font-weight: 600; color: #2c3e50; margin-bottom: 8px; padding-left: 8px; border-left: 3px solid #ff4d4f;">
|
||||
历史记录
|
||||
</div>
|
||||
<div style="border: 1px solid #e4e7ed; border-radius: 4px; max-height: 450px; overflow-y: auto;">
|
||||
<div v-for="item in scheduleNoHistory" :key="item.scheduleNo" class="history-item"
|
||||
@click="useHistoryRecord(item)"
|
||||
style="padding: 8px 10px; border-bottom: 1px solid #ecf0f1; cursor: pointer; font-size: 12px; transition: background 0.15s;">
|
||||
<div style="font-weight: 500; color: #2c3e50;">{{ item.scheduleNo }}</div>
|
||||
<div style="color: #7f8c8d; margin-top: 2px;">{{ item.customerName || '-' }}</div>
|
||||
<div style="color: #b0b0b0; font-size: 11px;">{{ item.prodDate || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="btnLoading" type="danger" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
@@ -376,7 +408,8 @@
|
||||
<el-input v-model="detailForm.material" placeholder="请输入材质" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排产吨数" prop="scheduleWeight">
|
||||
<el-input-number v-model="detailForm.scheduleWeight" :min="0" :precision="3" :controls="false" style="width:100%" />
|
||||
<el-input-number v-model="detailForm.scheduleWeight" :min="0" :precision="3" :controls="false"
|
||||
style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="detailForm.remark" type="textarea" :rows="2" placeholder="可选" />
|
||||
@@ -458,9 +491,10 @@ export default {
|
||||
dialogVisible: false,
|
||||
dialogTitle: '新增产需单',
|
||||
btnLoading: false,
|
||||
scheduleNoHistory: [],
|
||||
reqForm: this.getEmptyForm(),
|
||||
reqRules: {
|
||||
scheduleNo: [{ required: true, message: '排产单号不能为空', trigger: 'blur' }],
|
||||
scheduleNo: [{ required: true, message: '产需单号不能为空', trigger: 'blur' }],
|
||||
prodDate: [{ required: true, message: '生产日期不能为空', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
@@ -564,6 +598,17 @@ export default {
|
||||
|
||||
handleAdd() {
|
||||
this.resetForm()
|
||||
this.reqForm.scheduleNo = this.generateScheduleNo()
|
||||
this.reqForm.prodDate = this.getTodayStr()
|
||||
const lastForm = this.getLastFormData()
|
||||
if (lastForm) {
|
||||
Object.keys(lastForm).forEach(key => {
|
||||
if (key !== 'scheduleId' && key !== 'scheduleNo' && key !== 'prodDate' && lastForm[key] !== undefined && lastForm[key] !== '' && lastForm[key] !== null) {
|
||||
this.reqForm[key] = lastForm[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
this.scheduleNoHistory = this.getScheduleNoHistory()
|
||||
this.dialogTitle = '新增产需单'
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
@@ -586,9 +631,14 @@ export default {
|
||||
this.$refs.reqForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
const action = this.reqForm.scheduleId ? updateRequirement : addRequirement
|
||||
const isNew = !this.reqForm.scheduleId
|
||||
const action = isNew ? addRequirement : updateRequirement
|
||||
action(this.reqForm).then(() => {
|
||||
this.$modal.msgSuccess(this.reqForm.scheduleId ? '修改成功' : '新增成功')
|
||||
this.$modal.msgSuccess(isNew ? '新增成功' : '修改成功')
|
||||
if (isNew) {
|
||||
this.saveHistoryRecord(this.reqForm)
|
||||
this.saveLastFormData(this.reqForm)
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
@@ -615,6 +665,71 @@ export default {
|
||||
}).catch(() => { })
|
||||
},
|
||||
|
||||
getTodayStr() {
|
||||
return new Date().toISOString().split('T')[0]
|
||||
},
|
||||
|
||||
generateScheduleNo() {
|
||||
const now = new Date()
|
||||
const dateStr = now.getFullYear().toString() +
|
||||
(now.getMonth() + 1).toString().padStart(2, '0') +
|
||||
now.getDate().toString().padStart(2, '0')
|
||||
const prefix = 'PCXD' + dateStr
|
||||
const existingNums = this.reqList
|
||||
.filter(item => item.scheduleNo && item.scheduleNo.startsWith(prefix))
|
||||
.map(item => {
|
||||
const seq = parseInt(item.scheduleNo.substring(prefix.length), 10)
|
||||
return isNaN(seq) ? 0 : seq
|
||||
})
|
||||
const maxSeq = existingNums.length > 0 ? Math.max(...existingNums) : 0
|
||||
const newSeq = (maxSeq + 1).toString().padStart(3, '0')
|
||||
return prefix + newSeq
|
||||
},
|
||||
|
||||
getScheduleNoHistory() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('aps_requirement_history') || '[]')
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
},
|
||||
|
||||
saveHistoryRecord(formData) {
|
||||
if (!formData.scheduleNo) return
|
||||
const history = this.getScheduleNoHistory()
|
||||
const idx = history.findIndex(item => item.scheduleNo === formData.scheduleNo)
|
||||
if (idx >= 0) history.splice(idx, 1)
|
||||
history.unshift({ ...formData })
|
||||
delete history[0].scheduleId
|
||||
if (history.length > 20) history.pop()
|
||||
localStorage.setItem('aps_requirement_history', JSON.stringify(history))
|
||||
},
|
||||
|
||||
useHistoryRecord(item) {
|
||||
Object.keys(item).forEach(key => {
|
||||
if (key !== 'scheduleId' && item[key] !== undefined) {
|
||||
this.reqForm[key] = item[key]
|
||||
}
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reqForm && this.$refs.reqForm.clearValidate()
|
||||
})
|
||||
},
|
||||
|
||||
getLastFormData() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('aps_requirement_last_form') || 'null')
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
saveLastFormData(formData) {
|
||||
const data = { ...formData }
|
||||
delete data.scheduleId
|
||||
localStorage.setItem('aps_requirement_last_form', JSON.stringify(data))
|
||||
},
|
||||
|
||||
openBindDialog() {
|
||||
this.bindDialogVisible = true
|
||||
this.selectedBindOrders = []
|
||||
@@ -1223,4 +1338,8 @@ export default {
|
||||
.aps-bind-dialog ::v-deep .el-dialog__body {
|
||||
padding: 16px 20px 0 20px;
|
||||
}
|
||||
|
||||
.history-item:hover {
|
||||
background: #fdecea;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<el-button size="small" class="aps-btn-red" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||
<el-tabs v-model="activeTab" size="small" style="margin:0 0 0 16px;" @tab-click="handleQuery">
|
||||
<el-tab-pane label="待审核" name="pending" />
|
||||
<el-tab-pane label="已接收" name="accepted" />
|
||||
<el-tab-pane label="已排产" name="scheduled" />
|
||||
</el-tabs>
|
||||
<div v-if="summaryText" class="aps-sch-summary">
|
||||
@@ -161,6 +162,104 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 已接收 Tab -->
|
||||
<div v-loading="acceptedLoading" v-show="activeTab === 'accepted'" class="detail-card aps-sch-card">
|
||||
<div class="detail-card-header">
|
||||
<span>已接收产需单</span>
|
||||
<span v-if="acceptedScheduleList.length > 0" style="font-weight:normal;font-size:12px;opacity:0.8;">
|
||||
共 {{ acceptedScheduleList.length }} 个产需单
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-card-body" style="padding:0;">
|
||||
<div v-if="acceptedScheduleList.length > 0" class="aps-sch-list">
|
||||
<div v-for="sch in acceptedScheduleList" :key="sch.scheduleId" class="aps-sch-item">
|
||||
<div class="aps-sch-item-header">
|
||||
<div class="aps-sch-item-header-left">
|
||||
<span class="aps-sch-no">{{ sch.scheduleNo }}</span>
|
||||
<span class="aps-status-tag status-2">已接收</span>
|
||||
<span class="aps-sch-header-extra">
|
||||
{{ sch.customerName }} · {{ sch.businessUser }} · {{ sch.deliveryCycle }}天
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="req-info-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="req-td-label">排产单号</td><td class="req-td-value">{{ sch.scheduleNo }}</td>
|
||||
<td class="req-td-label">生产日期</td><td class="req-td-value">{{ sch.prodDate }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">业务员</td><td class="req-td-value">{{ sch.businessUser }}</td>
|
||||
<td class="req-td-label">联系电话</td><td class="req-td-value">{{ sch.businessPhone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">订货单位</td><td class="req-td-value">{{ sch.customerName }}</td>
|
||||
<td class="req-td-label">交货期(天)</td><td class="req-td-value">{{ sch.deliveryCycle }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">品名</td><td class="req-td-value" colspan="3">{{ sch.productType }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">产品用途</td><td class="req-td-value" colspan="3">{{ sch.usePurpose }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">厚度公差</td><td class="req-td-value">{{ sch.thicknessTolerance }}</td>
|
||||
<td class="req-td-label">宽度公差</td><td class="req-td-value">{{ sch.widthTolerance }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">表面质量</td><td class="req-td-value">{{ sch.surfaceQuality }}</td>
|
||||
<td class="req-td-label">表面处理</td><td class="req-td-value">{{ sch.surfaceTreatment }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">内径尺寸</td><td class="req-td-value">{{ sch.innerDiameter }}</td>
|
||||
<td class="req-td-label">外径要求</td><td class="req-td-value">{{ sch.outerDiameter }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">包装要求</td><td class="req-td-value">{{ sch.packReq }}</td>
|
||||
<td class="req-td-label">切边要求</td><td class="req-td-value">{{ sch.cutEdgeReq }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="req-td-label">单件重量</td><td class="req-td-value">{{ sch.singleCoilWeight }}</td>
|
||||
<td class="req-td-label">交货重量偏差</td><td class="req-td-value">{{ sch.weightDeviation }}</td>
|
||||
</tr>
|
||||
<tr v-if="sch.otherTechReq">
|
||||
<td class="req-td-label">其他技术要求</td><td class="req-td-value" colspan="3">{{ sch.otherTechReq }}</td>
|
||||
</tr>
|
||||
<tr v-if="sch.paymentDesc">
|
||||
<td class="req-td-label">付款情况说明</td><td class="req-td-value" colspan="3">{{ sch.paymentDesc }}</td>
|
||||
</tr>
|
||||
<tr v-if="sch.remark">
|
||||
<td class="req-td-label">备注</td><td class="req-td-value" colspan="3">{{ sch.remark }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div v-if="(sch.detailList || []).length > 0" class="aps-sch-item-details">
|
||||
<div class="aps-sch-detail-header">
|
||||
<span class="aps-sch-detail-col col-spec">规格</span>
|
||||
<span class="aps-sch-detail-col col-material">材质</span>
|
||||
<span class="aps-sch-detail-col col-weight">排产吨数</span>
|
||||
<span class="aps-sch-detail-col col-type">品名</span>
|
||||
<span class="aps-sch-detail-col col-remark">备注</span>
|
||||
</div>
|
||||
<div v-for="(d, di) in sch.detailList" :key="di" class="aps-sch-detail-row" @click="handleDetailClick(sch, d)">
|
||||
<span class="aps-sch-detail-col col-spec">{{ d.spec }}</span>
|
||||
<span class="aps-sch-detail-col col-material">{{ d.material }}</span>
|
||||
<span class="aps-sch-detail-col col-weight">{{ d.scheduleWeight }}</span>
|
||||
<span class="aps-sch-detail-col col-type">{{ sch.productType || d.productType || '' }}</span>
|
||||
<span class="aps-sch-detail-col col-remark">{{ d.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="aps-sch-item-empty">暂无明细</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="!acceptedLoading" style="padding:40px;text-align:center;color:#909399;">
|
||||
{{ hasQueried ? '该日期暂无已接收产需单' : '请选择日期查询' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 已排产 Tab -->
|
||||
<div v-loading="schLoading" v-show="activeTab === 'scheduled'" class="detail-card aps-sch-card">
|
||||
<div class="detail-card-header">
|
||||
@@ -169,85 +268,73 @@
|
||||
<span v-if="scheduledItemList.length > 0" style="font-weight:normal;font-size:12px;opacity:0.8;">
|
||||
共 {{ scheduledItemList.length }} 条
|
||||
</span>
|
||||
<span v-if="selectedItems.length >= 2" style="margin-left: auto;">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="warning"
|
||||
icon="el-icon-link"
|
||||
@click.stop="handleMergePrepare"
|
||||
>
|
||||
合并选中项 ({{ selectedItems.length }})
|
||||
</el-button>
|
||||
</span>
|
||||
<span v-else style="margin-left: auto;">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="warning"
|
||||
icon="el-icon-link"
|
||||
disabled
|
||||
>
|
||||
合并选中项
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div element-loading-text="正在加载已排产数据..." class="detail-card-body" style="padding:0;">
|
||||
<el-table
|
||||
v-if="scheduledItemList.length > 0"
|
||||
ref="scheduledTable"
|
||||
:data="scheduledItemList"
|
||||
border
|
||||
size="small"
|
||||
class="aps-table"
|
||||
:row-class-name="getItemRowClassName"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="45" align="center" />
|
||||
<el-table-column label="排产单号" prop="scheduleNo" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="生产日期" prop="prodDate" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="工序类型" prop="actionId" width="100" align="center" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ getActionIdName(scope.row.actionId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排产状态" prop="scheduleStatus" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="aps-status-tag" :class="'status-' + (scope.row.scheduleStatus || 1)">{{ statusMap[scope.row.scheduleStatus] || '未知' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格" prop="spec" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="材质" prop="material" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="排产吨数" prop="scheduleWeight" width="100" align="right" show-overflow-tooltip />
|
||||
<el-table-column label="品名项" prop="productItem" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="品名" prop="productType" min-width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="订货单位" prop="customerName" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="业务员" prop="businessUser" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="联系电话" prop="businessPhone" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="交货期(天)" prop="deliveryCycle" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="产品用途" prop="usePurpose" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="厚度公差" prop="thicknessTolerance" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="宽度公差" prop="widthTolerance" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="表面质量" prop="surfaceQuality" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="表面处理" prop="surfaceTreatment" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="内径尺寸" prop="innerDiameter" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="外径要求" prop="outerDiameter" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="包装要求" prop="packReq" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="切边要求" prop="cutEdgeReq" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="单件重量" prop="singleCoilWeight" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="交货重量偏差" prop="weightDeviation" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column label="其他技术要求" prop="otherTechReq" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="付款情况说明" prop="paymentDesc" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="单行排产备注" prop="rowRemark" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<div style="display:flex; justify-content:center; gap:0;">
|
||||
<el-button type="text" size="small" style="color:#409EFF;padding:0 6px;" @click="handleEditScheduled(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" style="color:#ff4d4f;padding:0 6px;" @click="handleDeleteScheduled(scope.row)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template v-if="scheduledItemList.length > 0">
|
||||
<!-- 步骤工序 Tab -->
|
||||
<div class="aps-step-tabs">
|
||||
<span
|
||||
v-for="tab in scheduledStepTabs"
|
||||
:key="tab"
|
||||
class="aps-step-tab"
|
||||
:class="{ 'aps-step-tab-active': scheduledStepTab === tab }"
|
||||
@click="scheduledStepTab = tab"
|
||||
>
|
||||
{{ tab }}
|
||||
<span class="aps-step-tab-count">{{ scheduledItemList.filter(i => normalizeStepName(i.stepName) === tab).length }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="scheduledTable"
|
||||
:data="currentStepItems"
|
||||
border
|
||||
size="small"
|
||||
class="aps-table"
|
||||
>
|
||||
<el-table-column label="排产单号" prop="scheduleNo" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="生产日期" prop="prodDate" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="工序步骤" prop="stepName" width="120" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="排产状态" prop="scheduleStatus" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="aps-status-tag" :class="'status-' + (scope.row.scheduleStatus || 1)">{{ statusMap[scope.row.scheduleStatus] || '未知' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格" prop="spec" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="材质" prop="material" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="排产吨数" prop="scheduleWeight" width="100" align="right" show-overflow-tooltip />
|
||||
<el-table-column label="品名项" prop="productItem" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="品名" prop="productType" min-width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="订货单位" prop="customerName" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="业务员" prop="businessUser" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="联系电话" prop="businessPhone" width="110" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="交货期(天)" prop="deliveryCycle" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="产品用途" prop="usePurpose" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="厚度公差" prop="thicknessTolerance" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="宽度公差" prop="widthTolerance" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="表面质量" prop="surfaceQuality" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="表面处理" prop="surfaceTreatment" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="内径尺寸" prop="innerDiameter" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="外径要求" prop="outerDiameter" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="包装要求" prop="packReq" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="切边要求" prop="cutEdgeReq" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="单件重量" prop="singleCoilWeight" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="交货重量偏差" prop="weightDeviation" min-width="110" show-overflow-tooltip />
|
||||
<el-table-column label="其他技术要求" prop="otherTechReq" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="付款情况说明" prop="paymentDesc" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="单行排产备注" prop="rowRemark" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<div style="display:flex; justify-content:center; gap:0;">
|
||||
<el-button type="text" size="small" style="color:#409EFF;padding:0 6px;" @click="handleEditScheduled(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" style="color:#ff4d4f;padding:0 6px;" @click="handleDeleteScheduled(scope.row)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<div v-else-if="!schLoading" style="padding:40px;text-align:center;color:#909399;">
|
||||
{{ hasQueried ? '该日期暂无已排产数据' : '请选择日期查询' }}
|
||||
</div>
|
||||
@@ -493,149 +580,48 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 合并排产明细对话框 -->
|
||||
<!-- 接收产需单弹窗 - 配置工序 -->
|
||||
<el-dialog
|
||||
title="合并排产明细"
|
||||
:visible.sync="mergeDialogVisible"
|
||||
width="850px"
|
||||
title="接收产需单 - 配置工序"
|
||||
:visible.sync="receiveDialogVisible"
|
||||
width="900px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div style="margin-bottom:12px;font-size:13px;color:#e67e22;">
|
||||
选中 {{ mergeForm.itemCount }} 条明细,请选择一个作为合并模板,下方字段将自动填充,您可修改后确认合并。
|
||||
请为每条明细配置工序,所有明细配置完成后才能接收。
|
||||
</div>
|
||||
|
||||
<!-- 选择模板 -->
|
||||
<el-table :data="mergeSourceRows" border size="small" style="margin-bottom:12px;" @row-click="pickMergeTemplate">
|
||||
<el-table-column width="50" align="center">
|
||||
|
||||
<el-table :data="receiveDetailList" border size="small" class="aps-table" max-height="400">
|
||||
<el-table-column label="规格" prop="spec" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="材质" prop="material" width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="排产吨数" prop="scheduleWeight" width="100" align="right" />
|
||||
<el-table-column label="品名" prop="productType" min-width="90" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="配置工序" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-radio v-model="mergeTemplateIndex" :label="scope.$index" @click.native.stop />
|
||||
<ProcessSelect
|
||||
v-model="scope.row.processId"
|
||||
placeholder="请选择工序"
|
||||
@change="(val, data) => handleReceiveProcessChange(scope.row, val, data)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="工序步骤" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.stepList && scope.row.stepList.length > 0" class="receive-steps-flow">
|
||||
<template v-for="(step, index) in scope.row.stepList">
|
||||
<span :key="step.stepId" class="receive-step-tag">{{ step.stepName }}</span>
|
||||
<span v-if="index < scope.row.stepList.length - 1" :key="'arrow-' + index" class="receive-step-arrow">→</span>
|
||||
</template>
|
||||
</div>
|
||||
<span v-else style="color:#909399;font-size:12px;">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排产单号" prop="scheduleNo" min-width="130" show-overflow-tooltip />
|
||||
<el-table-column label="规格" prop="spec" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="材质" prop="material" width="80" show-overflow-tooltip />
|
||||
<el-table-column label="排产吨数" prop="scheduleWeight" width="90" align="right" />
|
||||
<el-table-column label="品名" prop="productType" min-width="80" show-overflow-tooltip />
|
||||
<el-table-column label="订货单位" prop="customerName" min-width="120" show-overflow-tooltip />
|
||||
</el-table>
|
||||
|
||||
<!-- 合并表单 -->
|
||||
<el-form ref="mergeFormRef" :model="mergeForm" label-width="110px" size="small">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排产单号"><el-input v-model="mergeForm.scheduleNo" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="工序类型">
|
||||
<el-select v-model="mergeForm.actionId" placeholder="请选择工序类型" clearable filterable style="width:100%">
|
||||
<el-option v-for="p in processOptions" :key="p.actionId" :label="p.name" :value="p.actionId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="订货单位"><el-input v-model="mergeForm.customerName" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规格"><el-input v-model="mergeForm.spec" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="材质"><el-input v-model="mergeForm.material" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排产吨数(累加)">
|
||||
<el-input-number v-model="mergeForm.scheduleWeight" :min="0" :precision="3" :controls="false" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="品名"><el-input v-model="mergeForm.productType" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="品名项"><el-input v-model="mergeForm.productItem" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="业务员"><el-input v-model="mergeForm.businessUser" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话"><el-input v-model="mergeForm.businessPhone" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="交货期(天)">
|
||||
<el-input-number v-model="mergeForm.deliveryCycle" :min="0" :controls="false" style="width:100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="产品用途"><el-input v-model="mergeForm.usePurpose" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="厚度公差"><el-input v-model="mergeForm.thicknessTolerance" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="宽度公差"><el-input v-model="mergeForm.widthTolerance" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表面质量"><el-input v-model="mergeForm.surfaceQuality" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="表面处理"><el-input v-model="mergeForm.surfaceTreatment" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="内径尺寸"><el-input v-model="mergeForm.innerDiameter" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="外径要求"><el-input v-model="mergeForm.outerDiameter" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="包装要求"><el-input v-model="mergeForm.packReq" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="切边要求"><el-input v-model="mergeForm.cutEdgeReq" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="单件重量"><el-input v-model="mergeForm.singleCoilWeight" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="交货重量偏差"><el-input v-model="mergeForm.weightDeviation" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="其他技术要求"><el-input v-model="mergeForm.otherTechReq" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款情况说明"><el-input v-model="mergeForm.paymentDesc" /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注"><el-input v-model="mergeForm.remark" /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div style="margin-top:8px;font-size:12px;color:#909399;">
|
||||
合并后 schedule_detail_ids:{{ mergeForm.scheduleDetailIds }}
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="mergeBtnLoading" type="warning" @click="confirmMerge">确 定 合 并</el-button>
|
||||
<el-button @click="mergeDialogVisible = false">取 消</el-button>
|
||||
<el-button :loading="receiveBtnLoading" type="primary" :disabled="!canConfirmReceive" @click="confirmReceive">确 定 接 收</el-button>
|
||||
<el-button @click="receiveDialogVisible = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -651,13 +637,14 @@ import {
|
||||
listScheduleItem,
|
||||
updateScheduleItem,
|
||||
delScheduleItem,
|
||||
receiveScheduleItem,
|
||||
mergeScheduleItem
|
||||
receiveScheduleItem
|
||||
} from '@/api/aps/schedule'
|
||||
import { PROCESSES } from '@/utils/meta'
|
||||
import ProcessSelect from '@/components/KLPService/ProcessSelect/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'ApsSchedule',
|
||||
components: { ProcessSelect },
|
||||
data() {
|
||||
const today = new Date()
|
||||
const y = today.getFullYear()
|
||||
@@ -676,26 +663,13 @@ export default {
|
||||
statusMap: { 1: '待审核', 2: '已接收', 3: '已驳回' },
|
||||
processOptions: PROCESSES,
|
||||
|
||||
// 已接收
|
||||
acceptedScheduleList: [],
|
||||
acceptedLoading: false,
|
||||
|
||||
// 已排产
|
||||
scheduledItemList: [],
|
||||
selectedItems: [],
|
||||
sourceColorMap: {},
|
||||
|
||||
// 合并对话框
|
||||
mergeDialogVisible: false,
|
||||
mergeBtnLoading: false,
|
||||
mergeTemplateIndex: 0,
|
||||
mergeSourceRows: [],
|
||||
mergeForm: {
|
||||
itemCount: 0, scheduleNo: '', actionId: '', customerName: '', spec: '', material: '',
|
||||
scheduleWeight: 0, productType: '', productItem: '', businessUser: '',
|
||||
businessPhone: '', deliveryCycle: undefined, usePurpose: '',
|
||||
thicknessTolerance: '', widthTolerance: '', surfaceQuality: '',
|
||||
surfaceTreatment: '', innerDiameter: '', outerDiameter: '',
|
||||
packReq: '', cutEdgeReq: '', singleCoilWeight: '',
|
||||
weightDeviation: '', otherTechReq: '', paymentDesc: '',
|
||||
remark: '', scheduleDetailIds: ''
|
||||
},
|
||||
scheduledStepTab: '',
|
||||
|
||||
// 驳回
|
||||
rejectDialogVisible: false,
|
||||
@@ -714,14 +688,37 @@ export default {
|
||||
|
||||
// 下钻
|
||||
drillDialogVisible: false,
|
||||
drillOrder: null
|
||||
drillOrder: null,
|
||||
|
||||
// 接收产需单弹窗
|
||||
receiveDialogVisible: false,
|
||||
receiveBtnLoading: false,
|
||||
receiveScheduleId: null,
|
||||
receiveDetailList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeTab() {
|
||||
this.selectedItems = []
|
||||
computed: {
|
||||
canConfirmReceive() {
|
||||
if (!this.receiveDetailList || this.receiveDetailList.length === 0) return false
|
||||
return this.receiveDetailList.every(d => d.processId)
|
||||
},
|
||||
// 已排产按步骤分组:去掉括号及括号内文字
|
||||
scheduledStepTabs() {
|
||||
const names = this.scheduledItemList
|
||||
.map(item => this.normalizeStepName(item.stepName))
|
||||
.filter(Boolean)
|
||||
return [...new Set(names)]
|
||||
},
|
||||
// 当前选中的步骤tab对应的数据
|
||||
currentStepItems() {
|
||||
if (!this.scheduledStepTab) return this.scheduledItemList
|
||||
const tab = this.scheduledStepTab
|
||||
return this.scheduledItemList.filter(
|
||||
item => this.normalizeStepName(item.stepName) === tab
|
||||
)
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
created() {
|
||||
this.handleQuery()
|
||||
},
|
||||
@@ -775,6 +772,8 @@ export default {
|
||||
this.hasQueried = true
|
||||
if (this.activeTab === 'pending') {
|
||||
this.queryPending()
|
||||
} else if (this.activeTab === 'accepted') {
|
||||
this.queryAccepted()
|
||||
} else {
|
||||
this.queryScheduled()
|
||||
}
|
||||
@@ -808,25 +807,82 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// ====== 已接收 ======
|
||||
queryAccepted() {
|
||||
this.acceptedLoading = true
|
||||
this.acceptedScheduleList = []
|
||||
|
||||
listRequirement({
|
||||
prodDate: this.queryDate,
|
||||
scheduleStatus: 2,
|
||||
pageNum: 1,
|
||||
pageSize: 999
|
||||
}).then(res => {
|
||||
this.acceptedScheduleList = res.rows || []
|
||||
const totalCount = this.acceptedScheduleList.reduce((sum, sch) => sum + (sch.detailList || []).length, 0)
|
||||
this.summaryText = `共 ${this.acceptedScheduleList.length} 个已接收产需单,${totalCount} 条明细`
|
||||
}).catch(() => {
|
||||
this.acceptedScheduleList = []
|
||||
this.summaryText = ''
|
||||
}).finally(() => {
|
||||
this.acceptedLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleAccept(sch) {
|
||||
const details = sch.detailList || []
|
||||
if (details.length === 0) {
|
||||
this.$message.warning('该产需单无可排产的明细')
|
||||
return
|
||||
}
|
||||
this.$confirm(
|
||||
`确认接收产需单「${sch.scheduleNo}」的全部排产明细吗?共 ${details.length} 条明细`,
|
||||
'提示',
|
||||
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
|
||||
).then(() => {
|
||||
this.$message.info('正在处理接收...')
|
||||
receiveScheduleItem(sch.scheduleId).then(() => {
|
||||
this.$modal.msgSuccess('接收成功,排产明细已写入')
|
||||
this.queryPending()
|
||||
}).catch(() => {
|
||||
this.$modal.msgError('接收失败')
|
||||
})
|
||||
}).catch(() => {})
|
||||
// 初始化接收明细列表,为每条明细添加 processId 和 stepList 字段
|
||||
this.receiveScheduleId = sch.scheduleId
|
||||
this.receiveDetailList = details.map(d => ({
|
||||
...d,
|
||||
processId: undefined,
|
||||
stepList: []
|
||||
}))
|
||||
this.receiveDialogVisible = true
|
||||
},
|
||||
|
||||
handleReceiveProcessChange(row, processId, processData) {
|
||||
if (processData && processData.stepList) {
|
||||
row.stepList = processData.stepList
|
||||
} else {
|
||||
row.stepList = []
|
||||
}
|
||||
},
|
||||
|
||||
confirmReceive() {
|
||||
// 验证所有明细都配置了工序
|
||||
const unconfigured = this.receiveDetailList.filter(d => !d.processId)
|
||||
if (unconfigured.length > 0) {
|
||||
this.$message.warning(`还有 ${unconfigured.length} 条明细未配置工序,请为所有明细配置工序`)
|
||||
return
|
||||
}
|
||||
// 构建接收数据,传递每条明细的 processId 和 stepList
|
||||
const receiveData = {
|
||||
scheduleId: this.receiveScheduleId,
|
||||
detailProcessList: this.receiveDetailList.map(d => ({
|
||||
scheduleDetailId: d.scheduleDetailId || d.scheduleDetailIds,
|
||||
processId: d.processId,
|
||||
stepList: (d.stepList || []).map(s => ({
|
||||
stepId: s.stepId,
|
||||
stepOrder: s.stepOrder,
|
||||
stepName: s.stepName
|
||||
}))
|
||||
}))
|
||||
}
|
||||
this.receiveBtnLoading = true
|
||||
receiveScheduleItem(receiveData).then(() => {
|
||||
this.$modal.msgSuccess('接收成功,排产明细已写入')
|
||||
this.receiveDialogVisible = false
|
||||
this.queryPending()
|
||||
}).catch(() => {
|
||||
this.$modal.msgError('接收失败')
|
||||
}).finally(() => {
|
||||
this.receiveBtnLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleReject(sch) {
|
||||
@@ -864,16 +920,14 @@ export default {
|
||||
queryScheduled() {
|
||||
this.schLoading = true
|
||||
this.scheduledItemList = []
|
||||
this.sourceColorMap = {}
|
||||
this.selectedItems = []
|
||||
this.scheduledStepTab = ''
|
||||
|
||||
listScheduleItem({ prodDate: this.queryDate, pageNum: 1, pageSize: 999 }).then(res => {
|
||||
this.scheduledItemList = (res.rows || []).sort((a, b) => (a.scheduleNo || '').localeCompare(b.scheduleNo || ''))
|
||||
try {
|
||||
this.sourceColorMap = this.buildGroupColorMap(this.scheduledItemList)
|
||||
} catch (e) {
|
||||
console.error('buildGroupColorMap error:', e)
|
||||
this.sourceColorMap = {}
|
||||
// 默认选中第一个步骤tab
|
||||
const tabs = this.scheduledStepTabs
|
||||
if (tabs.length > 0) {
|
||||
this.scheduledStepTab = tabs[0]
|
||||
}
|
||||
const totalWeight = this.scheduledItemList.reduce((sum, d) => {
|
||||
const w = parseFloat(d.scheduleWeight)
|
||||
@@ -934,98 +988,6 @@ export default {
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// ====== 合并 ======
|
||||
handleSelectionChange(rows) {
|
||||
this.selectedItems = rows
|
||||
},
|
||||
|
||||
getItemRowClassName({ row }) {
|
||||
const key = row.scheduleNo
|
||||
if (!key) return ''
|
||||
const colorIndex = this.sourceColorMap[key]
|
||||
return colorIndex !== undefined ? `merge-source-${colorIndex}` : ''
|
||||
},
|
||||
|
||||
buildGroupColorMap(list) {
|
||||
const map = {}
|
||||
let colorIdx = 0
|
||||
list.forEach(item => {
|
||||
const key = item.scheduleNo
|
||||
if (!key) return
|
||||
if (!(key in map)) {
|
||||
map[key] = colorIdx % 5
|
||||
colorIdx++
|
||||
}
|
||||
})
|
||||
return map
|
||||
},
|
||||
|
||||
handleMergePrepare() {
|
||||
if (this.selectedItems.length < 2) {
|
||||
this.$message.warning('请至少选择2条排产明细进行合并')
|
||||
return
|
||||
}
|
||||
this.mergeSourceRows = [...this.selectedItems]
|
||||
this.mergeTemplateIndex = 0
|
||||
this.pickMergeTemplate(this.mergeSourceRows[0])
|
||||
this.mergeDialogVisible = true
|
||||
},
|
||||
|
||||
pickMergeTemplate(row) {
|
||||
const idx = this.mergeSourceRows.indexOf(row)
|
||||
if (idx >= 0) this.mergeTemplateIndex = idx
|
||||
this.mergeForm = {
|
||||
itemCount: this.mergeSourceRows.length,
|
||||
scheduleNo: row.scheduleNo || '',
|
||||
actionId: row.actionId != null ? Number(row.actionId) : '',
|
||||
customerName: row.customerName || '',
|
||||
spec: row.spec || '',
|
||||
material: row.material || '',
|
||||
scheduleWeight: this.mergeSourceRows.reduce((sum, r) => sum + (parseFloat(r.scheduleWeight) || 0), 0),
|
||||
productType: row.productType || '',
|
||||
productItem: row.productItem || '',
|
||||
businessUser: row.businessUser || '',
|
||||
businessPhone: row.businessPhone || '',
|
||||
deliveryCycle: row.deliveryCycle,
|
||||
usePurpose: row.usePurpose || '',
|
||||
thicknessTolerance: row.thicknessTolerance || '',
|
||||
widthTolerance: row.widthTolerance || '',
|
||||
surfaceQuality: row.surfaceQuality || '',
|
||||
surfaceTreatment: row.surfaceTreatment || '',
|
||||
innerDiameter: row.innerDiameter || '',
|
||||
outerDiameter: row.outerDiameter || '',
|
||||
packReq: row.packReq || '',
|
||||
cutEdgeReq: row.cutEdgeReq || '',
|
||||
singleCoilWeight: row.singleCoilWeight || '',
|
||||
weightDeviation: row.weightDeviation || '',
|
||||
otherTechReq: row.otherTechReq || '',
|
||||
paymentDesc: row.paymentDesc || '',
|
||||
remark: row.remark || '',
|
||||
scheduleDetailIds: this.mergeSourceRows.map(r => r.scheduleDetailIds || '').filter(Boolean).join(',')
|
||||
}
|
||||
},
|
||||
|
||||
confirmMerge() {
|
||||
this.mergeBtnLoading = true
|
||||
const ids = this.mergeSourceRows.map(r => r.scheduleId)
|
||||
const mergedBo = {
|
||||
...this.mergeForm,
|
||||
prodDate: this.queryDate,
|
||||
scheduleStatus: 2
|
||||
}
|
||||
delete mergedBo.itemCount
|
||||
mergeScheduleItem({ ids, mergedBo }).then(() => {
|
||||
this.$modal.msgSuccess(`合并成功:${ids.length} 条明细合并为 1 条`)
|
||||
this.mergeDialogVisible = false
|
||||
this.selectedItems = []
|
||||
this.queryScheduled()
|
||||
}).catch(() => {
|
||||
this.$modal.msgError('合并失败')
|
||||
}).finally(() => {
|
||||
this.mergeBtnLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// ====== 下钻 & 辅助方法 ======
|
||||
scheduleTotalWeight(sch) {
|
||||
const details = sch.detailList || []
|
||||
@@ -1038,6 +1000,12 @@ export default {
|
||||
return p ? p.name : (actionId || '')
|
||||
},
|
||||
|
||||
// 去掉步骤名称中的括号及括号内文字:镀锌(毛化)=> 镀锌
|
||||
normalizeStepName(name) {
|
||||
if (!name) return ''
|
||||
return name.replace(/[((][^))]*[))]/g, '').trim()
|
||||
},
|
||||
|
||||
handleDetailClick(sch, detail) {
|
||||
// 点击明细行查看来源订单
|
||||
if (!sch || !sch.orderList || sch.orderList.length === 0) {
|
||||
@@ -1350,20 +1318,85 @@ export default {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
// ====== 合并候选行颜色高亮(同一源排产单 → 同色) ======
|
||||
::v-deep .el-table__body tr.merge-source-0 > td {
|
||||
background-color: #f0f5ff !important;
|
||||
// ====== 接收弹窗步骤展示 ======
|
||||
.receive-steps-flow {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
::v-deep .el-table__body tr.merge-source-1 > td {
|
||||
background-color: #f6ffed !important;
|
||||
|
||||
.receive-step-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
background: $aps-silver-1;
|
||||
border: 1px solid $aps-silver-mid;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
color: $aps-text;
|
||||
}
|
||||
::v-deep .el-table__body tr.merge-source-2 > td {
|
||||
background-color: #fff7e6 !important;
|
||||
|
||||
.receive-step-arrow {
|
||||
color: $aps-red-2;
|
||||
font-size: 14px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
::v-deep .el-table__body tr.merge-source-3 > td {
|
||||
background-color: #f9f0ff !important;
|
||||
|
||||
// ====== 已排产步骤工序 Tab ======
|
||||
.aps-step-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 8px 12px;
|
||||
gap: 6px;
|
||||
background: $aps-silver-1;
|
||||
border-bottom: 1px solid $aps-border;
|
||||
}
|
||||
::v-deep .el-table__body tr.merge-source-4 > td {
|
||||
background-color: #fff0f6 !important;
|
||||
|
||||
.aps-step-tab {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: $aps-text-muted;
|
||||
background: $aps-white;
|
||||
border: 1px solid $aps-silver-mid;
|
||||
border-radius: $aps-radius;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
color: $aps-red-2;
|
||||
border-color: $aps-red-2;
|
||||
}
|
||||
}
|
||||
|
||||
.aps-step-tab-active {
|
||||
color: #fff;
|
||||
background: $aps-red-2;
|
||||
border-color: $aps-red-2;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.aps-step-tab-count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 18px;
|
||||
height: 16px;
|
||||
padding: 0 5px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
|
||||
.aps-step-tab-active & {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -81,7 +81,7 @@ const NODE_EVENT_CONFIG = {
|
||||
{ id: 'H', label: '加工完工质检', handler: 'handleOpen', params: { componentPath: 'mes/qc/qualityReview/index' } },
|
||||
{ id: 'I', label: '登记质量缺陷', handler: 'handleOpen', params: { componentPath: 'wms/coil/abnormal/extend' } },
|
||||
{ id: 'J', label: '质量等级判定', handler: 'handleOpen', params: { componentPath: 'wms/coil/abnormal/extend' } },
|
||||
{ id: 'K', label: '单卷档案', handler: 'handleOpen', params: { componentPath: 'wms/coil/info/index' } },
|
||||
// { id: 'K', label: '单卷档案', handler: 'handleOpen', params: { componentPath: 'wms/coil/info/index' } },
|
||||
{ id: 'L', label: '编排发货计划', handler: 'handleOpen', params: { componentPath: 'wms/delivery/waybill/index' } },
|
||||
{ id: 'M', label: '生成发货单', handler: 'handleOpen', params: { componentPath: 'wms/delivery/bills/index' } },
|
||||
{ id: 'N', label: '发货质量校验', handler: 'handleOpen', params: { componentPath: 'mes/qc/qualityReview/index' } },
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div v-if="enabled" class="section-container">
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Complaint Content · 投诉情况与客户诉求</div>
|
||||
<div class="detail-section-text">{{ data.complaintContent || '-' }}</div>
|
||||
<div class="complaint-main">
|
||||
<div class="complaint-label">Complaint Content · 投诉情况与客户诉求</div>
|
||||
<div class="complaint-body">{{ data.complaintContent || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="customerInfo">
|
||||
@@ -35,29 +35,29 @@
|
||||
<div class="detail-section-text">-</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Downstream User · 下游使用用户</div>
|
||||
<div class="detail-section-text">{{ data.downstreamUserName || '-' }}</div>
|
||||
</div>
|
||||
<div class="divider-label">Other Info · 其他信息</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Phone · 电话</div>
|
||||
<div class="detail-section-text">{{ data.phone || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Project Name · 工程名称</div>
|
||||
<div class="detail-section-text">{{ data.projectName || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Project Location · 使用地点</div>
|
||||
<div class="detail-section-text">{{ data.projectLocation || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section">
|
||||
<div class="detail-section-label">Product Usage · 产品用途</div>
|
||||
<div class="detail-section-text">{{ data.productUsage || '-' }}</div>
|
||||
<div class="secondary-grid">
|
||||
<div class="secondary-item">
|
||||
<span class="secondary-key">下游使用用户</span>
|
||||
<span class="secondary-val">{{ data.downstreamUserName || '-' }}</span>
|
||||
</div>
|
||||
<div class="secondary-item">
|
||||
<span class="secondary-key">电话</span>
|
||||
<span class="secondary-val">{{ data.phone || '-' }}</span>
|
||||
</div>
|
||||
<div class="secondary-item">
|
||||
<span class="secondary-key">工程名称</span>
|
||||
<span class="secondary-val">{{ data.projectName || '-' }}</span>
|
||||
</div>
|
||||
<div class="secondary-item">
|
||||
<span class="secondary-key">使用地点</span>
|
||||
<span class="secondary-val">{{ data.projectLocation || '-' }}</span>
|
||||
</div>
|
||||
<div class="secondary-item">
|
||||
<span class="secondary-key">产品用途</span>
|
||||
<span class="secondary-val">{{ data.productUsage || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="data.file">
|
||||
@@ -109,6 +109,37 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.section-container {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* ===== 投诉情况主体 — 突出显示 ===== */
|
||||
.complaint-main {
|
||||
margin-bottom: 18px;
|
||||
padding: 16px 18px;
|
||||
background: #fff;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-left: 4px solid #1e293b;
|
||||
}
|
||||
|
||||
.complaint-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
margin-bottom: 10px;
|
||||
letter-spacing: 0.4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.complaint-body {
|
||||
font-size: 15px;
|
||||
color: #1e293b;
|
||||
line-height: 1.8;
|
||||
word-break: break-all;
|
||||
min-height: 60px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
@@ -163,4 +194,45 @@ export default {
|
||||
font-size: 13px;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
/* ===== 分隔标签 ===== */
|
||||
.divider-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 0.4px;
|
||||
text-transform: uppercase;
|
||||
margin: 16px 0 10px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px dashed #e2e8f0;
|
||||
}
|
||||
|
||||
/* ===== 次要信息网格 ===== */
|
||||
.secondary-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px 16px;
|
||||
padding: 10px 12px;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.secondary-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.secondary-key {
|
||||
font-size: 10px;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.secondary-val {
|
||||
font-size: 12px;
|
||||
color: #475569;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<el-tag v-else-if="item.flowStatus === 4" type="success" size="mini">全部办结</el-tag>
|
||||
</div>
|
||||
<div class="item-actions">
|
||||
<el-button v-if="item.flowStatus === 4" size="mini" type="text" icon="el-icon-download"
|
||||
<el-button size="mini" type="text" icon="el-icon-download"
|
||||
@click.stop="handleExportPdf(item)" title="导出PDF"></el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(item)"></el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(item)"></el-button>
|
||||
@@ -70,7 +70,7 @@
|
||||
<HeaderControlSection :complaintNo="currentRow.complaintNo" :flowStatus="currentRow.flowStatus"
|
||||
:meta="currentRow">
|
||||
<template #actions>
|
||||
<el-button v-if="currentRow.flowStatus === 4" size="mini" type="text" icon="el-icon-download"
|
||||
<el-button size="mini" type="text" icon="el-icon-download"
|
||||
@click="handleExportPdf(currentRow)" title="导出PDF">导出</el-button>
|
||||
<el-button v-if="currentRow.flowStatus === 1" size="mini" type="primary" plain
|
||||
icon="el-icon-s-promotion" @click="handleOpinionDispatch">意见下发</el-button>
|
||||
|
||||
@@ -149,7 +149,7 @@ export default {
|
||||
customExportVisible: false,
|
||||
columnGroups: {
|
||||
'基本信息': ['itemTypeDesc', 'warehouseName', 'actualWarehouseName', 'dataTypeText'],
|
||||
'钢卷号': ['enterCoilNo', 'supplierCoilNo', 'currentCoilNo'],
|
||||
'钢卷号': ['enterCoilNo', 'supplierCoilNo', 'currentCoilNo', 'coilId'],
|
||||
'时间': ['createTime', 'exportTime', 'exportBy'],
|
||||
'物理属性': ['netWeight', 'length', 'specification', 'actualThickness', 'actualLength', 'actualWidth', 'theoreticalThickness', 'theoreticalLength'],
|
||||
'材质属性': ['material', 'manufacturer', 'surfaceTreatmentDesc', 'zincLayer', 'packingStatus', 'temperGrade', 'coatingType', 'chromePlateCoilNo', 'rawMaterialThickness'],
|
||||
|
||||
@@ -560,7 +560,7 @@ export default {
|
||||
customExportType: 'output',
|
||||
columnGroups: {
|
||||
'基本信息': ['itemTypeDesc', 'warehouseName', 'actualWarehouseName', 'dataTypeText'],
|
||||
'钢卷号': ['enterCoilNo', 'supplierCoilNo', 'currentCoilNo'],
|
||||
'钢卷号': ['enterCoilNo', 'supplierCoilNo', 'currentCoilNo', 'coilId'],
|
||||
'时间': ['createTime', 'exportTime', 'exportBy'],
|
||||
'物理属性': ['netWeight', 'length', 'specification', 'actualThickness', 'actualLength', 'actualWidth', 'theoreticalThickness', 'theoreticalLength', 'scheduleThickness'],
|
||||
'材质属性': ['material', 'manufacturer', 'surfaceTreatmentDesc', 'zincLayer', 'packingStatus', 'temperGrade', 'coatingType', 'chromePlateCoilNo', 'rawMaterialThickness'],
|
||||
|
||||
Reference in New Issue
Block a user