¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产任å¡ï¼æ¥å·¥ |
| | | import request from '@/utils/request' |
| | | |
| | | // æ¥è¯¢ç产å å·¥-æ£å¼åºç
¤ç§å表 |
| | | 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 |
| | | }) |
| | | } |
| | |
| | | <!-- é»è®¤æä½æé® --> |
| | | <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" |
| | |
| | | /> |
| | | </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" |
| | |
| | | required: true, |
| | | type: Boolean, |
| | | }); |
| | | const typeList = [ |
| | | { |
| | | value: 1, |
| | | label: "æå", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "åæ", |
| | | }, |
| | | ]; |
| | | const form = defineModel("form", { |
| | | required: true, |
| | | type: Object, |
| | |
| | | supplierName: [ |
| | | { required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }, |
| | | ], |
| | | type: [{ required: true, message: "è¯·éæ©ç±»å", trigger: "change" }], |
| | | coal: [{ required: true, message: "请è¾å
¥ç
¤ç§", trigger: "blur" }], |
| | | purchaseQuantity: [ |
| | | { required: true, message: "请è¾å
¥éè´æ°é", trigger: "blur" }, |
| | |
| | | }, |
| | | }, |
| | | { |
| | | prop: "type", |
| | | label: "ç
¤æç±»å", |
| | | minWidth: 120, |
| | | formatter: (row) => { |
| | | return row.type === 1 ? "æå" : "åæ"; |
| | | }, |
| | | }, |
| | | { |
| | | prop: "coalId", |
| | | label: "ç
¤ç§ç±»å", |
| | | minWidth: 120, |
| | |
| | | <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 |
| | |
| | | import {getCoalInfoList} from "@/api/production"; |
| | | import {userListAll} from "@/api/publicApi"; |
| | | |
| | | const typeList = [ |
| | | { |
| | | label: "æå", |
| | | value: 1, |
| | | }, |
| | | { |
| | | label: "åæ", |
| | | value: 2, |
| | | } |
| | | ] |
| | | const props = defineProps({ |
| | | modelValue: { |
| | | type: Array, |
| | |
| | | purchasePrice: "", |
| | | totalCost: "", |
| | | producerId: "", |
| | | type: 1, |
| | | ...rowData, |
| | | }; |
| | | tableData.value = [...tableData.value, defaultRow]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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); |
| | | }; |
| | | |
| | | // å¤çç
¤ç§éæ©åå |
| | | |
| | | // å¤çç
¤ç§éæ©ååï¼æ°æ¹æ³ï¼åç§°éæ©è½¬IDï¼ |
| | | const handleCoalSelectChange = (row, selectedName) => { |
| | | // æ ¹æ®éæ©çåç§°æ¾å°å¯¹åºçID |
| | | const coalItem = weekList.value.find(item => item.value === selectedName); |
| | | if (coalItem) { |
| | | row.coalId = coalItem.key; // 设置为ID |
| | | } 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) { |
| | | // 强å¶è§¦åè¡¨æ ¼éæ°æ¸²æä»¥ç¡®ä¿el-selectæ£ç¡®æ¾ç¤º |
| | | 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) { |
| | | // 强å¶è§¦åè¡¨æ ¼éæ°æ¸²æä»¥ç¡®ä¿el-selectæ£ç¡®æ¾ç¤º |
| | | 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; |
| | | }; |
| | | // å¤çç¨æ·éæ©ååï¼æ°æ¹æ³ï¼åç§°éæ©è½¬IDï¼ |
| | | 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; // 设置为ID |
| | | } 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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, // ä¿ååå§çidä½ä¸ºofficialId |
| | | usedQuantity: 0, // åå§ä½¿ç¨æ°é为0 |
| | | // å¯ä»¥æ ¹æ®éè¦æ·»å å
¶ä»å段 |
| | | }; |
| | | tableData.value.push(newItem); |
| | | addedCount++; |
| | | }); |
| | | |
| | | // æ´æ°selectedIdsï¼ç¡®ä¿å
嫿æå½åtableDataä¸ç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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * ç
¤ç§æ°æ®ç®¡çç»åå¼å½æ° |
| | | * æä¾ç
¤ç§æ°æ®çè·åãç¼åã转æ¢çåè½ |
| | | */ |
| | | 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) { |
| | | // 妿æ£å¨å è½½ï¼çå¾
å è½½å®æ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * å¯¹è¯æ¡ç®¡çç»åå¼å½æ° |
| | | * æä¾å¯¹è¯æ¡çæå¼ãå
³éãæ°æ®å¤ççåè½ |
| | | */ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * è¡¨æ ¼æ°æ®ç®¡çç»åå¼å½æ° |
| | | * æä¾å页ãæç´¢ãéæ©çéç¨åè½ |
| | | */ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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, // ä¿ååå§çidä½ä¸ºofficialId |
| | | usedQuantity: 0, // åå§ä½¿ç¨æ°é为0 |
| | | // å¯ä»¥æ ¹æ®éè¦æ·»å å
¶ä»å段 |
| | | }; |
| | | tableData.value.push(newItem); |
| | | addedCount++; |
| | | }); |
| | | |
| | | // æ´æ°selectedIdsï¼ç¡®ä¿å
嫿æå½åtableDataä¸ç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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * ç
¤ç§æ°æ®ç®¡çç»åå¼å½æ° |
| | | * æä¾ç
¤ç§æ°æ®çè·åãç¼åã转æ¢çåè½ |
| | | */ |
| | | 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) { |
| | | // 妿æ£å¨å è½½ï¼çå¾
å è½½å®æ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * å¯¹è¯æ¡ç®¡çç»åå¼å½æ° |
| | | * æä¾å¯¹è¯æ¡çæå¼ãå
³éãæ°æ®å¤ççåè½ |
| | | */ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * è¡¨æ ¼æ°æ®ç®¡çç»åå¼å½æ° |
| | | * æä¾å页ãæç´¢ãéæ©çéç¨åè½ |
| | | */ |
| | | 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 |
| | | }; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| | |
| | | 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 |
| | |
| | | </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> |
| | |
| | | // åå¹¶å¼¹æ¡ |
| | | const mergeVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const typeList = ref([ |
| | | { |
| | | label: "æå", |
| | | value: 1, |
| | | }, |
| | | { |
| | | label: "åæ", |
| | | value: 2, |
| | | }, |
| | | ]); |
| | | const data = reactive({ |
| | | form: { |
| | | supplierName: "", |