feat(qc): 优化质量评审审批流程,改为创建时预填内容领导仅确认

1.  调整审批接口为路径参数传递评审单ID,移除审批BO参数
2.  待审批页面改为只读展示已填写的审批意见和钢卷改判状态
3.  审批通过时直接执行改判,无需额外操作
4.  重构编辑弹窗和详情页的布局与展示逻辑
5.  移除独立的品质部意见编辑,整合到表单中
This commit is contained in:
王文昊
2026-07-04 14:35:20 +08:00
parent ec40ab90ba
commit 0f054c189d
6 changed files with 198 additions and 195 deletions

View File

@@ -51,12 +51,11 @@ export function submitQualityReview(reviewId) {
})
}
// 审批通过
export function approveQualityReview(data) {
// 审批通过(创建时已填好内容,领导仅确认)
export function approveQualityReview(reviewId) {
return request({
url: '/qc/qualityReview/approve',
method: 'post',
data: data
url: '/qc/qualityReview/approve/' + reviewId,
method: 'post'
})
}

View File

@@ -70,9 +70,7 @@
<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 === 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>
@@ -105,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>
@@ -141,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>
@@ -161,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>
@@ -224,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">
@@ -239,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">
@@ -272,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>
<!-- ===== 钢卷选择器嵌套在弹窗内 ===== -->
@@ -288,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>
@@ -350,12 +399,6 @@ export default {
// 钢卷选择
showCoilSelector: false,
// 品质部意见编辑独立于editForm避免串数据
opinionForm: {
deptOpinion: '',
deptSign: '',
deptSignDate: undefined
},
// 编辑弹窗
dialogVisible: false,
dialogTitle: '',
@@ -370,6 +413,9 @@ export default {
deptOpinion: '',
deptSign: '',
deptSignDate: undefined,
leaderOpinion: '',
leaderSign: '',
leaderSignDate: undefined,
coilList: []
},
rules: {
@@ -423,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 = ''
@@ -456,6 +495,9 @@ export default {
deptOpinion: '',
deptSign: '',
deptSignDate: undefined,
leaderOpinion: '',
leaderSign: '',
leaderSignDate: undefined,
coilList: []
}
this.editing = true
@@ -473,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
@@ -509,6 +554,7 @@ export default {
spec: coil.specification, // CoilSelector返回的字段名为specification
netWeight: coil.netWeight,
defectDesc: '',
regradeQuality: '', // 改判后等级,由创建者填写
groupSeq: startIdx + idx + 1,
beforeQuality: coil.qualityStatus || 'O'
}))
@@ -538,26 +584,8 @@ export default {
// ===== 审批 =====
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()
})
@@ -605,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">
@@ -782,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;

View File

@@ -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;