From 7ffa19f1fe3b37519e83ed1f86715154b13c00f3 Mon Sep 17 00:00:00 2001 From: maven <2163098428@qq.com> Date: 星期二, 26 八月 2025 15:16:10 +0800 Subject: [PATCH] yys 生产管控(完成基础逻辑) --- src/views/production/components/ProductionDetailsTable.vue | 30 src/views/warehouseManagement/index.vue | 31 src/views/production/productionReporting/components/useDialog.js | 62 + src/views/production/operationScheduling/components/useTableData.js | 132 +++ src/views/production/productionReporting/components/ProductionDialog.vue | 348 ++++++++ src/views/production/operationScheduling/index.vue | 250 ++++++ src/views/production/productionReporting/components/useTableData.js | 132 +++ src/api/productionScheduling/index.js | 38 src/views/production/operationScheduling/components/ProductionDetailsTable.vue | 360 +++++++++ src/views/production/productionReporting/components/useCoalData.js | 96 ++ src/components/Table/ETable.vue | 4 src/views/production/operationScheduling/components/ProductionDialog.vue | 410 ++++++++++ src/views/procureMent/index.vue | 8 src/views/production/operationScheduling/components/useDialog.js | 62 + src/views/procureMent/components/ProductionDialog.vue | 25 src/views/production/operationScheduling/components/useCoalData.js | 96 ++ src/views/production/productionReporting/index.vue | 277 ++++++ 17 files changed, 2,361 insertions(+), 0 deletions(-) diff --git a/src/api/productionScheduling/index.js b/src/api/productionScheduling/index.js new file mode 100644 index 0000000..3a2adb5 --- /dev/null +++ b/src/api/productionScheduling/index.js @@ -0,0 +1,38 @@ +// 鐢熶骇浠诲姟锛屾姤宸� +import request from '@/utils/request' + +// 鏌ヨ鐢熶骇鍔犲伐-姝e紡搴撶叅绉嶅垪琛� +export function listPage(query) { + return request({ + url: '/productionScheduling/list', + method: 'get', + params: query + }) +} + +// 鎺掍骇 +export function addProductionScheduling(data) { + return request({ + url: '/productionScheduling/addProductionScheduling', + method: 'post', + data: data + }) +} + +// 鍒犻櫎 +export function delProductionScheduling(data) { + return request({ + url: '/productionScheduling/delProductionScheduling', + method: 'delete', + data: data + }) +} + +//鎶ュ伐 +export function work(data) { + return request({ + url: '/productionScheduling/work', + method: 'post', + data: data + }) +} \ No newline at end of file diff --git a/src/components/Table/ETable.vue b/src/components/Table/ETable.vue index 3921d6b..b7089d2 100644 --- a/src/components/Table/ETable.vue +++ b/src/components/Table/ETable.vue @@ -53,6 +53,10 @@ <!-- 榛樿鎿嶄綔鎸夐挳 --> <el-button v-if="operations.includes('edit')" link type="primary" size="small" @click="handleEdit(scope.row)">缂栬緫</el-button> + <el-button v-if="operations.includes('scheduling') && scope.row.status != 3" link type="primary" size="small" + @click="handleEdit(scope.row)">鎺掍骇</el-button> + <el-button v-if="operations.includes('work') && scope.row.status != 3" link type="primary" size="small" + @click="handleEdit(scope.row)">鎶ュ伐</el-button> <el-button v-if="operations.includes('viewRow')" link type="primary" size="small" @click="handleView(scope.row)">鏌ョ湅</el-button> <el-button v-if="operations.includes('viewFile')" link type="primary" size="small" diff --git a/src/views/procureMent/components/ProductionDialog.vue b/src/views/procureMent/components/ProductionDialog.vue index 859cbea..79b2bac 100644 --- a/src/views/procureMent/components/ProductionDialog.vue +++ b/src/views/procureMent/components/ProductionDialog.vue @@ -30,6 +30,20 @@ /> </el-select> </el-form-item> + <el-form-item label="鐓ゆ枡绫诲瀷" prop="type"> + <el-select + v-model="form.type" + placeholder="璇烽�夋嫨鐓ょ" + :disabled="isViewMode" + > + <el-option + :label="item.label" + v-for="item in typeList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> <el-form-item label="鐓ょ" prop="coalId"> <el-select v-model="form.coalId" @@ -183,6 +197,16 @@ required: true, type: Boolean, }); +const typeList = [ + { + value: 1, + label: "鎴愬搧", + }, + { + value: 2, + label: "鍘熸枡", + }, +]; const form = defineModel("form", { required: true, type: Object, @@ -343,6 +367,7 @@ supplierName: [ { required: true, message: "璇疯緭鍏ヤ緵搴斿晢鍚嶇О", trigger: "blur" }, ], + type: [{ required: true, message: "璇烽�夋嫨绫诲瀷", trigger: "change" }], coal: [{ required: true, message: "璇疯緭鍏ョ叅绉�", trigger: "blur" }], purchaseQuantity: [ { required: true, message: "璇疯緭鍏ラ噰璐暟閲�", trigger: "blur" }, diff --git a/src/views/procureMent/index.vue b/src/views/procureMent/index.vue index 159c0fc..e067737 100644 --- a/src/views/procureMent/index.vue +++ b/src/views/procureMent/index.vue @@ -145,6 +145,14 @@ }, }, { + prop: "type", + label: "鐓ゆ枡绫诲瀷", + minWidth: 120, + formatter: (row) => { + return row.type === 1 ? "鎴愬搧" : "鍘熸枡"; + }, + }, + { prop: "coalId", label: "鐓ょ绫诲瀷", minWidth: 120, diff --git a/src/views/production/components/ProductionDetailsTable.vue b/src/views/production/components/ProductionDetailsTable.vue index 48308f4..43be265 100644 --- a/src/views/production/components/ProductionDetailsTable.vue +++ b/src/views/production/components/ProductionDetailsTable.vue @@ -1,5 +1,24 @@ <template> <el-table :data="tableData" :border="border" style="width: 100%"> + <el-table-column label="鐓ゆ枡绫诲瀷" min-width="120"> + <template #default="{ row, $index }"> + <el-select + clearable + v-model="row.type" + placeholder="璇烽�夋嫨鐓ゆ枡绫诲瀷" + filterable + :key="`coalId-select-${$index}-${typeList.length}`" + :disabled="isViewMode" + > + <el-option + v-for="(item, index) of typeList" + :key="`option-${index}-${item.value}`" + :label="item.label" + :value="item.value" + /> + </el-select> + </template> + </el-table-column> <el-table-column label="鐓ょ" min-width="120"> <template #default="{ row, $index }"> <el-select @@ -164,6 +183,16 @@ import {getCoalInfoList} from "@/api/production"; import {userListAll} from "@/api/publicApi"; +const typeList = [ + { + label: "鎴愬搧", + value: 1, + }, + { + label: "鍘熸枡", + value: 2, + } + ] const props = defineProps({ modelValue: { type: Array, @@ -387,6 +416,7 @@ purchasePrice: "", totalCost: "", producerId: "", + type: 1, ...rowData, }; tableData.value = [...tableData.value, defaultRow]; diff --git a/src/views/production/operationScheduling/components/ProductionDetailsTable.vue b/src/views/production/operationScheduling/components/ProductionDetailsTable.vue new file mode 100644 index 0000000..72b4064 --- /dev/null +++ b/src/views/production/operationScheduling/components/ProductionDetailsTable.vue @@ -0,0 +1,360 @@ +<template> + <el-table :data="tableData" :border="border" style="width: 100%"> + <el-table-column label="宸ュ簭" min-width="120"> + <template #default="{ row, $index }"> + <el-select + clearable + v-model="row.process" + placeholder="璇烽�夋嫨宸ュ簭" + filterable + :disabled="isViewMode" + > + <el-option + v-for="(item, index) of process_list" + :label="item.label" + :value="item.value" + /> + </el-select> + </template> + </el-table-column> + <el-table-column label="鍗曚綅" min-width="120"> + <template #default="{ row, $index }"> + <el-input + v-model="row.unit" + placeholder="璇疯緭鍏ュ崟浣�" + :disabled="isViewMode" + /> + </template> + + </el-table-column> + <el-table-column label="鎺掍骇鏁伴噺" min-width="120"> + <template #default="{ row, $index }"> + <el-input + v-model="row.schedulingNum" + placeholder="璇疯緭鍏ユ帓浜ф暟閲�" + type="number" + :disabled="isViewMode" + /> + </template> + </el-table-column> + + <el-table-column label="宸ユ椂瀹氶" min-width="120"> + <template #default="{ row, $index }"> + <el-input + v-model="row.workHours" + placeholder="璇疯緭鍏ュ伐鏃跺畾棰�" + type="number" + @input="handleInput('workHours', $index, $event)" + :disabled="isViewMode" + > + </el-input> + </template> + </el-table-column> + + <el-table-column label="鎺掍骇鏃ユ湡" min-width="120"> + <template #default="{ row, $index }"> + <el-date-picker + v-model="row.schedulingDate" + type="datetime" + clearable + placeholder="閫夋嫨鏃ユ湡" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + /> + </template> + </el-table-column> + + <el-table-column label="鎺掍骇浜�" min-width="120"> + <template #default="{ row, $index }"> + <el-select + clearable + v-model="row.schedulingUserId" + placeholder="璇烽�夋嫨鎺掍骇浜�" + filterable + :key="`producer-select-${$index}-${userList.length}`" + :disabled="isViewMode" + > + <el-option + v-for="(item, index) of userList" + :key="`option-${index}-${item.key}`" + :label="item.value" + :value="item.key" + /> + </el-select> + </template> + </el-table-column> + <el-table-column + label="鎿嶄綔" + width="120" + fixed="right" + v-if="dialogType !== 'viewRow'" + > + <template #default="{ $index }"> + <el-button + type="danger" + size="small" + @click="handleDelete($index)" + :icon="Delete" + > + 鍒犻櫎 + </el-button> + </template> + </el-table-column> + </el-table> +</template> + +<script setup name="ProductionDetailsTable"> +import {ref, computed, watch, onMounted, nextTick} from "vue"; +import {Delete} from "@element-plus/icons-vue"; +import {ElMessage} from "element-plus"; +import {getCoalFieldList} from "@/api/basicInformation/coalQualityMaintenance"; +import {userListAll} from "@/api/publicApi"; +const { proxy } = getCurrentInstance(); +const {process_list} = proxy.useDict("process_list"); + +const props = defineProps({ + modelValue: { + type: Array, + default: () => [], + }, + border: { + type: Boolean, + default: false, + }, + showOperations: { + type: Boolean, + default: true, + }, + autoCalculate: { + type: Boolean, + default: true, + }, + dialogType:{ + type: String, + default:'add' + } +}); +const isViewMode = computed(() => props.dialogType === "viewRow"); +const emit = defineEmits(["update:modelValue", "input-change", "delete-row"]); + +// 浣跨敤 v-model 杩涜鍙屽悜缁戝畾 +const tableData = computed({ + get() { + return props.modelValue; + }, + set(value) { + emit("update:modelValue", value); + }, +}); + +// 澶勭悊杈撳叆鍙樺寲 +const handleInput = (field, index, value) => { + // 纭繚杈撳叆鍊兼槸鏁板瓧鎴栫┖瀛楃涓茶�屼笖闈炶礋鏁� + if (!/^\d*\.?\d*$/.test(value) && value !== "") { + ElMessage.error("璇疯緭鍏ユ湁鏁堢殑鏁板瓧"); + return; + } + const newData = [...tableData.value]; + newData[index][field] = value; + + // 濡傛灉寮�鍚嚜鍔ㄨ绠楁�绘垚鏈� + if ( + props.autoCalculate && + [ + "laborCost", + "energyCost", + "equipmentDepreciation", + "purchasePrice", + ].includes(field) + ) { + calculateTotalCost(newData[index]); + } + + tableData.value = newData; + emit("input-change", {field, index, value, row: newData[index]}); +}; + +// 璁$畻鎬绘垚鏈� +const calculateTotalCost = (row) => { + const laborCost = parseFloat(row.laborCost) || 0; + const energyCost = parseFloat(row.energyConsumptionCost) || 0; + const equipmentDepreciation = parseFloat(row.equipmentDepreciation) || 0; + const purchasePrice = parseFloat(row.purchasePrice) || 0; + + row.totalCost = ( + laborCost + + energyCost + + equipmentDepreciation + + purchasePrice + ).toFixed(2); +}; + +// 鍒犻櫎琛� +const handleDelete = (index) => { + const newData = [...tableData.value]; + newData.splice(index, 1); + tableData.value = newData; + emit("delete-row", index); +}; + +// 澶勭悊鐓ょ閫夋嫨鍙樺寲 + +// 澶勭悊鐓ょ閫夋嫨鍙樺寲锛堟柊鏂规硶锛氬悕绉伴�夋嫨杞琁D锛� +const handleCoalSelectChange = (row, selectedName) => { + // 鏍规嵁閫夋嫨鐨勫悕绉版壘鍒板搴旂殑ID + const coalItem = weekList.value.find(item => item.value === selectedName); + if (coalItem) { + row.coalId = coalItem.key; // 璁剧疆涓篒D + } else { + row.coalId = ''; // 濡傛灉娌℃壘鍒帮紝娓呯┖ + } +}; + +// 鏍规嵁ID鑾峰彇鐓ょ鍚嶇О锛堢敤浜庢樉绀猴級 +const getCoalNameById = (id) => { + const coalId = weekList.value.find(item => item.key == id); + return coalId ? coalId.value : id; +}; + +const weekList = ref([]); + + +// 鐩戝惉琛ㄦ牸鏁版嵁鍙樺寲锛岀‘淇濇樉绀烘纭� +watch(() => props.modelValue, (newValue) => { + if (newValue && weekList.value.length > 0) { + // 褰撴暟鎹姞杞藉畬鎴愪笖weekList宸茶幏鍙栨椂锛岀‘淇濇樉绀烘纭� + } +}, {deep: true}); + +// 鐩戝惉weekList鍙樺寲锛屽綋涓嬫媺鏁版嵁鍔犺浇瀹屾垚鍚庡鐞嗘樉绀� +watch(weekList, (newList) => { + if (newList.length > 0 && tableData.value.length > 0) { + // 寮哄埗瑙﹀彂琛ㄦ牸閲嶆柊娓叉煋浠ョ‘淇漞l-select姝g‘鏄剧ず + nextTick(() => { + // 瑙﹀彂涓�涓井灏忕殑鏁版嵁鍙樺寲鏉ュ己鍒堕噸鏂版覆鏌� + const tempData = [...tableData.value]; + tableData.value = tempData; + }); + } +}, {deep: true}); + +onMounted(async () => { + let ress = await userListAll(); + ress.data.forEach(item => { + let obj = {}; + obj.value = item.nickName; + obj.key = item.userId; + userList.value.push(obj); + }); +}) +const dropdownList = ref([]); +// 鑾峰彇涓嬫媺鏁版嵁 +const getDropdownData = async () => { + let res = await getCoalFieldList(); + if (res.code === 200) { + dropdownList.value = res.data.map((item) => ({ + value: item.coal, + key: item.id, + })); + } else { + ElMessage.error("鑾峰彇涓嬫媺鏁版嵁澶辫触"); + } +}; +const userList = ref([]); +const getUserList = (async () => { + let res = await userListAll(); + if (res.code === 200) { + userList.value = res.data.map((item) => ({ + value: item.nickName, + key: item.userId, + })); + } else { + ElMessage.error("鑾峰彇鐢ㄦ埛鍒楄〃澶辫触"); + } +}) +// 鐩戝惉琛ㄦ牸鏁版嵁鍙樺寲锛岀‘淇濇樉绀烘纭� +watch(() => props.modelValue, (newValue) => { + if (newValue && userList.value.length > 0) { + // 褰撴暟鎹姞杞藉畬鎴愪笖weekList宸茶幏鍙栨椂锛岀‘淇濇樉绀烘纭� + } +}, {deep: true}); + +// 鐩戝惉userList鍙樺寲锛屽綋涓嬫媺鏁版嵁鍔犺浇瀹屾垚鍚庡鐞嗘樉绀� +watch(userList, (newList) => { + if (newList.length > 0 && tableData.value.length > 0) { + // 寮哄埗瑙﹀彂琛ㄦ牸閲嶆柊娓叉煋浠ョ‘淇漞l-select姝g‘鏄剧ず + nextTick(() => { + // 瑙﹀彂涓�涓井灏忕殑鏁版嵁鍙樺寲鏉ュ己鍒堕噸鏂版覆鏌� + const tempData = [...tableData.value]; + tableData.value = tempData; + }); + } +}, {deep: true}); + +const getUserNameById = (id) => { + const producer = userList.value.find(item => item.key == id); + return producer ? producer.value : id; +}; +// 澶勭悊鐢ㄦ埛閫夋嫨鍙樺寲锛堟柊鏂规硶锛氬悕绉伴�夋嫨杞琁D锛� +const handleUserSelectChange = (row, selectedName) => { + console.log("handleUserSelectChange", row, selectedName); + // 鏍规嵁閫夋嫨鐨勫悕绉版壘鍒板搴旂殑ID + const userItem = userList.value.find(item => item.value === selectedName); + if (userItem) { + row.producerId = userItem.key; // 璁剧疆涓篒D + } else { + row.producerId = ''; // 濡傛灉娌℃壘鍒帮紝娓呯┖ + } +}; +// 鏆撮湶鏂规硶缁欑埗缁勪欢浣跨敤 +defineExpose({ + calculateTotalCost, + getDropdownData, + getUserList, + getCoalNameById, // 鏆撮湶鑾峰彇鐓ょ鍚嶇О鐨勬柟娉� + weekList, // 鏆撮湶weekList璁╃埗缁勪欢鍙互璁块棶 + addRow: (rowData = {}) => { + const defaultRow = { + process: "宸ュ簭1", + unit: "椤�", + schedulingNum: "", + workHours: "", + schedulingDate: "", + schedulingUserId: "", + schedulingUserName: "" + }; + tableData.value = [...tableData.value, defaultRow]; + }, + clearData: () => { + tableData.value = []; + }, + // 娣诲姞涓�涓柟娉曟潵绛夊緟weekList鍔犺浇瀹屾垚 + waitForWeekList: () => { + return new Promise((resolve) => { + if (weekList.value.length > 0) { + resolve(); + } else { + const unwatch = watch(weekList, (newList) => { + if (newList.length > 0) { + unwatch(); + resolve(); + } + }); + } + }); + }, + // 寮哄埗鍒锋柊琛ㄦ牸鏄剧ず + forceRefresh: () => { + nextTick(() => { + const tempData = [...tableData.value]; + tableData.value = tempData; + }); + } +}); +</script> + +<style scoped> +:deep(.el-table .el-table__cell) { + padding: 8px 0; +} +</style> diff --git a/src/views/production/operationScheduling/components/ProductionDialog.vue b/src/views/production/operationScheduling/components/ProductionDialog.vue new file mode 100644 index 0000000..4e26ec9 --- /dev/null +++ b/src/views/production/operationScheduling/components/ProductionDialog.vue @@ -0,0 +1,410 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="宸ュ簭鎺掍骇" + width="1200px" + :close-on-click-modal="false" + @close="handleClose" + > + <div class="empty-table"> + <el-row :gutter="10"> + <el-col :span="2"> + <el-button type="primary" @click="addNewRow"> + <el-icon> + <Plus/> + </el-icon> + 鏂板 + </el-button> + </el-col> + <el-col :span="4"> + <div style="font-size: 16px;">寰呮帓浜ф暟閲忥細{{productionQuantity}}</div> + </el-col> + <!-- <el-col :span="2"> + <el-button type="danger" @click="clearAllRows"> + <el-icon> + <Delete /> + </el-icon> + 娓呯┖ + </el-button> + </el-col> --> + </el-row> + <ProductionDetailsTable + v-model="detailsTableData" + :border="false" + :show-operations="dialogType !== 'viewRow'" + :auto-calculate="true" + @input-change="handleDetailsChange" + @delete-row="handleDeleteRow" + :dialogType="dialogType" + /> + </div> + + <template #footer> + <div class="dialog-footer"> + <el-button + @click="handleClose" + >{{ dialogType === 'viewRow' ? '鍏� 闂�' : '鍙� 娑�' }} + </el-button + > + <!-- <el-button @click="handleReset" v-if="dialogType === 'edit'" + >閲� 缃�</el-button + > --> + <el-button + v-if="dialogType !== 'viewRow'" + type="primary" + :loading="loading" + @click="handleSubmit" + >纭� 瀹� + </el-button + > + </div> + </template> + </el-dialog> + <el-dialog + v-model="innerVisible" + width="1000" + title="閫夋嫨閰嶇疆鏁版嵁" + center + append-to-body + > + <div style="margin-bottom: 10px"> + <el-alert + v-if="tableData.length > 0" + :title="`褰撳墠宸查�夋嫨 ${tableData.length} 鏉℃暟鎹甡" + type="info" + :closable="false" + show-icon + /> + </div> + <ETable + :showIndex="false" + :showOverflowTooltip="false" + @selection-change="handleSelectionChange" + :showOperations="false" + ref="etableRef" + :tableData="formalDatabaseData" + :defaultSelectedIds="selectedIds" + :rowKey="'id'" + height="400" + @cell-edit="handleCellEdit" + :show-selection="true" + /> + <el-row :gutter="24" style="margin-top: 15px"> + <el-col :span="12"> + <el-text type="info"> + 宸查�夋嫨 {{ formalDatabaseSelectedData.length }} 鏉℃暟鎹� + </el-text> + </el-col> + <el-col :span="12" style="text-align: right"> + <el-button @click="innerVisible = false">鍙栨秷</el-button> + <el-button + type="primary" + @click="handleSelectData" + :disabled="formalDatabaseSelectedData.length === 0" + > + 纭畾娣诲姞 + </el-button> + </el-col> + </el-row> + </el-dialog> +</template> + +<script setup> +import {ref, reactive, watch, onMounted, nextTick, computed} from "vue"; +import ETable from "@/components/Table/ETable.vue"; +import ETableModify from "@/components/Table/EtableModify.vue"; +import ProductionDetailsTable from "./ProductionDetailsTable.vue"; +import {ElMessage, ElMessageBox, ElAlert, ElText} from "element-plus"; +import {Delete, Warning, Plus} from "@element-plus/icons-vue"; +import {validateFormData, validateNumber, deepClone, createDefaultProductionRow} from "@/utils/production"; +import {useCoalData} from "./useCoalData"; +import useUserStore from "@/store/modules/user"; +import {addProductionScheduling} from '@/api/productionScheduling/index' + +// Props 鍜� Emits +const props = defineProps({ + visible: {type: Boolean, default: false}, + type: {type: String, default: "add"}, + rowData: {type: Object, default: () => ({})}, +}); + +const dialogVisible = defineModel("visible", {type: Boolean, default: false}); +const emit = defineEmits(["update:visible", "success", "update:productionAndProcessing"]); + +// 鐢ㄦ埛淇℃伅鍜岀叅绉嶆暟鎹� +const userStore = useUserStore(); +const {getCoalNameById} = useCoalData(); +let userInfo; + +// 瀵硅瘽妗嗙姸鎬� +const innerVisible = ref(false); +const dialogType = ref("add"); +const loading = ref(false); +const etableRef = ref(null); + +// 鏁版嵁鐘舵�� +const tableData = ref([]); +const detailsTableData = ref([]); +const formalDatabaseData = ref([]); +const formalDatabaseSelectedData = ref([]); +const selectedIds = ref([]); +const currentRow = ref(null); +const copyForm = ref(null); +const coalList = ref([]) +const supplierList = ref([]); +const productionQuantity = ref(0); + +// 宸ュ叿鍑芥暟 +const debugIdMatching = () => { + if (formalDatabaseData.value.length > 0 && selectedIds.value.length > 0) { + const matchedRows = formalDatabaseData.value.filter((row) => + selectedIds.value.includes(row.id) + ); + } +}; + +const handleRowClick = (row) => { + currentRow.value = row; +}; + +// 鎵嬪姩璁剧疆琛ㄦ牸閫変腑鐘舵�� +const setTableSelection = (ids) => { + if (!etableRef.value || !Array.isArray(ids) || ids.length === 0) { + return; + } + + nextTick(() => { + setTimeout(() => { + try { + etableRef.value.clearSelection(); + const rowsToSelect = formalDatabaseData.value.filter((row) => + ids.includes(row.id) + ); + if (rowsToSelect.length > 0) { + etableRef.value.setRowsSelection(rowsToSelect, true); + } + } catch (error) { + } + }, 150); + }); +}; + +// 鍒濆鍖栧拰缂栬緫鍒濆鍖� +const Initialization = async () => { + tableData.value = []; + detailsTableData.value = []; + copyForm.value = null; + dialogType.value = "add"; + +}; + +const editInitialization = async (type, data) => { + productionQuantity.value = data.productionQuantity; + copyForm.value = deepClone(data); + tableData.value = data.productionInventoryList || []; + detailsTableData.value = data.productionList || []; + dialogType.value = type; + const existingOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = existingOfficialIds; + +}; +// 鐩戝惉瀵硅瘽妗嗙姸鎬侊紝鍦ㄦ墦寮�鏃惰缃�変腑鐘舵�� +watch(innerVisible, (newVal) => { + if (newVal && selectedIds.value.length > 0) { + setTimeout(() => setTableSelection(selectedIds.value), 200); + } + // 瀵硅瘽妗嗗叧闂椂娓呯┖閫夋嫨鐘舵�� + if (!newVal) { + formalDatabaseSelectedData.value = []; + } +}); + +defineExpose({ + Initialization, + editInitialization, +}); +const handleSelectData = (row) => { + tableData.value = []; + if (!innerVisible.value) return; + const selectedData = formalDatabaseSelectedData.value; + if (selectedData.length === 0) { + ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉℃暟鎹�"); + return; + } + let addedCount = 0; + let duplicateCount = 0; + selectedData.forEach((item) => { + const newItem = { + ...item, // 澶嶅埗鎵�鏈夊師濮嬫暟鎹� + officialId: item.id, // 淇濆瓨鍘熷鐨刬d浣滀负officialId + usedQuantity: 0, // 鍒濆浣跨敤鏁伴噺涓�0 + // 鍙互鏍规嵁闇�瑕佹坊鍔犲叾浠栧瓧娈� + }; + tableData.value.push(newItem); + addedCount++; + }); + + // 鏇存柊selectedIds锛岀‘淇濆寘鍚墍鏈夊綋鍓峵ableData涓殑officialId + const allOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = allOfficialIds; + + // 鍏抽棴閫夋嫨瀵硅瘽妗� + innerVisible.value = false; + + // 鏄剧ず缁撴灉娑堟伅 + let message = ""; + if (addedCount > 0) { + message += `鎴愬姛娣诲姞 ${addedCount} 鏉℃暟鎹甡; + } + if (duplicateCount > 0) { + message += (message ? "锛�" : "") + `璺宠繃 ${duplicateCount} 鏉¢噸澶嶆暟鎹甡; + } + if (message) { + ElMessage.success(message); + } else { + ElMessage.info("娌℃湁鏂版暟鎹娣诲姞"); + } +}; +const handleSelectionChange = (selection) => { + formalDatabaseSelectedData.value = selection; +}; +// 鎻愪氦琛ㄥ崟 - 浣跨敤宸ュ叿鍑芥暟楠岃瘉 +const handleSubmit = async () => { + // 楠岃瘉鐢熶骇鏄庣粏鏁版嵁 + const detailsValidation = validateFormData(detailsTableData.value, [ + "process", + "unit", + "schedulingNum", + "workHours", + "schedulingDate", + "schedulingUserId" + ]); + + if (!detailsValidation.isValid) { + ElMessage.warning(detailsValidation.message); + return; + } + let num = 0; + detailsTableData.value.forEach((row) => { + num += row.schedulingNum + }) + if(productionQuantity.value < num){ + ElMessage.warning("寰呮帓浜ф暟閲忎笉鑳藉皬浜庣敓浜ф槑缁嗘暟閲�") + } + console.log(copyForm.value) + detailsTableData.value.forEach((row) => { + row.type = copyForm.value.type + row.productionId = copyForm.value.id + row.coalId = copyForm.value.coalId + }) + detailsTableData.value[0].productionQuantity = copyForm.value.productionQuantity + try{ + const res = await addProductionScheduling(detailsTableData.value) + if (res.code === 200) { + dialogVisible.value = false; + emit("success"); + } else { + ElMessage.error("鎻愪氦澶辫触"); + } + }catch (error){ + ElMessage.error("鎻愪氦澶辫触锛岃閲嶈瘯"); + } +}; +// 鍏抽棴寮圭獥 +const handleClose = () => { + dialogVisible.value = false; +}; + +// 浣跨敤鏁伴噺楠岃瘉 - 浣跨敤宸ュ叿鍑芥暟 +const handleCellEdit = (row, prop, value) => { + if (prop === "usedQuantity") { + const validation = validateNumber(value, 0, Number(row.inventoryQuantity)); + + if (!validation.isValid) { + ElMessage.warning(validation.message); + row.usedQuantity = validation.value; + return; + } + + row.usedQuantity = validation.value; + } +}; + +// 澶勭悊鐢熶骇鏄庣粏琛ㄦ牸鐨勬搷浣� - 浣跨敤宸ュ叿鍑芥暟 +const addNewRow = () => { + const newRow = createDefaultProductionRow(userInfo); + detailsTableData.value.push(newRow); +}; + +// 閲嶇疆鏁版嵁 - 浣跨敤娣辨嫹璐� +const handleReset = () => { + if (copyForm.value) { + tableData.value = deepClone(copyForm.value.productionInventoryList) || []; + detailsTableData.value = deepClone(copyForm.value.productionList) || []; + } +}; + +// 鑾峰彇鐢ㄦ埛淇℃伅骞跺姞杞藉熀纭�鏁版嵁 +onMounted(async () => { + try { + userInfo = await userStore.getInfo(); + } catch (error) { + ElMessage.error("鍒濆鍖栧け璐ワ紝璇烽噸璇�"); + } +}); + +// 绠�鍖栫殑浜嬩欢澶勭悊鍑芥暟 +const handleDetailsChange = (data) => { +}; + +const handleDeleteRow = (index) => { + ElMessage.success(`宸插垹闄ょ ${index + 1} 琛屾暟鎹甡); +}; + +// 鍒犻櫎鍗曚釜宸查�夋暟鎹」 +const handleRemoveItem = (row) => { + const index = tableData.value.findIndex( + (item) => item.officialId === row.officialId + ); + if (index > -1) { + tableData.value.splice(index, 1); + + // 鏇存柊selectedIds + const updatedOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = updatedOfficialIds; + ElMessage.success("宸插垹闄ら�変腑椤�"); + } +}; + + +// 璁$畻鎬讳娇鐢ㄩ噺 +const totalUsedQuantity = computed(() => { + return tableData.value.reduce((total, item) => { + const usedQty = Number(item.usedQuantity) || 0; + return total + usedQty; + }, 0); +}); +</script> + +<style scoped lang="scss"> +.el-form { + .el-row { + padding-top: 20px; + background: rgba($color: #f8fafb, $alpha: 0.5); + } +} + +.el-row > .el-col > h1 { + font-weight: bolder; +} + +.empty-table > .el-row { + margin-bottom: 12px; +} +</style> diff --git a/src/views/production/operationScheduling/components/useCoalData.js b/src/views/production/operationScheduling/components/useCoalData.js new file mode 100644 index 0000000..9a86b81 --- /dev/null +++ b/src/views/production/operationScheduling/components/useCoalData.js @@ -0,0 +1,96 @@ +/** + * 鐓ょ鏁版嵁绠$悊缁勫悎寮忓嚱鏁� + * 鎻愪緵鐓ょ鏁版嵁鐨勮幏鍙栥�佺紦瀛樸�佽浆鎹㈢瓑鍔熻兘 + */ +import {ref, computed, watch} from 'vue'; +import {getCoalInfoList} from "@/api/production"; +import {ElMessage} from 'element-plus'; + +// 鍏ㄥ眬鐓ょ鏁版嵁缂撳瓨 +const coalData = ref([]); +const isLoading = ref(false); +const isLoaded = ref(false); + +export function useCoalData() { + + // 鑾峰彇鐓ょ鏁版嵁 + const getCoalData = async (forceRefresh = false) => { + if (isLoaded.value && !forceRefresh) { + return coalData.value; + } + + if (isLoading.value) { + // 濡傛灉姝e湪鍔犺浇锛岀瓑寰呭姞杞藉畬鎴� + return new Promise((resolve) => { + const unwatch = watch(isLoading, (loading) => { + if (!loading) { + unwatch(); + resolve(coalData.value); + } + }); + }); + } + + isLoading.value = true; + try { + const res = await getCoalInfoList(); + if (res.code === 200) { + coalData.value = res.data; + isLoaded.value = true; + return coalData.value; + } else { + ElMessage.error('鑾峰彇鐓ょ鏁版嵁澶辫触'); + return []; + } + } catch (error) { + ElMessage.error('鑾峰彇鐓ょ鏁版嵁澶辫触'); + console.error('鐓ょ鏁版嵁鑾峰彇閿欒:', error); + return []; + } finally { + isLoading.value = false; + } + }; + + // 鏍规嵁ID鑾峰彇鐓ょ鍚嶇О + const getCoalNameById = (id) => { + if (!id || coalData.value.length === 0) return id; + const coal = coalData.value.find(item => item.id == id); + return coal ? coal.coal : id; + }; + + // 鏍规嵁鍚嶇О鑾峰彇鐓ょID + const getCoalIdByName = (name) => { + if (!name || coalData.value.length === 0) return ''; + const coal = coalData.value.find(item => item.coal === name); + return coal ? coal.id : ''; + }; + + // 鐢熸垚涓嬫媺閫夐」 + const coalOptions = computed(() => { + return coalData.value.map(item => ({ + label: item.coal, + value: item.coal, + key: item.id + })); + }); + + // 鐢熸垚key-value鏄犲皠 + const coalMap = computed(() => { + const map = {}; + coalData.value.forEach(item => { + map[item.id] = item.coal; + }); + return map; + }); + + return { + coalData: computed(() => coalData.value), + coalOptions, + coalMap, + isLoading: computed(() => isLoading.value), + isLoaded: computed(() => isLoaded.value), + getCoalData, + getCoalNameById, + getCoalIdByName + }; +} diff --git a/src/views/production/operationScheduling/components/useDialog.js b/src/views/production/operationScheduling/components/useDialog.js new file mode 100644 index 0000000..3d33158 --- /dev/null +++ b/src/views/production/operationScheduling/components/useDialog.js @@ -0,0 +1,62 @@ +/** + * 瀵硅瘽妗嗙鐞嗙粍鍚堝紡鍑芥暟 + * 鎻愪緵瀵硅瘽妗嗙殑鎵撳紑銆佸叧闂�佹暟鎹鐞嗙瓑鍔熻兘 + */ +import {ref} from 'vue'; + +export function useDialog() { + const dialogVisible = ref(false); + const dialogType = ref('add'); + const dialogRef = ref(null); + const currentRowData = ref(null); + + // 鎵撳紑瀵硅瘽妗� + const openDialog = (type = 'add', rowData = null) => { + dialogType.value = type; + currentRowData.value = rowData; + dialogVisible.value = true; + + // 璋冪敤瀵硅瘽妗嗙粍浠剁殑鍒濆鍖栨柟娉� + if (dialogRef.value) { + if (type === 'add') { + dialogRef.value.Initialization?.(); + } else if ((type === 'edit' || type === 'viewRow' || type === 'scheduling') && rowData) { + dialogRef.value.editInitialization?.(type,rowData); + } + } + }; + const viewRow = (type,rowData) => { + dialogType.value = type; + currentRowData.value = rowData; + dialogVisible.value = true; + openDialog('viewRow', rowData); + }; + // 鍏抽棴瀵硅瘽妗� + const closeDialog = () => { + dialogVisible.value = false; + dialogType.value = 'add'; + currentRowData.value = null; + }; + + // 瀵硅瘽妗嗘垚鍔熷洖璋� + const handleDialogSuccess = (callback) => { + closeDialog(); + if (typeof callback === 'function') { + callback(); + } + }; + + return { + // 鐘舵�� + dialogVisible, + dialogType, + dialogRef, + currentRowData, + + // 鏂规硶 + openDialog, + closeDialog, + handleDialogSuccess, + viewRow + }; +} diff --git a/src/views/production/operationScheduling/components/useTableData.js b/src/views/production/operationScheduling/components/useTableData.js new file mode 100644 index 0000000..4f48ef6 --- /dev/null +++ b/src/views/production/operationScheduling/components/useTableData.js @@ -0,0 +1,132 @@ +/** + * 琛ㄦ牸鏁版嵁绠$悊缁勫悎寮忓嚱鏁� + * 鎻愪緵鍒嗛〉銆佹悳绱€�侀�夋嫨绛夐�氱敤鍔熻兘 + */ +import {ref, reactive} from 'vue'; +import {ElMessage, ElMessageBox} from 'element-plus'; + +export function useTableData(apiFunction, options = {}) { + const { + pageSize = 10, + searchField = 'searchAll' + } = options; + + // 鍝嶅簲寮忔暟鎹� + const tableData = ref([]); + const loading = ref(false); + const total = ref(0); + const selectedRows = ref([]); + + // 鏌ヨ鍙傛暟 + const queryParams = reactive({ + [searchField]: '', + current: 1, + size: pageSize, + }); + + // 鑾峰彇鍒楄〃鏁版嵁 + const getList = async () => { + loading.value = true; + try { + const params = { + [searchField]: queryParams[searchField], + current: queryParams.current, + size: queryParams.size, + }; + console.log('鏌ヨ鍙傛暟:', params); + const res = await apiFunction(params); + tableData.value = res.data.records || []; + total.value = res.data.total || 0; + } catch (error) { + ElMessage.error('鑾峰彇鏁版嵁澶辫触'); + console.error('API閿欒:', error); + } finally { + loading.value = false; + } + }; + + // 鎼滅储 + const handleSearch = () => { + queryParams.current = 1; + getList(); + }; + + // 閲嶇疆鎼滅储 + const handleReset = () => { + queryParams[searchField] = ''; + console.log('閲嶇疆鎼滅储鍙傛暟:', queryParams); + handleSearch(); + }; + + // 鍒嗛〉澶勭悊 + const handlePageChange = ({page, limit}) => { + if (page && page !== queryParams.current) { + queryParams.current = page; + } + if (limit && limit !== queryParams.size) { + queryParams.size = limit; + queryParams.current = 1; // 鏀瑰彉姣忛〉澶у皬鏃跺洖鍒扮涓�椤� + } + getList(); + }; + + // 琛ㄦ牸閫夋嫨澶勭悊 + const handleSelectionChange = (selection) => { + selectedRows.value = selection; + }; + + // 鎵归噺鍒犻櫎 + const deleteSelected = async (deleteFunction) => { + if (selectedRows.value.length === 0) { + ElMessage.warning('璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁'); + return; + } + + try { + await ElMessageBox.confirm( + `纭鍒犻櫎閫変腑鐨� ${selectedRows.value.length} 鏉℃暟鎹悧锛焋, + '鍒犻櫎纭', + { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning' + } + ); + + const ids = selectedRows.value.map(row => row.id); + await deleteFunction(ids); + + ElMessage.success('鍒犻櫎鎴愬姛'); + selectedRows.value = []; + getList(); + } catch (error) { + if (error !== 'cancel') { + ElMessage.error('鍒犻櫎澶辫触'); + console.error('鍒犻櫎閿欒:', error); + } + } + }; + + // 鍒锋柊鏁版嵁 + const refresh = () => { + getList(); + }; + + return { + // 鏁版嵁 + tableData, + loading, + total, + selectedRows, + queryParams, + + // 鏂规硶 + getList, + handleSearch, + handleReset, + handlePageChange, + handleSelectionChange, + deleteSelected, + refresh + }; +} diff --git a/src/views/production/operationScheduling/index.vue b/src/views/production/operationScheduling/index.vue new file mode 100644 index 0000000..ff8b2a6 --- /dev/null +++ b/src/views/production/operationScheduling/index.vue @@ -0,0 +1,250 @@ +<template> + <div class="app-container"> + <!-- 鎼滅储琛ㄥ崟 --> + <el-form :inline="true" :model="queryParams" class="search-form"> + <el-form-item label="鎼滅储"> + <el-input + v-model="queryParams.searchAll" + placeholder="璇疯緭鍏ュ叧閿瘝" + clearable + /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="handleSearch">鏌ヨ</el-button> + <el-button @click="handleReset">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <!-- 涓昏鍐呭鍖哄煙 --> + <el-card> + <!-- 鏁版嵁琛ㄦ牸 --> + <ETable + :showOverflowTooltip="false" + :loading="loading" + :table-data="tableData" + :columns="columns" + :current-page="queryParams.current" + :page-size="queryParams.size" + @selection-change="handleSelectionChange" + @edit="(row) => openDialog('scheduling', row)" + :show-selection="true" + :border="true" + :operations="['scheduling']" + :operationsWidth="200" + :show-overflow-tooltip="false" + style="width: 100%; height: calc(100vh - 26em)" + > + <template #coalId="{ row }"> + <div class="coal-tags"> + <template v-if="row.coalId"> + <el-tag + v-for="coal in parseCoalArray(row.coalId)" + :key="coal" + size="small" + type="primary" + class="coal-tag" + > + {{ getDisplayCoalName(coal) }} + </el-tag> + </template> + <span v-else class="no-data">--</span> + </div> + </template> + </ETable> + <!-- 鍒嗛〉缁勪欢 --> + <Pagination + :layout="'total, prev, pager, next, jumper'" + :total="total" + v-model:page="queryParams.current" + :limit="queryParams.size" + @pagination="handlePageChange" + /> + </el-card> + + <!-- 鐢熶骇瀵硅瘽妗� --> + <!-- handleProductionAndProcessing --> + <ProductionDialog + v-model:visible="dialogVisible" + ref="dialogRef" + :type="dialogType" + @update:productionAndProcessing="handleProductionAndProcessing" + @success="handleDialogSuccess" + /> + </div> +</template> + +<script setup> +import { onMounted, ref } from "vue"; +import { ElMessage } from "element-plus"; +import { Plus, Delete } from "@element-plus/icons-vue"; +import ProductionDialog from "./components/ProductionDialog.vue"; +import ETable from "@/components/Table/ETable.vue"; +import Pagination from "@/components/Pagination/index.vue"; +import { delPM,getProductionList } from "@/api/production"; +import { parseCoalArray } from "@/utils/production"; +import { useTableData } from "./components/useTableData.js"; +import { useDialog } from "./components/useDialog.js"; +import { useCoalData } from "./components/useCoalData.js"; +import { getCoalInfoList } from "@/api/production"; + +// 鐓ょ淇℃伅鍒楄〃 +const coalInfoList = ref([]); + +// 琛ㄦ牸鍒楅厤缃� +const columns = [ + { prop: "coalId", label: "鐓ょ", minWidth: 150, slot: true }, + { + prop: "status", + label: "鐘舵��", + minWidth: 150, + formatter: (row) => { + const statusMap = { + 1: '寰呮帓浜�', + 2: '鎺掍骇涓�', + 3: '宸叉帓浜�' + }; + return statusMap[row.status] || '鏈煡鐘舵��'; + } + }, + { prop: "producer", label: "鐢熶骇浜�", minWidth: 150 }, + { prop: "productionQuantity", label: "鐢熶骇鏁伴噺", minWidth: 120 }, + { prop: "laborCost", label: "浜哄伐鎴愭湰", minWidth: 150 }, + { prop: "energyConsumptionCost", label: "鑳借�楁垚鏈�", minWidth: 120 }, + { prop: "equipmentDepreciation", label: "璁惧鎶樻棫", minWidth: 143 }, + { prop: "totalCost", label: "鎬绘垚鏈�", minWidth: 150 }, +]; + +// 浣跨敤琛ㄦ牸鏁版嵁缁勫悎寮忓嚱鏁� +const { + tableData, + loading, + total, + selectedRows, + queryParams, + getList, + handleSearch, + handleReset, + handlePageChange, + handleSelectionChange, + deleteSelected, +} = useTableData(getProductionList, { pageSize: 10 }); + +// 浣跨敤瀵硅瘽妗嗙粍鍚堝紡鍑芥暟 +const { + dialogVisible, + dialogType, + dialogRef, + openDialog, + handleDialogSuccess: onDialogSuccess, +} = useDialog(); + +// 浣跨敤鐓ょ鏁版嵁缁勫悎寮忓嚱鏁� +const { getCoalNameById, getCoalData } = useCoalData(); + +// 鑾峰彇鐓ょ鏄剧ず鍚嶇О锛堝甫澶囩敤閫昏緫锛� +const getDisplayCoalName = (coalId) => { + // 浼樺厛浣跨敤 useCoalData 鐨勬柟娉� + let name = getCoalNameById(coalId); + + // 濡傛灉娌℃湁鎵惧埌锛屽皾璇曚粠 coalInfoList 涓煡鎵� + if (name === coalId && coalInfoList.value.length > 0) { + const found = coalInfoList.value.find((item) => item.id == coalId); + name = found ? found.coal : coalId; + } + + return name || coalId; +}; + +// 澶勭悊鐢熶骇鏁版嵁鏇存柊 +const handleProductionAndProcessing = (row, rows) => { + const index = tableData.value.findIndex((item) => item.id === rows.id); + if (index !== -1) { + tableData.value[index] = { ...tableData.value[index], ...row }; + } +}; + +// 瀵硅瘽妗嗘垚鍔熷洖璋� +const handleDialogSuccess = () => { + onDialogSuccess(() => { + getList(); + ElMessage.success("鎿嶄綔鎴愬姛"); + }); +}; + +// 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹� +onMounted(async () => { + try { + // 骞惰鍔犺浇鐓ょ鏁版嵁鍜岃〃鏍兼暟鎹� + await Promise.all([ + getCoalData(), // 棰勫姞杞界叅绉嶆暟鎹� + (async () => { + const res = await getCoalInfoList(); + if (res.code === 200) { + coalInfoList.value = res.data; + } + })(), + ]); + + // 鍔犺浇琛ㄦ牸鏁版嵁 + getList(); + } catch (error) { + ElMessage.error("鏁版嵁鍔犺浇澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯"); + } +}); +</script> + +<style scoped lang="scss"> +.production-container { + padding: 20px; + + .el-card:nth-child(1) { + margin-bottom: 20px; + } +} + +.search-bar { + margin-bottom: 20px; + display: flex; + gap: 10px; + + .el-input { + width: 20%; + } +} + +.search-form { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 20px; + + .el-form-item { + margin-right: 10px; + } + + .el-button { + margin-left: 10px; + } +} + +.coal-tags { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + + .coal-tag { + margin-right: 4px; + margin-bottom: 4px; + + &:last-child { + margin-right: 0; + } + } + + .no-data { + color: #999; + font-style: italic; + } +} +</style> diff --git a/src/views/production/productionReporting/components/ProductionDialog.vue b/src/views/production/productionReporting/components/ProductionDialog.vue new file mode 100644 index 0000000..4d6bf8c --- /dev/null +++ b/src/views/production/productionReporting/components/ProductionDialog.vue @@ -0,0 +1,348 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="鐢熶骇鎶ュ伐" + width="70%" + @close="handleClose" + > + <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="鎺掍骇鏁伴噺锛�"> + <el-input v-model="productionQuantity" placeholder="璇疯緭鍏�" clearable disabled/> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鏈鐢熶骇鏁伴噺锛�" prop="finishedNum"> + <el-input-number + v-model="form.finishedNum" + placeholder="璇疯緭鍏�" + :min="0" + :step="0.1" + :precision="2" + clearable + style="width: 100%" + @change="changeNum" + /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="寰呯敓浜ф暟閲忥細"> + <el-input v-model="pendingNum" placeholder="璇疯緭鍏�" clearable disabled/> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐢熶骇浜猴細" prop="schedulingUserId"> + <el-select + v-model="form.schedulingUserId" + placeholder="閫夋嫨浜哄憳" + style="width: 100%;" + > + <el-option + v-for="user in userList" + :key="user.userId" + :label="user.nickName" + :value="user.userId" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="handleSubmit">纭</el-button> + <el-button @click="handleClose">鍙栨秷</el-button> + </div> + </template> + </el-dialog> +</template> + +<script setup> +import {ref, reactive, watch, onMounted, nextTick, computed} from "vue"; +import ETable from "@/components/Table/ETable.vue"; +import ETableModify from "@/components/Table/EtableModify.vue"; +import {ElMessage, ElMessageBox, ElAlert, ElText} from "element-plus"; +import {Delete, Warning, Plus} from "@element-plus/icons-vue"; +import {validateFormData, validateNumber, deepClone, createDefaultProductionRow} from "@/utils/production"; +import {useCoalData} from "./useCoalData"; +import useUserStore from "@/store/modules/user"; +import {work} from '@/api/productionScheduling/index' +import {userListAll} from "@/api/publicApi"; +const userList = ref([]) + +const data = reactive({ + form: { + successNum: 0, + schedulingNum: 0, + finishedNum: 0, + schedulingUserId: "" + }, + rules: { + schedulingNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" },], + }, +}); +const { form, rules } = toRefs(data); +const changeNum = (value) => { + if (value > pendingNum.value) { + form.value.finishedNum = pendingNum.value + ElMessage.warning("鏈鐢熶骇鏁伴噺涓嶅彲澶т簬鎺掍骇鏁伴噺"); + } + pendingNum.value = pendingNum.value - form.value.finishedNum; +} +// Props 鍜� Emits +const props = defineProps({ + visible: {type: Boolean, default: false}, + type: {type: String, default: "add"}, + rowData: {type: Object, default: () => ({})}, +}); + +const dialogVisible = defineModel("visible", {type: Boolean, default: false}); +const emit = defineEmits(["update:visible", "success", "update:productionAndProcessing"]); + +// 鐢ㄦ埛淇℃伅鍜岀叅绉嶆暟鎹� +const userStore = useUserStore(); +const {getCoalNameById} = useCoalData(); +let userInfo; + +// 瀵硅瘽妗嗙姸鎬� +const innerVisible = ref(false); +const dialogType = ref("add"); +const loading = ref(false); +const etableRef = ref(null); + +// 鏁版嵁鐘舵�� +const tableData = ref([]); +const detailsTableData = ref([]); +const formalDatabaseData = ref([]); +const formalDatabaseSelectedData = ref([]); +const selectedIds = ref([]); +const currentRow = ref(null); +const copyForm = ref(null); +const productionQuantity = ref(0); +const pendingNum = ref(0); + + +const handleRowClick = (row) => { + currentRow.value = row; +}; + +// 鎵嬪姩璁剧疆琛ㄦ牸閫変腑鐘舵�� +const setTableSelection = (ids) => { + if (!etableRef.value || !Array.isArray(ids) || ids.length === 0) { + return; + } + + nextTick(() => { + setTimeout(() => { + try { + etableRef.value.clearSelection(); + const rowsToSelect = formalDatabaseData.value.filter((row) => + ids.includes(row.id) + ); + if (rowsToSelect.length > 0) { + etableRef.value.setRowsSelection(rowsToSelect, true); + } + } catch (error) { + } + }, 150); + }); +}; + +// 鍒濆鍖栧拰缂栬緫鍒濆鍖� +const Initialization = async () => { + tableData.value = []; + form.value = { + successNum: 0, + schedulingNum: 0, + finishedNum: 0, + schedulingUserId: "" + }; + detailsTableData.value = []; + copyForm.value = null; + dialogType.value = "add"; +}; + +const editInitialization = async (type, data) => { + //娓呯┖form + Initialization(); + productionQuantity.value = data.schedulingNum; + pendingNum.value = data.schedulingNum - data.successNum; + copyForm.value = deepClone(data); + tableData.value = data.productionInventoryList || []; + detailsTableData.value = data.productionList || []; + dialogType.value = type; + const existingOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = existingOfficialIds; + +}; +// 鐩戝惉瀵硅瘽妗嗙姸鎬侊紝鍦ㄦ墦寮�鏃惰缃�変腑鐘舵�� +watch(innerVisible, (newVal) => { + if (newVal && selectedIds.value.length > 0) { + setTimeout(() => setTableSelection(selectedIds.value), 200); + } + // 瀵硅瘽妗嗗叧闂椂娓呯┖閫夋嫨鐘舵�� + if (!newVal) { + formalDatabaseSelectedData.value = []; + } +}); + +defineExpose({ + Initialization, + editInitialization, +}); +const handleSelectData = (row) => { + tableData.value = []; + if (!innerVisible.value) return; + const selectedData = formalDatabaseSelectedData.value; + if (selectedData.length === 0) { + ElMessage.warning("璇疯嚦灏戦�夋嫨涓�鏉℃暟鎹�"); + return; + } + let addedCount = 0; + let duplicateCount = 0; + selectedData.forEach((item) => { + const newItem = { + ...item, // 澶嶅埗鎵�鏈夊師濮嬫暟鎹� + officialId: item.id, // 淇濆瓨鍘熷鐨刬d浣滀负officialId + usedQuantity: 0, // 鍒濆浣跨敤鏁伴噺涓�0 + // 鍙互鏍规嵁闇�瑕佹坊鍔犲叾浠栧瓧娈� + }; + tableData.value.push(newItem); + addedCount++; + }); + + // 鏇存柊selectedIds锛岀‘淇濆寘鍚墍鏈夊綋鍓峵ableData涓殑officialId + const allOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = allOfficialIds; + + // 鍏抽棴閫夋嫨瀵硅瘽妗� + innerVisible.value = false; + + // 鏄剧ず缁撴灉娑堟伅 + let message = ""; + if (addedCount > 0) { + message += `鎴愬姛娣诲姞 ${addedCount} 鏉℃暟鎹甡; + } + if (duplicateCount > 0) { + message += (message ? "锛�" : "") + `璺宠繃 ${duplicateCount} 鏉¢噸澶嶆暟鎹甡; + } + if (message) { + ElMessage.success(message); + } else { + ElMessage.info("娌℃湁鏂版暟鎹娣诲姞"); + } +}; +const handleSelectionChange = (selection) => { + formalDatabaseSelectedData.value = selection; +}; +// 鎻愪氦琛ㄥ崟 - 浣跨敤宸ュ叿鍑芥暟楠岃瘉 +const handleSubmit = async () => { + console.log(copyForm.value) + try{ + const res = await work({id: copyForm.value.id,successNum: form.value.finishedNum,schedulingUserId: form.value.schedulingUserId}) + if (res.code === 200) { + dialogVisible.value = false; + emit("success"); + } else { + ElMessage.error("鎻愪氦澶辫触"); + } + }catch (error){ + ElMessage.error("鎻愪氦澶辫触锛岃閲嶈瘯"); + } +}; +// 鍏抽棴寮圭獥 +const handleClose = () => { + dialogVisible.value = false; +}; + +// 浣跨敤鏁伴噺楠岃瘉 - 浣跨敤宸ュ叿鍑芥暟 +const handleCellEdit = (row, prop, value) => { + if (prop === "usedQuantity") { + const validation = validateNumber(value, 0, Number(row.inventoryQuantity)); + + if (!validation.isValid) { + ElMessage.warning(validation.message); + row.usedQuantity = validation.value; + return; + } + + row.usedQuantity = validation.value; + } +}; + +// 澶勭悊鐢熶骇鏄庣粏琛ㄦ牸鐨勬搷浣� - 浣跨敤宸ュ叿鍑芥暟 +const addNewRow = () => { + const newRow = createDefaultProductionRow(userInfo); + detailsTableData.value.push(newRow); +}; + + +// 鑾峰彇鐢ㄦ埛淇℃伅骞跺姞杞藉熀纭�鏁版嵁 +onMounted(async () => { + try { + let ress = await userListAll(); + userList.value = ress.data; + userInfo = await userStore.getInfo(); + } catch (error) { + ElMessage.error("鍒濆鍖栧け璐ワ紝璇烽噸璇�"); + } +}); + +// 绠�鍖栫殑浜嬩欢澶勭悊鍑芥暟 +const handleDetailsChange = (data) => { +}; + +const handleDeleteRow = (index) => { + ElMessage.success(`宸插垹闄ょ ${index + 1} 琛屾暟鎹甡); +}; + +// 鍒犻櫎鍗曚釜宸查�夋暟鎹」 +const handleRemoveItem = (row) => { + const index = tableData.value.findIndex( + (item) => item.officialId === row.officialId + ); + if (index > -1) { + tableData.value.splice(index, 1); + + // 鏇存柊selectedIds + const updatedOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = updatedOfficialIds; + ElMessage.success("宸插垹闄ら�変腑椤�"); + } +}; + + +// 璁$畻鎬讳娇鐢ㄩ噺 +const totalUsedQuantity = computed(() => { + return tableData.value.reduce((total, item) => { + const usedQty = Number(item.usedQuantity) || 0; + return total + usedQty; + }, 0); +}); +</script> + +<style scoped lang="scss"> +.el-form { + .el-row { + padding-top: 20px; + background: rgba($color: #f8fafb, $alpha: 0.5); + } +} + +.el-row > .el-col > h1 { + font-weight: bolder; +} + +.empty-table > .el-row { + margin-bottom: 12px; +} +</style> diff --git a/src/views/production/productionReporting/components/useCoalData.js b/src/views/production/productionReporting/components/useCoalData.js new file mode 100644 index 0000000..9a86b81 --- /dev/null +++ b/src/views/production/productionReporting/components/useCoalData.js @@ -0,0 +1,96 @@ +/** + * 鐓ょ鏁版嵁绠$悊缁勫悎寮忓嚱鏁� + * 鎻愪緵鐓ょ鏁版嵁鐨勮幏鍙栥�佺紦瀛樸�佽浆鎹㈢瓑鍔熻兘 + */ +import {ref, computed, watch} from 'vue'; +import {getCoalInfoList} from "@/api/production"; +import {ElMessage} from 'element-plus'; + +// 鍏ㄥ眬鐓ょ鏁版嵁缂撳瓨 +const coalData = ref([]); +const isLoading = ref(false); +const isLoaded = ref(false); + +export function useCoalData() { + + // 鑾峰彇鐓ょ鏁版嵁 + const getCoalData = async (forceRefresh = false) => { + if (isLoaded.value && !forceRefresh) { + return coalData.value; + } + + if (isLoading.value) { + // 濡傛灉姝e湪鍔犺浇锛岀瓑寰呭姞杞藉畬鎴� + return new Promise((resolve) => { + const unwatch = watch(isLoading, (loading) => { + if (!loading) { + unwatch(); + resolve(coalData.value); + } + }); + }); + } + + isLoading.value = true; + try { + const res = await getCoalInfoList(); + if (res.code === 200) { + coalData.value = res.data; + isLoaded.value = true; + return coalData.value; + } else { + ElMessage.error('鑾峰彇鐓ょ鏁版嵁澶辫触'); + return []; + } + } catch (error) { + ElMessage.error('鑾峰彇鐓ょ鏁版嵁澶辫触'); + console.error('鐓ょ鏁版嵁鑾峰彇閿欒:', error); + return []; + } finally { + isLoading.value = false; + } + }; + + // 鏍规嵁ID鑾峰彇鐓ょ鍚嶇О + const getCoalNameById = (id) => { + if (!id || coalData.value.length === 0) return id; + const coal = coalData.value.find(item => item.id == id); + return coal ? coal.coal : id; + }; + + // 鏍规嵁鍚嶇О鑾峰彇鐓ょID + const getCoalIdByName = (name) => { + if (!name || coalData.value.length === 0) return ''; + const coal = coalData.value.find(item => item.coal === name); + return coal ? coal.id : ''; + }; + + // 鐢熸垚涓嬫媺閫夐」 + const coalOptions = computed(() => { + return coalData.value.map(item => ({ + label: item.coal, + value: item.coal, + key: item.id + })); + }); + + // 鐢熸垚key-value鏄犲皠 + const coalMap = computed(() => { + const map = {}; + coalData.value.forEach(item => { + map[item.id] = item.coal; + }); + return map; + }); + + return { + coalData: computed(() => coalData.value), + coalOptions, + coalMap, + isLoading: computed(() => isLoading.value), + isLoaded: computed(() => isLoaded.value), + getCoalData, + getCoalNameById, + getCoalIdByName + }; +} diff --git a/src/views/production/productionReporting/components/useDialog.js b/src/views/production/productionReporting/components/useDialog.js new file mode 100644 index 0000000..3351cdc --- /dev/null +++ b/src/views/production/productionReporting/components/useDialog.js @@ -0,0 +1,62 @@ +/** + * 瀵硅瘽妗嗙鐞嗙粍鍚堝紡鍑芥暟 + * 鎻愪緵瀵硅瘽妗嗙殑鎵撳紑銆佸叧闂�佹暟鎹鐞嗙瓑鍔熻兘 + */ +import {ref} from 'vue'; + +export function useDialog() { + const dialogVisible = ref(false); + const dialogType = ref('add'); + const dialogRef = ref(null); + const currentRowData = ref(null); + + // 鎵撳紑瀵硅瘽妗� + const openDialog = (type = 'add', rowData = null) => { + dialogType.value = type; + currentRowData.value = rowData; + dialogVisible.value = true; + + // 璋冪敤瀵硅瘽妗嗙粍浠剁殑鍒濆鍖栨柟娉� + if (dialogRef.value) { + if (type === 'add') { + dialogRef.value.Initialization?.(); + } else if ((type === 'edit' || type === 'viewRow' || type === 'scheduling' || type === 'work') && rowData) { + dialogRef.value.editInitialization?.(type,rowData); + } + } + }; + const viewRow = (type,rowData) => { + dialogType.value = type; + currentRowData.value = rowData; + dialogVisible.value = true; + openDialog('viewRow', rowData); + }; + // 鍏抽棴瀵硅瘽妗� + const closeDialog = () => { + dialogVisible.value = false; + dialogType.value = 'add'; + currentRowData.value = null; + }; + + // 瀵硅瘽妗嗘垚鍔熷洖璋� + const handleDialogSuccess = (callback) => { + closeDialog(); + if (typeof callback === 'function') { + callback(); + } + }; + + return { + // 鐘舵�� + dialogVisible, + dialogType, + dialogRef, + currentRowData, + + // 鏂规硶 + openDialog, + closeDialog, + handleDialogSuccess, + viewRow + }; +} diff --git a/src/views/production/productionReporting/components/useTableData.js b/src/views/production/productionReporting/components/useTableData.js new file mode 100644 index 0000000..4f48ef6 --- /dev/null +++ b/src/views/production/productionReporting/components/useTableData.js @@ -0,0 +1,132 @@ +/** + * 琛ㄦ牸鏁版嵁绠$悊缁勫悎寮忓嚱鏁� + * 鎻愪緵鍒嗛〉銆佹悳绱€�侀�夋嫨绛夐�氱敤鍔熻兘 + */ +import {ref, reactive} from 'vue'; +import {ElMessage, ElMessageBox} from 'element-plus'; + +export function useTableData(apiFunction, options = {}) { + const { + pageSize = 10, + searchField = 'searchAll' + } = options; + + // 鍝嶅簲寮忔暟鎹� + const tableData = ref([]); + const loading = ref(false); + const total = ref(0); + const selectedRows = ref([]); + + // 鏌ヨ鍙傛暟 + const queryParams = reactive({ + [searchField]: '', + current: 1, + size: pageSize, + }); + + // 鑾峰彇鍒楄〃鏁版嵁 + const getList = async () => { + loading.value = true; + try { + const params = { + [searchField]: queryParams[searchField], + current: queryParams.current, + size: queryParams.size, + }; + console.log('鏌ヨ鍙傛暟:', params); + const res = await apiFunction(params); + tableData.value = res.data.records || []; + total.value = res.data.total || 0; + } catch (error) { + ElMessage.error('鑾峰彇鏁版嵁澶辫触'); + console.error('API閿欒:', error); + } finally { + loading.value = false; + } + }; + + // 鎼滅储 + const handleSearch = () => { + queryParams.current = 1; + getList(); + }; + + // 閲嶇疆鎼滅储 + const handleReset = () => { + queryParams[searchField] = ''; + console.log('閲嶇疆鎼滅储鍙傛暟:', queryParams); + handleSearch(); + }; + + // 鍒嗛〉澶勭悊 + const handlePageChange = ({page, limit}) => { + if (page && page !== queryParams.current) { + queryParams.current = page; + } + if (limit && limit !== queryParams.size) { + queryParams.size = limit; + queryParams.current = 1; // 鏀瑰彉姣忛〉澶у皬鏃跺洖鍒扮涓�椤� + } + getList(); + }; + + // 琛ㄦ牸閫夋嫨澶勭悊 + const handleSelectionChange = (selection) => { + selectedRows.value = selection; + }; + + // 鎵归噺鍒犻櫎 + const deleteSelected = async (deleteFunction) => { + if (selectedRows.value.length === 0) { + ElMessage.warning('璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁'); + return; + } + + try { + await ElMessageBox.confirm( + `纭鍒犻櫎閫変腑鐨� ${selectedRows.value.length} 鏉℃暟鎹悧锛焋, + '鍒犻櫎纭', + { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning' + } + ); + + const ids = selectedRows.value.map(row => row.id); + await deleteFunction(ids); + + ElMessage.success('鍒犻櫎鎴愬姛'); + selectedRows.value = []; + getList(); + } catch (error) { + if (error !== 'cancel') { + ElMessage.error('鍒犻櫎澶辫触'); + console.error('鍒犻櫎閿欒:', error); + } + } + }; + + // 鍒锋柊鏁版嵁 + const refresh = () => { + getList(); + }; + + return { + // 鏁版嵁 + tableData, + loading, + total, + selectedRows, + queryParams, + + // 鏂规硶 + getList, + handleSearch, + handleReset, + handlePageChange, + handleSelectionChange, + deleteSelected, + refresh + }; +} diff --git a/src/views/production/productionReporting/index.vue b/src/views/production/productionReporting/index.vue new file mode 100644 index 0000000..7a1d60e --- /dev/null +++ b/src/views/production/productionReporting/index.vue @@ -0,0 +1,277 @@ +<template> + <div class="app-container"> + <!-- 鎼滅储琛ㄥ崟 --> + <el-form :inline="true" :model="queryParams" class="search-form"> + <el-form-item label="鎼滅储"> + <el-input + v-model="queryParams.searchAll" + placeholder="璇疯緭鍏ュ叧閿瘝" + clearable + /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="handleSearch">鏌ヨ</el-button> + <el-button @click="handleReset">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <!-- 涓昏鍐呭鍖哄煙 --> + <el-card> + <!-- 鎿嶄綔鎸夐挳 --> + <div class="toolbar"> + <el-button + type="danger" + :icon="Delete" + :disabled="!selectedRows.length" + @click="() => deleteSelected(delProductionScheduling)" + > + 鍒犻櫎 + </el-button> + </div> + <!-- 鏁版嵁琛ㄦ牸 --> + <ETable + :showOverflowTooltip="false" + :loading="loading" + :table-data="tableData" + :columns="columns" + :current-page="queryParams.current" + :page-size="queryParams.size" + @selection-change="handleSelectionChange" + @edit="(row) => openDialog('work', row)" + :show-selection="true" + :border="true" + :operations="['work']" + :operationsWidth="200" + :show-overflow-tooltip="false" + style="width: 100%; height: calc(100vh - 26em)" + > + <template #coalId="{ row }"> + <div class="coal-tags"> + <template v-if="row.coalId"> + <el-tag + v-for="coal in parseCoalArray(row.coalId)" + :key="coal" + size="small" + type="primary" + class="coal-tag" + > + {{ getDisplayCoalName(coal) }} + </el-tag> + </template> + <span v-else class="no-data">--</span> + </div> + </template> + </ETable> + <!-- 鍒嗛〉缁勪欢 --> + <Pagination + :layout="'total, prev, pager, next, jumper'" + :total="total" + v-model:page="queryParams.current" + :limit="queryParams.size" + @pagination="handlePageChange" + /> + </el-card> + + <!-- 鐢熶骇瀵硅瘽妗� --> + <!-- handleProductionAndProcessing --> + <ProductionDialog + v-model:visible="dialogVisible" + ref="dialogRef" + :type="dialogType" + @update:productionAndProcessing="handleProductionAndProcessing" + @success="handleDialogSuccess" + /> + </div> +</template> + +<script setup> +import { onMounted, ref } from "vue"; +import { ElMessage } from "element-plus"; +import { Plus, Delete } from "@element-plus/icons-vue"; +import ProductionDialog from "./components/ProductionDialog.vue"; +import ETable from "@/components/Table/ETable.vue"; +import Pagination from "@/components/Pagination/index.vue"; +import { listPage,delProductionScheduling } from "@/api/productionScheduling"; +import { parseCoalArray } from "@/utils/production"; +import { useTableData } from "./components/useTableData.js"; +import { useDialog } from "./components/useDialog.js"; +import { useCoalData } from "./components/useCoalData.js"; +import { getCoalInfoList } from "@/api/production"; + +// 鐓ょ淇℃伅鍒楄〃 +const coalInfoList = ref([]); + +// 琛ㄦ牸鍒楅厤缃� +const columns = [ + { prop: "coalId", label: "鐓ょ", minWidth: 150, slot: true }, + { + prop: "type", + label: "鐓ゆ枡绫诲瀷", + minWidth: 150, + formatter: (row) => { + const statusMap = { + 1: '鎴愬搧', + 2: '鍘熸枡' + }; + return statusMap[row.type] || '鏈煡绫诲瀷'; + } + }, + { + prop: "status", + label: "鐘舵��", + minWidth: 150, + formatter: (row) => { + const statusMap = { + 1: '寰呯敓浜�', + 2: '鐢熶骇涓�', + 3: '宸插叆搴�' + }; + return statusMap[row.status] || '鏈煡鐘舵��'; + } + }, + { prop: "schedulingUserName", label: "鐢熶骇浜�", minWidth: 150 }, + { prop: "schedulingNum", label: "鐢熶骇鏁伴噺", minWidth: 120 }, + { prop: "successNum", label: "鍏ュ簱鏁伴噺", minWidth: 120, + formatter: (row) => { + return row.successNum || '0'; + } }, + { prop: "workHours", label: "宸ユ椂瀹氶", minWidth: 150 }, + { prop: "unit", label: "鍗曚綅", minWidth: 120 }, + { prop: "process", label: "宸ュ簭", minWidth: 143 }, + { prop: "schedulingDate", label: "鎺掍骇鏃ユ湡", minWidth: 150 }, +]; + +// 浣跨敤琛ㄦ牸鏁版嵁缁勫悎寮忓嚱鏁� +const { + tableData, + loading, + total, + selectedRows, + queryParams, + getList, + handleSearch, + handleReset, + handlePageChange, + handleSelectionChange, + deleteSelected, +} = useTableData(listPage, { pageSize: 10 }); + +// 浣跨敤瀵硅瘽妗嗙粍鍚堝紡鍑芥暟 +const { + dialogVisible, + dialogType, + dialogRef, + openDialog, + handleDialogSuccess: onDialogSuccess, +} = useDialog(); + +// 浣跨敤鐓ょ鏁版嵁缁勫悎寮忓嚱鏁� +const { getCoalNameById, getCoalData } = useCoalData(); + +// 鑾峰彇鐓ょ鏄剧ず鍚嶇О锛堝甫澶囩敤閫昏緫锛� +const getDisplayCoalName = (coalId) => { + // 浼樺厛浣跨敤 useCoalData 鐨勬柟娉� + let name = getCoalNameById(coalId); + + // 濡傛灉娌℃湁鎵惧埌锛屽皾璇曚粠 coalInfoList 涓煡鎵� + if (name === coalId && coalInfoList.value.length > 0) { + const found = coalInfoList.value.find((item) => item.id == coalId); + name = found ? found.coal : coalId; + } + + return name || coalId; +}; + +// 澶勭悊鐢熶骇鏁版嵁鏇存柊 +const handleProductionAndProcessing = (row, rows) => { + const index = tableData.value.findIndex((item) => item.id === rows.id); + if (index !== -1) { + tableData.value[index] = { ...tableData.value[index], ...row }; + } +}; + +// 瀵硅瘽妗嗘垚鍔熷洖璋� +const handleDialogSuccess = () => { + onDialogSuccess(() => { + getList(); + ElMessage.success("鎿嶄綔鎴愬姛"); + }); +}; + +// 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹� +onMounted(async () => { + try { + // 骞惰鍔犺浇鐓ょ鏁版嵁鍜岃〃鏍兼暟鎹� + await Promise.all([ + getCoalData(), // 棰勫姞杞界叅绉嶆暟鎹� + (async () => { + const res = await getCoalInfoList(); + if (res.code === 200) { + coalInfoList.value = res.data; + } + })(), + ]); + + // 鍔犺浇琛ㄦ牸鏁版嵁 + getList(); + } catch (error) { + ElMessage.error("鏁版嵁鍔犺浇澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯"); + } +}); +</script> + +<style scoped lang="scss"> +.production-container { + padding: 20px; + + .el-card:nth-child(1) { + margin-bottom: 20px; + } +} + +.search-bar { + margin-bottom: 20px; + display: flex; + gap: 10px; + + .el-input { + width: 20%; + } +} + +.search-form { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 20px; + + .el-form-item { + margin-right: 10px; + } + + .el-button { + margin-left: 10px; + } +} + +.coal-tags { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + + .coal-tag { + margin-right: 4px; + margin-bottom: 4px; + + &:last-child { + margin-right: 0; + } + } + + .no-data { + color: #999; + font-style: italic; + } +} +</style> diff --git a/src/views/warehouseManagement/index.vue b/src/views/warehouseManagement/index.vue index 32946d7..a7d612c 100644 --- a/src/views/warehouseManagement/index.vue +++ b/src/views/warehouseManagement/index.vue @@ -82,6 +82,11 @@ width="180" sortable /> + <el-table-column prop="type" label="鐓ゆ枡绫诲瀷"> + <template #default="scope"> + {{scope.row.type === 1 ? '鎴愬搧' : '鍘熸枡'}} + </template> + </el-table-column> <el-table-column prop="coal" label="鐓ょ" sortable /> <el-table-column prop="unit" label="鍗曚綅" width="70" /> <el-table-column @@ -440,6 +445,22 @@ </el-select> </el-form-item> </el-col> + <el-col :span="12"> + <el-form-item label="鐓ゆ枡绫诲瀷" prop="type"> + <el-select + v-model="mergeForm.type" + placeholder="璇烽�夋嫨鐓ゆ枡绫诲瀷" + :disabled="operationType === 'view'" + > + <el-option + :label="item.label" + v-for="item in typeList" + :key="item.value" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> </el-row> <el-divider></el-divider> <el-row> @@ -499,6 +520,16 @@ // 鍚堝苟寮规 const mergeVisible = ref(false); const operationType = ref(""); +const typeList = ref([ + { + label: "鎴愬搧", + value: 1, + }, + { + label: "鍘熸枡", + value: 2, + }, +]); const data = reactive({ form: { supplierName: "", -- Gitblit v1.9.3