| | |
| | | :expand-row-keys="expandRowKeys" |
| | | :show-summary="isShowSummary" |
| | | :summary-method="summaryMethod" |
| | | :default-expand-all="defaultExpandAll" |
| | | :tree-props="treeProps" |
| | | :lazy="lazy" |
| | | :load="load" |
| | | @row-click="rowClick" |
| | | @current-change="currentChange" |
| | | @selection-change="handleSelectionChange" |
| | |
| | | type: [String, Object], |
| | | default: () => ({ width: "100%" }), |
| | | }, |
| | | defaultExpandAll: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | treeProps: { |
| | | type: Object, |
| | | default: () => ({ children: "children", hasChildren: "hasChildren" }), |
| | | }, |
| | | lazy: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | load: { |
| | | type: Function, |
| | | default: null, |
| | | }, |
| | | }); |
| | | |
| | | const mergedHeaderCellStyle = computed(() => ({ |
| | |
| | | })); |
| | | |
| | | // Data |
| | | const multipleTable = ref(null); |
| | | const uploadRefs = ref([]); |
| | | const currentFiles = ref({}); |
| | | const uploadKeys = ref({}); |
| | |
| | | const handleSelectionChange = newSelection => { |
| | | emit("selection-change", newSelection); |
| | | }; |
| | | |
| | | // 展开/折叠树形节点 |
| | | const toggleRowExpansion = (row, expanded) => { |
| | | multipleTable.value?.toggleRowExpansion(row, expanded); |
| | | }; |
| | | |
| | | // 展开所有树形节点 |
| | | const expandAll = () => { |
| | | const expandRows = (rows) => { |
| | | rows?.forEach(row => { |
| | | if (row[props.treeProps.children]?.length > 0) { |
| | | multipleTable.value?.toggleRowExpansion(row, true); |
| | | expandRows(row[props.treeProps.children]); |
| | | } |
| | | }); |
| | | }; |
| | | expandRows(props.tableData); |
| | | }; |
| | | |
| | | // 折叠所有树形节点 |
| | | const collapseAll = () => { |
| | | const collapseRows = (rows) => { |
| | | rows?.forEach(row => { |
| | | if (row[props.treeProps.children]?.length > 0) { |
| | | collapseRows(row[props.treeProps.children]); |
| | | multipleTable.value?.toggleRowExpansion(row, false); |
| | | } |
| | | }); |
| | | }; |
| | | collapseRows(props.tableData); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | toggleRowExpansion, |
| | | expandAll, |
| | | collapseAll, |
| | | multipleTable |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="规格型号" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="库位" prop="warehouseName" show-overflow-tooltip /> |
| | | <el-table-column label="批号" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column label="单位" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column |
| | |
| | | prop="unit"> |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="库存类型" |
| | | prop="type" |
| | | <el-form-item label="仓库" |
| | | prop="warehouseId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择库存类型', |
| | | message: '请选择仓库', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select v-model="formState.type" |
| | | placeholder="请选择库存类型" |
| | | :disabled="isEdit"> |
| | | <el-option label="合格库存" |
| | | value="qualified" /> |
| | | <el-option label="不合格库存" |
| | | value="unqualified" /> |
| | | <el-select v-model="formState.warehouseId" |
| | | placeholder="请选择仓库" |
| | | clearable |
| | | :disabled="isEdit || !formState.productId" |
| | | @change="handleWarehouseChange" |
| | | style="width: 100%"> |
| | | <el-option v-for="warehouse in warehouseList" |
| | | :key="warehouse.id" |
| | | :label="warehouse.name" |
| | | :value="warehouse.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="出库数量" |
| | | prop="qualitity" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请输入出库数量', |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (formState.maxStock > 0 && value > formState.maxStock) { |
| | | callback('出库数量不能超过当前批号库存 ' + formState.maxStock); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | } |
| | | ]"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | :max="formState.maxStock > 0 ? formState.maxStock : undefined" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="批号" |
| | | prop="batchNo" |
| | |
| | | prop="currentStock"> |
| | | <el-input v-model="batchNoStockMap[formState.batchNo]" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="出库数量" |
| | | prop="qualitity" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请输入出库数量', |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (formState.maxStock > 0 && value > formState.maxStock) { |
| | | callback('出库数量不能超过当前批号库存 ' + formState.maxStock); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | } |
| | | ]"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | :max="formState.maxStock > 0 ? formState.maxStock : undefined" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="isEdit" |
| | | label="来源" |
| | | prop="recordType"> |
| | |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="库存类型" |
| | | prop="type" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择库存类型', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select v-model="formState.type" |
| | | placeholder="请选择库存类型" |
| | | :disabled="isEdit"> |
| | | <el-option label="合格库存" |
| | | value="qualified" /> |
| | | <el-option label="不合格库存" |
| | | value="unqualified" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="备注" |
| | |
| | | } from "@/api/basicData/enum.js"; |
| | | import { addStockOutRecordOnly } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { addUnqualifiedStockOutRecordOnly } from "@/api/inventoryManagement/stockUninventory.js"; |
| | | import { getWarehouseList } from "@/api/inventoryManagement/warehouse.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | |
| | | const batchNoList = ref([]); |
| | | // 批号库存映射 |
| | | const batchNoStockMap = ref({}); |
| | | // 仓库列表 |
| | | const warehouseList = ref([]); |
| | | // 原始batchNoMaps数据 |
| | | const rawBatchNoMaps = ref({}); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | warehouseId: null, // 仓库ID |
| | | type: undefined, |
| | | qualitity: 0, |
| | | batchNo: null, |
| | |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | warehouseId: null, |
| | | type: undefined, |
| | | qualitity: 0, |
| | | batchNo: null, |
| | |
| | | remark: "", |
| | | maxStock: 0, |
| | | }; |
| | | warehouseList.value = []; |
| | | batchNoList.value = []; |
| | | batchNoStockMap.value = {}; |
| | | rawBatchNoMaps.value = {}; |
| | | }; |
| | | |
| | | // 关闭对话框 |
| | | const closeDialog = () => { |
| | | dialogVisible.value = false; |
| | | resetForm(); |
| | | }; |
| | | |
| | | // 加载仓库列表 |
| | | const loadWarehouseList = async () => { |
| | | try { |
| | | const res = await getWarehouseList(); |
| | | if (res.code === 200) { |
| | | return res.data || []; |
| | | } |
| | | } catch (error) { |
| | | console.error('加载仓库列表失败', error); |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | // 产品选择处理 |
| | |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | // 从batchNoMaps获取批号列表和库存 |
| | | if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) { |
| | | batchNoList.value = Object.keys(product.batchNoMaps); |
| | | batchNoStockMap.value = product.batchNoMaps; |
| | | } else { |
| | | batchNoList.value = []; |
| | | batchNoStockMap.value = {}; |
| | | } |
| | | // 清空已选择的批号和最大库存 |
| | | // 解析batchNoMaps数据,格式为:{ 仓库ID: [{批号: 库存}, {批号: 库存}] } |
| | | warehouseList.value = []; |
| | | batchNoList.value = []; |
| | | batchNoStockMap.value = {}; |
| | | rawBatchNoMaps.value = {}; |
| | | formState.value.warehouseId = null; |
| | | formState.value.batchNo = null; |
| | | formState.value.maxStock = 0; |
| | | |
| | | if (product.batchNoMaps && Object.keys(product.batchNoMaps).length > 0) { |
| | | rawBatchNoMaps.value = product.batchNoMaps; |
| | | // 获取所有仓库信息用于反显名称 |
| | | const allWarehouses = await loadWarehouseList(); |
| | | const warehouseMap = {}; |
| | | allWarehouses.forEach(w => { |
| | | warehouseMap[w.id] = w.warehouseName || w.name || w.warehouseCode || `仓库${w.id}`; |
| | | }); |
| | | // 构建仓库列表 |
| | | warehouseList.value = Object.keys(product.batchNoMaps).map(warehouseId => ({ |
| | | id: warehouseId, |
| | | name: warehouseMap[warehouseId] || `仓库${warehouseId}` |
| | | })); |
| | | } |
| | | showProductSelect.value = false; |
| | | // 触发表单验证更新 |
| | | proxy.$refs["formRef"]?.validateField("productModelId"); |
| | | } |
| | | }; |
| | | |
| | | // 仓库选择变化处理 |
| | | const handleWarehouseChange = (warehouseId) => { |
| | | batchNoList.value = []; |
| | | batchNoStockMap.value = {}; |
| | | formState.value.batchNo = null; |
| | | formState.value.maxStock = 0; |
| | | |
| | | if (warehouseId && rawBatchNoMaps.value[warehouseId]) { |
| | | // 解析该仓库下的批号数据,格式为:[{批号: 库存}, {批号: 库存}] |
| | | const batchArray = rawBatchNoMaps.value[warehouseId]; |
| | | const batchMap = {}; |
| | | const batches = []; |
| | | |
| | | batchArray.forEach(item => { |
| | | const batchNo = Object.keys(item)[0]; |
| | | const stock = item[batchNo]; |
| | | batches.push(batchNo); |
| | | batchMap[batchNo] = stock; |
| | | }); |
| | | |
| | | batchNoList.value = batches; |
| | | batchNoStockMap.value = batchMap; |
| | | } |
| | | }; |
| | | |
| | | // 批号选择变化处理 |
| | | const handleBatchNoChange = (batchNo) => { |
| | | if (batchNo && batchNoStockMap.value[batchNo]) { |
| | |
| | | <el-table-column label="规格型号" |
| | | prop="model" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="库位" |
| | | prop="warehouseName" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="批号" |
| | | prop="batchNo" |
| | | show-overflow-tooltip/> |
| | |
| | | prop="unit"> |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="库存类型" |
| | | prop="type" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择库存类型', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select v-model="formState.type" |
| | | placeholder="请选择库存类型" |
| | | :disabled="isEdit"> |
| | | <el-option label="合格库存" |
| | | value="qualified" /> |
| | | <el-option label="不合格库存" |
| | | value="unqualified" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="库存数量" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="批号" |
| | | prop="batchNo"> |
| | | <el-input v-model="formState.batchNo" |
| | | placeholder="请输入批号" |
| | | :disabled="isEdit" /> |
| | | </el-form-item> |
| | | <el-form-item label="库位" |
| | | prop="warehouseId" |
| | | :rules="[ |
| | |
| | | :label="warehouse.warehouseName + ' - ' + warehouse.location" |
| | | :value="warehouse.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="批号" |
| | | prop="batchNo"> |
| | | <el-input v-model="formState.batchNo" |
| | | placeholder="请输入批号" |
| | | :disabled="isEdit" /> |
| | | </el-form-item> |
| | | <el-form-item label="库存数量" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="isEdit" |
| | | label="来源" |
| | |
| | | :max="formState.qualitity" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="库存类型" |
| | | prop="type" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择库存类型', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select v-model="formState.type" |
| | | placeholder="请选择库存类型" |
| | | :disabled="isEdit"> |
| | | <el-option label="合格库存" |
| | | value="qualified" /> |
| | | <el-option label="不合格库存" |
| | | value="unqualified" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="备注" |
| | | prop="remark"> |
| | | <el-input v-model="formState.remark" |
| | |
| | | <el-input v-model="formState.unit" |
| | | disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="库位" |
| | | prop="warehouseId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择库位', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select v-model="formState.warehouseId" |
| | | placeholder="请选择库位" |
| | | clearable |
| | | style="width: 100%"> |
| | | <el-option v-for="warehouse in warehouseList" |
| | | :key="warehouse.id" |
| | | :label="warehouse.warehouseName + ' - ' + warehouse.location" |
| | | :value="warehouse.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="批号" |
| | | prop="batchNo"> |
| | | <el-input v-model="formState.batchNo" |
| | | placeholder="请输入批号" /> |
| | | </el-form-item> |
| | | <el-form-item label="库存数量" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="库存类型" |
| | | prop="type" |
| | | :rules="[ |
| | |
| | | <el-option label="不合格库存" |
| | | value="unqualified" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="库存数量" |
| | | prop="qualitity"> |
| | | <el-input-number v-model="formState.qualitity" |
| | | :step="1" |
| | | :min="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="批号" |
| | | prop="batchNo"> |
| | | <el-input v-model="formState.batchNo" |
| | | placeholder="请输入批号" /> |
| | | </el-form-item> |
| | | <el-form-item v-if="formState.type === 'qualified'" |
| | | label="库存预警数量" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, watch, getCurrentInstance } from "vue"; |
| | | import { ref, computed, watch, getCurrentInstance, onMounted } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { addStockInRecordOnly } from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { createStockUnInventory } from "@/api/inventoryManagement/stockUninventory.js"; |
| | | import { getWarehouseList } from "@/api/inventoryManagement/warehouse.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | warehouseId: undefined, |
| | | type: undefined, |
| | | qualitity: 0, |
| | | batchNo: null, |
| | | warnNum: 0, |
| | | remark: "", |
| | | }); |
| | | |
| | | // 仓库列表 |
| | | const warehouseList = ref([]); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | // 获取仓库列表 |
| | | const fetchWarehouseList = () => { |
| | | getWarehouseList({ status: true }).then(res => { |
| | | warehouseList.value = res.data || []; |
| | | }).catch(() => { |
| | | proxy.$modal.msgError("获取仓库列表失败"); |
| | | }); |
| | | }; |
| | | |
| | | // 批号为空时转为 null |
| | | watch( |
| | |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | warehouseId: undefined, |
| | | type: undefined, |
| | | qualitity: 0, |
| | | batchNo: null, |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 组件挂载时加载仓库列表 |
| | | onMounted(() => { |
| | | fetchWarehouseList(); |
| | | }); |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | |
| | | <el-table-column label="产品大类" prop="productName" show-overflow-tooltip /> |
| | | <el-table-column label="规格型号" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="单位" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="库位" prop="warehouseName" show-overflow-tooltip /> |
| | | <el-table-column label="批号" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column label="合格库存数量" prop="qualifiedQuantity" show-overflow-tooltip /> |
| | | <el-table-column label="不合格库存数量" prop="unQualifiedQuantity" show-overflow-tooltip /> |