Browse Source

feat(quality): 添加质量问列表页面及详情组件

- 创建质量问题列表页面,包含查询条件和表格展示功能
- 实现质量问题的新增、编辑、删除、回复、赔偿、关闭等操作
- 添加质量问题详情组件,展示完整的质量问题信息
- 创建质量问题附件组件,支持附件管理功能
- 集成API接口,实现数据的增删改查和状态流转
- 设计表单验证规则,确保数据录入的准确性
- 实现分页查询和导出Excel功能
master
qiankanghui 1 week ago
parent
commit
2777cdc5b1
  1. 6
      src/api/quality/qualityIssue.js
  2. 195
      src/views/modules/quality/com_qualityIssueDetail.vue
  3. 696
      src/views/modules/quality/qualityIssueList.vue

6
src/api/quality/qualityIssue.js

@ -14,3 +14,9 @@ export const deleteQualityIssue = (data) => createAPI(`/srm/qualityIssue/delete`
// 保存回复 // 保存回复
export const saveReply = (data) => createAPI(`/srm/qualityIssue/saveReply`, 'post', data) export const saveReply = (data) => createAPI(`/srm/qualityIssue/saveReply`, 'post', data)
// 保存索赔
export const saveClaim = (data) => createAPI(`/srm/qualityIssue/saveClaim`, 'post', data)
// 关闭质量问题
export const closeQualityIssue = (data) => createAPI(`/srm/qualityIssue/close`, 'post', data)

195
src/views/modules/quality/com_qualityIssueDetail.vue

@ -1,9 +1,7 @@
<template> <template>
<div class="detail-container"> <div class="detail-container">
<!-- 第一行 -->
<!-- 第一行反馈单号问题日期供应商编码供应商名称供应商负责人 -->
<div class="detail-row"> <div class="detail-row">
<div class="detail-item"> <div class="detail-item">
<span class="label">反馈单号</span> <span class="label">反馈单号</span>
<span class="value">{{ detailData.issueNo }}</span> <span class="value">{{ detailData.issueNo }}</span>
@ -24,32 +22,109 @@
<span class="value">{{ detailData.supplierName }}</span> <span class="value">{{ detailData.supplierName }}</span>
</div> </div>
<div class="detail-item">
<span class="label">供应商负责人</span>
<span class="value">{{ detailData.supplierResponsible }}</span>
</div>
</div>
<!-- 第二行PlantClaim NoProduct CategoryPart No -->
<div class="detail-row">
<div class="detail-item">
<span class="label">Plant</span>
<span class="value">{{ detailData.plant }}</span>
</div>
<div class="detail-item">
<span class="label">Claim No</span>
<span class="value">{{ detailData.claimNo }}</span>
</div>
<div class="detail-item">
<span class="label">Product Category</span>
<span class="value">{{ detailData.productCategory }}</span>
</div>
<div class="detail-item">
<span class="label">Part No</span>
<span class="value">{{ detailData.partNo }}</span>
</div>
</div> </div>
<!-- 第二行 -->
<!-- 新增行PO No批次数量拒收批次数量投诉接收日期样品接收日期 -->
<div class="detail-row"> <div class="detail-row">
<div class="detail-item">
<span class="label">PO No</span>
<span class="value">{{ detailData.poNo }}</span>
</div>
<div class="detail-item">
<span class="label">批次数量</span>
<span class="value">{{ detailData.batchQty }}</span>
</div>
<div class="detail-item"> <div class="detail-item">
<span class="label">问题分类</span>
<span class="value">{{ detailData.issueCategory }}</span>
<span class="label">拒收批次数量</span>
<span class="value">{{ detailData.rejectBatchQty }}</span>
</div> </div>
<div class="detail-item">
<span class="label">投诉接收日期</span>
<span class="value">{{ formatDate(detailData.receiveComplaintDate) }}</span>
</div>
</div>
<div class="detail-row">
<div class="detail-item">
<span class="label">样品接收日期</span>
<span class="value">{{ formatDate(detailData.receiveSampleDate) }}</span>
</div>
</div>
<!-- 第三行问题简述 -->
<div class="detail-row">
<div class="detail-item long"> <div class="detail-item long">
<span class="label">问题简述</span> <span class="label">问题简述</span>
<span class="value">{{ detailData.issueSummary }}</span> <span class="value">{{ detailData.issueSummary }}</span>
</div> </div>
</div> </div>
<!-- 第三行 - 问题详细描述 -->
<!-- 四行问题详细描述 -->
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="label">问题详细描述</span> <span class="label">问题详细描述</span>
<div class="value textarea">{{ detailData.issueDescription }}</div> <div class="value textarea">{{ detailData.issueDescription }}</div>
</div> </div>
<!-- 第四行 -->
<!-- 五行LevelMode 1Mode 2Mode 3Inspector -->
<div class="detail-row"> <div class="detail-row">
<div class="detail-item">
<span class="label">Level</span>
<span class="value">{{ detailData.levelNo }}</span>
</div>
<div class="detail-item">
<span class="label">Mode 1</span>
<span class="value">{{ detailData.mode1 }}</span>
</div>
<div class="detail-item">
<span class="label">Mode 2</span>
<span class="value">{{ detailData.mode2 }}</span>
</div>
<div class="detail-item">
<span class="label">Mode 3</span>
<span class="value">{{ detailData.mode3 }}</span>
</div>
<div class="detail-item">
<span class="label">Inspector</span>
<span class="value">{{ detailData.inspector }}</span>
</div>
</div>
<!-- 第六行录入人回复录入时间回复要求回复日期状态 -->
<div class="detail-row">
<div class="detail-item"> <div class="detail-item">
<span class="label">录入人</span> <span class="label">录入人</span>
<span class="value">{{ detailData.createBy }}</span> <span class="value">{{ detailData.createBy }}</span>
@ -57,7 +132,7 @@
<div class="detail-item"> <div class="detail-item">
<span class="label">录入时间</span> <span class="label">录入时间</span>
<span class="value">{{ detailData.createDate }}</span>
<span class="value">{{ detailData.createBy }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
@ -69,24 +144,30 @@
<span class="label">状态</span> <span class="label">状态</span>
<span class="value">{{ detailData.status }}</span> <span class="value">{{ detailData.status }}</span>
</div> </div>
</div>
<!-- 第七行Why Escape -->
<div class="detail-row">
<div class="detail-item">
<span class="label">Why Escape</span>
<span class="value">{{ detailData.whyEscape }}</span>
</div>
</div> </div>
<!-- 第五行 - 原因分析 -->
<!-- 八行原因分析 -->
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="label">原因分析</span> <span class="label">原因分析</span>
<div class="value textarea">{{ detailData.analysis }}</div> <div class="value textarea">{{ detailData.analysis }}</div>
</div> </div>
<!-- 六行 - 后续措施 -->
<!-- 九行后续措施 -->
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="label">后续措施</span> <span class="label">后续措施</span>
<div class="value textarea">{{ detailData.analysis }}</div>
<div class="value textarea">{{ detailData.correctiveAction }}</div>
</div> </div>
<!-- 七行 -->
<!-- 十行回复人回复时间录入人回复录入时间回复 -->
<div class="detail-row"> <div class="detail-row">
<div class="detail-item"> <div class="detail-item">
<span class="label">回复人</span> <span class="label">回复人</span>
<span class="value">{{ detailData.replyBy }}</span> <span class="value">{{ detailData.replyBy }}</span>
@ -96,6 +177,62 @@
<span class="label">回复时间</span> <span class="label">回复时间</span>
<span class="value">{{ detailData.replyTime }}</span> <span class="value">{{ detailData.replyTime }}</span>
</div> </div>
<div class="detail-item">
<span class="label">录入人</span>
<span class="value">{{ detailData.entryBy }}</span>
</div>
<div class="detail-item">
<span class="label">录入时间</span>
<span class="value">{{ detailData.entryDate }}</span>
</div>
</div>
<!-- 第十一行索赔信息 -->
<div class="claim-section">
<div class="claim-title">索赔信息</div>
<div class="detail-row">
<div class="detail-item">
<span class="label">是否被索赔</span>
<span class="value">{{ detailData.claimFlag === 'Y' ? '是' : '否' }}</span>
</div>
<div class="detail-item">
<span class="label">被索赔金额</span>
<span class="value">{{ detailData.claimAmount }}</span>
</div>
<div class="detail-item long">
<span class="label">处置备注</span>
<span class="value">{{ detailData.disposalRemark }}</span>
</div>
</div>
<div class="detail-row">
<div class="detail-item">
<span class="label">录入人</span>
<span class="value">{{ detailData.entryBy }}</span>
</div>
<div class="detail-item">
<span class="label">录入时间</span>
<span class="value">{{ detailData.entryDate }}</span>
</div>
</div>
</div>
<!-- 第十二行关闭人关闭时间 -->
<div class="detail-row">
<div class="detail-item">
<span class="label">关闭人</span>
<span class="value">{{ detailData.closeBy }}</span>
</div>
<div class="detail-item">
<span class="label">关闭时间</span>
<span class="value">{{ detailData.closeDate }}</span>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -189,4 +326,32 @@ export default {
word-break: break-all; word-break: break-all;
} }
.detail-item.note {
flex: 1;
margin-right: 0;
}
.detail-item.note .label {
color: #909399;
font-weight: normal;
font-size: 12px;
}
/* 索赔信息区域样式 */
.claim-section {
border: 1px solid #dcdfe6;
padding: 15px;
margin-bottom: 18px;
background: #fff;
}
.claim-title {
font-size: 14px;
font-weight: 500;
color: #303133;
margin-bottom: 15px;
padding-left: 10px;
border-left: 3px solid #409eff;
}
</style> </style>

696
src/views/modules/quality/qualityIssueList.vue

@ -68,13 +68,29 @@
style="width: 100px; height: 100px"/></span> style="width: 100px; height: 100px"/></span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="180" label="操作">
<el-table-column fixed="right" header-align="center" align="center" width="240" label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<template v-if="scope.row.status !== '已回复'">
<a class="customer-a" @click="editQualityIssue(scope.row)">编辑 |</a>
<a class="customer-a" @click="deleteQualityIssue(scope.row)">删除 </a>
<a class="customer-a" @click="replyQualityIssue(scope.row)">| 回复</a>
</template>
<!-- 编辑 -->
<a v-if="scope.row.status === '已确认'"
class="customer-a"
@click="editQualityIssue(scope.row)">编辑 </a>
<!-- 删除 -->
<a v-if="scope.row.status === '已确认'"
class="customer-a"
@click="deleteQualityIssue(scope.row)">删除 </a>
<!-- 回复 -->
<a v-if="scope.row.status === '已确认'"
class="customer-a"
@click="replyQualityIssue(scope.row)">回复 </a>
<!-- 赔偿 -->
<a v-if="['已确认','已分析'].includes(scope.row.status)"
class="customer-a"
@click="compensationQualityIssue(scope.row)">赔偿 </a>
<!-- 关闭 -->
<a v-if="scope.row.status === '已分析'"
class="customer-a"
@click="closeQualityIssueAction(scope.row)">关闭</a>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -106,20 +122,20 @@
<el-dialog <el-dialog
title="质量问题 - 新增" title="质量问题 - 新增"
:visible.sync="addDialogVisible" :visible.sync="addDialogVisible"
width="45%"
top="10vh"
width="70%"
top="5vh"
:close-on-click-modal="false" :close-on-click-modal="false"
@close="handleCloseAddDialog"> @close="handleCloseAddDialog">
<el-form :model="addFormData" :rules="addRules" ref="addFormData" label-width="110px" size="mini" class="add-dialog-form"> <el-form :model="addFormData" :rules="addRules" ref="addFormData" label-width="110px" size="mini" class="add-dialog-form">
<!-- 第一行 --> <!-- 第一行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-col :span="6">
<el-form-item label="反馈单号"> <el-form-item label="反馈单号">
<el-input v-model="addFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input> <el-input v-model="addFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-col :span="6">
<el-form-item label="问题日期" prop="issueDate"> <el-form-item label="问题日期" prop="issueDate">
<el-date-picker <el-date-picker
v-model="addFormData.issueDate" v-model="addFormData.issueDate"
@ -131,7 +147,7 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-col :span="6">
<el-form-item label="要求回复日期" prop="requireReplyDate"> <el-form-item label="要求回复日期" prop="requireReplyDate">
<el-date-picker <el-date-picker
v-model="addFormData.requireReplyDate" v-model="addFormData.requireReplyDate"
@ -143,11 +159,62 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="状态">
<el-input v-model="addFormData.status" value="已确认" disabled size="mini"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 新增行PO No批次数量拒收批次数量投诉接收日期样品接收日期 -->
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="PO No">
<el-input v-model="addFormData.poNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="批次数量">
<el-input v-model="addFormData.batchQty" placeholder="请输入" size="mini" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="拒收批次数量">
<el-input v-model="addFormData.rejectBatchQty" placeholder="请输入" size="mini" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="投诉接收日期">
<el-date-picker
v-model="addFormData.receiveComplaintDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
size="mini"
style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="样品接收日期">
<el-date-picker
v-model="addFormData.receiveSampleDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
size="mini"
style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第二行 --> <!-- 第二行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-col :span="6">
<el-form-item label="供应商编码" prop="supplierNo"> <el-form-item label="供应商编码" prop="supplierNo">
<el-input v-model="addFormData.supplierNo" placeholder="请选择" readonly @click.native="selectSupplier" size="mini"> <el-input v-model="addFormData.supplierNo" placeholder="请选择" readonly @click.native="selectSupplier" size="mini">
<i slot="suffix" class="el-icon-search" style="cursor: pointer;"></i> <i slot="suffix" class="el-icon-search" style="cursor: pointer;"></i>
@ -159,35 +226,61 @@
<el-input v-model="addFormData.supplierName" disabled size="mini"></el-input> <el-input v-model="addFormData.supplierName" disabled size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="供应商负责人">
<el-input v-model="addFormData.supplierResponsible" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第三行 --> <!-- 第三行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-form-item label="问题分类" prop="issueCategory">
<el-select v-model="addFormData.issueCategory" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="产品外观" value="产品外观"></el-option>
<el-option label="产品性能" value="产品性能"></el-option>
<el-option label="尺寸不符" value="尺寸不符"></el-option>
<el-option label="材质问题" value="材质问题"></el-option>
<el-option label="包装破损" value="包装破损"></el-option>
<el-col :span="6">
<el-form-item label="Plant">
<el-select v-model="addFormData.plant" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Mx : Mexico" value="Mx"></el-option>
<el-option label="IR : Ireland" value="IR"></el-option>
<el-option label="TN : Tennessee" value="TN"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Claim No">
<el-input v-model="addFormData.claimNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Product Category">
<el-select v-model="addFormData.productCategory" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Metal Pen" value="Metal Pen"></el-option>
<el-option label="CUP" value="CUP"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="Part No">
<el-input v-model="addFormData.partNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第四行 --> <!-- 第四行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24">
<el-col :span="18">
<el-form-item label="问题简述" prop="issueSummary"> <el-form-item label="问题简述" prop="issueSummary">
<el-input v-model="addFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input> <el-input v-model="addFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="Inspector">
<el-input v-model="addFormData.inspector" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第五行 --> <!-- 第五行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24">
<el-col :span="18">
<el-form-item label="问题详细描述"> <el-form-item label="问题详细描述">
<el-input <el-input
v-model="addFormData.issueDescription" v-model="addFormData.issueDescription"
@ -199,6 +292,40 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<!-- 第六行 -->
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="Level">
<el-input v-model="addFormData.levelNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 1">
<el-select v-model="addFormData.mode1" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Appearance" value="Appearance"></el-option>
<el-option label="Function" value="Function"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 2">
<el-select v-model="addFormData.mode2" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Loose part" value="Loose part"></el-option>
<el-option label="Others" value="Others"></el-option>
<el-option label="Contamination" value="Contamination"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 3">
<el-select v-model="addFormData.mode3" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Part Missing" value="Part Missing"></el-option>
<el-option label="Glue" value="Glue"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -211,20 +338,20 @@
<el-dialog <el-dialog
title="质量问题 - 编辑" title="质量问题 - 编辑"
:visible.sync="editDialogVisible" :visible.sync="editDialogVisible"
width="45%"
top="10vh"
width="70%"
top="5vh"
:close-on-click-modal="false" :close-on-click-modal="false"
@close="handleCloseEditDialog"> @close="handleCloseEditDialog">
<el-form :model="editFormData" :rules="editRules" ref="editFormData" label-width="110px" size="mini" class="add-dialog-form"> <el-form :model="editFormData" :rules="editRules" ref="editFormData" label-width="110px" size="mini" class="add-dialog-form">
<!-- 第一行 --> <!-- 第一行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-col :span="6">
<el-form-item label="反馈单号"> <el-form-item label="反馈单号">
<el-input v-model="editFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input> <el-input v-model="editFormData.issueNo" placeholder="自动生成" disabled size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-col :span="6">
<el-form-item label="问题日期" prop="issueDate"> <el-form-item label="问题日期" prop="issueDate">
<el-date-picker <el-date-picker
v-model="editFormData.issueDate" v-model="editFormData.issueDate"
@ -236,7 +363,7 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-col :span="6">
<el-form-item label="要求回复日期" prop="requireReplyDate"> <el-form-item label="要求回复日期" prop="requireReplyDate">
<el-date-picker <el-date-picker
v-model="editFormData.requireReplyDate" v-model="editFormData.requireReplyDate"
@ -248,11 +375,62 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="状态">
<el-input v-model="editFormData.status" disabled size="mini"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 新增行PO No批次数量拒收批次数量投诉接收日期样品接收日期 -->
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="PO No">
<el-input v-model="editFormData.poNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="批次数量">
<el-input v-model="editFormData.batchQty" placeholder="请输入" size="mini" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="拒收批次数量">
<el-input v-model="editFormData.rejectBatchQty" placeholder="请输入" size="mini" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="投诉接收日期">
<el-date-picker
v-model="editFormData.receiveComplaintDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
size="mini"
style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="样品接收日期">
<el-date-picker
v-model="editFormData.receiveSampleDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
size="mini"
style="width: 100%">
</el-date-picker>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第二行 --> <!-- 第二行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-col :span="6">
<el-form-item label="供应商编码"> <el-form-item label="供应商编码">
<el-input v-model="editFormData.supplierNo" disabled size="mini"></el-input> <el-input v-model="editFormData.supplierNo" disabled size="mini"></el-input>
</el-form-item> </el-form-item>
@ -262,35 +440,61 @@
<el-input v-model="editFormData.supplierName" disabled size="mini"></el-input> <el-input v-model="editFormData.supplierName" disabled size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="供应商负责人">
<el-input v-model="editFormData.supplierResponsible" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第三行 --> <!-- 第三行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="8">
<el-form-item label="问题分类" prop="issueCategory">
<el-select v-model="editFormData.issueCategory" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="产品外观" value="产品外观"></el-option>
<el-option label="产品性能" value="产品性能"></el-option>
<el-option label="尺寸不符" value="尺寸不符"></el-option>
<el-option label="材质问题" value="材质问题"></el-option>
<el-option label="包装破损" value="包装破损"></el-option>
<el-col :span="6">
<el-form-item label="Plant">
<el-select v-model="editFormData.plant" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Mx : Mexico" value="Mx"></el-option>
<el-option label="IR : Ireland" value="IR"></el-option>
<el-option label="TN : Tennessee" value="TN"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="Claim No">
<el-input v-model="editFormData.claimNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Product Category">
<el-select v-model="editFormData.productCategory" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Metal Pen" value="Metal Pen"></el-option>
<el-option label="CUP" value="CUP"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Part No">
<el-input v-model="editFormData.partNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第四行 --> <!-- 第四行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24">
<el-col :span="18">
<el-form-item label="问题简述" prop="issueSummary"> <el-form-item label="问题简述" prop="issueSummary">
<el-input v-model="editFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input> <el-input v-model="editFormData.issueSummary" placeholder="请输入问题简述" size="mini"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6">
<el-form-item label="Inspector">
<el-input v-model="editFormData.inspector" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 第五行 --> <!-- 第五行 -->
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24">
<el-col :span="18">
<el-form-item label="问题详细描述"> <el-form-item label="问题详细描述">
<el-input <el-input
v-model="editFormData.issueDescription" v-model="editFormData.issueDescription"
@ -302,6 +506,40 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<!-- 第六行 -->
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="Level">
<el-input v-model="editFormData.levelNo" placeholder="请输入" size="mini"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 1">
<el-select v-model="editFormData.mode1" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Appearance" value="Appearance"></el-option>
<el-option label="Function" value="Function"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 2">
<el-select v-model="editFormData.mode2" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Loose part" value="Loose part"></el-option>
<el-option label="Others" value="Others"></el-option>
<el-option label="Contamination" value="Contamination"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Mode 3">
<el-select v-model="editFormData.mode3" placeholder="请选择" size="mini" style="width: 100%">
<el-option label="Part Missing" value="Part Missing"></el-option>
<el-option label="Glue" value="Glue"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -343,6 +581,14 @@
</div> </div>
<el-form :model="replyFormData" :rules="replyRules" ref="replyFormData" label-position="top" size="mini" class="reply-dialog-form"> <el-form :model="replyFormData" :rules="replyRules" ref="replyFormData" label-position="top" size="mini" class="reply-dialog-form">
<!-- Why Escape 下拉框 -->
<el-form-item label="Why Escape" prop="whyEscape">
<el-select v-model="replyFormData.whyEscape" placeholder="请选择流出原因" size="mini" style="width: 30%" clearable>
<el-option label="AQL" value="AQL"></el-option>
<el-option label="Transportation" value="Transportation"></el-option>
</el-select>
</el-form-item>
<!-- 原因分析 --> <!-- 原因分析 -->
<el-form-item label="原因分析" prop="analysis"> <el-form-item label="原因分析" prop="analysis">
<el-input <el-input
@ -372,12 +618,65 @@
</div> </div>
</el-dialog> </el-dialog>
<!-- 赔偿弹窗 -->
<el-dialog
title="质量问题 - 赔偿"
:visible.sync="compensationDialogVisible"
width="50%"
top="10vh"
:close-on-click-modal="false"
@close="handleCloseCompensationDialog">
<div class="compensation-dialog-info">
<el-row :gutter="20">
<el-col :span="8">
<div class="info-item">
<span class="info-label">反馈单号</span>
<span class="info-value">{{ compensationFormData.issueNo }}</span>
</div>
</el-col>
</el-row>
</div>
<el-form :model="compensationFormData" :rules="compensationRules" ref="compensationFormData" label-position="top" size="mini" class="compensation-dialog-form">
<!-- 索赔信息和被索赔金额 -->
<el-row :gutter="10">
<el-col :span="8">
<el-form-item label="索赔信息">
<el-checkbox v-model="compensationFormData.isClaimed">是否被索赔</el-checkbox>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="被索赔金额" prop="claimAmount">
<el-input v-model="compensationFormData.claimAmount" placeholder="请输入被索赔金额" size="mini"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 处置备注 -->
<el-form-item label="处置备注">
<el-input
v-model="compensationFormData.disposalRemark"
type="textarea"
:rows="3"
placeholder="请输入处置备注"
size="mini">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSaveCompensation" class="customer-bun-min">保存</el-button>
<el-button @click="handleCloseCompensationDialog" class="customer-bun-min">关闭</el-button>
</div>
</el-dialog>
<Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist> <Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist>
</div> </div>
</template> </template>
<script> <script>
import { queryQualityIssuePage, saveQualityIssue,deleteQualityIssue,updateQualityIssue, saveReply } from '@/api/quality/qualityIssue.js'
import { queryQualityIssuePage, saveQualityIssue,deleteQualityIssue,updateQualityIssue, saveReply, saveClaim, closeQualityIssue } from '@/api/quality/qualityIssue.js'
import Chooselist from '@/views/modules/common/Chooselist_eam' import Chooselist from '@/views/modules/common/Chooselist_eam'
import ComQualityIssueDetail from './com_qualityIssueDetail.vue' import ComQualityIssueDetail from './com_qualityIssueDetail.vue'
import ComQualityIssueAttachment from './com_qualityIssueAttachment.vue' import ComQualityIssueAttachment from './com_qualityIssueAttachment.vue'
@ -404,9 +703,25 @@ export default {
requireReplyDate: '', requireReplyDate: '',
supplierNo: '', supplierNo: '',
supplierName: '', supplierName: '',
supplierResponsible: '',
plant: '',
claimNo: '',
productCategory: '',
partNo: '',
poNo: '',
batchQty: '',
rejectBatchQty: '',
receiveComplaintDate: '',
receiveSampleDate: '',
issueCategory: '', issueCategory: '',
issueSummary: '', issueSummary: '',
issueDescription: ''
issueDescription: '',
inspector: '',
levelNo: '',
mode1: '',
mode2: '',
mode3: '',
status: '已确认'
}, },
addRules: { addRules: {
issueDate: [ issueDate: [
@ -433,9 +748,25 @@ export default {
requireReplyDate: '', requireReplyDate: '',
supplierNo: '', supplierNo: '',
supplierName: '', supplierName: '',
supplierResponsible: '',
plant: '',
claimNo: '',
productCategory: '',
partNo: '',
poNo: '',
batchQty: '',
rejectBatchQty: '',
receiveComplaintDate: '',
receiveSampleDate: '',
issueCategory: '', issueCategory: '',
issueSummary: '', issueSummary: '',
issueDescription: '', issueDescription: '',
inspector: '',
levelNo: '',
mode1: '',
mode2: '',
mode3: '',
status: '',
site: '' site: ''
}, },
editRules: { editRules: {
@ -459,6 +790,7 @@ export default {
issueNo: '', issueNo: '',
analysis: '', analysis: '',
correctiveAction: '', correctiveAction: '',
whyEscape:'',
replyBy: '', replyBy: '',
replyTime: '' replyTime: ''
}, },
@ -470,6 +802,20 @@ export default {
{ required: true, message: '请输入后续措施', trigger: 'blur' } { required: true, message: '请输入后续措施', trigger: 'blur' }
] ]
}, },
//
compensationDialogVisible: false,
compensationFormData: {
site: '',
issueNo: '',
isClaimed: false,
claimAmount: '',
disposalRemark: ''
},
compensationRules: {
claimAmount: [
{ required: true, message: '请输入被索赔金额', trigger: 'blur' }
]
},
tagNo: '', tagNo: '',
searchData: { searchData: {
issueNo: '', issueNo: '',
@ -783,9 +1129,25 @@ export default {
requireReplyDate: '', requireReplyDate: '',
supplierNo: '', supplierNo: '',
supplierName: '', supplierName: '',
supplierResponsible: '',
plant: '',
claimNo: '',
productCategory: '',
partNo: '',
poNo: '',
batchQty: '',
rejectBatchQty: '',
receiveComplaintDate: '',
receiveSampleDate: '',
issueCategory: '', issueCategory: '',
issueSummary: '', issueSummary: '',
issueDescription: ''
issueDescription: '',
inspector: '',
levelNo: '',
mode1: '',
mode2: '',
mode3: '',
status: '已确认'
} }
if (this.$refs.addFormData) { if (this.$refs.addFormData) {
this.$refs.addFormData.clearValidate() this.$refs.addFormData.clearValidate()
@ -800,13 +1162,29 @@ export default {
requireReplyDate: '', requireReplyDate: '',
supplierNo: '', supplierNo: '',
supplierName: '', supplierName: '',
supplierResponsible: '',
plant: '',
claimNo: '',
productCategory: '',
partNo: '',
poNo: '',
batchQty: '',
rejectBatchQty: '',
receiveComplaintDate: '',
receiveSampleDate: '',
issueCategory: '', issueCategory: '',
issueSummary: '', issueSummary: '',
issueDescription: '', issueDescription: '',
inspector: '',
levelNo: '',
mode1: '',
mode2: '',
mode3: '',
status: '',
site: '' site: ''
} }
if (this.$refs.currentFormData) {
this.$refs.currentFormData.clearValidate()
if (this.$refs.editFormData) {
this.$refs.editFormData.clearValidate()
} }
}, },
@ -829,9 +1207,25 @@ export default {
requireReplyDate: this.addFormData.requireReplyDate, requireReplyDate: this.addFormData.requireReplyDate,
supplierNo: this.addFormData.supplierNo, supplierNo: this.addFormData.supplierNo,
supplierName: this.addFormData.supplierName, supplierName: this.addFormData.supplierName,
supplierResponsible: this.addFormData.supplierResponsible,
plant: this.addFormData.plant,
claimNo: this.addFormData.claimNo,
productCategory: this.addFormData.productCategory,
partNo: this.addFormData.partNo,
poNo: this.addFormData.poNo,
batchQty: this.addFormData.batchQty ? parseFloat(this.addFormData.batchQty) : null,
rejectBatchQty: this.addFormData.rejectBatchQty ? parseFloat(this.addFormData.rejectBatchQty) : null,
receiveComplaintDate: this.addFormData.receiveComplaintDate,
receiveSampleDate: this.addFormData.receiveSampleDate,
issueCategory: this.addFormData.issueCategory, issueCategory: this.addFormData.issueCategory,
issueSummary: this.addFormData.issueSummary, issueSummary: this.addFormData.issueSummary,
issueDescription: this.addFormData.issueDescription, issueDescription: this.addFormData.issueDescription,
inspector: this.addFormData.inspector,
levelNo: this.addFormData.levelNo,
mode1: this.addFormData.mode1,
mode2: this.addFormData.mode2,
mode3: this.addFormData.mode3,
status: this.addFormData.status,
site: this.$store.state.user.site site: this.$store.state.user.site
} }
@ -867,9 +1261,25 @@ export default {
issueNo: this.editFormData.issueNo, issueNo: this.editFormData.issueNo,
issueDate: this.editFormData.issueDate, issueDate: this.editFormData.issueDate,
requireReplyDate: this.editFormData.requireReplyDate, requireReplyDate: this.editFormData.requireReplyDate,
supplierResponsible: this.editFormData.supplierResponsible,
plant: this.editFormData.plant,
claimNo: this.editFormData.claimNo,
productCategory: this.editFormData.productCategory,
partNo: this.editFormData.partNo,
poNo: this.editFormData.poNo,
batchQty: this.editFormData.batchQty ? parseFloat(this.editFormData.batchQty) : null,
rejectBatchQty: this.editFormData.rejectBatchQty ? parseFloat(this.editFormData.rejectBatchQty) : null,
receiveComplaintDate: this.editFormData.receiveComplaintDate,
receiveSampleDate: this.editFormData.receiveSampleDate,
issueCategory: this.editFormData.issueCategory, issueCategory: this.editFormData.issueCategory,
issueSummary: this.editFormData.issueSummary, issueSummary: this.editFormData.issueSummary,
issueDescription: this.editFormData.issueDescription
issueDescription: this.editFormData.issueDescription,
inspector: this.editFormData.inspector,
levelNo: this.editFormData.levelNo,
mode1: this.editFormData.mode1,
mode2: this.editFormData.mode2,
mode3: this.editFormData.mode3,
status: this.editFormData.status
} }
console.log('更新数据:', submitData) console.log('更新数据:', submitData)
@ -904,9 +1314,25 @@ export default {
requireReplyDate: row.requireReplyDate || '', requireReplyDate: row.requireReplyDate || '',
supplierNo: row.supplierNo || '', supplierNo: row.supplierNo || '',
supplierName: row.supplierName || '', supplierName: row.supplierName || '',
supplierResponsible: row.supplierResponsible || '',
plant: row.plant || '',
claimNo: row.claimNo || '',
productCategory: row.productCategory || '',
partNo: row.partNo || '',
poNo: row.poNo || '',
batchQty: row.batchQty || '',
rejectBatchQty: row.rejectBatchQty || '',
receiveComplaintDate: row.receiveComplaintDate || '',
receiveSampleDate: row.receiveSampleDate || '',
issueCategory: row.issueCategory || '', issueCategory: row.issueCategory || '',
issueSummary: row.issueSummary || '', issueSummary: row.issueSummary || '',
issueDescription: row.issueDescription || '', issueDescription: row.issueDescription || '',
inspector: row.inspector || '',
levelNo: row.levelNo || '',
mode1: row.mode1 || '',
mode2: row.mode2 || '',
mode3: row.mode3 || '',
status: row.status || '',
site: row.site || this.$store.state.user.site site: row.site || this.$store.state.user.site
} }
// //
@ -980,8 +1406,9 @@ export default {
this.replyFormData = { this.replyFormData = {
site: row.site || this.$store.state.user.site, site: row.site || this.$store.state.user.site,
issueNo: row.issueNo || '', issueNo: row.issueNo || '',
analysis: '',
correctiveAction: '',
analysis: row.analysis || '', //
correctiveAction: row.correctiveAction || '', //
whyEscape: row.whyEscape || '', //
replyBy: this.$store.state.user.name || '', replyBy: this.$store.state.user.name || '',
replyTime: currentDate replyTime: currentDate
} }
@ -1018,12 +1445,13 @@ export default {
handleSaveReply () { handleSaveReply () {
this.$refs.replyFormData.validate((valid) => { this.$refs.replyFormData.validate((valid) => {
if (valid) { if (valid) {
//
// - whyEscape
const submitData = { const submitData = {
site: this.replyFormData.site, site: this.replyFormData.site,
issueNo: this.replyFormData.issueNo, issueNo: this.replyFormData.issueNo,
analysis: this.replyFormData.analysis, analysis: this.replyFormData.analysis,
correctiveAction: this.replyFormData.correctiveAction
correctiveAction: this.replyFormData.correctiveAction,
whyEscape: this.replyFormData.whyEscape //
} }
console.log('回复数据:', submitData) console.log('回复数据:', submitData)
@ -1048,6 +1476,124 @@ export default {
}) })
}, },
//
compensationQualityIssue (row) {
this.compensationDialogVisible = true
//
this.compensationFormData = {
site: row.site || this.$store.state.user.site,
issueNo: row.issueNo || '',
isClaimed: row.claimFlag === 'Y' ? true : false,
claimAmount: row.claimAmount || '',
disposalRemark: row.disposalRemark || ''
}
//
this.$nextTick(() => {
if (this.$refs.compensationFormData) {
this.$refs.compensationFormData.clearValidate()
}
})
},
//
handleCloseCompensationDialog () {
this.compensationDialogVisible = false
this.resetCompensationForm()
},
//
resetCompensationForm () {
this.compensationFormData = {
site: '',
issueNo: '',
isClaimed: false,
claimAmount: '',
disposalRemark: ''
}
if (this.$refs.compensationFormData) {
this.$refs.compensationFormData.clearValidate()
}
},
//
handleSaveCompensation () {
this.$refs.compensationFormData.validate((valid) => {
if (valid) {
// - isClaimedclaimFlagY/N
const submitData = {
site: this.compensationFormData.site,
issueNo: this.compensationFormData.issueNo,
claimFlag: this.compensationFormData.isClaimed ? 'Y' : 'N',
claimAmount: this.compensationFormData.claimAmount ? parseFloat(this.compensationFormData.claimAmount) : null,
disposalRemark: this.compensationFormData.disposalRemark
}
console.log('赔偿数据:', submitData)
//
saveClaim(submitData).then(({ data }) => {
if (data.code === 0) {
this.$message.success('保存成功')
this.handleCloseCompensationDialog()
this.getMainData()
} else {
this.$message.error(data.msg || '保存失败')
}
}).catch((error) => {
console.error('赔偿接口错误:', error)
this.$message.error('保存失败,请稍后重试')
})
} else {
console.log('表单验证失败')
this.$message.warning('请填写完整的赔偿信息')
}
})
},
//
closeQualityIssueAction (row) {
this.$confirm('确定要关闭该质量问题吗?关闭后将无法修改!', '提示', {
confirmButtonText: '确定关闭',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
//
const loading = this.$loading({
lock: true,
text: '关闭中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
//
const closeParams = {
site: row.site || this.$store.state.user.site,
issueNo: row.issueNo
};
console.log('关闭参数:', closeParams);
//
closeQualityIssue(closeParams).then(({ data }) => {
loading.close();
if (data.code === 0) {
this.$message.success('关闭成功');
this.getMainData();
} else {
this.$message.error(data.msg || '关闭失败');
}
}).catch((error) => {
loading.close();
console.error('关闭接口错误:', error);
this.$message.error('关闭失败,请稍后重试');
});
}).catch(() => {
this.$message.info('已取消关闭');
});
},
// //
exportExcel () { exportExcel () {
console.log('开始导出...') console.log('开始导出...')
@ -1157,16 +1703,16 @@ export default {
} }
.add-dialog-form /deep/ .el-form-item { .add-dialog-form /deep/ .el-form-item {
margin-bottom: 10px;
margin-bottom: 8px;
} }
.add-dialog-form /deep/ .el-form-item__label { .add-dialog-form /deep/ .el-form-item__label {
text-align: left; text-align: left;
float: none; float: none;
display: block; display: block;
padding: 0 0 5px 0;
padding: 0 0 3px 0;
line-height: 1; line-height: 1;
font-size: 13px;
font-size: 12px;
} }
.add-dialog-form /deep/ .el-form-item__content { .add-dialog-form /deep/ .el-form-item__content {
@ -1225,4 +1771,52 @@ export default {
line-height: normal; line-height: normal;
} }
/* 赔偿弹窗样式 */
.compensation-dialog-info {
margin-bottom: 20px;
padding: 15px;
background-color: #f5f7fa;
border-radius: 4px;
}
.compensation-dialog-info .info-item {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.compensation-dialog-info .info-item:last-child {
margin-bottom: 0;
}
.compensation-dialog-info .info-label {
font-size: 13px;
color: #606266;
font-weight: 500;
min-width: 80px;
}
.compensation-dialog-info .info-value {
font-size: 13px;
color: #303133;
flex: 1;
}
.compensation-dialog-form /deep/ .el-form-item {
margin-bottom: 15px;
}
.compensation-dialog-form /deep/ .el-form-item__label {
font-size: 13px;
color: #606266;
font-weight: 500;
padding-bottom: 5px;
line-height: 1;
height: auto;
}
.compensation-dialog-form /deep/ .el-form-item__content {
line-height: normal;
}
</style> </style>
Loading…
Cancel
Save