| | |
| | | method: 'delete', |
| | | data |
| | | }) |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // 设å¤ç®¡ç |
| | | 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 |
| | | }) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç
¤ç§ä¿¡æ¯ |
| | | 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 |
| | | }) |
| | | } |
| | | |
| | |
| | | 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 |
| | | }) |
| | | } |
| | |
| | | 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', |
| | |
| | | nickName: '', |
| | | avatar: '', |
| | | roles: [], |
| | | permissions: [] |
| | | permissions: [], |
| | | userList: [] |
| | | }), |
| | | actions: { |
| | | // ç»å½ |
| | |
| | | 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; |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | |
| | | @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> |
| | |
| | | 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({}); |
| | |
| | | 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([]); |
| | |
| | | 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 }, |
| | |
| | | minWidth: 100, |
| | | formatter: (row) => row.usageStatus == 1 ? "å¯ç¨" : "ç¦ç¨" |
| | | }, |
| | | { prop: "usingDepartment", label: "使ç¨é¨é¨", minWidth: 100 }, |
| | | { prop: "purchaseDate", label: "éè´æ¥æ", minWidth: 100 }, |
| | | { prop: "purchasePrice", label: "éè´ä»·æ ¼", minWidth: 100 }, |
| | | ] |
| | | } |
| | | }, |
| | | |
| | | // åç»å¯ä»¥å¨è¿éæ·»å æ°çæ ç¾é¡µé
ç½® |
| | | }; |
| | | |
| | |
| | | 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) => { |
| | |
| | | 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) => { |
| | |
| | | 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) => { |
| | |
| | | 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 { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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: "请è¾å
¥è®¾å¤ID", 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| | |
| | | </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> |
| | |
| | | <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> |
| | |
| | | <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">æ£å¸¸</div> |
| | | </div> |
| | | <div class="inventory-item"> |
| | | <div class="item-name">ç²¾ç
¤</div> |
| | | <div class="item-value">8,765 å¨</div> |
| | | <div class="item-status normal">æ£å¸¸</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">æ£å¸¸</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> |
| | |
| | | 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([]); |
| | | |
| | | // çææ ééæºé¢è²ï¼HSLç®æ³ä¿è¯é«è¾¨è¯åº¦ãæåä¸åºç¼ï¼ |
| | | 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è¿å¶ï¼å¯éï¼å¦æéè¦hexæ ¼å¼ï¼ |
| | | 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"> |
| | |
| | | } |
| | | |
| | | .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 { |
| | |
| | | } |
| | | |
| | | .trend-value.up { |
| | | color: #67C23A; |
| | | color: #67c23a; |
| | | } |
| | | .trend-value.down { |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | /* ä¸é´å¾è¡¨åºå */ |
| | |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | .el-scrollbar__view{ |
| | | .el-scrollbar__view { |
| | | width: 100%; |
| | | } |
| | | .chart-container { |
| | |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 2px solid #f0f0f0; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .chart-content { |
| | |
| | | padding: 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | border-left: 3px solid #409EFF; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .item-name { |
| | |
| | | |
| | | .item-status.normal { |
| | | background: #f0f9ff; |
| | | color: #67C23A; |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .item-status.low { |
| | | background: #fef0e6; |
| | | color: #E6A23C; |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | /* æ±ç¶å¾å®¹å¨ */ |
| | |
| | | .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; |
| | | } |
| | |
| | | .top-cards { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | |
| | | .dashboard { |
| | | padding: 10px; |
| | | } |
| | | |
| | | |
| | | .stat-card { |
| | | padding: 15px; |
| | | } |
| | | |
| | | |
| | | .card-value { |
| | | font-size: 20px; |
| | | } |
| | |
| | | <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 |
| | |
| | | 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); |
| | |
| | | // è¿éæ·»å å®é
çæ¥è¯¢é»è¾ |
| | | getList(); |
| | | }; |
| | | const userStore = useUserStore(); |
| | | |
| | | // è·åç¨æ·ä¿¡æ¯ |
| | | const userInfo = ref({}); |
| | | onMounted(async () => { |
| | |
| | | { 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 }, |
| | | ]); |
| | | |
| | |
| | | |
| | | <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" |
| | | > |
| | |
| | | <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"; |
| | |
| | | |
| | | // å¤çè¾å
¥åå |
| | | const handleInput = (field, index, value) => { |
| | | // ç¡®ä¿è¾å
¥å¼æ¯æ°åæç©ºå符串èä¸éè´æ° |
| | | if (!/^\d*\.?\d*$/.test(value) && value !== "") { |
| | | ElMessage.error("请è¾å
¥ææçæ°å"); |
| | | return; |
| | | } |
| | | const newData = [...tableData.value]; |
| | | newData[index][field] = value; |
| | | |
| | |
| | | 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, |
| | | formatter: (row) => { |
| | | return coalList.value.find(coal => coal.id === row.coalId)?.coal || "--"; |
| | | } |
| | |
| | | ]; |
| | | |
| | | 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 || "--"; |
| | |
| | | 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("è·åé
ç½®æ°æ®å¤±è´¥"); |
| | | } |
| | | }; |
| | |
| | | }; |
| | | |
| | | // åå§ååç¼è¾åå§å |
| | | 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 || []; |
| | |
| | | .map((item) => item.officialId) |
| | | .filter((id) => id); |
| | | selectedIds.value = existingOfficialIds; |
| | | |
| | | // å è½½åºç¡æ°æ® |
| | | await loadBasicData(); |
| | | }; |
| | | // çå¬å¯¹è¯æ¡ç¶æï¼å¨æå¼æ¶è®¾ç½®éä¸ç¶æ |
| | | watch(innerVisible, (newVal) => { |
| | |
| | | } |
| | | }; |
| | | |
| | | // è·åç¨æ·ä¿¡æ¯ |
| | | // è·åç¨æ·ä¿¡æ¯å¹¶å è½½åºç¡æ°æ® |
| | | onMounted(async () => { |
| | | try { |
| | | userInfo = await userStore.getInfo(); |
| | | await loadBasicData(); |
| | | } catch (error) { |
| | | ElMessage.error("è·åç¨æ·ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯"); |
| | | ElMessage.error("åå§å失败ï¼è¯·éè¯"); |
| | | } |
| | | }); |
| | | |