| | |
| | | }); |
| | | }; |
| | | |
| | | // 编辑耗材入库(仅用于台账编辑) |
| | | export const editStockInStock = (data) => { |
| | | return request({ |
| | | url: "/consumablesInRecord/editStockInStock", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | export const batchDeleteConsumablesInRecords = (ids) => { |
| | | return request({ |
| | | url: "/consumablesInRecord", |
| | |
| | | data: ids, |
| | | }); |
| | | }; |
| | | |
| | | // 编辑耗材出库(仅用于台账编辑) |
| | | export const editStockOut = (data) => { |
| | | return request({ |
| | | url: "/consumablesOutRecord/editStockOut", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 编辑入库(用于库存台账编辑) |
| | | export const editStockInStock = (data) => { |
| | | return request({ |
| | | url: "/stockInRecord/editStockInStock", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | export const batchDeleteStockInRecords = (ids) => { |
| | | return request({ |
| | | url: "/stockInRecord", |
| | |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | // 编辑出库(库存台账编辑) |
| | | export const editStockOut = (data) => { |
| | | return request({ |
| | | url: "/stockOutRecord/editStockOut", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | |
| | | </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> |
| | |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="出库数量" |
| | | prop="stockOutNum" |
| | | label="数量" |
| | | prop="qualitity" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | <!-- <el-table-column |
| | | label="采购员" |
| | | prop="purchaser" |
| | | show-overflow-tooltip |
| | | /> |
| | | /> --> |
| | | <el-table-column |
| | | label="出库人" |
| | | 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> |
| | |
| | | {{ getRecordType(scope.row.recordType) }} |
| | | </template> |
| | | </el-table-column> --> |
| | | <el-table-column |
| | | label="车牌" |
| | | prop="licensePlateNo" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="操作" |
| | | width="120" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" |
| | | size="mini" |
| | | @click="handlePreview(scope.row)">导出过磅单</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- 不再展示过磅相关字段与导出操作 --> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | |
| | | /> |
| | | </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(); |
| | |
| | | } |
| | | }) |
| | | |
| | | 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([]); |
| | |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除 |
| | | @click="handleDelete" |
| | | v-if="hasCReceiptCancel">删除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <el-table-column label="单位" |
| | | prop="unit" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="入库数量" |
| | | prop="stockInNum" |
| | | <el-table-column label="数量" |
| | | prop="qualitity" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="车牌号" |
| | | prop="licensePlateNo" |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="毛重(吨)" |
| | | prop="grossWeight" |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="皮重(吨)" |
| | | prop="tareWeight" |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="净重(吨)" |
| | | prop="netWeight" |
| | | v-if="type === '0'" |
| | | <el-table-column label="采购员" |
| | | prop="purchaser" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="入库人" |
| | | prop="createBy" |
| | |
| | | {{ getRecordType(scope.row.recordType) }} |
| | | </template> |
| | | </el-table-column> --> |
| | | <el-table-column label="过磅日期" |
| | | prop="weighingDate" |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="过磅员" |
| | | prop="weighingOperator" |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="操作" |
| | | <!-- <el-table-column label="操作" |
| | | width="120" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" |
| | | size="mini" |
| | | @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> |
| | | </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> |
| | |
| | | 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(); |
| | | |
| | |
| | | default: '0' |
| | | } |
| | | }) |
| | | |
| | | const hasCReceiptEdit = computed(() => checkPermi(['c_receipt_edit'])); |
| | | const hasCReceiptCancel = computed(() => checkPermi(['c_receipt_cancel'])); |
| | | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 编辑耗材入库 |
| | | 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(); |
| | |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | |
| | | <!-- productType === 0:原材料 --> |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | | :rules="[{ required: true, message: '请输入车牌号', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="formState.licensePlateNo" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="毛重(吨)" |
| | | prop="grossWeight" |
| | | :rules="[{ required: true, message: '请输入毛重', trigger: ['blur','change'] }]" |
| | | v-if="type === 'qualified'" |
| | | label="数量" |
| | | prop="qualitity" |
| | | :rules="[{ required: true, message: '请输入数量', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.grossWeight" |
| | | :step="0.01" |
| | | v-model="formState.qualitity" |
| | | :min="0" |
| | | :step="1" |
| | | :precision="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeight" |
| | | controls-position="right" |
| | | placeholder="请输入数量" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="皮重(吨)" |
| | | prop="tareWeight" |
| | | :rules="[{ required: true, message: '请输入皮重', trigger: ['blur','change'] }]" |
| | | v-if="type === 'qualified'" |
| | | label="采购员" |
| | | prop="purchaser" |
| | | :rules="[{ required: true, message: '请输入采购员', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.tareWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeight" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | :rules="[{ required: true, message: '请先输入毛重和皮重自动计算净重', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.netWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="过磅日期" |
| | | prop="weighingDate" |
| | | :rules="[{ required: true, message: '请选择过磅日期', trigger: 'change' }]" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="formState.weighingDate" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | placeholder="请选择过磅日期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | v-if="type === 'qualified' && formState.productType === 0" |
| | | label="过磅员" |
| | | prop="weighingOperator" |
| | | :rules="[{ required: true, message: '请输入过磅员', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="formState.weighingOperator" /> |
| | | <el-input v-model="formState.purchaser" placeholder="请输入采购员" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="备注" prop="remark"> |
| | |
| | | productModelName: "", |
| | | unit: "", |
| | | productType: undefined, |
| | | // 过磅相关字段(仅原材料合格品使用) |
| | | licensePlateNo: "", |
| | | grossWeight: undefined, |
| | | tareWeight: undefined, |
| | | netWeight: undefined, |
| | | weighingDate: undefined, |
| | | weighingOperator: "", |
| | | qualitity: undefined, |
| | | purchaser: "", |
| | | remark: '', |
| | | }); |
| | | |
| | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // 重置表单数据 |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | unit: "", |
| | | productType: undefined, |
| | | qualitity: undefined, |
| | | purchaser: "", |
| | | remark: '', |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产品选择处理 |
| | | const handleProductSelect = async (products) => { |
| | | formState.value.weighingDate = undefined; |
| | | formState.value.grossWeight = undefined; |
| | | formState.value.tareWeight = undefined; |
| | | formState.value.netWeight = undefined; |
| | | formState.value.qualitity = undefined; |
| | | formState.value.purchaser = ""; |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | formState.value.productId = product.productId; |
| | |
| | | showProductSelectDialog.value = false; |
| | | // 触发表单验证更新 |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | |
| | | // 净重 = 毛重 - 皮重 |
| | | const computeNetWeight = () => { |
| | | const { grossWeight, tareWeight } = formState.value; |
| | | if (grossWeight != null && tareWeight != null) { |
| | | const net = Number(grossWeight) - Number(tareWeight); |
| | | // 保留两位小数,且不为负 |
| | | const safeNet = Number(net.toFixed(2)); |
| | | formState.value.netWeight = safeNet > 0 ? safeNet : 0; |
| | | } else { |
| | | formState.value.netWeight = undefined; |
| | | } |
| | | }; |
| | | |
| | |
| | | <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="qualitity" show-overflow-tooltip /> |
| | | <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip /> |
| | | <!-- <el-table-column label="库存预警数量" prop="warnNum" show-overflow-tooltip /> --> |
| | | <el-table-column label="净重(吨)" prop="netWeight" show-overflow-tooltip /> |
| | | <el-table-column label="数量" prop="qualitity" show-overflow-tooltip /> |
| | | <!-- <el-table-column label="采购员" prop="purchaser" show-overflow-tooltip /> --> |
| | | <el-table-column label="备注" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" min-width="60" align="center"> |
| | |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | | > |
| | | <el-input v-model="formState.licensePlateNo" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="毛重(吨)" |
| | | prop="grossWeight" |
| | | label="数量" |
| | | prop="qualitity" |
| | | :rules="[{ required: true, message: '请输入数量', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.grossWeight" |
| | | :step="0.01" |
| | | v-model="formState.qualitity" |
| | | :min="0" |
| | | :step="1" |
| | | :precision="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeight" |
| | | controls-position="right" |
| | | placeholder="请输入数量" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="皮重(吨)" |
| | | prop="tareWeight" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.tareWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeight" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.netWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅日期" |
| | | prop="weighingDate" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="formState.weighingDate" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | placeholder="请选择过磅日期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅员" |
| | | prop="weighingOperator" |
| | | > |
| | | <el-input v-model="formState.weighingOperator" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="备注" prop="remark"> |
| | |
| | | initFormData() |
| | | }) |
| | | |
| | | const isRawMaterial = computed(() => { |
| | | return props.record.parentName === '原材料'; |
| | | }) |
| | | |
| | | const ledgerNetWeight = computed(() => { |
| | | const n = Number(props.record?.netWeight ?? 0); |
| | | return Number.isFinite(n) ? n : 0; |
| | | }); |
| | | |
| | | const initFormData = () => { |
| | | if (props.record) { |
| | | formState.value = { |
| | |
| | | productName: "", |
| | | model: "", |
| | | unit: "", |
| | | // 过磅相关字段 |
| | | licensePlateNo: "", |
| | | grossWeight: undefined, |
| | | tareWeight: undefined, |
| | | netWeight: undefined, |
| | | weighingDate: undefined, |
| | | weighingOperator: "", |
| | | qualitity: undefined, |
| | | remark: '', |
| | | }); |
| | | |
| | |
| | | productName: "", |
| | | model: "", |
| | | unit: "", |
| | | licensePlateNo: "", |
| | | grossWeight: undefined, |
| | | tareWeight: undefined, |
| | | netWeight: undefined, |
| | | weighingDate: undefined, |
| | | weighingOperator: "", |
| | | qualitity: undefined, |
| | | remark: '', |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 净重 = 毛重 - 皮重 |
| | | const computeNetWeight = () => { |
| | | const { grossWeight, tareWeight } = formState.value; |
| | | if (grossWeight != null && tareWeight != null) { |
| | | const net = Number(grossWeight) - Number(tareWeight); |
| | | const safeNet = Number(net.toFixed(2)); |
| | | const computedNet = safeNet > 0 ? safeNet : 0; |
| | | const maxNet = ledgerNetWeight.value; |
| | | if (Number.isFinite(maxNet) && maxNet > 0 && computedNet > maxNet) { |
| | | const cappedNet = Number(maxNet.toFixed(2)); |
| | | formState.value.netWeight = cappedNet; |
| | | // 同步毛重,保持:净重 = 毛重 - 皮重 |
| | | const tare = Number(tareWeight); |
| | | if (Number.isFinite(tare)) { |
| | | formState.value.grossWeight = Number((tare + cappedNet).toFixed(2)); |
| | | } |
| | | proxy?.$modal?.msgWarning?.(`领用净重不能超过台账净重(${maxNet.toFixed(2)} 吨)`); |
| | | return; |
| | | } |
| | | formState.value.netWeight = computedNet; |
| | | } else { |
| | | formState.value.netWeight = undefined; |
| | | } |
| | | }; |
| | | |
| | | // 产品选择处理 |
| | |
| | | proxy.$modal.msgError("请选择规格"); |
| | | return; |
| | | } |
| | | const maxNet = ledgerNetWeight.value; |
| | | const usedNet = Number(formState.value.netWeight ?? 0); |
| | | if (Number.isFinite(maxNet) && maxNet > 0 && Number.isFinite(usedNet) && usedNet > maxNet) { |
| | | proxy.$modal.msgError(`领用净重不能超过台账净重(${maxNet.toFixed(2)} 吨)`); |
| | | const availableQty = Number(props.record?.qualitity ?? 0); |
| | | const useQty = Number(formState.value.qualitity ?? 0); |
| | | if (Number.isFinite(availableQty) && Number.isFinite(useQty) && useQty > availableQty) { |
| | | proxy.$modal.msgError(`领用数量不能超过库存数量(${availableQty})`); |
| | | return; |
| | | } |
| | | if (props.type === 'qualified') { |
| | |
| | | |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: '原材料不合格数', |
| | | name: '入厂不合格数', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | |
| | | data: [] |
| | | }, |
| | | { |
| | | name: '过程不合格数', |
| | | name: '车间不合格数', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | |
| | | } |
| | | const barLegend = { |
| | | show: true, |
| | | data: ['原材料不合格数', '过程不合格数', '出厂不合格数'] |
| | | data: ['入厂不合格数', '车间不合格数', '出厂不合格数'] |
| | | } |
| | | const barLegend1 = { |
| | | show: true, |
| | |
| | | </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="hasDispatchCancel">删除</el-button> |
| | | <!-- <el-button type="primary" plain @click="handlePrint">打印</el-button> --> |
| | | </div> |
| | | </div> |
| | |
| | | prop="unit" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | <!-- <el-table-column |
| | | label="出库数量" |
| | | prop="stockOutNum" |
| | | show-overflow-tooltip |
| | | /> |
| | | /> --> |
| | | <el-table-column |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="操作" |
| | | width="120" |
| | | width="260" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" |
| | | size="mini" |
| | | @click="handlePreview(scope.row)">导出过磅单</el-button> |
| | | <el-button |
| | | v-if="scope.row.recordType === '0' && hasDispatchEdit" |
| | | type="primary" |
| | | size="mini" |
| | | @click="handleEdit(scope.row)" |
| | | >编辑</el-button> |
| | | <el-button |
| | | v-if="scope.row.recordType === '0'" |
| | | type="primary" |
| | | size="mini" |
| | | @click="handlePreview(scope.row)" |
| | | >导出过磅单</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog |
| | | v-model="isShowEditModal" |
| | | title="编辑出库" |
| | | width="800" |
| | | @close="closeEditModal" |
| | | > |
| | | <el-form label-width="140px" :model="editForm" label-position="top" ref="editFormRef"> |
| | | <!-- <el-form-item |
| | | label="出库数量" |
| | | prop="stockOutNum" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.stockOutNum" |
| | | :min="0" |
| | | :step="1" |
| | | :precision="0" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> --> |
| | | |
| | | <el-form-item |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | | :rules="[{ required: true, message: '请输入车牌号', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="editForm.licensePlateNo" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="毛重(吨)" |
| | | prop="grossWeight" |
| | | :rules="[{ required: true, message: '请输入毛重', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.grossWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeightEdit" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="皮重(吨)" |
| | | prop="tareWeight" |
| | | :rules="[{ required: true, message: '请输入皮重', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.tareWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeightEdit" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | :rules="[{ required: true, message: '净重由毛重和皮重自动计算', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.netWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅日期" |
| | | prop="weighingDate" |
| | | :rules="[{ required: true, message: '请选择过磅日期', trigger: 'change' }]" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="editForm.weighingDate" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | placeholder="请选择过磅日期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅员" |
| | | prop="weighingOperator" |
| | | :rules="[{ required: true, message: '请输入过磅员', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="editForm.weighingOperator" /> |
| | | </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> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | |
| | | |
| | | <script setup> |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref } from "vue"; |
| | | import { ref, computed } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { checkPermi } from "@/utils/permission.js"; |
| | | import { |
| | | getStockOutPage, |
| | | delStockOut, |
| | | editStockOut, |
| | | } from "@/api/inventoryManagement/stockOut.js"; |
| | | import { |
| | | findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions, |
| | |
| | | default: '0' |
| | | } |
| | | }) |
| | | |
| | | const hasDispatchEdit = computed(() => checkPermi(['dispatch_edit'])); |
| | | const hasDispatchCancel = computed(() => checkPermi(['dispatch_cancel'])); |
| | | |
| | | // 打印相关 |
| | | const printPreviewVisible = ref(false); |
| | |
| | | proxy.$download.name(row.weighbridgeDocPath); |
| | | } |
| | | |
| | | // 编辑出库 |
| | | const isShowEditModal = ref(false); |
| | | const editFormRef = ref(null); |
| | | const editForm = ref({}); |
| | | |
| | | // 毛重 - 皮重 计算净重(保留两位小数,且不为负) |
| | | const computeNetWeightEdit = () => { |
| | | const gross = Number(editForm.value?.grossWeight ?? NaN); |
| | | const tare = Number(editForm.value?.tareWeight ?? NaN); |
| | | if (Number.isFinite(gross) && Number.isFinite(tare)) { |
| | | const net = gross - tare; |
| | | const safeNet = Number(net.toFixed(2)); |
| | | editForm.value.netWeight = safeNet > 0 ? safeNet : 0; |
| | | } else { |
| | | editForm.value.netWeight = undefined; |
| | | } |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | editForm.value = { ...row }; |
| | | computeNetWeightEdit(); |
| | | isShowEditModal.value = true; |
| | | }; |
| | | |
| | | const closeEditModal = () => { |
| | | isShowEditModal.value = false; |
| | | editForm.value = {}; |
| | | editFormRef.value?.clearValidate?.(); |
| | | }; |
| | | |
| | | const handleEditSubmit = () => { |
| | | editFormRef.value?.validate?.((valid) => { |
| | | if (!valid) return; |
| | | const { stockOutNum, ...payload } = editForm.value || {}; |
| | | editStockOut(payload).then(() => { |
| | | closeEditModal(); |
| | | proxy.$modal.msgSuccess("编辑成功"); |
| | | getList(); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("是否确认导出?", "导出", { |
| | |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除 |
| | | @click="handleDelete" |
| | | v-if="hasReceiptCancel">删除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <el-table-column label="单位" |
| | | prop="unit" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="入库数量" |
| | | <!-- <el-table-column label="入库数量" |
| | | prop="stockInNum" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip/> --> |
| | | <el-table-column label="车牌号" |
| | | prop="licensePlateNo" |
| | | v-if="type === '0'" |
| | |
| | | v-if="type === '0'" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="操作" |
| | | width="120" |
| | | width="260" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button v-if="scope.row.recordType === '0' && hasReceiptEdit" |
| | | type="primary" |
| | | size="mini" |
| | | @click="handleEdit(scope.row)" |
| | | >编辑</el-button> |
| | | <el-button v-if="scope.row.recordType === '0'" |
| | | type="primary" |
| | | size="mini" |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog |
| | | v-model="isShowEditModal" |
| | | title="编辑入库" |
| | | width="800" |
| | | @close="closeEditModal" |
| | | > |
| | | <el-form label-width="140px" :model="editForm" label-position="top" ref="editFormRef"> |
| | | <!-- <el-form-item |
| | | label="入库数量" |
| | | prop="stockInNum" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.stockInNum" |
| | | :min="0" |
| | | :step="1" |
| | | :precision="0" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> --> |
| | | |
| | | <template v-if="type === '0'"> |
| | | <el-form-item |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | | :rules="[{ required: true, message: '请输入车牌号', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input v-model="editForm.licensePlateNo" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="毛重(吨)" |
| | | prop="grossWeight" |
| | | :rules="[{ required: true, message: '请输入毛重', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.grossWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeightEdit" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="皮重(吨)" |
| | | prop="tareWeight" |
| | | :rules="[{ required: true, message: '请输入皮重', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.tareWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | @change="computeNetWeightEdit" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | :rules="[{ required: true, message: '请输入净重', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="editForm.netWeight" |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅日期" |
| | | prop="weighingDate" |
| | | :rules="[{ required: true, message: '请选择过磅日期', trigger: 'change' }]" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="editForm.weighingDate" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | placeholder="请选择过磅日期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="过磅员" |
| | | prop="weighingOperator" |
| | | :rules="[{ required: true, message: '请输入过磅员', trigger: ['blur', 'change'] }]" |
| | | > |
| | | <el-input v-model="editForm.weighingOperator" /> |
| | | </el-form-item> |
| | | </template> |
| | | </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> |
| | | <div style="margin-top: 12px; display: flex; justify-content: flex-end;"> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | |
| | | toRefs, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | computed, |
| | | } from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { checkPermi } from "@/utils/permission.js"; |
| | | import { |
| | | getStockInRecordListPage, |
| | | batchDeleteStockInRecords, |
| | | editStockInStock, |
| | | } from "@/api/inventoryManagement/stockInRecord.js"; |
| | | import { |
| | | findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions, |
| | |
| | | default: '0' |
| | | } |
| | | }) |
| | | |
| | | const hasReceiptEdit = computed(() => checkPermi(['receipt_edit'])); |
| | | const hasReceiptCancel = computed(() => checkPermi(['receipt_cancel'])); |
| | | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | |
| | | proxy.$download.name(row.weighbridgeDocPath); |
| | | } |
| | | |
| | | // 编辑 |
| | | const isShowEditModal = ref(false); |
| | | const editFormRef = ref(null); |
| | | const editForm = ref({}); |
| | | |
| | | // 毛重 - 皮重 计算净重(保留两位小数,且不为负) |
| | | const computeNetWeightEdit = () => { |
| | | const gross = Number(editForm.value?.grossWeight ?? NaN); |
| | | const tare = Number(editForm.value?.tareWeight ?? NaN); |
| | | if (Number.isFinite(gross) && Number.isFinite(tare)) { |
| | | const net = gross - tare; |
| | | const safeNet = Number(net.toFixed(2)); |
| | | editForm.value.netWeight = safeNet > 0 ? safeNet : 0; |
| | | } else { |
| | | editForm.value.netWeight = undefined; |
| | | } |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | editForm.value = { ...row }; |
| | | if (props.type === '0') { |
| | | computeNetWeightEdit(); |
| | | } |
| | | isShowEditModal.value = true; |
| | | }; |
| | | |
| | | const closeEditModal = () => { |
| | | isShowEditModal.value = false; |
| | | editForm.value = {}; |
| | | // 清理表单校验状态(有 ref 时) |
| | | editFormRef.value?.clearValidate?.(); |
| | | }; |
| | | |
| | | const handleEditSubmit = () => { |
| | | editFormRef.value?.validate?.((valid) => { |
| | | if (!valid) return; |
| | | editStockInStock(editForm.value).then(() => { |
| | | closeEditModal(); |
| | | proxy.$modal.msgSuccess("编辑成功"); |
| | | getList(); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("是否确认导出?", "导出", { |
| | |
| | | <el-table-column label="库存数量" prop="qualitity" show-overflow-tooltip /> |
| | | <el-table-column label="冻结数量" prop="lockedQuantity" show-overflow-tooltip /> |
| | | <!-- <el-table-column label="库存预警数量" prop="warnNum" show-overflow-tooltip /> --> |
| | | <el-table-column label="净重(吨)" prop="netWeight" show-overflow-tooltip /> |
| | | <!-- <el-table-column label="净重(吨)" prop="netWeight" show-overflow-tooltip /> --> |
| | | <el-table-column label="备注" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" min-width="60" align="center"> |
| | |
| | | <el-form-item |
| | | label="车牌号" |
| | | prop="licensePlateNo" |
| | | :rules="[{ required: true, message: '请输入车牌号', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="formState.licensePlateNo" /> |
| | | </el-form-item> |
| | |
| | | <el-form-item |
| | | label="毛重(吨)" |
| | | prop="grossWeight" |
| | | :rules="[{ required: true, message: '请输入毛重', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.grossWeight" |
| | |
| | | <el-form-item |
| | | label="皮重(吨)" |
| | | prop="tareWeight" |
| | | :rules="[{ required: true, message: '请输入皮重', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.tareWeight" |
| | |
| | | <el-form-item |
| | | label="净重(吨)" |
| | | prop="netWeight" |
| | | :rules="[{ required: true, message: '净重由毛重和皮重自动计算', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input-number |
| | | v-model="formState.netWeight" |
| | |
| | | <el-form-item |
| | | label="过磅日期" |
| | | prop="weighingDate" |
| | | :rules="[{ required: true, message: '请选择过磅日期', trigger: 'change' }]" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | |
| | | <el-form-item |
| | | label="过磅员" |
| | | prop="weighingOperator" |
| | | :rules="[{ required: true, message: '请输入过磅员', trigger: ['blur','change'] }]" |
| | | > |
| | | <el-input v-model="formState.weighingOperator" /> |
| | | </el-form-item> |
| | |
| | | formState.value = { |
| | | ...props.record, |
| | | } |
| | | // 初始化时也触发一次净重计算,避免接口回填后净重为空 |
| | | computeNetWeight() |
| | | } |
| | | } |
| | | |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="产品名称:" prop="productId"> |
| | | <el-tree-select |
| | | v-if="operationType !== 'edit'" |
| | | v-model="form.productId" |
| | | placeholder="请选择" |
| | | clearable |
| | |
| | | @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> |
| | |
| | | <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> |
| | |
| | | }, |
| | | 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" }], |
| | |
| | | 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) => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | const getProductOptions = async () => { |
| | | const res = await productTreeList(); |
| | | productOptions.value = convertIdToValue(res); |
| | | }; |
| | | const getModels = (value) => { |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | |
| | | }) |
| | | }; |
| | | |
| | | // 编辑模式/或任意需要时:只拉取规格型号列表,不清空已回填的字段 |
| | | 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++) { |
| | |
| | | } |
| | | 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; |
| | |
| | | <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"> |
| | |
| | | |
| | | <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: { |
| | |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const hasNonconformingEdit = computed(() => checkPermi(["nonconforming_edit"])); |
| | | const hasNonconformingCancel = computed(() => checkPermi(["nonconforming_cancel"])); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "检测日期", |
| | |
| | | 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([]); |
| | |
| | | |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | if (type !== 'add' && row?.inspectState === 1) { |
| | | proxy.$modal.msgWarning("已处理的数据不能再编辑"); |
| | | return; |
| | | } |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | |
| | | const currentProductId = ref(0); |
| | | const modelOptions = ref([]); |
| | | |
| | | const getTodayStr = () => { |
| | | const now = new Date(); |
| | | const y = now.getFullYear(); |
| | | const m = String(now.getMonth() + 1).padStart(2, "0"); |
| | | const d = String(now.getDate()).padStart(2, "0"); |
| | | return `${y}-${m}-${d}`; |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type; |
| | |
| | | }) |
| | | // 先重置表单数据(保持字段完整,避免弹窗首次渲染时触发必填红框“闪一下”) |
| | | form.value = { |
| | | checkTime: "", |
| | | checkTime: getTodayStr(), |
| | | supplier: "", |
| | | productName: "", |
| | | productId: "", |
| | |
| | | <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"> |
| | |
| | | </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"; |
| | |
| | | findRawMaterialListPage, |
| | | submitRawMaterial, updateCheckUserName,downloadRawMaterial |
| | | } from "@/api/qualityManagement/rawMaterial.js"; |
| | | import { checkPermi } from "@/utils/permission.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | }, |
| | | }); |
| | | const {searchForm, rules} = toRefs(data); |
| | | |
| | | const hasRawCancel = computed(() => checkPermi(["raw_cancel"])); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "检测日期", |
| | |
| | | disabled: (row) => { |
| | | // 已提交则禁用 |
| | | if (row.inspectState == 1) return true; |
| | | // 如果检验员有值,只有当前登录用户能编辑 |
| | | if (row.checkUserName) { |
| | | return row.checkUserName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | { |
| | |
| | | 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", |
| | |
| | | }, |
| | | // vite 相关配置 |
| | | server: { |
| | | port: 80, |
| | | port: 8001, |
| | | host: true, |
| | | open: true, |
| | | proxy: { |