| | |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="批号" prop="batchNo"> |
| | | <el-input |
| | | v-model="formState.batchNo" |
| | | clearable |
| | | placeholder="可输入批号,留空将自动生成" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="库存数量" |
| | | prop="qualitity" |
| | |
| | | productModelName: "", |
| | | materialCode: "", |
| | | unit: "", |
| | | batchNo: "", |
| | | qualitity: 0, |
| | | warnNum: 0, |
| | | remark: '', |
| | | }); |
| | | |
| | | /** 未填写批号时生成唯一批号(前端生成,后端也可再覆盖) */ |
| | | const generateBatchNo = () => { |
| | | const d = new Date(); |
| | | const pad = (n) => String(n).padStart(2, "0"); |
| | | const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`; |
| | | const r = Math.floor(Math.random() * 10000) |
| | | .toString() |
| | | .padStart(4, "0"); |
| | | return `PH${ts}${r}`; |
| | | }; |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | materialCode: "", |
| | | unit: "", |
| | | batchNo: "", |
| | | qualitity: 0, |
| | | warnNum: 0, |
| | | remark: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | |
| | | proxy.$modal.msgError("请选择规格"); |
| | | return; |
| | | } |
| | | const payload = { ...formState.value }; |
| | | const bn = (payload.batchNo || "").trim(); |
| | | payload.batchNo = bn || generateBatchNo(); |
| | | |
| | | if (props.type === 'qualified') { |
| | | createStockInventory(formState.value).then(res => { |
| | | createStockInventory(payload).then(res => { |
| | | // 关闭模态框 |
| | | isShow.value = false; |
| | | // 告知父组件已完成 |
| | |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | }) |
| | | } else { |
| | | createStockUnInventory(formState.value).then(res => { |
| | | createStockUnInventory(payload).then(res => { |
| | | // 关闭模态框 |
| | | isShow.value = false; |
| | | // 告知父组件已完成 |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">产品大类:</span> |
| | | <span class="search_title ml10">产品名称:</span> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请输入" |
| | | clearable/> |
| | | <span class="search_title ml10">规格型号:</span> |
| | | <el-input v-model="searchForm.model" |
| | | style="width: 240px" |
| | | placeholder="请输入" |
| | | clearable/> |
| | |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="产品大类" prop="productName" show-overflow-tooltip /> |
| | | <el-table-column label="规格型号" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="批号" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column label="料号" prop="materialCode" show-overflow-tooltip /> |
| | | <el-table-column label="单位" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip /> |
| | |
| | | |
| | | <script setup> |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from 'vue' |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import { getStockInventoryListPage } from "@/api/inventoryManagement/stockInventory.js"; |
| | | const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue")); |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: '', |
| | | model: '', |
| | | } |
| | | }) |
| | | const { searchForm } = toRefs(data) |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">产品大类:</span> |
| | | <span class="search_title ml10">产品名称:</span> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请输入" |
| | | clearable/> |
| | | <span class="search_title ml10">规格型号:</span> |
| | | <el-input v-model="searchForm.model" |
| | | style="width: 240px" |
| | | placeholder="请输入" |
| | | clearable/> |
| | |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="产品大类" prop="productName" show-overflow-tooltip /> |
| | | <el-table-column label="规格型号" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="批号" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column label="料号" prop="materialCode" show-overflow-tooltip /> |
| | | <el-table-column label="单位" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip /> |
| | |
| | | |
| | | <script setup> |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance, defineAsyncComponent } from 'vue' |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { getStockUninventoryListPage } from "@/api/inventoryManagement/stockUninventory.js"; |
| | | const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue")); |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: '', |
| | | model: '', |
| | | } |
| | | }) |
| | | const { searchForm } = toRefs(data) |
| | |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="批号:" |
| | | prop="batchNo"> |
| | | <el-input v-model="productForm.batchNo" |
| | | clearable |
| | | placeholder="选填,可输入批号;留空将自动生成" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | materialCode: "", |
| | | batchNo: "", |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | /** 与库存新增一致:未填批号时前端生成(PH + 时间戳 + 随机数) */ |
| | | const generateProductBatchNo = () => { |
| | | const d = new Date(); |
| | | const pad = (n) => String(n).padStart(2, "0"); |
| | | const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`; |
| | | const r = Math.floor(Math.random() * 10000) |
| | | .toString() |
| | | .padStart(4, "0"); |
| | | return `PH${ts}${r}`; |
| | | }; |
| | | |
| | | const ensureProductBatchNo = () => { |
| | | const v = (productForm.value.batchNo ?? "").toString().trim(); |
| | | productForm.value.batchNo = v || generateProductBatchNo(); |
| | | }; |
| | | |
| | | // 提交产品表单 |
| | | const submitProduct = () => { |
| | | proxy.$refs["productFormRef"].validate(valid => { |
| | | if (valid) { |
| | | ensureProductBatchNo(); |
| | | if (operationType.value === "edit") { |
| | | submitProductEdit(); |
| | | } else { |
| | |
| | | <div class="title">基础信息</div> |
| | | <div class="sub"> |
| | | <span class="mr12">生产订单号:{{ header.npsNo || "-" }}</span> |
| | | <span class="mr12">生产批号:{{ header.lotNo || "-" }}</span> |
| | | <span class="mr12">生产批号:{{ header.batchNo || "-" }}</span> |
| | | <span class="mr12">产品名称:{{ header.productCategory || "-" }}</span> |
| | | <span class="mr12">规格:{{ header.specificationModel || "-" }}</span> |
| | | <span class="mr12">料号:{{ header.materialCode || "-" }}</span> |
| | |
| | | const header = computed(() => ({ |
| | | orderId: route.query.orderId, |
| | | npsNo: route.query.npsNo, |
| | | lotNo: route.query.lotNo, |
| | | batchNo: route.query.batchNo, |
| | | productCategory: route.query.productCategory, |
| | | specificationModel: route.query.specificationModel, |
| | | materialCode: route.query.materialCode, |
| | |
| | | </el-form-item> |
| | | <el-form-item |
| | | label="生产批号" |
| | | prop="lotNo" |
| | | prop="batchNo" |
| | | > |
| | | <el-input v-model="formState.lotNo" placeholder="请输入生产批号" /> |
| | | <el-input v-model="formState.batchNo" placeholder="选填,可输入批号;留空将自动生成" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | |
| | | unit: "", |
| | | priority: undefined, |
| | | quantity: 0, |
| | | lotNo: "", |
| | | batchNo: "", |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | |
| | | materialCode: "", |
| | | priority: priority_type.value && priority_type.value.length > 0 ? priority_type.value[2].value : undefined, |
| | | quantity: '', |
| | | lotNo: "", |
| | | batchNo: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | |
| | | }, |
| | | { |
| | | label: "生产批号", |
| | | prop: "lotNo", |
| | | prop: "batchNo", |
| | | width: '120px', |
| | | }, |
| | | { |
| | |
| | | query: { |
| | | orderId: row.id, |
| | | npsNo: row.npsNo || "", |
| | | lotNo: row.lotNo || "", |
| | | batchNo: row.batchNo || "", |
| | | productCategory: row.productCategory || "", |
| | | specificationModel: row.specificationModel || "", |
| | | materialCode: row.materialCode || "", |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="生产批号:"> |
| | | <el-input |
| | | :model-value="productionBatchDisplay" |
| | | disabled |
| | | placeholder="—" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="指标选择:" prop="testStandardId"> |
| | | <el-select |
| | | v-model="form.testStandardId" |
| | |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" clearable :precision="2" :disabled="quantityDisabled"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="料号:" prop="materialCode"> |
| | | <el-input v-model="form.materialCode" placeholder="请输入" disabled/> |
| | |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.qualifiedQuantity" placeholder="请输入" clearable :precision="2" disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不良原因:" prop="defectiveReason"> |
| | | <el-select v-model="form.defectiveReason" placeholder="请选择" clearable style="width: 100%"> |
| | |
| | | defectiveReason: undefined, |
| | | unit: "", |
| | | materialCode: "", |
| | | /** 来自生产工单/台账,仅展示 */ |
| | | batchNo: "", |
| | | qualifiedQuantity: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | |
| | | const quantityDisabled = computed(() => { |
| | | const v = form.value || {}; |
| | | return !!(v.productMainId != null || v.purchaseLedgerId != null); |
| | | }); |
| | | |
| | | /** 生产批号展示(接口可能为 batchNo 或 productionBatchNo) */ |
| | | const productionBatchDisplay = computed(() => { |
| | | const f = form.value || {}; |
| | | const v = f.batchNo ?? f.productionBatchNo; |
| | | if (v === null || v === undefined || String(v).trim() === "") { |
| | | return ""; |
| | | } |
| | | return String(v); |
| | | }); |
| | | const supplierList = ref([]); |
| | | const productOptions = ref([]); |
| | |
| | | // 先保存 testStandardId,避免被清空 |
| | | const savedTestStandardId = row.testStandardId; |
| | | // 先设置表单数据,但暂时清空 testStandardId,等选项加载完成后再设置 |
| | | form.value = {...row, testStandardId: ''} |
| | | form.value = { ...row, testStandardId: "" }; |
| | | // 生产批号:与生产工单字段对齐,兼容多种后端字段名 |
| | | form.value.batchNo = |
| | | row.batchNo ?? row.productionBatchNo ?? form.value.batchNo ?? ""; |
| | | currentProductId.value = row.productId || 0 |
| | | // 清空验证状态,避免数据加载过程中的校验闪烁 |
| | | nextTick(() => { |
| | |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "生产批号", |
| | | prop: "batchNo", |
| | | width: 140 |
| | | }, |
| | | { |
| | | label: "检验员", |
| | | prop: "checkName", |
| | | }, |
| | |
| | | params.entryDate = undefined |
| | | qualityInspectListPage({...params, inspectType: 2}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | const records = res.data.records || []; |
| | | tableData.value = records.map((row) => ({ |
| | | ...row, |
| | | batchNo: row.batchNo ?? row.productionBatchNo ?? "", |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="生产批号:"> |
| | | <el-input |
| | | :model-value="productionBatchDisplay" |
| | | disabled |
| | | placeholder="—" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs} from "vue"; |
| | | import { ref, reactive, toRefs, computed, getCurrentInstance } from "vue"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import { |
| | | getQualityUnqualifiedInfo, |
| | |
| | | model: "", |
| | | unit: "", |
| | | materialCode: "", |
| | | /** 来自业务数据,仅展示 */ |
| | | batchNo: "", |
| | | quantity: "", |
| | | checkCompany: "", |
| | | checkResult: "", |
| | |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | const productionBatchDisplay = computed(() => { |
| | | const f = form.value || {}; |
| | | const v = f.batchNo ?? f.productionBatchNo; |
| | | if (v === null || v === undefined || String(v).trim() === "") { |
| | | return ""; |
| | | } |
| | | return String(v); |
| | | }); |
| | | |
| | | const productOptions = ref([]); |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); // 检验员/处理人下拉列表 |
| | |
| | | model: '', |
| | | unit: '', |
| | | materialCode: '', |
| | | batchNo: '', |
| | | quantity: '', |
| | | productName: '', |
| | | }; |
| | |
| | | getQualityUnqualifiedInfo(row.id).then(res => { |
| | | const { inspectState, ...rest } = (res.data || {}) |
| | | form.value = { ...rest } |
| | | form.value.batchNo = |
| | | rest.batchNo ?? rest.productionBatchNo ?? form.value.batchNo ?? "" |
| | | }) |
| | | } |
| | | } |
| | |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增</el-button> |
| | | <!-- <el-button type="primary" @click="openForm('add')">新增</el-button> --> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | </div> |
| | |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "生产批号", |
| | | prop: "batchNo", |
| | | width: 140, |
| | | }, |
| | | { |
| | | label: "料号", |
| | | prop: "materialCode", |
| | | }, |
| | |
| | | params.entryDate = undefined |
| | | qualityUnqualifiedListPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | const records = res.data.records || []; |
| | | tableData.value = records.map((row) => ({ |
| | | ...row, |
| | | batchNo: row.batchNo ?? row.productionBatchNo ?? "", |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |