refactor: 优化多个页面UI与交互细节

1. 修改钢卷追踪页面标题,调整crm钢卷表格列宽与按钮文本
2. 优化采购审核、到货、计划页面表格列配置,添加材质列
3. 为多个页面添加详情加载状态,统一按钮间距样式
4. 新增采购到货页面模板下载功能,修复产品内容组件单元格内边距
This commit is contained in:
砂糖
2026-07-06 10:36:56 +08:00
parent ed69b65e96
commit f343552729
6 changed files with 69 additions and 34 deletions

View File

@@ -55,7 +55,7 @@
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip /> <el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="发货状态" align="center" prop="status" width="150"> <el-table-column label="发货状态" align="center" prop="status" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.status === 1" type="success" size="mini">已发货</el-tag> <el-tag v-if="scope.row.status === 1" type="success" size="mini">已发货</el-tag>
<el-tag v-else type="info" size="mini">未发货</el-tag> <el-tag v-else type="info" size="mini">未发货</el-tag>
@@ -72,7 +72,7 @@
</el-button> </el-button>
<el-button size="mini" type="text" icon="el-icon-search" <el-button size="mini" type="text" icon="el-icon-search"
@click="handleDigitalCoilNo(scope.row)">数字钢卷</el-button> @click="handleDigitalCoilNo(scope.row)">数字钢卷</el-button>
<el-button size="mini" type="text" icon="el-icon-search" @click="handleTrace(scope.row)">追溯</el-button> <el-button size="mini" type="text" icon="el-icon-search" @click="handleTrace(scope.row)">钢卷追溯</el-button>
</template> </template>
</el-table-column> </el-table-column>
</KLPTable> </KLPTable>
@@ -282,4 +282,10 @@ export default {
}, },
} }
} }
</script> </script>
<style>
.el-table .el-button + .el-button {
margin-left: 0;
}
</style>

View File

@@ -39,49 +39,49 @@
<!-- 产品行 --> <!-- 产品行 -->
<div v-for="(item, index) in products" :key="index" class="table-row" :class="{ 'table-row-hover': !readonly }"> <div v-for="(item, index) in products" :key="index" class="table-row" :class="{ 'table-row-hover': !readonly }">
<div class="table-cell"> <div class="table-cell edit-cell">
<div class="serial-number"> <div class="serial-number">
<span>{{ index + 1 }}</span> <span>{{ index + 1 }}</span>
<el-button v-if="!readonly && products.length > 1" type="text" size="mini" icon="el-icon-delete" <el-button v-if="!readonly && products.length > 1" type="text" size="mini" icon="el-icon-delete"
class="delete-btn" @click="removeProduct(index)" /> class="delete-btn" @click="removeProduct(index)" />
</div> </div>
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.spec" placeholder="请输入规格" :readonly="readonly" size="small" /> <el-input v-model="item.spec" placeholder="请输入规格" :readonly="readonly" size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-select v-model="item.material" placeholder="请选择材质" :disabled="readonly" size="small" filterable allow-create clearable style="width:100%;"> <el-select v-model="item.material" placeholder="请选择材质" :disabled="readonly" size="small" filterable allow-create clearable style="width:100%;">
<el-option v-for="opt in materialOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> <el-option v-for="opt in materialOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select> </el-select>
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.quantity" placeholder="请输入数量" :readonly="readonly" size="small" <el-input v-model="item.quantity" placeholder="请输入数量" :readonly="readonly" size="small"
@change="onQuantityChange(item)" /> @change="onQuantityChange(item)" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.taxPrice" placeholder="请输入含税单价" :readonly="readonly" size="small" <el-input v-model="item.taxPrice" placeholder="请输入含税单价" :readonly="readonly" size="small"
@change="onTaxPriceChange(item)" /> @change="onTaxPriceChange(item)" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.taxDivisor" placeholder="税率除数" :readonly="readonly" <el-input v-model="item.taxDivisor" placeholder="税率除数" :readonly="readonly"
size="small" /> size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.noTaxPrice" placeholder="无税单价" :readonly="readonly" <el-input v-model="item.noTaxPrice" placeholder="无税单价" :readonly="readonly"
size="small" /> size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.taxTotal" placeholder="含税总额" :readonly="readonly" size="small" /> <el-input v-model="item.taxTotal" placeholder="含税总额" :readonly="readonly" size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.noTaxTotal" placeholder="无税总额" :readonly="readonly" <el-input v-model="item.noTaxTotal" placeholder="无税总额" :readonly="readonly"
size="small" /> size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.taxAmount" placeholder="税额" :readonly="readonly" size="small" /> <el-input v-model="item.taxAmount" placeholder="税额" :readonly="readonly" size="small" />
</div> </div>
<div class="table-cell"> <div class="table-cell edit-cell">
<el-input v-model="item.remark" placeholder="请输入备注" :readonly="readonly" size="small" /> <el-input v-model="item.remark" placeholder="请输入备注" :readonly="readonly" size="small" />
</div> </div>
</div> </div>
@@ -397,6 +397,10 @@ export default {
align-items: center; align-items: center;
} }
.edit-cell {
padding: 0px;
}
.table-cell:last-child { .table-cell:last-child {
border-right: none; border-right: none;
} }

View File

@@ -66,7 +66,7 @@
<p>从左侧选择一条采购合同进行审核</p> <p>从左侧选择一条采购合同进行审核</p>
</div> </div>
<div v-else class="pa-view"> <div v-else class="pa-view" v-loading="detailLoading">
<div class="pa-d-head"> <div class="pa-d-head">
<div> <div>
<span class="pa-d-title">{{ current.planNo }}</span> <span class="pa-d-title">{{ current.planNo }}</span>
@@ -91,8 +91,9 @@
<div class="pa-section">采购要求<span class="pa-section-hint" v-if="current.items && current.items.length"> {{ current.items.length }} </span></div> <div class="pa-section">采购要求<span class="pa-section-hint" v-if="current.items && current.items.length"> {{ current.items.length }} </span></div>
<el-table :data="current.items || []" border size="mini" max-height="320" class="pa-table"> <el-table :data="current.items || []" border size="mini" max-height="320" class="pa-table">
<el-table-column label="#" type="index" width="44" align="center" /> <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="规格" prop="spec" min-width="160" show-overflow-tooltip />
<el-table-column label="总重量(T)" prop="weight" min-width="110" align="right" /> <el-table-column label="材质" prop="material" min-width="100" show-overflow-tooltip />
<el-table-column label="总重量(T)" prop="weight" min-width="100" align="right" />
<el-table-column label="厂商" prop="manufacturer" min-width="180" show-overflow-tooltip /> <el-table-column label="厂商" prop="manufacturer" min-width="180" show-overflow-tooltip />
<template slot="empty"><span>无采购要求</span></template> <template slot="empty"><span>无采购要求</span></template>
</el-table> </el-table>
@@ -131,6 +132,7 @@ export default {
return { return {
loading: true, loading: true,
buttonLoading: false, buttonLoading: false,
detailLoading: false,
total: 0, total: 0,
pendingCount: 0, pendingCount: 0,
planList: [], planList: [],
@@ -175,10 +177,11 @@ export default {
this.getList() this.getList()
}, },
selectPlan(row) { selectPlan(row) {
this.detailLoading = true
getPurchasePlan(row.planId).then(res => { getPurchasePlan(row.planId).then(res => {
this.current = res.data || {} this.current = res.data || {}
this.auditOpinion = this.current.auditOpinion || '' this.auditOpinion = this.current.auditOpinion || ''
}) }).finally(() => { this.detailLoading = false })
}, },
doAudit(status) { doAudit(status) {
this.buttonLoading = true this.buttonLoading = true
@@ -192,10 +195,11 @@ export default {
this.getList(true) // 刷新列表但保留右侧当前计划 this.getList(true) // 刷新列表但保留右侧当前计划
this.loadPendingCount() this.loadPendingCount()
// 右侧停留在刚审核的计划:状态/历史即时更新,驳回后可直接重新审核 // 右侧停留在刚审核的计划:状态/历史即时更新,驳回后可直接重新审核
this.detailLoading = true
getPurchasePlan(pid).then(res => { getPurchasePlan(pid).then(res => {
this.current = res.data || {} this.current = res.data || {}
this.auditOpinion = '' this.auditOpinion = ''
}) }).finally(() => { this.detailLoading = false })
}).finally(() => { this.buttonLoading = false }) }).finally(() => { this.buttonLoading = false })
}, },
auditText(s) { auditText(s) {

View File

@@ -53,7 +53,7 @@
<p>从左侧选择一条采购合同</p> <p>从左侧选择一条采购合同</p>
</div> </div>
<div v-else> <div v-else v-loading="detailLoading">
<div class="pd-d-head"> <div class="pd-d-head">
<div> <div>
<span class="pd-d-title">{{ current.planNo }}</span> <span class="pd-d-title">{{ current.planNo }}</span>
@@ -61,6 +61,7 @@
</div> </div>
<div class="pd-head-act"> <div class="pd-head-act">
<el-button size="small" icon="el-icon-refresh" :loading="refreshing" @click="doRefreshArrival">刷新到货</el-button> <el-button size="small" icon="el-icon-refresh" :loading="refreshing" @click="doRefreshArrival">刷新到货</el-button>
<el-button size="small" icon="el-icon-download" @click="downloadTemplate">下载模板</el-button>
<el-upload <el-upload
:headers="upload.headers" :headers="upload.headers"
:action="uploadUrl" :action="uploadUrl"
@@ -94,9 +95,10 @@
<div class="pd-sec-title">采购要求</div> <div class="pd-sec-title">采购要求</div>
<el-table :data="current.items" border size="mini" max-height="300"> <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="#" type="index" width="44" align="center" />
<el-table-column label="规格" prop="spec" min-width="200" show-overflow-tooltip /> <el-table-column label="规格" prop="spec" min-width="160" show-overflow-tooltip />
<el-table-column label="总重量(T)" prop="weight" min-width="110" align="right" /> <el-table-column label="材质" prop="material" min-width="100" show-overflow-tooltip />
<el-table-column label="厂商" prop="manufacturer" min-width="180" show-overflow-tooltip /> <el-table-column label="总重量(T)" prop="weight" min-width="100" align="right" />
<el-table-column label="厂商" prop="manufacturer" min-width="150" show-overflow-tooltip />
<template slot="empty"><span>无采购要求</span></template> <template slot="empty"><span>无采购要求</span></template>
</el-table> </el-table>
@@ -162,6 +164,7 @@ import {
refreshArrival refreshArrival
} from '@/api/erp/purchasePlan' } from '@/api/erp/purchasePlan'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import * as XLSX from 'xlsx'
export default { export default {
name: 'ErpPurchaseDelivery', name: 'ErpPurchaseDelivery',
@@ -176,6 +179,7 @@ export default {
deliveryList: [], deliveryList: [],
deliveryLoading: false, deliveryLoading: false,
refreshing: false, refreshing: false,
detailLoading: false,
upload: { headers: { Authorization: 'Bearer ' + getToken() } }, upload: { headers: { Authorization: 'Bearer ' + getToken() } },
progressColor: '#5b8db8' progressColor: '#5b8db8'
} }
@@ -220,7 +224,8 @@ export default {
refreshDetail() { refreshDetail() {
const planId = this.current.planId const planId = this.current.planId
if (!planId) return if (!planId) return
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } }) this.detailLoading = true
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } }).finally(() => { this.detailLoading = false })
this.deliveryLoading = true this.deliveryLoading = true
listDelivery(planId).then(res => { this.deliveryList = res.data || [] }).finally(() => { this.deliveryLoading = false }) listDelivery(planId).then(res => { this.deliveryList = res.data || [] }).finally(() => { this.deliveryLoading = false })
}, },
@@ -269,6 +274,15 @@ export default {
}, },
contractStatusText(v) { contractStatusText(v) {
return { 0: '草稿', 1: '生效', 2: '作废', 3: '已完成' }[v] || '—' return { 0: '草稿', 1: '生效', 2: '作废', 3: '已完成' }[v] || '—'
},
downloadTemplate() {
const headers = ['日期', '牌号', '规格', '卷号', '单卷重量', '车号', '数量', '件数', '销售', '钢厂到站']
const sampleRow = ['2026-01-01', 'Q235B', '1.0*1250*C', 'COIL0001', '20.50', '辽A12345', '60.8', '3', 'XS001', '沈阳站']
const wb = XLSX.utils.book_new()
const ws = XLSX.utils.aoa_to_sheet([headers, sampleRow])
ws['!cols'] = headers.map(h => ({ wch: h.length > 4 ? 14 : 10 }))
XLSX.utils.book_append_sheet(wb, ws, '到货模板')
XLSX.writeFile(wb, '到货导入模板.xlsx')
} }
} }
} }

View File

@@ -124,10 +124,13 @@
</div> </div>
<el-table :data="form.items" border size="mini" max-height="340"> <el-table :data="form.items" border size="mini" max-height="340">
<el-table-column label="#" type="index" width="44" align="center" /> <el-table-column label="#" type="index" width="44" align="center" />
<el-table-column label="规格" min-width="220"> <el-table-column label="规格" min-width="160">
<template slot-scope="s"><el-input v-model="s.row.spec" size="mini" placeholder="如 3.00×1230" /></template> <template slot-scope="s"><el-input v-model="s.row.spec" size="mini" placeholder="如 3.00×1230" /></template>
</el-table-column> </el-table-column>
<el-table-column label="总重量(T)" min-width="120"> <el-table-column label="材质" min-width="120">
<template slot-scope="s"><el-input v-model="s.row.material" size="mini" placeholder="如 Q235B" /></template>
</el-table-column>
<el-table-column label="总重量(T)" min-width="110">
<template slot-scope="s"><el-input v-model="s.row.weight" size="mini" /></template> <template slot-scope="s"><el-input v-model="s.row.weight" size="mini" /></template>
</el-table-column> </el-table-column>
<el-table-column label="厂商" min-width="200"> <el-table-column label="厂商" min-width="200">
@@ -157,7 +160,7 @@
</div> </div>
<!-- 查看 --> <!-- 查看 -->
<div v-else class="pp-view"> <div v-else class="pp-view" v-loading="detailLoading">
<div class="pp-d-head"> <div class="pp-d-head">
<div> <div>
<span class="pp-d-title">{{ current.planNo }}</span> <span class="pp-d-title">{{ current.planNo }}</span>
@@ -212,9 +215,10 @@
<el-tab-pane label="采购要求" name="items"> <el-tab-pane label="采购要求" name="items">
<el-table :data="current.items" border size="mini" max-height="340"> <el-table :data="current.items" border size="mini" max-height="340">
<el-table-column label="#" type="index" width="44" align="center" /> <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="规格" prop="spec" min-width="160" show-overflow-tooltip />
<el-table-column label="总重量(T)" prop="weight" min-width="110" align="right" /> <el-table-column label="材质" prop="material" min-width="100" show-overflow-tooltip />
<el-table-column label="厂商" prop="manufacturer" min-width="180" show-overflow-tooltip /> <el-table-column label="总重量(T)" prop="weight" min-width="100" align="right" />
<el-table-column label="厂商" prop="manufacturer" min-width="150" show-overflow-tooltip />
<template slot="empty"><span>无采购要求</span></template> <template slot="empty"><span>无采购要求</span></template>
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
@@ -367,6 +371,7 @@ export default {
}, },
buttonLoading: false, buttonLoading: false,
submitLoading: false, submitLoading: false,
detailLoading: false,
selectedContracts: [], selectedContracts: [],
// 合同选择器 // 合同选择器
pickerOpen: false, pickerOpen: false,
@@ -419,7 +424,8 @@ export default {
refreshDetail() { refreshDetail() {
const planId = this.current.planId const planId = this.current.planId
if (!planId) return if (!planId) return
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } }) this.detailLoading = true
getPurchasePlan(planId).then(res => { this.current = { ...this.current, ...(res.data || {}) } }).finally(() => { this.detailLoading = false })
}, },
// ---- 新增 / 编辑 ---- // ---- 新增 / 编辑 ----
resetForm() { resetForm() {
@@ -431,6 +437,7 @@ export default {
this.mode = 'edit' this.mode = 'edit'
}, },
handleEdit() { handleEdit() {
this.detailLoading = true
getPurchasePlan(this.current.planId).then(res => { getPurchasePlan(this.current.planId).then(res => {
const d = res.data || {} const d = res.data || {}
this.form = { this.form = {
@@ -440,7 +447,7 @@ export default {
} }
this.selectedContracts = [] this.selectedContracts = []
this.mode = 'edit' this.mode = 'edit'
}) }).finally(() => { this.detailLoading = false })
}, },
cancelEdit() { cancelEdit() {
this.mode = this.planList.length ? 'view' : 'empty' this.mode = this.planList.length ? 'view' : 'empty'
@@ -520,7 +527,7 @@ export default {
}).catch(() => cb([])) }).catch(() => cb([]))
}, },
blankItem() { blankItem() {
return { spec: '', weight: '', manufacturer: '' } return { spec: '', material: '', weight: '', manufacturer: '' }
}, },
addItem() { addItem() {
// 新行继承上一行的厂商(同批多为同厂),规格/重量留空 // 新行继承上一行的厂商(同批多为同厂),规格/重量留空

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="app-container acid-do-container"> <div class="app-container acid-do-container">
<div class="search-section"> <div class="search-section">
<h3 class="page-title">综合钢卷修正</h3> <h3 class="page-title">钢卷追踪</h3>
<el-form :model="materialQueryParams" ref="materialQueryForm" size="small" :inline="true" class="search-form"> <el-form :model="materialQueryParams" ref="materialQueryForm" size="small" :inline="true" class="search-form">
<el-form-item label="入场钢卷号" prop="enterCoilNo"> <el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="materialQueryParams.enterCoilNo" placeholder="请输入入场钢卷号" clearable <el-input v-model="materialQueryParams.enterCoilNo" placeholder="请输入入场钢卷号" clearable