Merge remote-tracking branch 'origin/0.8.X' into 0.8.X

This commit is contained in:
2026-07-06 10:55:07 +08:00
16 changed files with 311 additions and 125 deletions

View File

@@ -0,0 +1,10 @@
-- ------------------------------------------------------------
-- 质量评审 — 钢卷明细增加逻辑库区字段
-- V16__qc_quality_review_warehouse.sql
-- ------------------------------------------------------------
ALTER TABLE `qc_quality_review_coil`
ADD COLUMN `before_warehouse_id` bigint DEFAULT NULL COMMENT '改判前逻辑库区ID' AFTER `before_quality`,
ADD COLUMN `before_warehouse_name` varchar(100) DEFAULT NULL COMMENT '改判前逻辑库区名称' AFTER `before_warehouse_id`,
ADD COLUMN `target_warehouse_id` bigint DEFAULT NULL COMMENT '改判后目标库区ID' AFTER `regrade_quality`,
ADD COLUMN `target_warehouse_name` varchar(100) DEFAULT NULL COMMENT '改判后目标库区名称' AFTER `target_warehouse_id`;

View File

@@ -55,9 +55,21 @@ public class QcQualityReviewCoil extends BaseEntity {
/** 改判前质量等级 */
private String beforeQuality;
/** 改判前逻辑库区ID */
private Long beforeWarehouseId;
/** 改判前逻辑库区名称 */
private String beforeWarehouseName;
/** 改判后质量状态字典regrade_quality_type */
private String regradeQuality;
/** 改判后目标库区ID */
private Long targetWarehouseId;
/** 改判后目标库区名称 */
private String targetWarehouseName;
/** 执行状态0=待执行 1=已执行 */
private Long executeStatus;

View File

@@ -55,9 +55,21 @@ public class QcQualityReviewCoilBo extends BaseEntity {
/** 改判前质量等级 */
private String beforeQuality;
/** 改判前逻辑库区ID */
private Long beforeWarehouseId;
/** 改判前逻辑库区名称 */
private String beforeWarehouseName;
/** 改判后质量状态 */
private String regradeQuality;
/** 改判后目标库区ID */
private Long targetWarehouseId;
/** 改判后目标库区名称 */
private String targetWarehouseName;
/** 执行状态 */
private Long executeStatus;

View File

@@ -53,9 +53,21 @@ public class QcQualityReviewCoilVo extends BaseEntity {
/** 改判前质量等级 */
private String beforeQuality;
/** 改判前逻辑库区ID */
private Long beforeWarehouseId;
/** 改判前逻辑库区名称 */
private String beforeWarehouseName;
/** 改判后质量状态 */
private String regradeQuality;
/** 改判后目标库区ID */
private Long targetWarehouseId;
/** 改判后目标库区名称 */
private String targetWarehouseName;
/** 执行状态 */
private Long executeStatus;

View File

@@ -11,7 +11,9 @@ import com.klp.common.core.page.TableDataInfo;
import com.klp.common.utils.StringUtils;
import com.klp.common.helper.LoginHelper;
import com.klp.domain.WmsMaterialCoil;
import com.klp.domain.WmsWarehouse;
import com.klp.mapper.WmsMaterialCoilMapper;
import com.klp.mapper.WmsWarehouseMapper;
import com.klp.service.IWmsMaterialCoilService;
import com.klp.mes.qc.domain.QcQualityReview;
import com.klp.mes.qc.domain.QcQualityReviewCoil;
@@ -43,13 +45,11 @@ import java.util.*;
@Service
public class QcQualityReviewServiceImpl implements IQcQualityReviewService {
/** 技术部逻辑库IDC/D级改判后移入此库区 */
private static final Long TECH_WAREHOUSE_ID = 2019583656787259393L;
private final QcQualityReviewMapper baseMapper;
private final QcQualityReviewCoilMapper coilMapper;
private final QcQualityReviewLogMapper logMapper;
private final WmsMaterialCoilMapper wmsMaterialCoilMapper;
private final WmsWarehouseMapper wmsWarehouseMapper;
private final IWmsMaterialCoilService wmsMaterialCoilService;
/**
@@ -313,12 +313,11 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService {
coil.getCoilId(), coil.getRegradeQuality(), reason);
}
// 2. 根据改判后质量等级自动更新钢卷所在逻辑库区
Long targetWarehouseId = determineTargetWarehouse(coil.getRegradeQuality());
if (targetWarehouseId != null && coil.getCoilId() != null) {
// 2. 使用手动指定的目标逻辑库区更新钢卷所在库区
if (coil.getTargetWarehouseId() != null && coil.getCoilId() != null) {
wmsMaterialCoilMapper.update(null, Wrappers.<WmsMaterialCoil>lambdaUpdate()
.eq(WmsMaterialCoil::getCoilId, coil.getCoilId())
.set(WmsMaterialCoil::getWarehouseId, targetWarehouseId));
.set(WmsMaterialCoil::getWarehouseId, coil.getTargetWarehouseId()));
}
// 3. 更新明细执行状态
@@ -359,10 +358,12 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService {
coil.setGroupSeq(seq);
}
// 若未传改判前质量等级,从钢卷表获取
if (StringUtils.isBlank(coil.getBeforeQuality()) && coil.getCoilId() != null) {
if (coil.getCoilId() != null) {
WmsMaterialCoil wmsCoil = wmsMaterialCoilMapper.selectById(coil.getCoilId());
if (wmsCoil != null) {
coil.setBeforeQuality(wmsCoil.getQualityStatus());
if (StringUtils.isBlank(coil.getBeforeQuality())) {
coil.setBeforeQuality(wmsCoil.getQualityStatus());
}
if (StringUtils.isBlank(coil.getCurrentCoilNo())) {
coil.setCurrentCoilNo(wmsCoil.getCurrentCoilNo());
}
@@ -372,6 +373,14 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService {
if (coil.getNetWeight() == null) {
coil.setNetWeight(wmsCoil.getNetWeight());
}
// 自动带出当前逻辑库区
if (coil.getBeforeWarehouseId() == null && wmsCoil.getWarehouseId() != null) {
coil.setBeforeWarehouseId(wmsCoil.getWarehouseId());
WmsWarehouse wh = wmsWarehouseMapper.selectById(wmsCoil.getWarehouseId());
if (wh != null) {
coil.setBeforeWarehouseName(wh.getWarehouseName());
}
}
}
}
coilMapper.insert(coil);
@@ -402,23 +411,6 @@ public class QcQualityReviewServiceImpl implements IQcQualityReviewService {
return "QR-" + dateStr + "-" + String.format("%04d", count + 1);
}
/**
* 根据改判后质量等级确定目标逻辑库区
* O/A/B → 不移动C+/C/C- → 技术部逻辑库D+/D/D- → 技术部逻辑库
*/
private Long determineTargetWarehouse(String regradeQuality) {
if (regradeQuality == null) return null;
// O/A/B 级不移动
if ("O".equals(regradeQuality) || "A".equals(regradeQuality) || "B".equals(regradeQuality)) {
return null;
}
// C/D 级 → 技术部逻辑库
if (regradeQuality.startsWith("C") || regradeQuality.startsWith("D")) {
return TECH_WAREHOUSE_ID;
}
return null;
}
private void validEntityBeforeSave(QcQualityReview entity) {
if (StringUtils.isBlank(entity.getProductName())) {
throw new RuntimeException("产品名称不能为空");

View File

@@ -16,7 +16,11 @@
<result property="netWeight" column="net_weight"/>
<result property="defectDesc" column="defect_desc"/>
<result property="beforeQuality" column="before_quality"/>
<result property="beforeWarehouseId" column="before_warehouse_id"/>
<result property="beforeWarehouseName" column="before_warehouse_name"/>
<result property="regradeQuality" column="regrade_quality"/>
<result property="targetWarehouseId" column="target_warehouse_id"/>
<result property="targetWarehouseName" column="target_warehouse_name"/>
<result property="executeStatus" column="execute_status"/>
<result property="executeTime" column="execute_time"/>
<result property="remark" column="remark"/>

View File

@@ -55,7 +55,7 @@
<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">
<el-tag v-if="scope.row.status === 1" type="success" size="mini">已发货</el-tag>
<el-tag v-else type="info" size="mini">未发货</el-tag>
@@ -72,7 +72,7 @@
</el-button>
<el-button size="mini" type="text" icon="el-icon-search"
@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>
</el-table-column>
</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 class="table-cell">
<div class="table-cell edit-cell">
<div class="serial-number">
<span>{{ index + 1 }}</span>
<el-button v-if="!readonly && products.length > 1" type="text" size="mini" icon="el-icon-delete"
class="delete-btn" @click="removeProduct(index)" />
</div>
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.spec" placeholder="请输入规格" :readonly="readonly" size="small" />
</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-option v-for="opt in materialOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.quantity" placeholder="请输入数量" :readonly="readonly" size="small"
@change="onQuantityChange(item)" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.taxPrice" placeholder="请输入含税单价" :readonly="readonly" size="small"
@change="onTaxPriceChange(item)" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.taxDivisor" placeholder="税率除数" :readonly="readonly"
size="small" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.noTaxPrice" placeholder="无税单价" :readonly="readonly"
size="small" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.taxTotal" placeholder="含税总额" :readonly="readonly" size="small" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.noTaxTotal" placeholder="无税总额" :readonly="readonly"
size="small" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.taxAmount" placeholder="税额" :readonly="readonly" size="small" />
</div>
<div class="table-cell">
<div class="table-cell edit-cell">
<el-input v-model="item.remark" placeholder="请输入备注" :readonly="readonly" size="small" />
</div>
</div>
@@ -397,6 +397,10 @@ export default {
align-items: center;
}
.edit-cell {
padding: 0px;
}
.table-cell:last-child {
border-right: none;
}

View File

@@ -66,7 +66,7 @@
<p>从左侧选择一条采购合同进行审核</p>
</div>
<div v-else class="pa-view">
<div v-else class="pa-view" v-loading="detailLoading">
<div class="pa-d-head">
<div>
<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>
<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="规格" 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="spec" min-width="160" show-overflow-tooltip />
<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 />
<template slot="empty"><span>无采购要求</span></template>
</el-table>
@@ -131,6 +132,7 @@ export default {
return {
loading: true,
buttonLoading: false,
detailLoading: false,
total: 0,
pendingCount: 0,
planList: [],
@@ -175,10 +177,11 @@ export default {
this.getList()
},
selectPlan(row) {
this.detailLoading = true
getPurchasePlan(row.planId).then(res => {
this.current = res.data || {}
this.auditOpinion = this.current.auditOpinion || ''
})
}).finally(() => { this.detailLoading = false })
},
doAudit(status) {
this.buttonLoading = true
@@ -192,10 +195,11 @@ export default {
this.getList(true) // 刷新列表但保留右侧当前计划
this.loadPendingCount()
// 右侧停留在刚审核的计划:状态/历史即时更新,驳回后可直接重新审核
this.detailLoading = true
getPurchasePlan(pid).then(res => {
this.current = res.data || {}
this.auditOpinion = ''
})
}).finally(() => { this.detailLoading = false })
}).finally(() => { this.buttonLoading = false })
},
auditText(s) {

View File

@@ -53,7 +53,7 @@
<p>从左侧选择一条采购合同</p>
</div>
<div v-else>
<div v-else v-loading="detailLoading">
<div class="pd-d-head">
<div>
<span class="pd-d-title">{{ current.planNo }}</span>
@@ -61,6 +61,7 @@
</div>
<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-download" @click="downloadTemplate">下载模板</el-button>
<el-upload
:headers="upload.headers"
:action="uploadUrl"
@@ -94,9 +95,10 @@
<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 />
<el-table-column label="规格" prop="spec" min-width="160" show-overflow-tooltip />
<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="150" show-overflow-tooltip />
<template slot="empty"><span>无采购要求</span></template>
</el-table>
@@ -162,6 +164,7 @@ import {
refreshArrival
} from '@/api/erp/purchasePlan'
import { getToken } from '@/utils/auth'
import * as XLSX from 'xlsx'
export default {
name: 'ErpPurchaseDelivery',
@@ -176,6 +179,7 @@ export default {
deliveryList: [],
deliveryLoading: false,
refreshing: false,
detailLoading: false,
upload: { headers: { Authorization: 'Bearer ' + getToken() } },
progressColor: '#5b8db8'
}
@@ -220,7 +224,8 @@ export default {
refreshDetail() {
const planId = this.current.planId
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
listDelivery(planId).then(res => { this.deliveryList = res.data || [] }).finally(() => { this.deliveryLoading = false })
},
@@ -269,6 +274,15 @@ export default {
},
contractStatusText(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>
<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="规格" 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>
</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>
</el-table-column>
<el-table-column label="厂商" min-width="200">
@@ -157,7 +160,7 @@
</div>
<!-- 查看 -->
<div v-else class="pp-view">
<div v-else class="pp-view" v-loading="detailLoading">
<div class="pp-d-head">
<div>
<span class="pp-d-title">{{ current.planNo }}</span>
@@ -212,9 +215,10 @@
<el-tab-pane label="采购要求" name="items">
<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="规格" 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 />
<el-table-column label="规格" prop="spec" min-width="160" show-overflow-tooltip />
<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="150" show-overflow-tooltip />
<template slot="empty"><span>无采购要求</span></template>
</el-table>
</el-tab-pane>
@@ -367,6 +371,7 @@ export default {
},
buttonLoading: false,
submitLoading: false,
detailLoading: false,
selectedContracts: [],
// 合同选择器
pickerOpen: false,
@@ -419,7 +424,8 @@ export default {
refreshDetail() {
const planId = this.current.planId
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() {
@@ -431,6 +437,7 @@ export default {
this.mode = 'edit'
},
handleEdit() {
this.detailLoading = true
getPurchasePlan(this.current.planId).then(res => {
const d = res.data || {}
this.form = {
@@ -440,7 +447,7 @@ export default {
}
this.selectedContracts = []
this.mode = 'edit'
})
}).finally(() => { this.detailLoading = false })
},
cancelEdit() {
this.mode = this.planList.length ? 'view' : 'empty'
@@ -520,7 +527,7 @@ export default {
}).catch(() => cb([]))
},
blankItem() {
return { spec: '', weight: '', manufacturer: '' }
return { spec: '', material: '', weight: '', manufacturer: '' }
},
addItem() {
// 新行继承上一行的厂商(同批多为同厂),规格/重量留空

View File

@@ -124,12 +124,22 @@
<el-tag size="mini" type="danger">{{ scope.row.beforeQuality }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="regradeQuality" label="改判后" width="110" align="center">
<el-table-column prop="regradeQuality" label="改判后" width="100" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.regradeQuality" size="mini" type="warning">{{ scope.row.regradeQuality }}</el-tag>
<span v-else class="text-muted">待指定</span>
</template>
</el-table-column>
<el-table-column prop="beforeWarehouseName" label="当前库区" width="100">
<template slot-scope="scope">
<span>{{ scope.row.beforeWarehouseName || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="targetWarehouseName" label="改判后库区" width="120">
<template slot-scope="scope">
<span>{{ scope.row.targetWarehouseName || '不移动' }}</span>
</template>
</el-table-column>
</el-table>
</el-card>
@@ -170,9 +180,15 @@
<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">
<el-table-column prop="regradeQuality" label="改判后等级" width="100" align="center">
<template slot-scope="s"><el-tag size="mini" type="warning">{{ s.row.regradeQuality }}</el-tag></template>
</el-table-column>
<el-table-column prop="beforeWarehouseName" label="当前库区" width="100" />
<el-table-column prop="targetWarehouseName" label="改判后库区" width="120">
<template slot-scope="s">
<span>{{ s.row.targetWarehouseName || '不移动' }}</span>
</template>
</el-table-column>
</el-table>
</div>
@@ -228,7 +244,7 @@
</div>
<!-- 编辑弹窗 -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="960px" :close-on-click-modal="false" append-to-body class="review-dialog">
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="1200px" :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">
@@ -274,19 +290,37 @@
<el-table-column prop="supplierCoilNo" label="原料卷号" min-width="130" />
<el-table-column prop="spec" label="规格(mm)" width="100" />
<el-table-column prop="netWeight" label="卷重(t)" width="80" align="right" />
<el-table-column prop="defectDesc" label="缺陷描述" min-width="160">
<el-table-column prop="defectDesc" label="缺陷描述" min-width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.defectDesc" size="mini" placeholder="输入缺陷描述" />
<el-input v-model="scope.row.defectDesc" size="mini" placeholder="输入缺陷" />
</template>
</el-table-column>
<el-table-column prop="regradeQuality" label="改判后等级" min-width="130">
<el-table-column prop="beforeQuality" label="当前等级" width="80" align="center">
<template slot-scope="scope">
<el-select v-model="scope.row.regradeQuality" placeholder="请选择" size="mini">
<el-tag size="mini" type="danger">{{ scope.row.beforeQuality }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="regradeQuality" label="改判后等级" width="120">
<template slot-scope="scope">
<el-select v-model="scope.row.regradeQuality" placeholder="请选择" size="mini" style="width:100%;">
<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">
<el-table-column prop="beforeWarehouseName" label="当前库区" width="100">
<template slot-scope="scope">
<span>{{ scope.row.beforeWarehouseName || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="targetWarehouseId" label="改判后库区" width="140">
<template slot-scope="scope">
<el-select v-model="scope.row.targetWarehouseId" placeholder="请选择" size="mini" style="width:100%;" @change="onTargetWarehouseChange(scope.row)">
<el-option label="不移动" :value="null" />
<el-option v-for="w in warehouseOptions" v-if="w.warehouseType === 1" :key="w.warehouseId" :label="w.warehouseName" :value="w.warehouseId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="操作" width="55" 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>
@@ -372,6 +406,7 @@ import { listQualityReview, getQualityReview, addQualityReview, updateQualityRev
submitQualityReview, approveQualityReview, rejectQualityReview, executeQualityReview,
listQualityReviewCoil, listQualityReviewLog } from '@/api/mes/qc/qualityReview'
import CoilSelector from '@/components/CoilSelector'
import { listWarehouse } from '@/api/wms/warehouse'
export default {
name: 'QualityReview',
@@ -398,6 +433,7 @@ export default {
// 钢卷选择
showCoilSelector: false,
warehouseOptions: [], // 库区下拉选项
// 编辑弹窗
dialogVisible: false,
@@ -436,6 +472,11 @@ export default {
created() {
this.getList()
},
watch: {
dialogVisible(val) {
if (val) this.loadWarehouseOptions()
}
},
methods: {
// ===== 列表 =====
handleQuery() {
@@ -546,24 +587,51 @@ export default {
// ===== 钢卷选择(弹窗内) =====
onDialogCoilConfirm(selected) {
if (!selected || selected.length === 0) return
const existingIds = new Set(this.editForm.coilList.map(c => c.coilId))
const newSelected = selected.filter(coil => !existingIds.has(coil.coilId))
const dupCount = selected.length - newSelected.length
if (dupCount > 0) {
this.$message.warning(`已跳过 ${dupCount} 个重复钢卷`)
}
if (newSelected.length === 0) return
const startIdx = this.editForm.coilList.length || 0
const newCoils = selected.map((coil, idx) => ({
const newCoils = newSelected.map((coil, idx) => ({
coilId: coil.coilId,
currentCoilNo: coil.currentCoilNo,
supplierCoilNo: coil.supplierCoilNo || coil.enterCoilNo,
spec: coil.specification, // CoilSelector返回的字段名为specification
spec: coil.specification,
netWeight: coil.netWeight,
defectDesc: '',
regradeQuality: '', // 改判后等级,由创建者填写
regradeQuality: '',
beforeWarehouseId: coil.warehouseId || null,
beforeWarehouseName: this.getWarehouseName(coil.warehouseId),
targetWarehouseId: null,
targetWarehouseName: '',
groupSeq: startIdx + idx + 1,
beforeQuality: coil.qualityStatus || 'O'
}))
this.editForm.coilList = [...(this.editForm.coilList || []), ...newCoils]
},
getWarehouseName(warehouseId) {
if (!warehouseId) return ''
const wh = this.warehouseOptions.find(w => w.warehouseId === warehouseId)
return wh ? wh.warehouseName : ''
},
handleRemoveCoil(index) {
this.coilList.splice(index, 1)
},
// ===== 库区选择 =====
loadWarehouseOptions() {
listWarehouse().then(res => {
this.warehouseOptions = res.data || []
})
},
onTargetWarehouseChange(row) {
const selected = this.warehouseOptions.find(w => w.warehouseId === row.targetWarehouseId)
row.targetWarehouseName = selected ? selected.warehouseName : ''
},
// ===== 提交送审 =====
handleSubmit() {
this.$confirm('确认提交送审?', '提示', { type: 'warning' }).then(() => {

View File

@@ -64,9 +64,15 @@
<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">
<el-table-column prop="regradeQuality" label="改判后等级" width="100" align="center">
<template slot-scope="s"><el-tag size="mini" type="warning">{{ s.row.regradeQuality }}</el-tag></template>
</el-table-column>
<el-table-column prop="beforeWarehouseName" label="当前库区" width="100" />
<el-table-column prop="targetWarehouseName" label="改判后库区" width="120">
<template slot-scope="s">
<span>{{ s.row.targetWarehouseName || '不移动' }}</span>
</template>
</el-table-column>
</el-table>
</div>
<div style="margin-top:12px;">

View File

@@ -138,8 +138,9 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 文件列表表格 -->
<KLPTable v-loading="loading" :data="fileList" @selection-change="handleSelectionChange" highlight-current-row @row-click="handleRowClick">
<!-- 文件列表表格固定高度可滚动 -->
<div class="file-table-wrapper">
<KLPTable v-loading="loading" :data="fileList" @selection-change="handleSelectionChange" highlight-current-row @row-click="handleRowClick">
<el-table-column type="selection" width="55" align="center" v-if="activeTab === 'my' || activeTab === 'all'" />
<el-table-column label="文件名称" align="center" prop="fileName" :show-overflow-tooltip="true">
<template slot-scope="scope">
@@ -166,6 +167,30 @@
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
<!-- 选中文件元数据卡片 -->
<div class="file-meta-card" v-if="selectedFile">
<el-descriptions :column="2" border size="small">
<el-descriptions-item label="文件名称">{{ selectedFile.fileName }}</el-descriptions-item>
<el-descriptions-item label="文件类型">
<dict-tag :options="dict.type.sys_file_type" :value="selectedFile.fileType"/>
</el-descriptions-item>
<el-descriptions-item label="文件大小">{{ formatFileSize(selectedFile.fileSize) }}</el-descriptions-item>
<el-descriptions-item label="文件后缀">{{ selectedFile.suffix || '-' }}</el-descriptions-item>
<el-descriptions-item label="浏览次数">{{ selectedFile.viewCount != null ? selectedFile.viewCount : 0 }} </el-descriptions-item>
<el-descriptions-item label="订单编号">{{ selectedFile.orderNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属部门">{{ selectedFile.dept || '-' }}</el-descriptions-item>
<el-descriptions-item label="可见范围">
<el-tag :type="selectedFile.scopeType === 1 ? 'success' : 'warning'" size="small">
{{ selectedFile.scopeType === 1 ? '公开' : '私有' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="上传人">{{ selectedFile.createBy }}</el-descriptions-item>
<el-descriptions-item label="上传时间">{{ parseTime(selectedFile.createTime) }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ selectedFile.remark || '-' }}</el-descriptions-item>
</el-descriptions>
</div>
</div>
<!-- 拖拽分隔条 -->
<div class="resize-handle" @mousedown="startResize" :class="{ dragging: isDragging }"></div>
@@ -179,19 +204,11 @@
<div class="preview-header">
<span class="preview-filename" :title="selectedFile.fileName">{{ selectedFile.fileName }}</span>
<div>
<el-button size="mini" type="text" @click="handlePreview(selectedFile)">预览</el-button>
<el-button size="mini" plain icon="el-icon-info" @click="handleShowInfo(selectedFile)">查看</el-button>
<el-button size="mini" type="primary" icon="el-icon-download" @click="downloadFile(selectedFile)">下载</el-button>
<el-button v-if="canEdit(selectedFile)" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(selectedFile)">编辑</el-button>
<el-button v-if="canEdit(selectedFile)" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(selectedFile)">删除</el-button>
</div>
</div>
<div class="preview-meta">
<span>{{ formatFileSize(selectedFile.fileSize) }}</span>
<dict-tag :options="dict.type.sys_file_type" :value="selectedFile.fileType" />
<span>{{ selectedFile.createBy }}</span>
<span>{{ parseTime(selectedFile.createTime) }}</span>
</div>
<div class="preview-comment">
<div class="comment-bar" @click="commentExpanded = !commentExpanded">
<span><i class="el-icon-chat-dot-round"></i> 评论 ({{ comments.length }})</span>
@@ -862,12 +879,15 @@ export default {
/* 左右分栏布局 */
.file-layout {
display: flex;
align-items: flex-start;
align-items: stretch;
gap: 0;
}
.file-left {
flex-shrink: 0;
display: flex;
flex-direction: column;
height: calc(100vh - 240px);
}
.file-right {
@@ -915,12 +935,10 @@ export default {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 4px;
height: calc(100vh - 280px);
min-height: 450px;
height: 100%;
min-height: calc(100vh - 300px);
display: flex;
flex-direction: column;
position: sticky;
top: 16px;
}
.preview-empty {
@@ -948,17 +966,6 @@ export default {
margin-right: 12px;
}
.preview-meta {
padding: 8px 16px;
border-bottom: 1px solid #ebeef5;
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
font-size: 12px;
color: #909399;
}
.preview-comment {
border-bottom: 1px solid #ebeef5;
}
@@ -1042,7 +1049,6 @@ export default {
}
.preview-content {
flex: 1;
overflow: auto;
display: flex;
}
@@ -1057,6 +1063,17 @@ export default {
align-items: center;
height: 400px;
}
/* 左侧表格区域撑满剩余空间可滚动 */
.file-table-wrapper {
flex: 1;
overflow-y: auto;
}
/* 左侧文件元数据卡片 */
.file-meta-card {
margin-top: 12px;
}
</style>
<!-- 表格选中行高亮 scoped穿透 el-table -->

View File

@@ -145,8 +145,9 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 文件列表表格 -->
<KLPTable v-loading="loading" :data="fileList" @selection-change="handleSelectionChange" :highlight-current-row="activeTab === 'share' || activeTab === 'related'" @row-click="handleRowClick">
<!-- 文件列表表格固定高度可滚动 -->
<div :class="['file-table-wrapper', { scrolling: activeTab === 'share' || activeTab === 'related' }]">
<KLPTable v-loading="loading" :data="fileList" @selection-change="handleSelectionChange" :highlight-current-row="activeTab === 'share' || activeTab === 'related'" @row-click="handleRowClick">
<el-table-column type="selection" width="55" align="center" v-if="activeTab === 'my' || activeTab === 'all'" />
<el-table-column label="文件名称" align="center" prop="fileName" :show-overflow-tooltip="true">
<template slot-scope="scope">
@@ -217,6 +218,30 @@
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
<!-- 选中文件元数据卡片仅共享文件 / 与我相关 tab -->
<div class="file-meta-card" v-if="selectedFile && (activeTab === 'share' || activeTab === 'related')">
<el-descriptions :column="2" border size="small">
<el-descriptions-item label="文件名称">{{ selectedFile.fileName }}</el-descriptions-item>
<el-descriptions-item label="文件类型">
<dict-tag :options="dict.type.sys_file_type" :value="selectedFile.fileType"/>
</el-descriptions-item>
<el-descriptions-item label="文件大小">{{ formatFileSize(selectedFile.fileSize) }}</el-descriptions-item>
<el-descriptions-item label="文件后缀">{{ selectedFile.suffix || '-' }}</el-descriptions-item>
<el-descriptions-item label="浏览次数">{{ selectedFile.viewCount != null ? selectedFile.viewCount : 0 }} </el-descriptions-item>
<el-descriptions-item label="订单编号">{{ selectedFile.orderNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="所属部门">{{ selectedFile.dept || '-' }}</el-descriptions-item>
<el-descriptions-item label="可见范围">
<el-tag :type="selectedFile.scopeType === 1 ? 'success' : 'warning'" size="small">
{{ selectedFile.scopeType === 1 ? '公开' : '私有' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="上传人">{{ selectedFile.createBy }}</el-descriptions-item>
<el-descriptions-item label="上传时间">{{ parseTime(selectedFile.createTime) }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ selectedFile.remark || '-' }}</el-descriptions-item>
</el-descriptions>
</div>
</div>
<!-- 拖拽分隔条共享文件 / 与我相关 tab -->
@@ -232,18 +257,11 @@
<div class="preview-header">
<span class="preview-filename" :title="selectedFile.fileName">{{ selectedFile.fileName }}</span>
<div>
<el-button size="mini" plain icon="el-icon-info" @click="handleShowInfo(selectedFile)">查看</el-button>
<el-button size="mini" type="primary" icon="el-icon-download" @click="downloadFile(selectedFile)">下载</el-button>
<el-button v-if="canEdit(selectedFile)" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(selectedFile)">编辑</el-button>
<el-button v-if="canEdit(selectedFile)" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(selectedFile)">删除</el-button>
</div>
</div>
<div class="preview-meta">
<span>{{ formatFileSize(selectedFile.fileSize) }}</span>
<dict-tag :options="dict.type.sys_file_type" :value="selectedFile.fileType" />
<span>{{ selectedFile.createBy }}</span>
<span>{{ parseTime(selectedFile.createTime) }}</span>
</div>
<div class="preview-comment">
<div class="comment-bar" @click="commentExpanded = !commentExpanded">
<span><i class="el-icon-chat-dot-round"></i> 评论 ({{ comments.length }})</span>
@@ -928,12 +946,15 @@ export default {
/* 左右分栏布局 */
.file-layout {
display: flex;
align-items: flex-start;
align-items: stretch;
gap: 0;
}
.file-left {
flex-shrink: 0;
display: flex;
flex-direction: column;
height: calc(100vh - 240px);
}
.file-right {
@@ -981,12 +1002,10 @@ export default {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 4px;
height: calc(100vh - 280px);
min-height: 450px;
height: 100%;
min-height: calc(100vh - 300px);
display: flex;
flex-direction: column;
position: sticky;
top: 16px;
}
.preview-empty {
@@ -1014,17 +1033,6 @@ export default {
margin-right: 12px;
}
.preview-meta {
padding: 8px 16px;
border-bottom: 1px solid #ebeef5;
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
font-size: 12px;
color: #909399;
}
.preview-comment {
border-bottom: 1px solid #ebeef5;
}
@@ -1108,7 +1116,6 @@ export default {
}
.preview-content {
flex: 1;
overflow: auto;
display: flex;
}
@@ -1123,6 +1130,17 @@ export default {
align-items: center;
height: 400px;
}
/* 左侧表格区域撑满剩余空间可滚动(仅 share / related tab */
.file-table-wrapper.scrolling {
flex: 1;
overflow-y: auto;
}
/* 左侧文件元数据卡片 */
.file-meta-card {
margin-top: 12px;
}
</style>
<!-- 表格选中行高亮 scoped穿透 el-table -->

View File

@@ -1,7 +1,7 @@
<template>
<div class="app-container acid-do-container">
<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-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="materialQueryParams.enterCoilNo" placeholder="请输入入场钢卷号" clearable