From 8fc09566cc3ee8d0dae10992de31d0f09f257bb4 Mon Sep 17 00:00:00 2001 From: zhang_12370 <z2864490065@outlook.com> Date: 星期二, 08 七月 2025 17:58:04 +0800 Subject: [PATCH] 1、删除通过审核进入正式库存的采购记录,页面弹出报错信息 2、开发首页模块 3、开发设备领用记录 4、调整生产明细不能为负数 5、修复采购登记人匹配问题 --- src/views/index.vue | 707 +++++++++++++++++---------- src/views/procureMent/index.vue | 20 src/views/production/components/ProductionDetailsTable.vue | 9 src/api/equipment/requisition/index.js | 23 src/store/modules/user.js | 18 src/views/equipment/management/index.vue | 109 ++++ src/api/publicApi/index.js | 20 src/views/equipment/management/mould/equipmentRequisitionDialog.vue | 199 +++++++ src/api/equipment/management/index.js | 2 src/views/equipment/management/mould/usageRecord.vue | 241 +++++++++ src/api/home/index.js | 23 src/views/production/components/ProductionDialog.vue | 86 ++- 12 files changed, 1,146 insertions(+), 311 deletions(-) diff --git a/src/api/equipment/management/index.js b/src/api/equipment/management/index.js index f7d7725..f64bff1 100644 --- a/src/api/equipment/management/index.js +++ b/src/api/equipment/management/index.js @@ -29,4 +29,4 @@ method: 'delete', data }) -} \ No newline at end of file +} diff --git a/src/api/equipment/requisition/index.js b/src/api/equipment/requisition/index.js new file mode 100644 index 0000000..65c23d1 --- /dev/null +++ b/src/api/equipment/requisition/index.js @@ -0,0 +1,23 @@ +// 璁惧绠$悊 +import request from '@/utils/request' + + +// /equipmentUsageRecord/list +// 鏌ヨ璁惧浣跨敤璁板綍 +export function getUsageRecordList(query) { + return request({ + url: '/equipmentUsageRecord/list', + method: 'get', + params: query + }) +} + +// /equipmentUsageRecord/addOrEditUsageRecord +// 娣诲姞鎴栫紪杈戣澶囦娇鐢ㄨ褰� +export function addOrEditUsageRecord(data) { + return request({ + url: '/equipmentUsageRecord/addOrEditUsageRecord', + method: 'post', + data + }) +} \ No newline at end of file diff --git a/src/api/home/index.js b/src/api/home/index.js new file mode 100644 index 0000000..d6fc960 --- /dev/null +++ b/src/api/home/index.js @@ -0,0 +1,23 @@ +// 鐓ょ淇℃伅 +import request from '@/utils/request' + +// /homePage/allInfo +// 鑾峰彇棣栭〉淇℃伅 +export function getCoalInfo(query) { + return request({ + url: '/homePage/allInfo', + method: 'get', + params: query + }) +} + +// /homePage/yearlySales +// 鑾峰彇骞村害閿�鍞俊鎭� +export function getYearlySales(data) { + return request({ + url: '/homePage/yearlySales', + method: 'post', + data: data + }) +} + diff --git a/src/api/publicApi/index.js b/src/api/publicApi/index.js index 8156ad0..a226d22 100644 --- a/src/api/publicApi/index.js +++ b/src/api/publicApi/index.js @@ -9,4 +9,24 @@ url: '/system/user/listAll', method: 'get' }) +} + +// /equipmentManagement/equipmentList +// 鏌ヨ璁惧鍒楄〃 +export function getEquipmentList(query) { + return request({ + url: '/equipmentManagement/equipmentList', + method: 'get', + params: query + }) +} + +// /coalInfo/coalInfoList +// 鏌ヨ鐓ょ鍒楄〃 +export function getCoalInfoList(query) { + return request({ + url: '/coalInfo/coalInfoList', + method: 'get', + params: query + }) } \ No newline at end of file diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 2c6398f..1ef23e6 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -2,6 +2,7 @@ import { getToken, setToken, removeToken } from '@/utils/auth' import { isHttp, isEmpty } from "@/utils/validate" import defAva from '@/assets/images/profile.jpg' +import {userListAll} from '@/api/publicApi/index.js' const useUserStore = defineStore( 'user', @@ -13,7 +14,8 @@ nickName: '', avatar: '', roles: [], - permissions: [] + permissions: [], + userList: [] }), actions: { // 鐧诲綍 @@ -70,6 +72,20 @@ reject(error) }) }) + }, + + // 鑾峰彇鐢ㄦ埛鍒楄〃锛堝鏋滃凡缂撳瓨鍒欑洿鎺ヨ繑鍥烇紝鍚﹀垯閲嶆柊鑾峰彇锛� + async getUserList () { + if (Array.isArray(this.userList) && this.userList.length > 0) { + return this.userList; + } + // 涓虹┖鏃堕噸鏂拌幏鍙� + return userListAll().then(res => { + this.userList = res.data; + return this.userList; + }).catch(error => { + throw error; + }); } } }) diff --git a/src/views/equipment/management/index.vue b/src/views/equipment/management/index.vue index 2ceb04b..5c29464 100644 --- a/src/views/equipment/management/index.vue +++ b/src/views/equipment/management/index.vue @@ -87,12 +87,28 @@ @pagination="handPagination" /> <managementDialog + v-if="activeTab == 'management'" v-model:copyForm="copyForm" v-model:managementFormDialog="manaDialog" :addOrEdit="addOrEdit" :form="form" @submit="getList" ></managementDialog> + <EquipmentRequisition + v-if="activeTab == 'equipmentRequisition'" + v-model="equipmentRequisitionDialog" + :formData="form" + :maxQuantity="getMaxQuantity()" + @submit="onEquipmentRequisitionSubmit" + /> + <UsageRecord + v-if="activeTab == 'usageRecord'" + v-model:copyForm="copyForm" + v-model:usageRecordDialog="usageRecordDialog" + :addOrEdit="addOrEdit" + :form="form" + @submit="getList" + /> </el-card> </div> </template> @@ -106,10 +122,13 @@ import DataTable from "@/components/Table/ETable.vue"; import Pagination from "@/components/Pagination"; import managementDialog from "./mould/managementDialog.vue"; +import EquipmentRequisition from "./mould/equipmentRequisitionDialog.vue"; +import UsageRecord from "./mould/usageRecord.vue"; // API 鏈嶅姟瀵煎叆 import { useDelete } from "@/hooks/useDelete.js"; import { getManagementList, delEquipment } from "@/api/equipment/management/index.js"; +import { getUsageRecordList } from "@/api/equipment/requisition/index.js"; // 鍝嶅簲寮忕姸鎬佺鐞� const form = ref({}); @@ -117,6 +136,8 @@ const copyForm = ref({}); const addOrEdit = ref("add"); const manaDialog = ref(false); +const equipmentRequisitionDialog = ref(false); +const usageRecordDialog = ref(false); const loading = ref(false); const activeTab = ref("management"); const selectedRows = ref([]); @@ -141,6 +162,48 @@ api: getManagementList, deleteApi: delEquipment, columns: [ + { prop: "equipmentNo", label: "璁惧缂栧彿", minWidth: 100 }, + { prop: "equipmentName", label: "璁惧鍚嶇О", minWidth: 100 }, + { prop: "quantity", label: "鏁伴噺", minWidth: 100 }, + { prop: "specification", label: "瑙勬牸鍨嬪彿", minWidth: 100 }, + { + prop: "usageStatus", + label: "浣跨敤鐘舵��", + minWidth: 100, + formatter: (row) => row.usageStatus == 1 ? "鍚敤" : "绂佺敤" + }, + { prop: "purchaseDate", label: "閲囪喘鏃ユ湡", minWidth: 100 }, + { prop: "purchasePrice", label: "閲囪喘浠锋牸", minWidth: 100 }, + ] + }, + equipmentRequisition:{ + label: "璁惧棰嗙敤", + searchPlaceholder: "璁惧缂栧彿/璁惧鍚嶇О/瑙勬牸鍨嬪彿", + showSearch: true, + api: getUsageRecordList, + deleteApi: null, + columns: [ + { prop: "userId", label: "棰嗙敤浜�", minWidth: 100 }, + { prop: "equipmentId", label: "璁惧ID", minWidth: 100 }, + { prop: "usageQuantity", label: "棰嗙敤鏁伴噺", minWidth: 100 }, + { + prop: "equipmentStatus", + label: "浣跨敤鐘舵��", + minWidth: 100, + formatter: (row) => row.usageStatus == 1 ? "鍚敤" : "绂佺敤" + }, + { prop: "usageStartTime", label: "浣跨敤寮�濮嬫椂闂�", minWidth: 100 }, + { prop: "usageEndTime", label: "浣跨敤缁撴潫鏃堕棿", minWidth: 100 }, + { prop: "remarks", label: "澶囨敞", minWidth: 100 }, + ] + }, + usageRecord:{ + label: "棰嗙敤璁板綍", + searchPlaceholder: "璁惧缂栧彿/璁惧鍚嶇О/瑙勬牸鍨嬪彿", + showSearch: true, + api: getManagementList, + deleteApi: delEquipment, + columns: [ { prop: "equipmentId", label: "璁惧缂栧彿", minWidth: 100 }, { prop: "equipmentName", label: "璁惧鍚嶇О", minWidth: 100 }, { prop: "quantity", label: "鏁伴噺", minWidth: 100 }, @@ -151,11 +214,11 @@ minWidth: 100, formatter: (row) => row.usageStatus == 1 ? "鍚敤" : "绂佺敤" }, - { prop: "usingDepartment", label: "浣跨敤閮ㄩ棬", minWidth: 100 }, { prop: "purchaseDate", label: "閲囪喘鏃ユ湡", minWidth: 100 }, { prop: "purchasePrice", label: "閲囪喘浠锋牸", minWidth: 100 }, ] - } + }, + // 鍚庣画鍙互鍦ㄨ繖閲屾坊鍔犳柊鐨勬爣绛鹃〉閰嶇疆 }; @@ -209,7 +272,15 @@ addOrEdit.value = "add"; form.value = {}; title.value = `鏂板${currentTabConfig.value.label}`; - manaDialog.value = true; + // 閫氱敤鐨� + copyForm.value = {}; + if (activeTab.value === "equipmentRequisition") { + equipmentRequisitionDialog.value = true; + } else if (activeTab.value === "usageRecord") { + usageRecordDialog.value = true; + } else { + manaDialog.value = true; + } }; const handleEdit = (row) => { @@ -217,7 +288,13 @@ addOrEdit.value = "edit"; title.value = `缂栬緫${currentTabConfig.value.label}`; copyForm.value = { ...row }; - manaDialog.value = true; + if (activeTab.value === "equipmentRequisition") { + equipmentRequisitionDialog.value = true; + } else if (activeTab.value === "usageRecord") { + usageRecordDialog.value = true; + } else { + manaDialog.value = true; + } }; const handleView = (row) => { @@ -225,7 +302,13 @@ addOrEdit.value = "viewRow"; title.value = `鏌ョ湅${currentTabConfig.value.label}`; copyForm.value = { ...row }; - manaDialog.value = true; + if (activeTab.value === "equipmentRequisition") { + equipmentRequisitionDialog.value = true; + } else if (activeTab.value === "usageRecord") { + usageRecordDialog.value = true; + } else { + manaDialog.value = true; + } }; const handPagination = (val) => { @@ -250,6 +333,22 @@ successText: "鍒犻櫎鎴愬姛", }); +// 鑾峰彇璁惧鏈�澶у彲棰嗙敤鏁伴噺 +const getMaxQuantity = () => { + if (form.value.equipmentId) { + const equipment = tableData.value.find(item => item.equipmentId === form.value.equipmentId); + return equipment ? equipment.quantity : null; + } + return null; +}; + +// 璁惧棰嗙敤寮圭獥鎻愪氦澶勭悊 +const onEquipmentRequisitionSubmit = (formData) => { + ElMessage.success('璁惧棰嗙敤鎴愬姛'); + equipmentRequisitionDialog.value = false; + getList(); +}; + // 鏁版嵁鑾峰彇 const getList = async () => { try { diff --git a/src/views/equipment/management/mould/equipmentRequisitionDialog.vue b/src/views/equipment/management/mould/equipmentRequisitionDialog.vue new file mode 100644 index 0000000..b6382ef --- /dev/null +++ b/src/views/equipment/management/mould/equipmentRequisitionDialog.vue @@ -0,0 +1,199 @@ +<template> + <el-dialog + v-model="visible" + :title="isEdit ? '缂栬緫璁惧棰嗙敤' : '鏂板璁惧棰嗙敤'" + width="600px" + @close="handleClose" + > + <el-form :model="form" :rules="rules" ref="formRef" label-width="150px"> + <el-form-item label="棰嗙敤浜�" prop="userId"> + <el-select v-model="form.userId" placeholder="璇烽�夋嫨"> + <el-option + v-for="item in userList" + :key="item.userId" + :label="item.nickName" + :value="item.userId" + /> + </el-select> + </el-form-item> + <el-form-item label="璁惧鍚嶇О" prop="equipmentId"> + <el-select v-model="form.equipmentId" placeholder="璇烽�夋嫨"> + <el-option + v-for="item in equipmentList" + :key="item.id" + :label="item.equipmentName" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item label="璁惧搴撳瓨" prop="equipmentStock"> + <el-input + :value=" + equipmentList.find((item) => item.id == form.equipmentId) + ?.quantity || 0 + " + disabled + style="width: 100%" + /> + </el-form-item> + <el-form-item label="棰嗙敤鏁伴噺" prop="usageQuantity"> + <el-input-number + v-model="form.usageQuantity" + :min="1" + :max="maxQuantity || 999" + style="width: 100%" + /> + <span + v-if="maxQuantity !== null" + style="color: #999; font-size: 12px; margin-left: 8px" + >(鏈�澶歿{ maxQuantity }}鍙�)</span + > + </el-form-item> + <el-form-item label="浣跨敤鐘舵��" prop="equipmentStatus"> + <el-select v-model="form.equipmentStatus" placeholder="璇烽�夋嫨"> + <el-option label="鍚敤" :value="1" /> + <el-option label="绂佺敤" :value="0" /> + <el-option label="缁翠慨涓�" :value="2" /> + <el-option label="鎶ュ簾" :value="3" /> + <el-option label="寰呴鐢�" :value="4" /> + </el-select> + </el-form-item> + <el-form-item label="浣跨敤寮�濮嬫椂闂�" prop="usageStartTime"> + <el-date-picker + v-model="form.usageStartTime" + type="datetime" + placeholder="閫夋嫨寮�濮嬫椂闂�" + style="width: 100%" + value-format="YYYY-MM-DD" + format="YYYY-MM-DD" + /> + </el-form-item> + <!-- <el-form-item label="浣跨敤缁撴潫鏃堕棿" prop="usageEndTime"> + <el-date-picker + v-model="form.usageEndTime" + type="datetime" + placeholder="閫夋嫨缁撴潫鏃堕棿" + style="width: 100%" + /> + </el-form-item> --> + <el-form-item label="澶囨敞" prop="remarks"> + <el-input + v-model="form.remarks" + type="textarea" + placeholder="璇疯緭鍏ュ娉�" + /> + </el-form-item> + </el-form> + <template #footer> + <el-button @click="handleClose">鍙栨秷</el-button> + <el-button type="primary" @click="handleSubmit">纭畾</el-button> + </template> + </el-dialog> +</template> + +<script setup> +import { ref, watch, computed, onMounted } from "vue"; +import { ElMessage } from "element-plus"; +import { getEquipmentList } from "@/api/publicApi/index.js"; +import { addOrEditUsageRecord } from "@/api/equipment/requisition/index.js"; + +import useUserStore from "@/store/modules/user"; + +onMounted(() => {}); +const userStore = useUserStore(); +let userList = ref([]); +userStore.getUserList().then((res) => { + userList.value = res; +}); +// 鑾峰彇璁惧鍒楄〃 +const equipmentList = ref([]); +getEquipmentList().then((res) => { + equipmentList.value = res.data; +}); +const props = defineProps({ + modelValue: Boolean, + formData: { + type: Object, + default: () => ({}), + }, +}); +const maxQuantity = computed(() => { + if (!props.formData.equipmentId) return 0; + const eq = equipmentList.value.find( + (item) => item.id == props.formData.equipmentId + ); + // 闃叉涓�0鎴栬礋鏁帮紝鏈�灏忎负1 + return eq && eq.quantity > 0 ? eq.quantity : 999; +}); +const emit = defineEmits(["update:modelValue", "submit"]); + +const visible = computed({ + get: () => props.modelValue, + set: (v) => emit("update:modelValue", v), +}); + +const isEdit = computed(() => !!props.formData?.id); +const formRef = ref(); + +// 榛樿琛ㄥ崟鍒濆鍊� +const defaultForm = { + userId: "", + equipmentId: "", + usageQuantity: 1, + equipmentStatus: 1, + usageStartTime: "", + remarks: "" +}; +const form = ref({ ...defaultForm }); + +watch( + () => props.formData, + (val) => { + if (val && Object.keys(val).length > 0) { + form.value = { ...defaultForm, ...val }; + } else { + // 鏂板缓鏃堕噸缃负鍒濆鍊硷紝闃叉鑴忔暟鎹� + form.value = { ...defaultForm }; + } + }, + { immediate: true } +); + +const rules = { + userId: [{ required: true, message: "璇疯緭鍏ラ鐢ㄤ汉", trigger: "blur" }], + equipmentId: [{ required: true, message: "璇疯緭鍏ヨ澶嘔D", trigger: "blur" }], + usageQuantity: [ + { required: true, message: "璇疯緭鍏ラ鐢ㄦ暟閲�", trigger: "blur" }, + { type: "number", min: 1, message: "鑷冲皯棰嗙敤1鍙�", trigger: "blur" }, + { + validator: (rule, value, callback) => { + if (maxQuantity.value !== null && value > maxQuantity.value) { + callback(new Error("棰嗙敤鏁伴噺涓嶈兘澶т簬璁惧鏁伴噺")); + } else { + callback(); + } + }, + trigger: "blur", + }, + ], + equipmentStatus: [ + { required: true, message: "璇烽�夋嫨浣跨敤鐘舵��", trigger: "change" }, + ], + usageStartTime: [ + { required: true, message: "璇烽�夋嫨寮�濮嬫椂闂�", trigger: "change" }, + ], +}; + +function handleClose() { + emit("update:modelValue", false); +} + +function handleSubmit() { + formRef.value.validate((valid) => { + if (!valid) return; + let res = addOrEditUsageRecord(form.value); + emit("submit", { ...form.value }); + handleClose(); + }); +} +</script> diff --git a/src/views/equipment/management/mould/usageRecord.vue b/src/views/equipment/management/mould/usageRecord.vue new file mode 100644 index 0000000..b092d33 --- /dev/null +++ b/src/views/equipment/management/mould/usageRecord.vue @@ -0,0 +1,241 @@ +<template> + <div> + <el-dialog + v-model="dialogVisible" + :title="addOrEdit === 'edit' ? '缂栬緫' : '鏂板' + '璁惧'" + width="800" + :title-style="{ textAlign: 'center' }" + :close-on-click-modal="false" + :before-close="handleClose" + > + <el-form + ref="formRef" + :model="formData" + :rules="rules" + label-width="auto" + > + <el-row :gutter="20"> + <el-col :span="11"> + <el-form-item label="璁惧缂栧彿" prop="equipmentId"> + <el-input + v-model="formData.equipmentId" + placeholder="璇疯緭鍏ヨ澶囩紪鍙�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="璁惧鍚嶇О" prop="equipmentName"> + <el-input + v-model="formData.equipmentName" + placeholder="璇疯緭鍏ヨ澶囧悕绉�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="鏁伴噺" prop="quantity"> + <el-input + v-model="formData.quantity" + placeholder="璇疯緭鍏ユ暟閲�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="瑙勬牸鍨嬪彿" prop="specification"> + <el-input + v-model="formData.specification" + placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="浣跨敤鐘舵��" prop="usageStatus"> + <el-select + v-model="formData.usageStatus" + placeholder="璇烽�夋嫨浣跨敤鐘舵��" + :disabled="isViewMode" + > + <el-option label="鍚敤" value="1" /> + <el-option label="绂佺敤" value="0" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="浣跨敤閮ㄩ棬" prop="usingDepartment"> + <el-input + v-model="formData.usingDepartment" + placeholder="璇疯緭鍏ヤ娇鐢ㄩ儴闂�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="瀛樻斁浣嶇疆" prop="storageLocation"> + <el-input + v-model="formData.storageLocation" + placeholder="璇疯緭鍏ュ瓨鏀句綅缃�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="閲囪喘浠锋牸" prop="purchasePrice"> + <el-input + v-model="formData.purchasePrice" + placeholder="璇疯緭鍏ラ噰璐环鏍�" + :disabled="isViewMode" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11"> + <el-form-item label="閲囪喘鏃ユ湡" prop="purchaseDate"> + <el-date-picker + v-model="formData.purchaseDate" + type="date" + placeholder="璇烽�夋嫨閲囪喘鏃ユ湡" + size="default" + :value-format="'YYYY-MM-DD'" + style="width: 100%;" + :disabled="isViewMode" + /> + </el-form-item> + </el-col> + </el-row> + <el-form-item class="dialog-footer"> + <el-button v-if="!isViewMode" @click="cancelForm">鍙栨秷</el-button> + <el-button v-if="!isViewMode" type="primary" @click="submitForm">纭畾</el-button> + </el-form-item> + </el-form> + </el-dialog> + </div> +</template> + +<script setup> +import { ref, watch, computed, reactive } from "vue"; +import { addOrEditEquipment } from "@/api/equipment/management/index.js"; + +const props = defineProps({ + beforeClose: { + type: Function, + default: () => {}, + }, + form: { + type: Object, + default: () => ({}), + }, + addOrEdit: { + type: String, + default: "add", + }, + title: { + type: String, + default: "", + }, +}); + +const emit = defineEmits(["submit", "handleBeforeClose"]); + +// 璁$畻灞炴�э細缁熶竴鎺у埗鏄惁绂佺敤 +const isViewMode = computed(() => props.addOrEdit === "viewRow"); + +// 琛ㄥ崟寮曠敤鍜屾暟鎹� +const formRef = ref(null); +const formData = ref({}); +const copyForm = defineModel("copyForm", { + required: true, + type: Object, + default: () => ({}), +}); + +// 寮圭獥鍙鎬� +const dialogVisible = defineModel("managementFormDialog", { + required: true, + type: Boolean, +}); + +// 鐩戝惉澶栭儴浼犲叆鐨勮〃鍗曟暟鎹彉鍖栵紝鍚堝苟鐩戝惉閫昏緫 +watch( + [() => props.form, () => props.addOrEdit], + ([newForm, newAddOrEdit]) => { + formData.value = { ...newForm }; + }, + { deep: true, immediate: true } +); +// 鎻愪氦琛ㄥ崟 +const submitForm = async () => { + if (!formRef.value) return; + + await formRef.value.validate(async (valid) => { + if (!valid) return; + + try { + const result = await addOrEditEquipment({ ...formData.value }); + const title = props.title.includes("鏂板") ? "鏂板" : "缂栬緫"; + + if (result.code === 200 && result.msg) { + ElMessage.success(`${title}鎴愬姛锛�${result.msg}`); + emit("submit", { title, ...formData.value, result }); + closeDialog(); + } else { + ElMessage.error(`${title}澶辫触锛�${result.msg}`); + } + } catch (error) { + console.error("鎻愪氦澶辫触:", error); + ElMessage.error("鎻愪氦澶辫触锛岃閲嶈瘯"); + } + }); +}; + +// 鍏抽棴寮圭獥鐨勭粺涓�鏂规硶 +const closeDialog = () => { + emit("update:managementFormDialog", false); + formData.value = {}; +}; + +// 鍙栨秷琛ㄥ崟 +const cancelForm = () => { + closeDialog(); +}; + +// 閲嶇疆琛ㄥ崟 +const resetForm = () => { + if (!formRef.value) return; + formData.value = JSON.parse(JSON.stringify(copyForm.value)); +}; + +// 鍏抽棴寮圭獥 +const handleClose = () => { + emit("handleBeforeClose"); + closeDialog(); +}; +const rules = reactive({ + equipmentId: [ + { required: true, message: "璇疯緭鍏ヤ緵璐у晢鍚嶇О", trigger: "blur" }, + ], +}); +</script> +<style lang="scss" scoped> +.dialog-footer { + display: flex; + justify-content: flex-end; + margin-top: 20px; + flex-direction: column; +} + +// 鍙负dialog澶撮儴鍔犱笅鍒掔嚎 +:deep(.el-dialog__header) { + border-bottom: 1px solid #e8eaec; + padding: 0 20px 10px 0; + margin-bottom: 14px; +} +</style> diff --git a/src/views/index.vue b/src/views/index.vue index 525a893..473aff0 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -8,24 +8,50 @@ </div> <div class="card-content"> <div class="card-title">钀ユ敹閲戦</div> - <div class="card-value">楼1,234,567</div> - <div class="card-trend"> + <div class="card-value"> + 楼{{ + homePageData.revenueAmount + ? formatThousand(homePageData.revenueAmount) + : "--" + }} + </div> + <div class="card-trend" v-if="homePageData.trend == '+'"> <span class="trend-label">杈冩槰鏃�</span> - <span class="trend-value up">+12.5%</span> + <span class="trend-value up">+ {{ homePageData.changeRate }}</span> + </div> + <div class="card-trend" v-if="homePageData.trend == '-'"> + <span class="trend-label">杈冩槰鏃�</span> + <span class="trend-value down" + >- {{ homePageData.changeRate }}</span + > </div> </div> </div> - + <div class="stat-card supply"> <div class="card-icon"> <i class="el-icon-truck"></i> </div> <div class="card-content"> <div class="card-title">渚涘簲閲�</div> - <div class="card-value">8,965 鍚�</div> - <div class="card-trend"> + <div class="card-value"> + {{ + homePageData.saleQuantity + ? formatThousand(homePageData.saleQuantity) + : "--" + }}鍚� + </div> + <div class="card-trend" v-if="homePageData.trendQuantity == '+'"> <span class="trend-label">杈冩槰鏃�</span> - <span class="trend-value up">+8.2%</span> + <span class="trend-value up" + >+ {{ homePageData.saleQuantityRate }}</span + > + </div> + <div class="card-trend" v-if="homePageData.trendQuantity == '-'"> + <span class="trend-label">杈冩槰鏃�</span> + <span class="trend-value down" + >- {{ homePageData.saleQuantityRate }}</span + > </div> </div> </div> @@ -37,9 +63,25 @@ <div class="chart-title">钀ユ敹鍒嗗竷</div> <div ref="pieChart" class="chart-content pie-chart"></div> </div> - + <div class="chart-container"> - <div class="chart-title">渚涘簲閲忚秼鍔�</div> + <div class="chart-title"> + <span>渚涘簲閲忚秼鍔�</span> + <div> + <el-date-picker + :locale="zhCN" + v-model="selectMonth" + type="monthrange" + placeholder="閫夋嫨鏃ユ湡" + format="YYYY/MM" + value-format="YYYY-MM" + range-separator="鑷�" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + @change="searchMonth" + /> + </div> + </div> <div ref="areaChart" class="chart-content area-chart"></div> </div> </div> @@ -52,25 +94,10 @@ <h3>搴撳瓨缁熻</h3> </div> <div class="inventory-items"> - <div class="inventory-item"> - <div class="item-name">鍘熺叅</div> - <div class="item-value">15,432 鍚�</div> - <div class="item-status normal">姝e父</div> - </div> - <div class="inventory-item"> - <div class="item-name">绮剧叅</div> - <div class="item-value">8,765 鍚�</div> - <div class="item-status normal">姝e父</div> - </div> - <div class="inventory-item"> - <div class="item-name">鐒︾叅</div> - <div class="item-value">3,241 鍚�</div> - <div class="item-status low">鍋忎綆</div> - </div> - <div class="inventory-item"> - <div class="item-name">鍧楃叅</div> - <div class="item-value">6,789 鍚�</div> - <div class="item-status normal">姝e父</div> + <div class="inventory-item" v-for="(item, index) in inventoryList.Yvalues" :key="index"> + <div class="item-name">{{ inventoryList.Xkeys[index]? inventoryList.Xkeys[index] : "--"}}</div> + <div class="item-value">{{ item ? formatThousand(item) : "0" }}</div> + <div class="item-status">鍚�</div> </div> </div> </div> @@ -93,236 +120,376 @@ style="width: 100%" :header-cell-style="tableHeaderStyle" > - <el-table-column prop="product" label="浜у搧" width="80"></el-table-column> - <el-table-column prop="quantity" label="鏁伴噺" width="80"></el-table-column> - <el-table-column prop="amount" label="閲戦" width="90"></el-table-column> - <el-table-column prop="status" label="鐘舵��" width="70"> - <template #default="scope"> - <el-tag - :type="scope.row.status === '宸插畬鎴�' ? 'success' : 'warning'" - size="small" - > - {{ scope.row.status }} - </el-tag> - </template> - </el-table-column> + <el-table-column + prop="product" + label="浜у搧" + mini-width="50" + ></el-table-column> + <el-table-column + prop="quantity" + label="鏁伴噺" + mini-width="50" + ></el-table-column> + <el-table-column + prop="amount" + label="閲戦" + mini-width="50" + ></el-table-column> </el-table> </div> </div> </div> </template> -<script> -import * as echarts from 'echarts' +<!-- 鍒犻櫎澶氫綑鐨� script 缁撴潫鏍囩 --> +<script setup> +import { getCoalInfo, getYearlySales } from "@/api/home/index"; +import { ref, onMounted, nextTick } from "vue"; +import zhCn from "element-plus/dist/locale/zh-cn.mjs"; -export default { - name: 'Dashboard', - data() { - return { - salesData: [ - { product: '鍘熺叅', quantity: '1,234鍚�', amount: '楼456,789', status: '宸插畬鎴�' }, - { product: '绮剧叅', quantity: '567鍚�', amount: '楼234,567', status: '宸插畬鎴�' }, - { product: '鐒︾叅', quantity: '890鍚�', amount: '楼345,678', status: '杩涜涓�' }, - { product: '鍧楃叅', quantity: '432鍚�', amount: '楼123,456', status: '宸插畬鎴�' }, - { product: '鐓ゆ偿', quantity: '678鍚�', amount: '楼234,567', status: '杩涜涓�' } - ], - tableHeaderStyle: { - backgroundColor: '#f5f7fa', - color: '#606266', - fontSize: '12px' - } - } - }, - mounted() { - this.$nextTick(() => { - this.initCharts() - }) - }, - methods: { - initCharts() { - this.initPieChart() - this.initAreaChart() - this.initBarChart() - }, - - initPieChart() { - const chart = echarts.init(this.$refs.pieChart) - const option = { - tooltip: { - trigger: 'item', - formatter: '{a} <br/>{b}: {c} ({d}%)' - }, - legend: { - orient: 'vertical', - left: 'right', - top: 'center', - textStyle: { - fontSize: 12 - } - }, - series: [ - { - name: '钀ユ敹鍒嗗竷', - type: 'pie', - radius: ['30%', '70%'], - center: ['40%', '50%'], - avoidLabelOverlap: false, - label: { - show: false, - position: 'center' - }, - emphasis: { - label: { - show: true, - fontSize: '16', - fontWeight: 'bold' - } - }, - labelLine: { - show: false - }, - data: [ - { value: 335, name: '鍘熺叅', itemStyle: { color: '#409EFF' } }, - { value: 310, name: '绮剧叅', itemStyle: { color: '#67C23A' } }, - { value: 234, name: '鐒︾叅', itemStyle: { color: '#E6A23C' } }, - { value: 135, name: '鍧楃叅', itemStyle: { color: '#F56C6C' } }, - { value: 155, name: '鍏朵粬', itemStyle: { color: '#909399' } } - ] - } - ] - } - chart.setOption(option) - - // 鍝嶅簲寮� - window.addEventListener('resize', () => { - chart.resize() - }) - }, - - initAreaChart() { - const chart = echarts.init(this.$refs.areaChart) - const option = { - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'cross', - label: { - backgroundColor: '#6a7985' - } - } - }, - legend: { - data: ['渚涘簲閲�'], - top: 10 - }, - grid: { - left: '3%', - right: '4%', - bottom: '3%', - containLabel: true - }, - xAxis: [ - { - type: 'category', - boundaryGap: false, - data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�'], - axisLabel: { - fontSize: 12 - } - } - ], - yAxis: [ - { - type: 'value', - axisLabel: { - fontSize: 12 - } - } - ], - series: [ - { - name: '渚涘簲閲�', - type: 'line', - stack: 'Total', - areaStyle: { - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: 'rgba(64, 158, 255, 0.3)' }, - { offset: 1, color: 'rgba(64, 158, 255, 0.1)' } - ]) - }, - emphasis: { - focus: 'series' - }, - data: [1200, 1320, 1010, 1340, 900, 1230, 1100], - lineStyle: { - color: '#409EFF' - }, - itemStyle: { - color: '#409EFF' - } - } - ] - } - chart.setOption(option) - - // 鍝嶅簲寮� - window.addEventListener('resize', () => { - chart.resize() - }) - }, - - initBarChart() { - const chart = echarts.init(this.$refs.barChart) - const option = { - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'shadow' - } - }, - grid: { - left: '3%', - right: '4%', - bottom: '3%', - containLabel: true - }, - xAxis: { - type: 'category', - data: ['鍘熺叅', '绮剧叅', '鐒︾叅', '鍧楃叅', '鐓ゆ偿'], - axisLabel: { - fontSize: 11 - } - }, - yAxis: { - type: 'value', - axisLabel: { - fontSize: 11 - } - }, - series: [ - { - name: '閿�閲�', - type: 'bar', - data: [320, 302, 301, 334, 290], - itemStyle: { - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: '#409EFF' }, - { offset: 1, color: '#79bbff' } - ]) - }, - barWidth: '60%' - } - ] - } - chart.setOption(option) - - // 鍝嶅簲寮� - window.addEventListener('resize', () => { - chart.resize() - }) - } +// 鍏煎妯℃澘鍙橀噺鍚嶏紝鏆撮湶缁欐ā鏉夸娇鐢� +const zhCN = zhCn; +import * as echarts from "echarts"; + +const homePageData = ref({}); +const selectMonth = ref([]); + +// 鐢熸垚鏃犻檺闅忔満棰滆壊锛圚SL绠楁硶淇濊瘉楂樿鲸璇嗗害銆佹煍鍜屼笉鍒虹溂锛� +function generateRandomColors(count = 10) { + const colors = []; + const goldenAngle = 137.508; // 榛勯噾瑙掑害锛屼繚璇侀鑹插垎甯冨潎鍖� + + for (let i = 0; i < count; i++) { + // 浣跨敤榛勯噾瑙掑害鍒嗗壊纭繚棰滆壊宸紓澶� + const hue = (i * goldenAngle) % 360; + + // 楗卞拰搴︼細40-70% 閬垮厤杩囦簬椴滆壋 + const saturation = 40 + Math.random() * 30; + + // 鏄庡害锛�45-75% 閬垮厤杩囨殫鎴栬繃浜� + const lightness = 45 + Math.random() * 30; + + colors.push( + `hsl(${Math.round(hue)}, ${Math.round(saturation)}%, ${Math.round( + lightness + )}%)` + ); } + + return colors; } + +// HSL杞�16杩涘埗锛堝彲閫夛紝濡傛灉闇�瑕乭ex鏍煎紡锛� +function hslToHex(hsl) { + const match = hsl.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/); + if (!match) return hsl; + + const h = parseInt(match[1]) / 360; + const s = parseInt(match[2]) / 100; + const l = parseInt(match[3]) / 100; + + const hue2rgb = (p, q, t) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; + + let r, g, b; + if (s === 0) { + r = g = b = l; + } else { + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + const toHex = (c) => { + const hex = Math.round(c * 255).toString(16); + return hex.length === 1 ? "0" + hex : hex; + }; + + return `#${toHex(r)}${toHex(g)}${toHex(b)}`; +} + +// 渚挎嵎鏂规硶锛氱洿鎺ヨ幏鍙�16杩涘埗棰滆壊鏁扮粍 +function getRandomHexColors(count = 1) { + return generateRandomColors(count).map(hslToHex); +} + +// 鍗冨垎浣嶆牸寮忓寲鍑芥暟 +function formatThousand(num) { + if (typeof num === "number") return num.toLocaleString(); + if (typeof num === "string") { + const n = Number(num.replace(/,/g, "")); + if (isNaN(n)) return num; + return n.toLocaleString(); + } + return num; +} + +// 閿�鍞暟鎹師濮� +const salesData = [ + { product: "鍘熺叅", quantity: "1234鍚�", amount: "楼456789", status: "宸插畬鎴�" }, + { product: "绮剧叅", quantity: "567鍚�", amount: "楼234567", status: "宸插畬鎴�" }, + { product: "鐒︾叅", quantity: "890鍚�", amount: "楼345678", status: "杩涜涓�" }, + { product: "鍧楃叅", quantity: "432鍚�", amount: "楼123456", status: "宸插畬鎴�" }, + { product: "鐓ゆ偿", quantity: "20000鍚�", amount: "楼234567", status: "杩涜涓�" }, +]; + +const tableHeaderStyle = { + backgroundColor: "#f5f7fa", + color: "#606266", + fontSize: "12px", +}; + +// 鍥捐〃ref +const pieChart = ref(null); +const areaChart = ref(null); +const barChart = ref(null); + +// 楗煎浘鍒濆鍖� +const initPieChart = () => { + const chart = echarts.init(pieChart.value); + const option = { + tooltip: { + trigger: "item", + formatter: "{a} <br/>{b}: {c} ({d}%)", + }, + legend: { + orient: "vertical", + left: "right", + top: "center", + textStyle: { + fontSize: 12, + }, + }, + series: [ + { + name: "钀ユ敹鍒嗗竷", + type: "pie", + radius: ["30%", "70%"], + center: ["40%", "50%"], + avoidLabelOverlap: false, + label: { + show: false, + position: "center", + }, + emphasis: { + label: { + show: true, + fontSize: "16", + fontWeight: "bold", + }, + }, + labelLine: { + show: false, + }, + data: revenueDistribution.value, + }, + ], + }; + chart.setOption(option); + window.addEventListener("resize", () => { + chart.resize(); + }); +}; + +// 闈㈢Н鍥惧垵濮嬪寲 +const initAreaChart = () => { + const chart = echarts.init(areaChart.value); + const option = { + title: { + show: supplyTrend.value.length == 0, // 娌℃暟鎹墠鏄剧ず + extStyle: { + color: "grey", + fontSize: 20, + }, + text: "鏆傛棤鏁版嵁", + left: "center", + top: "center", + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "cross", + label: { + backgroundColor: "#6a7985", + }, + }, + }, + legend: { + data: ["渚涘簲閲�"], + top: 10, + }, + grid: { + left: "3%", + right: "4%", + bottom: "3%", + containLabel: true, + }, + xAxis: [ + { + type: "category", + boundaryGap: false, + data: supplyTrend.value.Xkeys || [], + axisLabel: { + fontSize: 12, + }, + }, + ], + yAxis: [ + { + type: "value", + axisLabel: { + fontSize: 12, + }, + }, + ], + series: [ + { + name: "渚涘簲閲�", + type: "line", + stack: "Total", + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: "rgba(64, 158, 255, 0.3)" }, + { offset: 1, color: "rgba(64, 158, 255, 0.1)" }, + ]), + }, + emphasis: { + focus: "series", + }, + data: supplyTrend.value.Yvalues || [], + lineStyle: { + color: "#409EFF", + }, + itemStyle: { + color: "#409EFF", + }, + }, + ], + }; + chart.setOption(option); + window.addEventListener("resize", () => { + chart.resize(); + }); +}; + +// 鏌辩姸鍥惧垵濮嬪寲 +const initBarChart = () => { + const chart = echarts.init(barChart.value); + const option = { + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + grid: { + left: "3%", + right: "4%", + bottom: "3%", + containLabel: true, + }, + xAxis: { + type: "category", + data: ["鍘熺叅", "绮剧叅", "鐒︾叅", "鍧楃叅", "鐓ゆ偿"], + axisLabel: { + fontSize: 11, + }, + }, + yAxis: { + type: "value", + axisLabel: { + fontSize: 11, + }, + }, + series: [ + { + name: "閿�閲�", + type: "bar", + data: [320, 302, 301, 334, 290], + itemStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: "#409EFF" }, + { offset: 1, color: "#79bbff" }, + ]), + }, + barWidth: "60%", + }, + ], + }; + chart.setOption(option); + window.addEventListener("resize", () => { + chart.resize(); + }); +}; +// 鏀跺叆鍒嗗竷鏁版嵁 +const revenueDistribution = ref([]); + +// 鍒濆鍖栨墍鏈夊浘琛� +const initCharts = () => { + initPieChart(); + initAreaChart(); + initBarChart(); +}; + +const getList = async () => { + try { + searchMonth(); + const res = await getCoalInfo(); + homePageData.value = res.data || {}; + revenueDistribution.value = []; + if (homePageData.value.revenueDistribution) { + Object.keys(homePageData.value.revenueDistribution).forEach((key) => { + let obj = {}; + obj.name = key; + obj.value = homePageData.value.revenueDistribution[key]; + obj.itemStyle = { + color: getRandomHexColors(1)[0], // 浣跨敤闅忔満棰滆壊 + }; + revenueDistribution.value.push(obj); + }); + } + if (homePageData.value.inventory) { + let inventoryListXkeys = Object.keys(homePageData.value.inventory); + let inventoryListYvalues = Object.values(homePageData.value.inventory); + inventoryList.value = { + Xkeys: inventoryListXkeys, + Yvalues: inventoryListYvalues, + }; + } + console.log(inventoryList.value) + // 鏁版嵁鍔犺浇瀹屾垚鍚庨噸鏂板垵濮嬪寲鍥捐〃 + nextTick(() => { + initCharts(); + }); + } catch (error) { + console.error("鑾峰彇鐓ょ淇℃伅澶辫触:", error); + } +}; +const inventoryList = ref([]); + +const supplyTrend = ref({}); +const searchMonth = async () => { + let res = await getYearlySales({ + timeRange: selectMonth.value ? selectMonth.value : null, + }); + let Xkeys = Object.keys(res.data.data); + let Yvalues = Object.values(res.data.data); + supplyTrend.value = { + Xkeys, + Yvalues, + }; +}; +onMounted(() => { + getList(); +}); </script> <style scoped lang="scss"> @@ -363,11 +530,11 @@ } .revenue .card-icon { - background: linear-gradient(135deg, #409EFF, #79bbff); + background: linear-gradient(135deg, #409eff, #79bbff); } .supply .card-icon { - background: linear-gradient(135deg, #67C23A, #95d475); + background: linear-gradient(135deg, #67c23a, #95d475); } .card-content { @@ -397,7 +564,10 @@ } .trend-value.up { - color: #67C23A; + color: #67c23a; +} +.trend-value.down { + color: #f56c6c; } /* 涓棿鍥捐〃鍖哄煙 */ @@ -406,7 +576,7 @@ gap: 20px; margin-bottom: 20px; } -.el-scrollbar__view{ +.el-scrollbar__view { width: 100%; } .chart-container { @@ -424,6 +594,8 @@ margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #f0f0f0; + display: flex; + justify-content: space-between; } .chart-content { @@ -471,7 +643,7 @@ padding: 12px; background: #f8f9fa; border-radius: 6px; - border-left: 3px solid #409EFF; + border-left: 3px solid #409eff; } .item-name { @@ -493,12 +665,12 @@ .item-status.normal { background: #f0f9ff; - color: #67C23A; + color: #67c23a; } .item-status.low { background: #fef0e6; - color: #E6A23C; + color: #e6a23c; } /* 鏌辩姸鍥惧鍣� */ @@ -519,22 +691,21 @@ .bottom-card.table .el-table th { padding: 8px 0; } -:deep(.el-scrollbar__view){ +:deep(.el-scrollbar__view) { width: 100% !important; - } -:deep(.el-table__header,){ - width: 100% !important; - } -:deep(.el-table__body,){ - width: 100% !important; - } +:deep(.el-table__header, ) { + width: 100% !important; +} +:deep(.el-table__body, ) { + width: 100% !important; +} /* 鍝嶅簲寮忚璁� */ @media (max-width: 1200px) { .bottom-section { flex-direction: column; } - + .chart-section { flex-direction: column; } @@ -544,15 +715,15 @@ .top-cards { flex-direction: column; } - + .dashboard { padding: 10px; } - + .stat-card { padding: 15px; } - + .card-value { font-size: 20px; } diff --git a/src/views/procureMent/index.vue b/src/views/procureMent/index.vue index 3881e50..24929ac 100644 --- a/src/views/procureMent/index.vue +++ b/src/views/procureMent/index.vue @@ -20,9 +20,9 @@ <el-button type="primary" :icon="Plus" @click="handleAdd" >鏂板缓 </el-button> - <el-button type="danger" :icon="Delete" @click="handleDelete" + <!-- <el-button type="danger" :icon="Delete" @click="handleDelete" >鍒犻櫎 - </el-button> + </el-button> --> </el-row> <!-- 琛ㄦ牸缁勪欢 --> <data-table @@ -76,8 +76,12 @@ delPR } from "@/api/procureMent"; import { useDelete } from "@/hooks/useDelete"; - +const userStore = useUserStore(); import useUserStore from "@/store/modules/user"; +let userList = ref([]); +userStore.getUserList().then((res) => { + userList.value = res; +}); // 寮曞叆瀛楀吀鏁版嵁 const { proxy } = getCurrentInstance(); const dialogFormVisible = ref(false); @@ -109,7 +113,7 @@ // 杩欓噷娣诲姞瀹為檯鐨勬煡璇㈤�昏緫 getList(); }; -const userStore = useUserStore(); + // 鑾峰彇鐢ㄦ埛淇℃伅 const userInfo = ref({}); onMounted(async () => { @@ -148,7 +152,13 @@ { prop: "totalPriceIncludingTax", label: "鎬讳环锛堝惈绋庯級", minWidth: 100 }, { prop: "taxRate", label: "绋庣巼", minWidth: 100 }, { prop: "priceExcludingTax", label: "涓嶅惈绋庡崟浠�", minWidth: 100 }, - { prop: "registrantId", label: "鐧昏浜�", minWidth: 100 }, + { prop: "registrantId", label: "鐧昏浜�", minWidth: 100, + formatter: (row) => { + // 鍖归厤鐢ㄦ埛淇℃伅 + const user = userList.value.find((user) => user.userId === row.registrantId); + return user ? user.nickName : "鏈煡鐢ㄦ埛"; + }, + }, { prop: "registrationDate", label: "鐧昏鏃ユ湡", minWidth: 100 }, ]); diff --git a/src/views/production/components/ProductionDetailsTable.vue b/src/views/production/components/ProductionDetailsTable.vue index dd89b4b..13cd614 100644 --- a/src/views/production/components/ProductionDetailsTable.vue +++ b/src/views/production/components/ProductionDetailsTable.vue @@ -50,10 +50,13 @@ <el-table-column label="鑳借�楁垚鏈�" min-width="120"> <template #default="{ row, $index }"> + <!-- 涓嶈兘涓鸿礋鏁� --> <el-input v-model="row.energyConsumptionCost" placeholder="璇疯緭鍏ヨ兘鑰楁垚鏈�" type="number" + min="0" + step="0.01" @input="handleInput('energyConsumptionCost', $index, $event)" :disabled="isViewMode" > @@ -156,6 +159,7 @@ <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 {getCoalInfoList} from "@/api/production"; import {userListAll} from "@/api/publicApi"; @@ -197,6 +201,11 @@ // 澶勭悊杈撳叆鍙樺寲 const handleInput = (field, index, value) => { + // 纭繚杈撳叆鍊兼槸鏁板瓧鎴栫┖瀛楃涓茶�屼笖闈炶礋鏁� + if (!/^\d*\.?\d*$/.test(value) && value !== "") { + ElMessage.error("璇疯緭鍏ユ湁鏁堢殑鏁板瓧"); + return; + } const newData = [...tableData.value]; newData[index][field] = value; diff --git a/src/views/production/components/ProductionDialog.vue b/src/views/production/components/ProductionDialog.vue index c14ca96..8619bee 100644 --- a/src/views/production/components/ProductionDialog.vue +++ b/src/views/production/components/ProductionDialog.vue @@ -200,10 +200,10 @@ const currentRow = ref(null); const copyForm = ref(null); const coalList = ref([]) -const supplierList = ref({}); +const supplierList = ref([]); // 琛ㄦ牸鍒楅厤缃� const columns = [ - {prop: "coalId", label: "鐓ょ", minwidth: 60,slot:false, + {prop: "coalId", label: "鐓ょ", minwidth: 60,slot:true, formatter: (row) => { return coalList.value.find(coal => coal.id === row.coalId)?.coal || "--"; } @@ -219,11 +219,6 @@ ]; const formalDatabaseColumns = ref([ - {prop: "supplierId", label: "渚涘簲鍟嗗悕绉�", minwidth: 150 - ,formatter: (row) => { - return supplierList.value.find(supplier => supplier.id === row.supplierId)?.supplierName || "--"; - } - }, {prop: "coalId", label: "鐓ょ", minwidth: 60, formatter: (row) => { return coalList.value.find(coal => coal.id === row.coalId)?.coal || "--"; @@ -247,29 +242,51 @@ currentRow.value = row; }; +// 鑾峰彇鍩虹鏁版嵁锛堢叅绉嶅拰渚涘簲鍟嗭級 +const loadBasicData = async () => { + try { + const [coalResponse, supplierResponse] = await Promise.all([ + getCoalInfoList(), + getSupplyList() + ]); + + coalList.value = coalResponse.data || []; + supplierList.value = supplierResponse.data || []; + } catch (error) { + ElMessage.error("鑾峰彇鍩虹鏁版嵁澶辫触"); + } +}; + // 鑾峰彇閰嶇疆鏁版嵁 const handlData = async () => { innerVisible.value = true; - let OfficialAll = await getOfficialAll(); - let getSupplierList = await getSupplyList(); - let getCoalName = await getCoalInfoList(); - coalList.value = getCoalName.data || []; - supplierList.value = getSupplierList.data || []; - if (OfficialAll.code === 200) { - formalDatabaseData.value = OfficialAll.data; - const existingOfficialIds = tableData.value - .map((item) => item.officialId) - .filter((id) => id); - selectedIds.value = existingOfficialIds; - debugIdMatching(); - nextTick(() => { - setTimeout(() => { - if (etableRef.value && existingOfficialIds.length > 0) { - etableRef.value.setDefaultSelection(); - } - }, 100); - }); - } else { + + // 纭繚鍩虹鏁版嵁宸插姞杞� + if (coalList.value.length === 0 || supplierList.value.length === 0) { + await loadBasicData(); + } + + try { + const OfficialAll = await getOfficialAll(); + + if (OfficialAll.code === 200) { + formalDatabaseData.value = OfficialAll.data; + const existingOfficialIds = tableData.value + .map((item) => item.officialId) + .filter((id) => id); + selectedIds.value = existingOfficialIds; + debugIdMatching(); + nextTick(() => { + setTimeout(() => { + if (etableRef.value && existingOfficialIds.length > 0) { + etableRef.value.setDefaultSelection(); + } + }, 100); + }); + } else { + ElMessage.error("鑾峰彇閰嶇疆鏁版嵁澶辫触"); + } + } catch (error) { ElMessage.error("鑾峰彇閰嶇疆鏁版嵁澶辫触"); } }; @@ -296,14 +313,17 @@ }; // 鍒濆鍖栧拰缂栬緫鍒濆鍖� -const Initialization = () => { +const Initialization = async () => { tableData.value = []; detailsTableData.value = []; copyForm.value = null; dialogType.value = "add"; + + // 鍔犺浇鍩虹鏁版嵁 + await loadBasicData(); }; -const editInitialization = (type,data) => { +const editInitialization = async (type, data) => { copyForm.value = deepClone(data); tableData.value = data.productionInventoryList || []; detailsTableData.value = data.productionList || []; @@ -312,6 +332,9 @@ .map((item) => item.officialId) .filter((id) => id); selectedIds.value = existingOfficialIds; + + // 鍔犺浇鍩虹鏁版嵁 + await loadBasicData(); }; // 鐩戝惉瀵硅瘽妗嗙姸鎬侊紝鍦ㄦ墦寮�鏃惰缃�変腑鐘舵�� watch(innerVisible, (newVal) => { @@ -457,12 +480,13 @@ } }; -// 鑾峰彇鐢ㄦ埛淇℃伅 +// 鑾峰彇鐢ㄦ埛淇℃伅骞跺姞杞藉熀纭�鏁版嵁 onMounted(async () => { try { userInfo = await userStore.getInfo(); + await loadBasicData(); } catch (error) { - ElMessage.error("鑾峰彇鐢ㄦ埛淇℃伅澶辫触锛岃閲嶈瘯"); + ElMessage.error("鍒濆鍖栧け璐ワ紝璇烽噸璇�"); } }); -- Gitblit v1.9.3