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