<template>
|
<div>
|
<el-dialog
|
v-model="dialogFormVisible"
|
:title="operationType === 'add' ? '新增不合格品处理单' : '编辑不合格品处理单'"
|
width="80%"
|
@close="closeDia"
|
>
|
<el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
|
<!-- 第一行:项目名称、项目编号 -->
|
<el-row :gutter="30">
|
<el-col :span="12">
|
<el-form-item label="项目名称:" prop="projectName">
|
<el-input v-model="form.projectName" placeholder="请输入项目名称" clearable/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="项目编号:" prop="projectNo">
|
<el-input v-model="form.projectNo" placeholder="请输入项目编号" clearable/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第二行:设备名称、设备图号 -->
|
<el-row :gutter="30">
|
<el-col :span="12">
|
<el-form-item label="设备名称:" prop="equipmentName">
|
<el-input v-model="form.equipmentName" placeholder="请输入设备名称" clearable/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="设备图号:" prop="equipmentDrawingNo">
|
<el-input v-model="form.equipmentDrawingNo" placeholder="请输入设备图号" clearable/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第三行:物料/部件名称、物料图号 -->
|
<el-row :gutter="30">
|
<el-col :span="12">
|
<el-form-item label="物料/部件名称:" prop="materialName">
|
<el-input v-model="form.materialName" placeholder="请输入物料/部件名称" clearable/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="物料图号:" prop="materialDrawingNo">
|
<el-input v-model="form.materialDrawingNo" placeholder="请输入物料图号" clearable/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第四行:型号规格、材质、数量、不合格数 -->
|
<el-row :gutter="30">
|
<el-col :span="6">
|
<el-form-item label="型号规格:" prop="specificationModel">
|
<el-input v-model="form.specificationModel" placeholder="请输入型号规格" clearable/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="材质:" prop="materialQuality">
|
<el-input v-model="form.materialQuality" placeholder="请输入材质" clearable/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="数量:" prop="quantity">
|
<el-input-number :step="1" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入数量" :precision="0"/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="不合格数:" prop="unqualifiedQuantity">
|
<el-input-number :step="1" :min="0" style="width: 100%" v-model="form.unqualifiedQuantity" placeholder="请输入不合格数" :precision="0"/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第五行:不合格工序、供货商名称 -->
|
<el-row :gutter="30">
|
<el-col :span="12">
|
<el-form-item label="不合格工序:" prop="unqualifiedProcess">
|
<el-radio-group v-model="form.unqualifiedProcess">
|
<el-radio :label="1">来料</el-radio>
|
<el-radio :label="2">制程</el-radio>
|
<el-radio :label="3">成品</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="供货商名称:" prop="supplierName">
|
<el-input v-model="form.supplierName" placeholder="请输入供货商名称" clearable/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第六行:检验员、检验日期、责任人、责任部门 -->
|
<el-row :gutter="30">
|
<el-col :span="6">
|
<el-form-item label="检验员:" prop="inspectorName">
|
<el-select v-model="form.inspectorName" placeholder="请选择" clearable style="width: 100%">
|
<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="检验日期:" prop="inspectDate">
|
<el-date-picker
|
v-model="form.inspectDate"
|
type="date"
|
placeholder="请选择日期"
|
value-format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
clearable
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="责任人:" prop="responsiblePerson">
|
<el-select v-model="form.responsiblePerson" placeholder="请选择" clearable style="width: 100%">
|
<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="6">
|
<el-form-item label="责任部门:" prop="responsibleDept">
|
<el-input v-model="form.responsibleDept" placeholder="请输入责任部门" clearable/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第七行:问题描述 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="问题描述:" prop="problemDescription">
|
<el-input
|
v-model="form.problemDescription"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入问题描述"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第八行:原因分析及建议 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="原因分析及建议:" prop="reasonAnalysis">
|
<el-input
|
v-model="form.reasonAnalysis"
|
type="textarea"
|
:rows="4"
|
placeholder="请输入原因分析及建议"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第九行:纠正措施 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="纠正措施:" prop="correctionAction">
|
<el-input
|
v-model="form.correctionAction"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入纠正措施"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十行:处置方式 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="处置方式:" prop="disposalMethod">
|
<el-radio-group v-model="form.disposalMethod">
|
<el-radio :label="1">让步接收</el-radio>
|
<el-radio :label="2">厂内维修</el-radio>
|
<el-radio :label="3">返厂维修</el-radio>
|
<el-radio :label="4">换货</el-radio>
|
<el-radio :label="5">退货</el-radio>
|
<el-radio :label="6">报废</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十一行:厂内/返厂维修评估 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="厂内/返厂维修评估:" prop="repairEvaluation">
|
<el-input
|
v-model="form.repairEvaluation"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入厂内/返厂维修评估"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十二行:预防措施 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="预防措施:" prop="preventiveAction">
|
<el-input
|
v-model="form.preventiveAction"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入预防措施"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十三行:状态 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="状态:" prop="status">
|
<el-radio-group v-model="form.status">
|
<el-radio :label="0">草稿</el-radio>
|
<el-radio :label="1">待审核</el-radio>
|
<el-radio :label="2">审批中</el-radio>
|
<el-radio :label="3">已完成</el-radio>
|
<el-radio :label="4">已驳回</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十四行:备注 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="备注:" prop="remark">
|
<el-input
|
v-model="form.remark"
|
type="textarea"
|
:rows="3"
|
placeholder="请输入备注"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<!-- 第十五行:不良品照片 -->
|
<el-row :gutter="30">
|
<el-col :span="24">
|
<el-form-item label="不良品照片:" prop="defectivePhotos">
|
<el-upload
|
v-model:file-list="defectivePhotoFileList"
|
:action="upload.url"
|
multiple
|
ref="defectivePhotoUploadRef"
|
auto-upload
|
accept="image/*"
|
:headers="upload.headers"
|
:before-upload="handleBeforeUpload"
|
:on-error="handleUploadError"
|
:on-success="handleDefectivePhotoUploadSuccess"
|
:on-remove="handleDefectivePhotoRemove"
|
>
|
<el-button type="primary" v-if="operationType !== 'view'">上传</el-button>
|
<template #tip v-if="operationType !== 'view'">
|
<div class="el-upload__tip">
|
文件格式支持 jpg,jpeg,png,gif,bmp
|
</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="submitForm">确认</el-button>
|
<el-button @click="closeDia">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, toRefs, getCurrentInstance } from "vue";
|
import {
|
getQualityUnqualifiedInfo,
|
qualityUnqualifiedAdd,
|
qualityUnqualifiedUpdate
|
} from "@/api/qualityManagement/nonconformingManagement.js";
|
import {userListNoPage} from "@/api/system/user.js";
|
import useUserStore from "@/store/modules/user";
|
import { getToken } from "@/utils/auth";
|
const { proxy } = getCurrentInstance()
|
const userStore = useUserStore()
|
const emit = defineEmits(['close'])
|
|
const dialogFormVisible = ref(false);
|
const operationType = ref('')
|
const defectivePhotoFileList = ref([]);
|
const defectivePhotoUploadRef = ref(null);
|
const upload = reactive({
|
url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
|
headers: { Authorization: "Bearer " + getToken() },
|
});
|
|
const data = reactive({
|
form: {
|
// 基本信息
|
projectName: '',
|
projectNo: '',
|
equipmentName: '',
|
equipmentDrawingNo: '',
|
materialName: '',
|
materialDrawingNo: '',
|
specificationModel: '',
|
materialQuality: '',
|
quantity: 0,
|
unqualifiedQuantity: 0,
|
unqualifiedProcess: undefined,
|
supplierName: '',
|
inspectorName: '',
|
inspectDate: '',
|
responsiblePerson: '',
|
responsibleDept: '',
|
|
// 问题描述和处理
|
problemDescription: '',
|
reasonAnalysis: '',
|
correctionAction: '',
|
disposalMethod: undefined,
|
repairEvaluation: '',
|
preventiveAction: '',
|
|
// 状态
|
status: 0,
|
remark: '',
|
|
// 附件
|
defectivePhotos: '',
|
tempFileIds: [],
|
},
|
rules: {
|
projectName: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
|
materialName: [{ required: true, message: "请输入物料/部件名称", trigger: "blur" }],
|
quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
|
unqualifiedQuantity: [{ required: true, message: "请输入不合格数", trigger: "blur" }],
|
inspectorName: [{ required: true, message: "请选择检验员", trigger: "change" }],
|
inspectDate: [{ required: true, message: "请选择检验日期", trigger: "change" }],
|
problemDescription: [{ required: true, message: "请输入问题描述", trigger: "blur" }],
|
},
|
});
|
|
const { form, rules } = toRefs(data);
|
const userList = ref([]); // 检验员/责任人下拉列表
|
|
// 打开弹框
|
const openDialog = async (type, row) => {
|
operationType.value = type;
|
try {
|
const userRes = await userListNoPage();
|
userList.value = userRes.data || [];
|
} catch (e) {
|
console.error("加载用户列表失败", e);
|
userList.value = [];
|
}
|
dialogFormVisible.value = true;
|
if (operationType.value === 'add') {
|
defectivePhotoFileList.value = [];
|
form.value = {
|
projectName: '',
|
projectNo: '',
|
equipmentName: '',
|
equipmentDrawingNo: '',
|
materialName: '',
|
materialDrawingNo: '',
|
specificationModel: '',
|
materialQuality: '',
|
quantity: 0,
|
unqualifiedQuantity: 0,
|
unqualifiedProcess: undefined,
|
supplierName: '',
|
inspectorName: userStore.nickName || '',
|
inspectDate: '',
|
responsiblePerson: '',
|
responsibleDept: '',
|
problemDescription: '',
|
reasonAnalysis: '',
|
correctionAction: '',
|
disposalMethod: undefined,
|
repairEvaluation: '',
|
preventiveAction: '',
|
status: 0,
|
remark: '',
|
defectivePhotos: '',
|
tempFileIds: [],
|
};
|
} else {
|
defectivePhotoFileList.value = [];
|
form.value = {};
|
}
|
|
if (operationType.value === 'edit') {
|
getQualityUnqualifiedInfo(row.id).then(res => {
|
const data = res.data?.records?.[0] || res.data || {}
|
form.value = { ...data }
|
})
|
}
|
}
|
|
// 提交产品表单
|
const submitForm = () => {
|
proxy.$refs.formRef.validate(valid => {
|
if (valid) {
|
if (operationType.value === "add") {
|
qualityUnqualifiedAdd(form.value).then(res => {
|
proxy.$modal.msgSuccess("提交成功");
|
closeDia();
|
})
|
} else {
|
qualityUnqualifiedUpdate(form.value).then(res => {
|
proxy.$modal.msgSuccess("提交成功");
|
closeDia();
|
})
|
}
|
}
|
})
|
}
|
|
// 上传前校检
|
function handleBeforeUpload() {
|
proxy.$modal.loading("正在上传文件,请稍候...");
|
return true;
|
}
|
|
function handleUploadError() {
|
proxy.$modal.msgError("上传文件失败");
|
proxy.$modal.closeLoading();
|
}
|
|
// 不良品照片上传成功
|
function handleDefectivePhotoUploadSuccess(res, file) {
|
proxy.$modal.closeLoading();
|
if (res?.code === 200) {
|
const tempId = res?.data?.tempId;
|
const tempPath = res?.data?.tempPath || res?.data?.url || "";
|
const originalName = res?.data?.originalName || file?.name || "图片";
|
|
if (!form.value.tempFileIds) form.value.tempFileIds = [];
|
if (tempId) form.value.tempFileIds.push(tempId);
|
|
file.url = tempPath;
|
file.name = originalName;
|
} else {
|
proxy.$modal.msgError(res?.msg || "上传失败");
|
}
|
}
|
|
// 不良品照片移除
|
function handleDefectivePhotoRemove(file, fileList) {
|
const tempId = file?.response?.data?.tempId;
|
if (tempId && form.value.tempFileIds) {
|
const idx = form.value.tempFileIds.indexOf(tempId);
|
if (idx > -1) form.value.tempFileIds.splice(idx, 1);
|
}
|
defectivePhotoFileList.value = fileList;
|
}
|
|
const closeDia = () => {
|
dialogFormVisible.value = false;
|
emit('close')
|
}
|
|
defineExpose({
|
openDialog,
|
})
|
</script>
|