| src/api/consumablesLogistics/consumablesInRecord.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/consumablesLogistics/consumablesOutRecord.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/consumablesLogistics/dispatchLog/Record.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/consumablesLogistics/receiptManagement/Record.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/nonconformingManagement/components/formDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/nonconformingManagement/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/rawMaterial/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/consumablesLogistics/consumablesInRecord.js
@@ -17,6 +17,15 @@ }); }; // 编辑耗材入库(仅用于台账编辑) export const editStockInStock = (data) => { return request({ url: "/consumablesInRecord/editStockInStock", method: "post", data, }); }; export const batchDeleteConsumablesInRecords = (ids) => { return request({ url: "/consumablesInRecord", src/api/consumablesLogistics/consumablesOutRecord.js
@@ -17,3 +17,12 @@ data: ids, }); }; // 编辑耗材出库(仅用于台账编辑) export const editStockOut = (data) => { return request({ url: "/consumablesOutRecord/editStockOut", method: "post", data, }); }; src/views/consumablesLogistics/dispatchLog/Record.vue
@@ -28,7 +28,12 @@ </div> <div> <el-button @click="handleOut">导出</el-button> <el-button type="danger" plain @click="handleDelete">删除</el-button> <el-button type="danger" plain @click="handleDelete" v-if="hasCDispatchCancel" >删除</el-button> <!-- <el-button type="primary" plain @click="handlePrint">打印</el-button> --> </div> </div> @@ -86,6 +91,16 @@ prop="createBy" show-overflow-tooltip /> <el-table-column label="操作" width="160" align="center"> <template #default="scope"> <el-button v-if="hasCDispatchEdit" type="primary" size="mini" @click="handleEdit(scope.row)" >编辑</el-button> </template> </el-table-column> <!-- <el-table-column label="来源" prop="recordType" show-overflow-tooltip> @@ -105,21 +120,66 @@ /> </div> </div> <el-dialog title="编辑出库信息" v-model="isShowEditModal" width="600px" > <el-form ref="editFormRef" :model="editForm" label-width="90px" > <el-form-item label="数量" prop="qualitity" :rules="[{ required: true, message: '请输入数量', trigger: ['blur', 'change'] }]" > <el-input-number v-model="editForm.qualitity" :min="0" :step="1" :precision="0" controls-position="right" style="width: 100%" placeholder="请输入数量" /> </el-form-item> <el-form-item label="采购员" prop="purchaser" :rules="[{ required: true, message: '请输入采购员', trigger: ['blur', 'change'] }]" > <el-input v-model="editForm.purchaser" placeholder="请输入采购员" /> </el-form-item> </el-form> <template #footer> <el-button @click="closeEditModal">取消</el-button> <el-button type="primary" @click="handleEditSubmit">确定</el-button> </template> </el-dialog> </template> <script setup> import pagination from "@/components/PIMTable/Pagination.vue"; import { ref, reactive, toRefs, getCurrentInstance } from "vue"; import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue"; import { ElMessageBox } from "element-plus"; import useUserStore from "@/store/modules/user"; import { getCurrentDate } from "@/utils/index.js"; import { getConsumablesOutRecordPage, delConsumablesOutRecord, editStockOut, } from "@/api/consumablesLogistics/consumablesOutRecord.js"; import { findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions, } from "@/api/basicData/enum.js"; import { checkPermi } from "@/utils/permission.js"; const userStore = useUserStore(); const { proxy } = getCurrentInstance(); @@ -142,6 +202,46 @@ } }) const hasCDispatchEdit = computed(() => checkPermi(['c_dispatch_edit'])); const hasCDispatchCancel = computed(() => checkPermi(['c_dispatch_cancel'])); // 编辑弹框数据 const isShowEditModal = ref(false); const editFormRef = ref(); const editForm = reactive({ id: undefined, qualitity: undefined, purchaser: "", }); const handleEdit = (row) => { editForm.id = row.id; editForm.qualitity = row.qualitity; editForm.purchaser = row.purchaser ?? ""; isShowEditModal.value = true; }; const closeEditModal = () => { isShowEditModal.value = false; editForm.id = undefined; editForm.qualitity = undefined; editForm.purchaser = ""; editFormRef.value?.clearValidate?.(); }; const handleEditSubmit = () => { editFormRef.value?.validate?.((valid) => { if (!valid) return; editStockOut({ ...editForm }).then(() => { closeEditModal(); proxy.$modal.msgSuccess("编辑成功"); getList(); }); }); }; // 打印相关 const printPreviewVisible = ref(false); const printData = ref([]); src/views/consumablesLogistics/receiptManagement/Record.vue
@@ -34,7 +34,8 @@ <el-button @click="handleOut">导出</el-button> <el-button type="danger" plain @click="handleDelete">删除 @click="handleDelete" v-if="hasCReceiptCancel">删除 </el-button> </div> </div> @@ -95,6 +96,18 @@ @click="handlePreview(scope.row)">导出过磅单</el-button> </template> </el-table-column> --> <el-table-column label="操作" width="120" align="center"> <template #default="scope"> <el-button v-if="hasCReceiptEdit" type="primary" size="mini" @click="handleEdit(scope.row)" >编辑</el-button> </template> </el-table-column> </el-table> <div style="margin-top: 12px; display: flex; justify-content: flex-end;"> <pagination v-show="total > 0" @@ -106,6 +119,51 @@ </div> </div> </div> <el-dialog v-model="isShowEditModal" title="编辑入库" width="600" @close="closeEditModal" > <el-form label-width="100px" :model="editForm" label-position="top" ref="editFormRef" > <el-form-item label="数量" prop="qualitity" :rules="[{ required: true, message: '请输入数量', trigger: ['blur', 'change'] }]" > <el-input-number v-model="editForm.qualitity" :min="0" :step="1" :precision="0" controls-position="right" style="width: 100%" placeholder="请输入数量" /> </el-form-item> <el-form-item label="采购员" prop="purchaser" :rules="[{ required: true, message: '请输入采购员', trigger: ['blur', 'change'] }]" > <el-input v-model="editForm.purchaser" placeholder="请输入采购员" /> </el-form-item> </el-form> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="handleEditSubmit">确认</el-button> <el-button @click="closeEditModal">取消</el-button> </div> </template> </el-dialog> </template> <script setup> @@ -116,15 +174,18 @@ toRefs, onMounted, getCurrentInstance, computed, } from "vue"; import {ElMessageBox} from "element-plus"; import { getConsumablesInRecordListPage, batchDeleteConsumablesInRecords, editStockInStock, } from "@/api/consumablesLogistics/consumablesInRecord.js"; import { findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions, } from "@/api/basicData/enum.js"; import { checkPermi } from "@/utils/permission.js"; const {proxy} = getCurrentInstance(); @@ -135,6 +196,9 @@ default: '0' } }) const hasCReceiptEdit = computed(() => checkPermi(['c_receipt_edit'])); const hasCReceiptCancel = computed(() => checkPermi(['c_receipt_cancel'])); const tableData = ref([]); const selectedRows = ref([]); @@ -253,6 +317,37 @@ }); }; // 编辑耗材入库 const isShowEditModal = ref(false); const editFormRef = ref(null); const editForm = ref({}); const handleEdit = (row) => { editForm.value = { id: row.id, qualitity: row.qualitity, purchaser: row.purchaser, }; isShowEditModal.value = true; }; const closeEditModal = () => { isShowEditModal.value = false; editForm.value = {}; editFormRef.value?.clearValidate?.(); }; const handleEditSubmit = () => { editFormRef.value?.validate?.((valid) => { if (!valid) return; editStockInStock(editForm.value).then(() => { closeEditModal(); proxy.$modal.msgSuccess("编辑成功"); getList(); }); }); }; onMounted(() => { getList(); fetchStockRecordTypeOptions(); src/views/qualityManagement/nonconformingManagement/components/formDia.vue
@@ -11,6 +11,7 @@ <el-col :span="12"> <el-form-item label="产品名称:" prop="productId"> <el-tree-select v-if="operationType !== 'edit'" v-model="form.productId" placeholder="请选择" clearable @@ -18,7 +19,13 @@ @change="getModels" :data="productOptions" :render-after-expand="false" :disabled="operationType === 'edit'" style="width: 100%" /> <!-- 编辑态:不依赖下拉选项回显,直接展示文本 --> <el-input v-else v-model="form.productName" disabled style="width: 100%" /> </el-form-item> @@ -26,16 +33,28 @@ <el-col :span="12"> <el-form-item label="规格型号:" prop="productModelId"> <el-select v-if="operationType !== 'edit'" v-model="form.productModelId" placeholder="请选择" clearable :disabled="operationType === 'edit'" filterable readonly @change="handleChangeModel" > <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> </el-select> <!-- 编辑态:不展示规格型号列表,直接展示文本 --> <el-input v-else v-model="form.model" disabled style="width: 100%" /> </el-form-item> </el-col> </el-row> @@ -187,7 +206,7 @@ }, rules: { checkTime: [{ required: true, message: "请选择检测日期", trigger: "change" }], checkUserName: [{ required: true, message: "请选择检验员", trigger: "change" }], checkName: [{ required: true, message: "请选择检验员", trigger: "change" }], productId: [{ required: true, message: "请选择产品名称", trigger: "change" }], productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }], batchNo: [{ required: true, message: "请输入批号", trigger: "blur" }], @@ -203,27 +222,114 @@ const modelOptions = ref([]) // 打开弹框 const openDialog = (type, row) => { const openDialog = async (type, row) => { operationType.value = type; userListNoPage().then(res => { userList.value = res.data || []; }) dialogFormVisible.value = true; form.value = {} getProductOptions(); // 编辑态不校验规格型号(prop 仍绑定 productModelId,但编辑态改为文本展示) data.rules.productModelId = [ { required: type !== "edit", message: "请选择规格型号", trigger: "change", }, ]; // 先加载下拉选项,确保编辑数据可以正确匹配回显 const userRes = await userListNoPage(); userList.value = userRes.data || []; await getProductOptions(); // 处理结果默认“报废”,且不可选择其它项 form.value.dealResult = getScrapDealResultValue(); if (operationType.value === 'edit') { getQualityUnqualifiedInfo(row.id).then(res => { const { inspectState, ...rest } = (res.data || {}) form.value = { ...rest, dealResult: getScrapDealResultValue() } }) const fallback = row || {}; const res = await getQualityUnqualifiedInfo(fallback.id); const { inspectState, ...rest } = res.data || {}; // 先用列表行数据把“必回显字段”直接填上,避免详情接口字段名不一致导致全空。 const productName = rest?.productName ?? fallback?.productName; const modelName = rest?.model ?? fallback?.model; const checkTypeValue = rest?.checkType ?? fallback?.checkType; const checkNameValue = rest?.checkName ?? rest?.checkUserName ?? fallback?.checkName ?? fallback?.checkUserName; const productId = rest?.productId ?? findProductIdByLabel(productOptions.value, productName); // 先回填字段(productModelId 需要依赖 modelOptions,稍后再补) const normalizedProductId = normalizeProductIdByOptions(productId); // 编辑态产品名称展示只展示 label,避免树组件回显依赖 value 匹配 const productNameLabel = rest?.productName ?? fallback?.productName ?? findNodeById(productOptions.value, normalizedProductId) ?? productName; form.value = { ...rest, productName: productNameLabel, productId: normalizedProductId, productModelId: rest?.productModelId ?? undefined, model: rest?.model ?? fallback?.model, unit: rest?.unit ?? fallback?.unit, batchNo: rest?.batchNo ?? fallback?.batchNo ?? "", checkType: checkTypeValue === undefined || checkTypeValue === null ? undefined : Number(checkTypeValue), checkName: checkNameValue ?? "", checkTime: rest?.checkTime ?? fallback?.checkTime ?? "", defectivePhenomena: rest?.defectivePhenomena ?? fallback?.defectivePhenomena ?? "", dealName: rest?.dealName ?? fallback?.dealName ?? "", dealTime: rest?.dealTime ?? fallback?.dealTime ?? "", dealResult: getScrapDealResultValue(), }; // 规格型号下拉需要依赖 productId await loadModelsForProductId(form.value.productId); // 规格型号回显(如详情没给 productModelId,就用 model 名称反查) if (!form.value.productModelId) { form.value.productModelId = findModelIdByModel( modelOptions.value, modelName ); } // 根据 productModelId 回填 model/unit if (form.value.productModelId) { form.value.productModelId = normalizeModelIdByOptions(form.value.productModelId); handleChangeModel(form.value.productModelId); } else if (modelName) { // productModelId 仍然拿不到时,至少保证 model/unit 文本回显 const matched = (modelOptions.value || []).find((m) => { const model = String(m?.model ?? ""); const id = String(m?.id ?? ""); const target = String(modelName ?? ""); return model === target || id === target; }) ?? null; if (matched) { form.value.model = matched.model ?? form.value.model; form.value.unit = matched.unit ?? form.value.unit; } else { form.value.model = modelName; } } const getProductOptions = () => { productTreeList().then((res) => { } } const getProductOptions = async () => { const res = await productTreeList(); productOptions.value = convertIdToValue(res); }); }; const getModels = (value) => { form.value.productName = findNodeById(productOptions.value, value); @@ -236,9 +342,41 @@ }) }; // 编辑模式/或任意需要时:只拉取规格型号列表,不清空已回填的字段 const loadModelsForProductId = async (productId) => { if (!productId) return; const res = await modelList({ id: productId }); modelOptions.value = res || []; // 让单位/型号等字段保持与当前 productModelId 一致 if (form.value.productModelId) { form.value.productModelId = normalizeModelIdByOptions(form.value.productModelId); handleChangeModel(form.value.productModelId); } }; const handleChangeModel = (value) => { form.value.model = modelOptions.value.find(item => item.id == value)?.model || ''; form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || ''; }; // 解决回显时类型不一致导致 el-tree-select / el-select 只显示 value(id) const normalizeProductIdByOptions = (productId) => { if (productId === undefined || productId === null) return productId; const target = String(productId); const stack = Array.isArray(productOptions.value) ? [...productOptions.value] : []; while (stack.length) { const node = stack.shift(); if (node && String(node?.value ?? "") === target) return node?.value; if (node?.children?.length) stack.push(...node.children); } return productId; }; const normalizeModelIdByOptions = (modelId) => { if (modelId === undefined || modelId === null) return modelId; const target = String(modelId); return (modelOptions.value || []).find((m) => String(m?.id ?? "") === target)?.id ?? modelId; }; const findNodeById = (nodes, productId) => { for (let i = 0; i < nodes.length; i++) { @@ -254,6 +392,33 @@ } return null; // 没有找到节点,返回null }; // 根据树节点 label 回填 value(编辑回显兜底用) const findProductIdByLabel = (nodes, label) => { const target = String(label ?? ""); if (!target) return undefined; const stack = Array.isArray(nodes) ? [...nodes] : []; while (stack.length) { const node = stack.shift(); if (node && String(node?.label ?? "") === target) return node?.value; if (node?.children?.length) stack.push(...node.children); } return undefined; }; // 根据规格型号名称反查 id(编辑回显兜底用) const findModelIdByModel = (models, model) => { const target = String(model ?? ""); if (!target) return undefined; return ( (models || []).find((m) => { const mModel = String(m?.model ?? ""); const mId = String(m?.id ?? ""); return mModel === target || mId === target; })?.id ); }; function convertIdToValue(data) { return data.map((item) => { const { id, children, ...rest } = item; src/views/qualityManagement/nonconformingManagement/index.vue
@@ -37,7 +37,12 @@ <div> <el-button type="primary" @click="openForm('add')">新增</el-button> <el-button @click="handleOut">导出</el-button> <el-button type="danger" plain @click="handleDelete">删除</el-button> <el-button type="danger" plain @click="handleDelete" v-if="hasNonconformingCancel" >删除</el-button> </div> </div> <div class="table_list"> @@ -60,12 +65,13 @@ <script setup> import { Search } from "@element-plus/icons-vue"; import {onMounted, ref} from "vue"; import { onMounted, ref, computed } from "vue"; import FormDia from "@/views/qualityManagement/nonconformingManagement/components/formDia.vue"; import {ElMessageBox} from "element-plus"; import {qualityUnqualifiedDel, qualityUnqualifiedListPage} from "@/api/qualityManagement/nonconformingManagement.js"; import InspectionFormDia from "@/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue"; import dayjs from "dayjs"; import { checkPermi } from "@/utils/permission.js"; const data = reactive({ searchForm: { @@ -78,6 +84,10 @@ }, }); const { searchForm } = toRefs(data); const hasNonconformingEdit = computed(() => checkPermi(["nonconforming_edit"])); const hasNonconformingCancel = computed(() => checkPermi(["nonconforming_cancel"])); const tableColumn = ref([ { label: "检测日期", @@ -154,6 +164,23 @@ prop: "dealTime", width: 120 }, { dataType: "action", label: "操作", align: "center", fixed: "right", width: 180, operation: [ { name: "编辑", type: "text", showHide: (row) => hasNonconformingEdit.value, clickFun: (row) => { openForm("edit", row); }, }, ], }, ]); const tableData = ref([]); const selectedRows = ref([]); @@ -206,10 +233,6 @@ // 打开弹框 const openForm = (type, row) => { if (type !== 'add' && row?.inspectState === 1) { proxy.$modal.msgWarning("已处理的数据不能再编辑"); return; } nextTick(() => { formDia.value?.openDialog(type, row) }) src/views/qualityManagement/rawMaterial/index.vue
@@ -45,7 +45,7 @@ <div> <el-button type="primary" @click="openForm('add')">新增</el-button> <el-button @click="handleOut">导出</el-button> <el-button type="danger" plain @click="handleDelete">删除</el-button> <el-button type="danger" plain @click="handleDelete" v-if="hasRawCancel">删除</el-button> </div> </div> <div class="table_list"> @@ -86,7 +86,7 @@ </template> <script setup> import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick, computed} from "vue"; import InspectionFormDia from "@/views/qualityManagement/rawMaterial/components/inspectionFormDia.vue"; import FormDia from "@/views/qualityManagement/rawMaterial/components/formDia.vue"; import {ElMessageBox} from "element-plus"; @@ -99,6 +99,7 @@ findRawMaterialListPage, submitRawMaterial, updateCheckUserName,downloadRawMaterial } from "@/api/qualityManagement/rawMaterial.js"; import { checkPermi } from "@/utils/permission.js"; const data = reactive({ searchForm: { @@ -114,6 +115,8 @@ }, }); const {searchForm, rules} = toRefs(data); const hasRawCancel = computed(() => checkPermi(["raw_cancel"])); const tableColumn = ref([ { label: "检测日期", @@ -190,11 +193,6 @@ disabled: (row) => { // 已提交则禁用 if (row.inspectState == 1) return true; // 如果检验员有值,只有当前登录用户能编辑 if (row.checkUserName) { return row.checkUserName !== userStore.nickName; } return false; } }, { @@ -216,20 +214,20 @@ return false; } }, { name: "分配检验员", type: "text", clickFun: (row) => { if (!row.checkUserName) { open(row) } else { proxy.$modal.msgError("检验员已存在"); } }, disabled: (row) => { return row.inspectState === 1 || row.checkUserName || row.checkUserName !== ''; } }, // { // name: "分配检验员", // type: "text", // clickFun: (row) => { // if (!row.checkUserName) { // open(row) // } else { // proxy.$modal.msgError("检验员已存在"); // } // }, // disabled: (row) => { // return row.inspectState === 1 || row.checkUserName || row.checkUserName !== ''; // } // }, { name: "下载", type: "text",