¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç¨æ°´ç®¡ç |
| | | import request from "@/utils/request"; |
| | | |
| | | // ç¨æ°´è®¾å¤-å页æ¥è¯¢ |
| | | export function waterEquipmentListPage(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è¶å¿-å页æ¥è¯¢ |
| | | export function listPageByWaterTrend(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/listPageByTrend', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-å é¤ |
| | | export function waterEquipmentDelete(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/delete', |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-æ°å¢ |
| | | export function waterEquipmentAdd(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/add', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-ä¿®æ¹ |
| | | export function waterEquipmentUpdate(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤ä¸ææ¡æ¥è¯¢ |
| | | export function waterDeviceList(query) { |
| | | return request({ |
| | | url: '/waterEquipmentConsumption/deviceList', |
| | | method: 'get', |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-å页æ¥è¯¢ |
| | | export function waterBillListPage(query) { |
| | | return request({ |
| | | url: '/waterBill/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-æ°å¢ |
| | | export function waterBillAdd(query) { |
| | | return request({ |
| | | url: '/waterBill/add', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-ä¿®æ¹ |
| | | export function waterBillUpdate(query) { |
| | | return request({ |
| | | url: '/waterBill/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-å é¤ |
| | | export function waterBillDelete(query) { |
| | | return request({ |
| | | url: '/waterBill/delete', |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å¨æ°ç½é¢è¦å表 |
| | | export const getStockWarningPage = (params) => { |
| | | return request({ |
| | | url: "/gasTankWarning/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢å¨æ°ç½é¢è¦è§å |
| | | export const addStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // ä¿®æ¹å¨æ°ç½é¢è¦è§å |
| | | export const updateStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/update", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤å¨æ°ç½é¢è¦è§å |
| | | export const deleteStockWarning = (ids) => { |
| | | return request({ |
| | | url: "/gasTankWarning/delete", |
| | | method: "delete", |
| | | data: { ids }, |
| | | }); |
| | | }; |
| | | |
| | | // æ¹éå¤ç卿°ç½é¢è¦ |
| | | export const batchProcessStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/batchProcess", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // 导åºå¨æ°ç½é¢è¦æ°æ® |
| | | export const exportStockWarning = (params) => { |
| | | return request({ |
| | | url: "/gasTankWarning/export", |
| | | method: "get", |
| | | params, |
| | | responseType: "blob", |
| | | }); |
| | | }; |
| | | |
| | | // æ ¹æ®IDè·å卿°ç½é¢è¦è¯¦æ
|
| | | export const getStockWarningById = (id) => { |
| | | return request({ |
| | | url: `/gasTankWarning/${id}`, |
| | | method: "get", |
| | | }); |
| | | }; |
| | | |
| | | // å¯ç¨/ç¦ç¨é¢è¦è§å |
| | | export const toggleStockWarningStatus = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/toggleStatus", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // è·åé¢è¦ç»è®¡ä¿¡æ¯ |
| | | export const getStockWarningStatistics = () => { |
| | | return request({ |
| | | url: "/gasTankWarning/statistics", |
| | | method: "get", |
| | | }); |
| | | }; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="ç¨æ°´è®¾å¤" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ï¼" prop="code"> |
| | | <el-select |
| | | v-model="form.code" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="setName" |
| | | :disabled="operationType !== 'add'" |
| | | > |
| | | <el-option |
| | | v-for="item in codeList" |
| | | :key="item.deviceModel" |
| | | :label="item.deviceName" |
| | | :value="item.deviceModel" |
| | | > |
| | | {{item.deviceName + '--' + item.deviceModel}} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯æ¥éå¶æ°´éï¼" prop="everyNum"> |
| | | <el-input |
| | | v-model="form.everyNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢å®æµéï¼" prop="flowRating"> |
| | | <el-input |
| | | v-model="form.flowRating" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®é
æµéï¼" prop="flowActual"> |
| | | <el-input |
| | | v-model="form.flowActual" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¿è¡æ¶é´ï¼" prop="runDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.runDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="彿¥ç¨æ°´éï¼" prop="dayNum"> |
| | | <el-input |
| | | v-model="form.dayNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹åä»·ï¼" prop="waterPrice"> |
| | | <el-input |
| | | v-model="form.waterPrice" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´ç±»åï¼" prop="waterType"> |
| | | <el-select |
| | | v-model="form.waterType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="å·¥ä¸ç¨æ°´" value="industrial" /> |
| | | <el-option label="çæ´»ç¨æ°´" value="domestic" /> |
| | | <el-option label="æ¶é²ç¨æ°´" value="fire" /> |
| | | <el-option label="绿åç¨æ°´" value="greening" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, nextTick} from "vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {waterDeviceList, waterEquipmentAdd, waterEquipmentUpdate} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | name: "", |
| | | code: "", |
| | | everyNum: "", |
| | | flowRating: "", |
| | | flowActual: "", |
| | | runDate: "", |
| | | dayNum: "", |
| | | waterPrice: "", |
| | | waterType: "", |
| | | }, |
| | | rules: { |
| | | code: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | runDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | everyNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | flowRating: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | flowActual: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | dayNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | | const codeList = ref([]) |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value = {} |
| | | proxy.resetForm("formRef"); |
| | | waterDeviceList().then((res) => { |
| | | codeList.value = res.data; |
| | | }); |
| | | if (type === "edit") { |
| | | form.value = {...row} |
| | | } |
| | | } |
| | | const setName = (code) => { |
| | | const index = codeList.value.findIndex(item => item.deviceModel === code); |
| | | if (index > -1) { |
| | | console.log(codeList) |
| | | form.value.name = codeList.value[index].deviceName; |
| | | } |
| | | } |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | waterEquipmentAdd(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå") |
| | | closeDia() |
| | | }) |
| | | } else { |
| | | waterEquipmentUpdate(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå") |
| | | closeDia() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="水费管ç" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ï¼" prop="code"> |
| | | <el-select |
| | | v-model="form.code" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="setName" |
| | | :disabled="operationType !== 'add'" |
| | | > |
| | | <el-option |
| | | v-for="item in codeList" |
| | | :key="item.deviceModel" |
| | | :label="item.deviceName" |
| | | :value="item.deviceModel" |
| | | > |
| | | {{item.deviceName + '--' + item.deviceModel}} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´éï¼" prop="waterConsumption"> |
| | | <el-input |
| | | v-model="form.waterConsumption" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹åä»·ï¼" prop="waterPrice"> |
| | | <el-input |
| | | v-model="form.waterPrice" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹éé¢ï¼" prop="waterBill"> |
| | | <el-input |
| | | v-model="form.waterBill" |
| | | placeholder="èªå¨è®¡ç®" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è®¡è´¹æ¥æï¼" prop="billDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.billDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´ç±»åï¼" prop="waterType"> |
| | | <el-select |
| | | v-model="form.waterType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="å·¥ä¸ç¨æ°´" value="industrial" /> |
| | | <el-option label="çæ´»ç¨æ°´" value="domestic" /> |
| | | <el-option label="æ¶é²ç¨æ°´" value="fire" /> |
| | | <el-option label="绿åç¨æ°´" value="greening" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, nextTick, watch} from "vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {waterDeviceList, waterBillAdd, waterBillUpdate} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | name: "", |
| | | code: "", |
| | | waterConsumption: "", |
| | | waterPrice: "", |
| | | waterBill: "", |
| | | billDate: "", |
| | | waterType: "", |
| | | }, |
| | | rules: { |
| | | code: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | waterConsumption: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | billDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | waterType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | | const codeList = ref([]) |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value = {} |
| | | proxy.resetForm("formRef"); |
| | | waterDeviceList().then((res) => { |
| | | codeList.value = res.data; |
| | | }); |
| | | if (type === "edit") { |
| | | form.value = {...row} |
| | | } |
| | | } |
| | | const setName = (code) => { |
| | | const index = codeList.value.findIndex(item => item.deviceModel === code); |
| | | if (index > -1) { |
| | | console.log(codeList) |
| | | form.value.name = codeList.value[index].deviceName; |
| | | } |
| | | } |
| | | |
| | | // è®¡ç®æ°´è´¹éé¢ |
| | | const calculateWaterBill = () => { |
| | | if (form.value.waterConsumption && form.value.waterPrice) { |
| | | form.value.waterBill = (parseFloat(form.value.waterConsumption) * parseFloat(form.value.waterPrice)).toFixed(2); |
| | | } |
| | | } |
| | | |
| | | // çå¬ç¨æ°´éåæ°´è´¹åä»·åå |
| | | watch([() => form.value.waterConsumption, () => form.value.waterPrice], () => { |
| | | calculateWaterBill(); |
| | | }); |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | waterBillAdd(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå") |
| | | closeDia() |
| | | }) |
| | | } else { |
| | | waterBillUpdate(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå") |
| | | closeDia() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="info" plain icon="Upload" @click="handleImport">导å
¥</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <el-dialog |
| | | :title="upload.title" |
| | | v-model="upload.open" |
| | | width="400px" |
| | | append-to-body |
| | | @close="handleDialogClose" |
| | | > |
| | | <el-upload |
| | | ref="uploadRef" |
| | | :limit="1" |
| | | accept=".xlsx, .xls" |
| | | :headers="upload.headers" |
| | | :action="upload.url" |
| | | :disabled="upload.isUploading" |
| | | :before-upload="upload.beforeUpload" |
| | | :on-progress="upload.onProgress" |
| | | :on-success="upload.onSuccess" |
| | | :on-error="upload.onError" |
| | | :on-change="upload.onChange" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip text-center"> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link |
| | | type="primary" |
| | | :underline="false" |
| | | style="font-size: 12px; vertical-align: baseline" |
| | | @click="importTemplate" |
| | | >ä¸è½½æ¨¡æ¿</el-link |
| | | > |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitFileForm">ç¡® å®</el-button> |
| | | <el-button @click="upload.open = false">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, nextTick} from "vue"; |
| | | import FormDia from "@/views/energyManagement/waterManagement/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {getToken} from "@/utils/auth.js"; |
| | | import {waterEquipmentDelete, waterEquipmentListPage} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "name", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "code", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "é¢å®æµé", |
| | | prop: "flowRating", |
| | | }, |
| | | { |
| | | label: "å®é
æµé", |
| | | prop: "flowActual", |
| | | }, |
| | | { |
| | | label: "è¿è¡æ¶é´", |
| | | prop: "runDate", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "彿¥ç¨æ°´é", |
| | | prop: "dayNum", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "æ¯æ¥éå¶æ°´é", |
| | | prop: "everyNum", |
| | | width:220 |
| | | }, |
| | | { |
| | | label: "æ°´è´¹åä»·", |
| | | prop: "waterPrice", |
| | | width: 120, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼å®¢æ·å¯¼å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼å®¢æ·å¯¼å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/waterEquipmentConsumption/importData", |
| | | // æä»¶ä¸ä¼ åçåè° |
| | | beforeUpload: (file) => { |
| | | console.log('æä»¶å³å°ä¸ä¼ ', file); |
| | | // å¯ä»¥å¨æ¤å¤åæä»¶ç±»åæå¤§å°æ ¡éª |
| | | const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls'); |
| | | if (!isValid) { |
| | | proxy.$modal.msgError("åªè½ä¸ä¼ Excel æä»¶"); |
| | | } |
| | | return isValid; |
| | | }, |
| | | // æä»¶ç¶ææ¹åæ¶çåè° |
| | | onChange: (file, fileList) => { |
| | | console.log('æä»¶ç¶ææ¹å', file, fileList); |
| | | }, |
| | | // æä»¶ä¸ä¼ æåæ¶çåè° |
| | | onSuccess: (response, file, fileList) => { |
| | | console.log('ä¸ä¼ æå', response, file, fileList); |
| | | if(response.code === 200){ |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | }else if(response.code === 500){ |
| | | proxy.$modal.msgError(response.msg); |
| | | }else{ |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | upload.open = false; |
| | | getList(); |
| | | }, |
| | | // æä»¶ä¸ä¼ 失败æ¶çåè° |
| | | onError: (error, file, fileList) => { |
| | | console.log('ä¸ä¼ 失败', error, file, fileList); |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | upload.open = false; |
| | | }, |
| | | // æä»¶ä¸ä¼ è¿åº¦æ¹åæ¶çåè° |
| | | onProgress: (event, file, fileList) => { |
| | | console.log('ä¸ä¼ è¿åº¦', event, file, fileList); |
| | | upload.isUploading = true; |
| | | }, |
| | | }); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | waterEquipmentListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | /** 导å
¥æé®æä½ */ |
| | | function handleImport() { |
| | | upload.title = "ç¨æ°´è®¾å¤"; |
| | | upload.open = true; |
| | | // æ¸
ç©ºä¸æ¬¡ä¸ä¼ çæä»¶å表 |
| | | nextTick(() => { |
| | | proxy.$refs["uploadRef"]?.clearFiles(); |
| | | }); |
| | | } |
| | | function importTemplate() { |
| | | proxy.download( |
| | | "/waterEquipmentConsumption/export", |
| | | {}, |
| | | 'ç¨æ°´è®¾å¤å¯¼å
¥æ¨¡ç.xlsx' |
| | | ); |
| | | } |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | | proxy.$refs["uploadRef"].submit(); |
| | | } |
| | | |
| | | /** å¼¹æ¡å
³éæ¶æ¸
空æä»¶å表 */ |
| | | function handleDialogClose() { |
| | | nextTick(() => { |
| | | proxy.$refs["uploadRef"]?.clearFiles(); |
| | | }); |
| | | } |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | waterEquipmentDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, nextTick} from "vue"; |
| | | import FormDia from "@/views/energyManagement/waterManagement/components/waterBillForm.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {waterBillDelete, waterBillListPage} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "name", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "code", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "ç¨æ°´é", |
| | | prop: "waterConsumption", |
| | | }, |
| | | { |
| | | label: "æ°´è´¹åä»·", |
| | | prop: "waterPrice", |
| | | }, |
| | | { |
| | | label: "æ°´è´¹éé¢", |
| | | prop: "waterBill", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "è®¡è´¹æ¥æ", |
| | | prop: "billDate", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ç¨æ°´ç±»å", |
| | | prop: "waterType", |
| | | width:120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | waterBillListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | waterBillDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive} from "vue"; |
| | | import {listPageByWaterTrend} from "@/api/energyManagement/waterManagement.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "name", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "code", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è¿è¡æ¶é´", |
| | | prop: "runDate", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "æ¨æ¥ç¨æ°´é", |
| | | prop: "toDayNum", |
| | | }, |
| | | { |
| | | label: "æ¬æå¹³åæ°´é", |
| | | prop: "avgNum", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "è¶å¿", |
| | | prop: "trend", |
| | | width: 220, |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listPageByWaterTrend({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <h2>éåç½å¼è´§è½¦çæ§</h2> |
| | | <div class="header-actions"> |
| | | <!-- <el-button type="primary" @click="addTank">æ°å¢å¨ç½</el-button>--> |
| | | <!-- <el-button @click="exportData">å¯¼åºæ°æ®</el-button>--> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åä¸ªä¸»è¦æ¨¡å --> |
| | | <div class="modules-container"> |
| | | <!-- 1. åºæ¬ä¿¡æ¯æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>1. åºæ¬ä¿¡æ¯</span> |
| | | <el-button type="text" @click="handleEditBasicInfo">ç¼è¾</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="info-grid"> |
| | | <div class="info-item"> |
| | | <label>å¨ç½ç¼å·ï¼</label> |
| | | <span>{{ basicInfo.tankCode }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å¨ç½åç§°ï¼</label> |
| | | <span>{{ basicInfo.tankName }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å¨ç½ç±»åï¼</label> |
| | | <span>{{ basicInfo.tankType }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>设计ååï¼</label> |
| | | <span>{{ basicInfo.designPressure }} MPa</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å·¥ä½ååï¼</label> |
| | | <span>{{ basicInfo.workingPressure }} MPa</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>容积ï¼</label> |
| | | <span>{{ basicInfo.volume }} m³</span> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 2. çæµåæ°æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>2. çæµåæ°</span> |
| | | <el-button type="text" @click="refreshMonitoring">å·æ°</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="monitoring-grid"> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">åå</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.pressureStatus)"> |
| | | {{ monitoringData.pressure }} MPa |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.pressureStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">温度</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.temperatureStatus)"> |
| | | {{ monitoringData.temperature }} â |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.temperatureStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">æ°ä½æµåº¦</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.gasStatus)"> |
| | | {{ monitoringData.gasConcentration }} ppm |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.gasStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">æµé</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.flowStatus)"> |
| | | {{ monitoringData.flow }} m³/h |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.flowStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 3. å®å
¨è£
置模å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>3. å®å
¨è£
ç½®</span> |
| | | <el-button type="text" @click="checkSafetyDevices">æ£æ¥</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="safety-grid"> |
| | | <div class="safety-item" v-for="device in safetyDevices" :key="device.name"> |
| | | |
| | | <div class="device-info"> |
| | | <div class="device-name">{{ device.name }}</div> |
| | | <div class="device-status" :class="device.status"> |
| | | {{ device.status === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 4. ç»´æ¤è®°å½æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>4. ç»´æ¤è®°å½</span> |
| | | <el-button type="text" @click="addMaintenanceRecord">æ·»å è®°å½</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="maintenance-list"> |
| | | <div class="maintenance-item" v-for="record in maintenanceRecords" :key="record.id"> |
| | | <div class="record-header"> |
| | | <span class="record-date">{{ record.date }}</span> |
| | | <el-tag :type="record.type === 'inspection' ? 'primary' : 'success'" size="small"> |
| | | {{ record.type === 'inspection' ? 'æ£éª' : 'ç»´æ¤' }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="record-content"> |
| | | <div class="record-title">{{ record.title }}</div> |
| | | <div class="record-desc">{{ record.description }}</div> |
| | | <div class="record-operator">æä½äººï¼{{ record.operator }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- ç¼è¾åºæ¬ä¿¡æ¯å¼¹çª --> |
| | | <el-dialog v-model="basicInfoDialogVisible" title="ç¼è¾åºæ¬ä¿¡æ¯" width="600px"> |
| | | <el-form :model="editBasicInfo" label-width="120px"> |
| | | <el-form-item label="å¨ç½ç¼å·"> |
| | | <el-input v-model="editBasicInfo.tankCode" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¨ç½åç§°"> |
| | | <el-input v-model="editBasicInfo.tankName" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¨ç½ç±»å"> |
| | | <el-select v-model="editBasicInfo.tankType" style="width: 100%"> |
| | | <el-option label="æ¶²åæ°ä½å¨ç½" value="æ¶²åæ°ä½å¨ç½" /> |
| | | <el-option label="åå容å¨" value="åå容å¨" /> |
| | | <el-option label="常åå¨ç½" value="常åå¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设计åå"> |
| | | <el-input-number v-model="editBasicInfo.designPressure" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥ä½åå"> |
| | | <el-input-number v-model="editBasicInfo.workingPressure" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="容积"> |
| | | <el-input-number v-model="editBasicInfo.volume" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="basicInfoDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveBasicInfo">ä¿å</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ·»å ç»´æ¤è®°å½å¼¹çª --> |
| | | <el-dialog v-model="maintenanceDialogVisible" title="æ·»å ç»´æ¤è®°å½" width="600px"> |
| | | <el-form :model="newMaintenanceRecord" label-width="120px"> |
| | | <el-form-item label="è®°å½ç±»å"> |
| | | <el-select v-model="newMaintenanceRecord.type" style="width: 100%"> |
| | | <el-option label="æ£éª" value="inspection" /> |
| | | <el-option label="ç»´æ¤" value="maintenance" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ é¢"> |
| | | <el-input v-model="newMaintenanceRecord.title" /> |
| | | </el-form-item> |
| | | <el-form-item label="æè¿°"> |
| | | <el-input type="textarea" v-model="newMaintenanceRecord.description" :rows="3" /> |
| | | </el-form-item> |
| | | <el-form-item label="æä½äºº"> |
| | | <el-input v-model="newMaintenanceRecord.operator" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="maintenanceDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveMaintenanceRecord">ä¿å</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | |
| | | // åºæ¬ä¿¡æ¯ |
| | | const basicInfo = reactive({ |
| | | tankCode: 'GT001', |
| | | tankName: 'æ¶²åæ°å¨ç½A', |
| | | tankType: 'æ¶²åæ°ä½å¨ç½', |
| | | designPressure: 1.6, |
| | | workingPressure: 0.8, |
| | | volume: 100.5 |
| | | }) |
| | | |
| | | // çæµåæ° |
| | | const monitoringData = reactive({ |
| | | pressure: 0.8, |
| | | pressureStatus: 'normal', |
| | | temperature: 25.5, |
| | | temperatureStatus: 'normal', |
| | | gasConcentration: 0.1, |
| | | gasStatus: 'normal', |
| | | flow: 15.2, |
| | | flowStatus: 'normal' |
| | | }) |
| | | |
| | | // å®å
¨è£
ç½® |
| | | const safetyDevices = ref([ |
| | | { name: 'å®å
¨é', status: 'normal' }, |
| | | { name: 'ååä¼ æå¨', status: 'normal' }, |
| | | { name: 'æ¸©åº¦ä¼ æå¨', status: 'normal' }, |
| | | { name: 'æ°ä½æ£æµå¨', status: 'normal' }, |
| | | { name: 'çç ´ç', status: 'normal' }, |
| | | { name: 'æ³åè£
ç½®', status: 'normal' } |
| | | ]) |
| | | |
| | | // ç»´æ¤è®°å½ |
| | | const maintenanceRecords = ref([ |
| | | { |
| | | id: 1, |
| | | date: '2024-01-15', |
| | | type: 'inspection', |
| | | title: '年度æ£éª', |
| | | description: 'æç
§TSG 21-2016æ åè¿è¡å¹´åº¦æ£éªï¼è®¾å¤ç¶æè¯å¥½', |
| | | operator: 'å¼ å·¥ç¨å¸' |
| | | }, |
| | | { |
| | | id: 2, |
| | | date: '2024-02-20', |
| | | type: 'maintenance', |
| | | title: 'å®å
¨éç»´æ¤', |
| | | description: 'æ´æ¢å®å
¨éå¯å°åï¼æ ¡ååå设å®å¼', |
| | | operator: 'ææå¸' |
| | | }, |
| | | { |
| | | id: 3, |
| | | date: '2024-03-10', |
| | | type: 'inspection', |
| | | title: 'ååæµè¯', |
| | | description: 'è¿è¡åå容卿°´åè¯éªï¼ç¬¦åè®¾è®¡è¦æ±', |
| | | operator: 'çæ£éªå' |
| | | } |
| | | ]) |
| | | |
| | | // å¼¹çªæ§å¶ |
| | | const basicInfoDialogVisible = ref(false) |
| | | const maintenanceDialogVisible = ref(false) |
| | | |
| | | // ç¼è¾è¡¨åæ°æ® |
| | | const editBasicInfo = reactive({ ...basicInfo }) |
| | | const newMaintenanceRecord = reactive({ |
| | | type: 'inspection', |
| | | title: '', |
| | | description: '', |
| | | operator: '' |
| | | }) |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | const getStatusClass = (status) => { |
| | | return status === 'normal' ? 'status-normal' : 'status-warning' |
| | | } |
| | | |
| | | // æ°å¢å¨ç½ |
| | | const addTank = () => { |
| | | ElMessage.success('æ°å¢å¨ç½åè½') |
| | | } |
| | | |
| | | // å¯¼åºæ°æ® |
| | | const exportData = () => { |
| | | ElMessage.success('å¯¼åºæå') |
| | | } |
| | | |
| | | // ç¼è¾åºæ¬ä¿¡æ¯ |
| | | const handleEditBasicInfo = () => { |
| | | Object.assign(editBasicInfo, basicInfo) |
| | | basicInfoDialogVisible.value = true |
| | | } |
| | | |
| | | // ä¿ååºæ¬ä¿¡æ¯ |
| | | const saveBasicInfo = () => { |
| | | Object.assign(basicInfo, editBasicInfo) |
| | | basicInfoDialogVisible.value = false |
| | | ElMessage.success('ä¿åæå') |
| | | } |
| | | |
| | | // å·æ°çæµæ°æ® |
| | | const refreshMonitoring = () => { |
| | | // æ¨¡ææ°æ®æ´æ° |
| | | monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2) |
| | | monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1) |
| | | monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2) |
| | | monitoringData.flow = (Math.random() * 10 + 10).toFixed(1) |
| | | ElMessage.success('æ°æ®å·²å·æ°') |
| | | } |
| | | |
| | | // æ£æ¥å®å
¨è£
ç½® |
| | | const checkSafetyDevices = () => { |
| | | // æ¨¡ææ£æ¥è¿ç¨ |
| | | safetyDevices.value.forEach(device => { |
| | | device.status = Math.random() > 0.1 ? 'normal' : 'warning' |
| | | }) |
| | | ElMessage.success('å®å
¨è£
ç½®æ£æ¥å®æ') |
| | | } |
| | | |
| | | // æ·»å ç»´æ¤è®°å½ |
| | | const addMaintenanceRecord = () => { |
| | | newMaintenanceRecord.type = 'inspection' |
| | | newMaintenanceRecord.title = '' |
| | | newMaintenanceRecord.description = '' |
| | | newMaintenanceRecord.operator = '' |
| | | maintenanceDialogVisible.value = true |
| | | } |
| | | |
| | | // ä¿åç»´æ¤è®°å½ |
| | | const saveMaintenanceRecord = () => { |
| | | const record = { |
| | | id: Date.now(), |
| | | date: new Date().toISOString().split('T')[0], |
| | | ...newMaintenanceRecord |
| | | } |
| | | maintenanceRecords.value.unshift(record) |
| | | maintenanceDialogVisible.value = false |
| | | ElMessage.success('è®°å½æ·»å æå') |
| | | } |
| | | |
| | | // 模æå®æ¶æ°æ®æ´æ° |
| | | onMounted(() => { |
| | | setInterval(() => { |
| | | monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2) |
| | | monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1) |
| | | monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2) |
| | | monitoringData.flow = (Math.random() * 10 + 10).toFixed(1) |
| | | }, 5000) |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | background: #f5f5f5; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: white; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | |
| | | h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | |
| | | .modules-container { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 20px; |
| | | } |
| | | |
| | | .module-card { |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | .info-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | |
| | | label { |
| | | font-weight: bold; |
| | | color: #606266; |
| | | } |
| | | |
| | | span { |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .monitoring-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .monitor-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 2px solid transparent; |
| | | |
| | | .monitor-label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .monitor-value { |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | margin-bottom: 5px; |
| | | |
| | | &.status-normal { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | &.status-warning { |
| | | color: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .monitor-status { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .safety-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .safety-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 2px solid transparent; |
| | | |
| | | .device-icon { |
| | | margin-right: 15px; |
| | | } |
| | | |
| | | .device-info { |
| | | flex: 1; |
| | | |
| | | .device-name { |
| | | font-weight: bold; |
| | | color: #303133; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .device-status { |
| | | font-size: 12px; |
| | | padding: 2px 8px; |
| | | border-radius: 10px; |
| | | display: inline-block; |
| | | |
| | | &.normal { |
| | | background: #f0f9ff; |
| | | color: #409eff; |
| | | } |
| | | |
| | | &.warning { |
| | | background: #fef7e0; |
| | | color: #e6a23c; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .maintenance-list { |
| | | max-height: 300px; |
| | | overflow-y: auto; |
| | | |
| | | .maintenance-item { |
| | | padding: 15px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | margin-bottom: 10px; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .record-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .record-date { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .record-content { |
| | | .record-title { |
| | | font-weight: bold; |
| | | color: #303133; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .record-desc { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .record-operator { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ååºå¼è®¾è®¡ |
| | | @media (max-width: 1200px) { |
| | | .modules-container { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .info-grid, |
| | | .monitoring-grid, |
| | | .safety-grid { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢è¡¨å --> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="卿°ç½åç§°ï¼"> |
| | | <el-input v-model="searchForm.tankName" placeholder="请è¾å
¥å¨æ°ç½åç§°" clearable style="width: 200px" /> |
| | | </el-form-item> |
| | | <el-form-item label="卿°ç½ç±»åï¼"> |
| | | <el-select v-model="searchForm.tankType" placeholder="è¯·éæ©å¨æ°ç½ç±»å" clearable style="width: 200px"> |
| | | <el-option label="æ¶²åæ°å¨ç½" value="æ¶²åæ°å¨ç½" /> |
| | | <el-option label="å缩æ°å¨ç½" value="å缩æ°å¨ç½" /> |
| | | <el-option label="å¤©ç¶æ°å¨ç½" value="å¤©ç¶æ°å¨ç½" /> |
| | | <el-option label="æ°§æ°å¨ç½" value="æ°§æ°å¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="é¢è¦ç±»åï¼"> |
| | | <el-select v-model="searchForm.warningType" placeholder="è¯·éæ©é¢è¦ç±»å" clearable style="width: 200px"> |
| | | <el-option label="æ°ä½ä¸è¶³" value="æ°ä½ä¸è¶³" /> |
| | | <el-option label="ååå¼å¸¸" value="ååå¼å¸¸" /> |
| | | <el-option label="温度å¼å¸¸" value="温度å¼å¸¸" /> |
| | | <el-option label="æ³æ¼é¢è¦" value="æ³æ¼é¢è¦" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="é¢è¦çº§å«ï¼"> |
| | | <el-select v-model="searchForm.warningLevel" placeholder="è¯·éæ©é¢è¦çº§å«" clearable style="width: 200px"> |
| | | <el-option label="ç´§æ¥" value="ç´§æ¥" /> |
| | | <el-option label="éè¦" value="éè¦" /> |
| | | <el-option label="ä¸è¬" value="ä¸è¬" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | <el-button @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- æ°æ®è¡¨æ ¼ --> |
| | | <div class="table_list"> |
| | | <!-- æä½æé® --> |
| | | <div class="table-operations"> |
| | | <el-button type="primary" @click="handleAdd">æ°å¢é¢è¦è§å</el-button> |
| | | <el-button type="success" @click="handleBatchProcess">æ¹éå¤ç</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | style="width: 100%" |
| | | height="calc(100vh - 280px)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | |
| | | <!-- åºç¡ä¿¡æ¯å段 --> |
| | | <el-table-column label="卿°ç½ç¼ç " prop="tankCode" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="卿°ç½åç§°" prop="tankName" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="卿°ç½ç±»å" prop="tankType" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="容积(m³)" prop="volume" width="100" show-overflow-tooltip /> |
| | | |
| | | <!-- åºåç¸å
³å段 --> |
| | | <el-table-column label="å½åæ°ä½é" prop="currentGasLevel" width="120" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <span :class="getGasLevelClass(scope.row)">{{ scope.row.currentGasLevel }}%</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å®å
¨æ°ä½é" prop="safetyGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æä½æ°ä½é" prop="minGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æé«æ°ä½é" prop="maxGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="å½ååå(MPa)" prop="currentPressure" width="140" show-overflow-tooltip /> |
| | | |
| | | <!-- é¢è¦è§ååæ®µ --> |
| | | <el-table-column label="é¢è¦ç±»å" prop="warningType" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag :type="getWarningTypeTag(scope.row.warningType)"> |
| | | {{ scope.row.warningType }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é¢è¦çº§å«" prop="warningLevel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag :type="getWarningLevelTag(scope.row.warningLevel)"> |
| | | {{ scope.row.warningLevel }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é¢è¦éå¼" prop="warningThreshold" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯å¦å¯ç¨" prop="isEnabled" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- æ¶é´ç¸å
³å段 --> |
| | | <el-table-column label="é¢è¦æ¶é´" prop="warningTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è¦æç»å¤©æ°" prop="warningDuration" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æåæ´æ°æ¶é´" prop="lastUpdateTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è®¡å
è£
æ¶é´" prop="expectedRefillTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è®¡ç¼ºæ°æ¶é´" prop="expectedShortageTime" width="150" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div v-if="scope.row.expectedShortageTime"> |
| | | <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired"> |
| | | <el-tag type="danger">已缺æ°</el-tag> |
| | | </div> |
| | | <div v-else class="countdown-timer"> |
| | | <span :class="getCountdownClass(scope.row.expectedShortageTime)"> |
| | | {{ getCountdown(scope.row.expectedShortageTime).text }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- æä½å --> |
| | | <el-table-column fixed="right" label="æä½" width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="success" size="small" @click="handleProcess(scope.row)">å¤ç</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾é¢è¦è§åå¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢é¢è¦è§å' : 'ç¼è¾é¢è¦è§å'" |
| | | width="50%" |
| | | @close="closeDialog" |
| | | > |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="140px"> |
| | | <el-row :gutter="20"> |
| | | <!-- åºç¡ä¿¡æ¯ --> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½ç¼ç ï¼" prop="tankCode"> |
| | | <el-input v-model="form.tankCode" placeholder="请è¾å
¥å¨æ°ç½ç¼ç " /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½åç§°ï¼" prop="tankName"> |
| | | <el-input v-model="form.tankName" placeholder="请è¾å
¥å¨æ°ç½åç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½ç±»åï¼" prop="tankType"> |
| | | <el-select v-model="form.tankType" placeholder="è¯·éæ©å¨æ°ç½ç±»å" style="width: 100%"> |
| | | <el-option label="æ¶²åæ°å¨ç½" value="æ¶²åæ°å¨ç½" /> |
| | | <el-option label="å缩æ°å¨ç½" value="å缩æ°å¨ç½" /> |
| | | <el-option label="å¤©ç¶æ°å¨ç½" value="å¤©ç¶æ°å¨ç½" /> |
| | | <el-option label="æ°§æ°å¨ç½" value="æ°§æ°å¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="specificationModel"> |
| | | <el-input v-model="form.specificationModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="容积(m³)ï¼" prop="volume"> |
| | | <el-input-number v-model="form.volume" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½åæ°ä½é(%)ï¼" prop="currentGasLevel"> |
| | | <el-input-number v-model="form.currentGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- åºåç¸å
³ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®å
¨æ°ä½é(%)ï¼" prop="safetyGasLevel"> |
| | | <el-input-number v-model="form.safetyGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æä½æ°ä½é(%)ï¼" prop="minGasLevel"> |
| | | <el-input-number v-model="form.minGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æé«æ°ä½é(%)ï¼" prop="maxGasLevel"> |
| | | <el-input-number v-model="form.maxGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½ååå(MPa)ï¼" prop="currentPressure"> |
| | | <el-input-number v-model="form.currentPressure" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- é¢è¦è§å --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦ç±»åï¼" prop="warningType"> |
| | | <el-select v-model="form.warningType" placeholder="è¯·éæ©é¢è¦ç±»å" style="width: 100%"> |
| | | <el-option label="æ°ä½ä¸è¶³" value="æ°ä½ä¸è¶³" /> |
| | | <el-option label="ååå¼å¸¸" value="ååå¼å¸¸" /> |
| | | <el-option label="温度å¼å¸¸" value="温度å¼å¸¸" /> |
| | | <el-option label="æ³æ¼é¢è¦" value="æ³æ¼é¢è¦" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦çº§å«ï¼" prop="warningLevel"> |
| | | <el-select v-model="form.warningLevel" placeholder="è¯·éæ©é¢è¦çº§å«" style="width: 100%"> |
| | | <el-option label="ç´§æ¥" value="ç´§æ¥" /> |
| | | <el-option label="éè¦" value="éè¦" /> |
| | | <el-option label="ä¸è¬" value="ä¸è¬" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦éå¼ï¼" prop="warningThreshold"> |
| | | <el-input-number v-model="form.warningThreshold" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦å¯ç¨ï¼" prop="isEnabled"> |
| | | <el-switch v-model="form.isEnabled" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æ¶é´ç¸å
³ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦æ¶é´ï¼" prop="warningTime"> |
| | | <el-date-picker |
| | | v-model="form.warningTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è¦æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è®¡å
è£
æ¶é´ï¼" prop="expectedRefillTime"> |
| | | <el-date-picker |
| | | v-model="form.expectedRefillTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è®¡å
è£
æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è®¡ç¼ºæ°æ¶é´ï¼" prop="expectedShortageTime"> |
| | | <el-date-picker |
| | | v-model="form.expectedShortageTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è®¡ç¼ºæ°æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦è§åæè¿°ï¼" prop="warningRule"> |
| | | <el-input |
| | | v-model="form.warningRule" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥é¢è¦è§åæè¿°" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 缺æ°é¢è¦å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="shortageWarningVisible" |
| | | title="â ï¸ ç¼ºæ°é¢è¦" |
| | | width="400px" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | :show-close="false" |
| | | > |
| | | <div class="shortage-warning-content"> |
| | | <div class="warning-icon"> |
| | | <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon> |
| | | </div> |
| | | <div class="warning-message"> |
| | | <h3>{{ currentWarningTank.tankName }}</h3> |
| | | <p>卿°ç½å·²ç¼ºæ°ï¼è¯·åæ¶å¤çï¼</p> |
| | | <p class="warning-details"> |
| | | 卿°ç½ç¼ç ï¼{{ currentWarningTank.tankCode }}<br> |
| | | 卿°ç½ç±»åï¼{{ currentWarningTank.tankType }}<br> |
| | | å½åæ°ä½éï¼{{ currentWarningTank.currentGasLevel }}% |
| | | </p> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleShortageWarning">ç«å³å¤ç</el-button> |
| | | <el-button @click="closeShortageWarning">ç¨åå¤ç</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 缺æ°é¢è¦å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="shortageWarningVisible" |
| | | title="â ï¸ ç¼ºæ°é¢è¦" |
| | | width="400px" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | :show-close="false" |
| | | > |
| | | <div class="shortage-warning-content"> |
| | | <div class="warning-icon"> |
| | | <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon> |
| | | </div> |
| | | <div class="warning-message"> |
| | | <h3>{{ currentWarningTank.tankName }}</h3> |
| | | <p>卿°ç½å·²ç¼ºæ°ï¼è¯·åæ¶å¤çï¼</p> |
| | | <p class="warning-details"> |
| | | 卿°ç½ç¼ç ï¼{{ currentWarningTank.tankCode }}<br> |
| | | 卿°ç½ç±»åï¼{{ currentWarningTank.tankType }}<br> |
| | | å½åæ°ä½éï¼{{ currentWarningTank.currentGasLevel }}% |
| | | </p> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleShortageWarning">ç«å³å¤ç</el-button> |
| | | <el-button @click="closeShortageWarning">ç¨åå¤ç</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, onUnmounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { WarningFilled } from '@element-plus/icons-vue' |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | // 注éæAPI导å
¥ï¼ä½¿ç¨åæ°æ® |
| | | // import { |
| | | // getStockWarningPage, |
| | | // addStockWarning, |
| | | // updateStockWarning, |
| | | // deleteStockWarning, |
| | | // batchProcessStockWarning, |
| | | // exportStockWarning, |
| | | // toggleStockWarningStatus |
| | | // } from '@/api/inventoryManagement/stockWarning.js' |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | const selectedRows = ref([]) |
| | | const dialogFormVisible = ref(false) |
| | | const operationType = ref('add') |
| | | const total = ref(0) |
| | | |
| | | // 缺æ°é¢è¦ç¸å
³ |
| | | const shortageWarningVisible = ref(false) |
| | | const currentWarningTank = ref({}) |
| | | const countdownTimer = ref(null) |
| | | |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | tankName: '', |
| | | tankType: '', |
| | | warningType: '', |
| | | warningLevel: '' |
| | | }) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | id: null, |
| | | tankCode: '', |
| | | tankName: '', |
| | | tankType: '', |
| | | specificationModel: '', |
| | | volume: 0, |
| | | currentGasLevel: 0, |
| | | safetyGasLevel: 0, |
| | | minGasLevel: 0, |
| | | maxGasLevel: 0, |
| | | currentPressure: 0, |
| | | warningType: '', |
| | | warningLevel: '', |
| | | warningThreshold: 0, |
| | | isEnabled: true, |
| | | warningTime: '', |
| | | warningDuration: 0, |
| | | lastUpdateTime: '', |
| | | expectedRefillTime: '', |
| | | expectedShortageTime: '', |
| | | warningRule: '' |
| | | }) |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | tankCode: [{ required: true, message: '请è¾å
¥å¨æ°ç½ç¼ç ', trigger: 'blur' }], |
| | | tankName: [{ required: true, message: '请è¾å
¥å¨æ°ç½åç§°', trigger: 'blur' }], |
| | | tankType: [{ required: true, message: 'è¯·éæ©å¨æ°ç½ç±»å', trigger: 'change' }], |
| | | warningType: [{ required: true, message: 'è¯·éæ©é¢è¦ç±»å', trigger: 'change' }], |
| | | warningLevel: [{ required: true, message: 'è¯·éæ©é¢è¦çº§å«', trigger: 'change' }], |
| | | warningThreshold: [{ required: true, message: '请è¾å
¥é¢è¦éå¼', trigger: 'blur' }] |
| | | } |
| | | |
| | | // è·åå计æ¶ä¿¡æ¯ |
| | | const getCountdown = (expectedTime) => { |
| | | if (!expectedTime) return { text: '-', isExpired: false } |
| | | |
| | | const now = new Date().getTime() |
| | | const expected = new Date(expectedTime).getTime() |
| | | const diff = expected - now |
| | | |
| | | if (diff <= 0) { |
| | | return { text: '已缺æ°', isExpired: true } |
| | | } |
| | | |
| | | const days = Math.floor(diff / (1000 * 60 * 60 * 24)) |
| | | const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) |
| | | const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)) |
| | | |
| | | if (days > 0) { |
| | | return { text: `${days}天${hours}å°æ¶`, isExpired: false } |
| | | } else if (hours > 0) { |
| | | return { text: `${hours}å°æ¶${minutes}åé`, isExpired: false } |
| | | } else { |
| | | return { text: `${minutes}åé`, isExpired: false } |
| | | } |
| | | } |
| | | |
| | | // è·ååè®¡æ¶æ ·å¼ç±» |
| | | const getCountdownClass = (expectedTime) => { |
| | | if (!expectedTime) return '' |
| | | |
| | | const now = new Date().getTime() |
| | | const expected = new Date(expectedTime).getTime() |
| | | const diff = expected - now |
| | | |
| | | if (diff <= 0) { |
| | | return 'countdown-expired' |
| | | } else if (diff <= 24 * 60 * 60 * 1000) { // 24å°æ¶å
|
| | | return 'countdown-urgent' |
| | | } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7天å
|
| | | return 'countdown-warning' |
| | | } else { |
| | | return 'countdown-normal' |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥ç¼ºæ°é¢è¦ |
| | | const checkShortageWarnings = () => { |
| | | tableData.value.forEach(tank => { |
| | | if (tank.expectedShortageTime) { |
| | | const countdown = getCountdown(tank.expectedShortageTime) |
| | | if (countdown.isExpired && !tank.warningShown) { |
| | | // æ è®°å·²æ¾ç¤ºé¢è¦ï¼é¿å
éå¤å¼¹æ¡ |
| | | tank.warningShown = true |
| | | showShortageWarning(tank) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æ¾ç¤ºç¼ºæ°é¢è¦å¼¹æ¡ |
| | | const showShortageWarning = (tank) => { |
| | | currentWarningTank.value = tank |
| | | shortageWarningVisible.value = true |
| | | |
| | | // ææ¾æç¤ºé³ï¼å¯éï¼ |
| | | // const audio = new Audio('/path/to/warning-sound.mp3') |
| | | // audio.play() |
| | | } |
| | | |
| | | // å¤ç缺æ°é¢è¦ |
| | | const handleShortageWarning = () => { |
| | | ElMessage.success(`æ£å¨å¤ç卿°ç½ ${currentWarningTank.value.tankName} ç缺æ°é®é¢`) |
| | | shortageWarningVisible.value = false |
| | | // è¿éå¯ä»¥è°ç¨å¤çAPI |
| | | } |
| | | // å¤ç缺æ°é¢è¦ |
| | | const closeShortageWarning = () => { |
| | | // ElMessage.success(`æ£å¨å¤ç卿°ç½ ${currentWarningTank.value.tankName} ç缺æ°é®é¢`) |
| | | shortageWarningVisible.value = false |
| | | // è¿éå¯ä»¥è°ç¨å¤çAPI |
| | | } |
| | | |
| | | |
| | | |
| | | // çæåæ°æ® |
| | | const generateMockData = () => { |
| | | const mockData = [ |
| | | { |
| | | id: 1, |
| | | tankCode: 'TANK001', |
| | | tankName: 'æ¶²åæ°å¨ç½A', |
| | | tankType: 'æ¶²åæ°å¨ç½', |
| | | specificationModel: 'LPG-5000L', |
| | | volume: 5000, |
| | | currentGasLevel: 15, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 95, |
| | | currentPressure: 2.5, |
| | | warningType: 'æ°ä½ä¸è¶³', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 20, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 08:30:00', |
| | | warningDuration: 3, |
| | | lastUpdateTime: '2024-01-15 10:00:00', |
| | | expectedRefillTime: '2024-01-16 14:00:00', |
| | | expectedShortageTime: '2024-01-15 18:30:00', // ä»å¤©ä¸å6:30ç¼ºæ° |
| | | warningRule: '彿°ä½éä½äº20%æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 2, |
| | | tankCode: 'TANK002', |
| | | tankName: 'å缩æ°å¨ç½B', |
| | | tankType: 'å缩æ°å¨ç½', |
| | | specificationModel: 'COMP-3000L', |
| | | volume: 3000, |
| | | currentGasLevel: 45, |
| | | safetyGasLevel: 25, |
| | | minGasLevel: 15, |
| | | maxGasLevel: 90, |
| | | currentPressure: 8.2, |
| | | warningType: 'ååå¼å¸¸', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 10, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-14 16:20:00', |
| | | warningDuration: 2, |
| | | lastUpdateTime: '2024-01-15 09:15:00', |
| | | expectedRefillTime: '2024-01-17 09:00:00', |
| | | expectedShortageTime: '2024-01-18 12:00:00', // 3天åç¼ºæ° |
| | | warningRule: 'å½ååè¶
è¿8MPaæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 3, |
| | | tankCode: 'TANK003', |
| | | tankName: 'å¤©ç¶æ°å¨ç½C', |
| | | tankType: 'å¤©ç¶æ°å¨ç½', |
| | | specificationModel: 'NG-8000L', |
| | | volume: 8000, |
| | | currentGasLevel: 75, |
| | | safetyGasLevel: 20, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 95, |
| | | currentPressure: 4.8, |
| | | warningType: '温度å¼å¸¸', |
| | | warningLevel: 'ä¸è¬', |
| | | warningThreshold: 5, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-13 11:45:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 08:45:00', |
| | | expectedRefillTime: '2024-01-20 10:00:00', |
| | | expectedShortageTime: '2024-01-22 15:30:00', // 7天åç¼ºæ° |
| | | warningRule: '彿¸©åº¦è¶
è¿60°Cæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 4, |
| | | tankCode: 'TANK004', |
| | | tankName: 'æ°§æ°å¨ç½D', |
| | | tankType: 'æ°§æ°å¨ç½', |
| | | specificationModel: 'O2-2000L', |
| | | volume: 2000, |
| | | currentGasLevel: 8, |
| | | safetyGasLevel: 25, |
| | | minGasLevel: 5, |
| | | maxGasLevel: 90, |
| | | currentPressure: 6.5, |
| | | warningType: 'æ³æ¼é¢è¦', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 15, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 07:15:00', |
| | | warningDuration: 4, |
| | | lastUpdateTime: '2024-01-15 11:30:00', |
| | | expectedRefillTime: '2024-01-15 16:00:00', |
| | | expectedShortageTime: '2024-01-15 14:00:00', // ä»å¤©ä¸å2ç¹ç¼ºæ° |
| | | warningRule: '彿£æµå°æ°ä½æ³æ¼æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 5, |
| | | tankCode: 'TANK005', |
| | | tankName: 'æ¶²åæ°å¨ç½E', |
| | | tankType: 'æ¶²åæ°å¨ç½', |
| | | specificationModel: 'LPG-6000L', |
| | | volume: 6000, |
| | | currentGasLevel: 35, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 15, |
| | | maxGasLevel: 95, |
| | | currentPressure: 3.2, |
| | | warningType: 'æ°ä½ä¸è¶³', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 20, |
| | | isEnabled: false, |
| | | warningTime: '2024-01-14 14:30:00', |
| | | warningDuration: 2, |
| | | lastUpdateTime: '2024-01-15 09:00:00', |
| | | expectedRefillTime: '2024-01-19 08:00:00', |
| | | expectedShortageTime: '2024-01-21 10:00:00', // 6天åç¼ºæ° |
| | | warningRule: '彿°ä½éä½äº20%æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 6, |
| | | tankCode: 'TANK006', |
| | | tankName: 'å缩æ°å¨ç½F', |
| | | tankType: 'å缩æ°å¨ç½', |
| | | specificationModel: 'COMP-4000L', |
| | | volume: 4000, |
| | | currentGasLevel: 85, |
| | | safetyGasLevel: 20, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 90, |
| | | currentPressure: 7.8, |
| | | warningType: 'ååå¼å¸¸', |
| | | warningLevel: 'ä¸è¬', |
| | | warningThreshold: 8, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-12 09:20:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 08:30:00', |
| | | expectedRefillTime: '2024-01-25 14:00:00', |
| | | expectedShortageTime: '2024-01-28 16:00:00', // 13天åç¼ºæ° |
| | | warningRule: 'å½ååè¶
è¿8MPaæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 7, |
| | | tankCode: 'TANK007', |
| | | tankName: 'å¤©ç¶æ°å¨ç½G', |
| | | tankType: 'å¤©ç¶æ°å¨ç½', |
| | | specificationModel: 'NG-10000L', |
| | | volume: 10000, |
| | | currentGasLevel: 92, |
| | | safetyGasLevel: 15, |
| | | minGasLevel: 8, |
| | | maxGasLevel: 95, |
| | | currentPressure: 5.2, |
| | | warningType: '温度å¼å¸¸', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 6, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-11 16:45:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 07:45:00', |
| | | expectedRefillTime: '2024-01-30 09:00:00', |
| | | expectedShortageTime: '2024-02-05 12:00:00', // 21天åç¼ºæ° |
| | | warningRule: '彿¸©åº¦è¶
è¿60°Cæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 8, |
| | | tankCode: 'TANK008', |
| | | tankName: 'æ°§æ°å¨ç½H', |
| | | tankType: 'æ°§æ°å¨ç½', |
| | | specificationModel: 'O2-1500L', |
| | | volume: 1500, |
| | | currentGasLevel: 12, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 8, |
| | | maxGasLevel: 90, |
| | | currentPressure: 4.5, |
| | | warningType: 'æ³æ¼é¢è¦', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 12, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 06:30:00', |
| | | warningDuration: 5, |
| | | lastUpdateTime: '2024-01-15 12:15:00', |
| | | expectedRefillTime: '2024-01-15 20:00:00', |
| | | expectedShortageTime: '2024-01-15 17:30:00', // ä»å¤©ä¸å5:30ç¼ºæ° |
| | | warningRule: '彿£æµå°æ°ä½æ³æ¼æ¶è§¦åé¢è¦' |
| | | } |
| | | ] |
| | | |
| | | // æ ¹æ®æç´¢æ¡ä»¶è¿æ»¤æ°æ® |
| | | let filteredData = mockData.filter(item => { |
| | | if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false |
| | | if (searchForm.tankType && item.tankType !== searchForm.tankType) return false |
| | | if (searchForm.warningType && item.warningType !== searchForm.warningType) return false |
| | | if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false |
| | | return true |
| | | }) |
| | | |
| | | // å页å¤ç |
| | | const start = (page.current - 1) * page.size |
| | | const end = start + page.size |
| | | const paginatedData = filteredData.slice(start, end) |
| | | |
| | | return { |
| | | records: paginatedData, |
| | | total: filteredData.length |
| | | } |
| | | } |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = async () => { |
| | | tableLoading.value = true |
| | | try { |
| | | // 模æç½ç»å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | |
| | | const result = generateMockData() |
| | | tableData.value = result.records |
| | | total.value = result.total |
| | | |
| | | // æ£æ¥ç¼ºæ°é¢è¦ |
| | | checkShortageWarnings() |
| | | } catch (error) { |
| | | console.error('è·åå表失败:', error) |
| | | ElMessage.error('è·åå表失败') |
| | | } finally { |
| | | tableLoading.value = false |
| | | } |
| | | } |
| | | |
| | | // æç´¢ |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // éç½®æç´¢ |
| | | const resetQuery = () => { |
| | | Object.keys(searchForm).forEach(key => { |
| | | searchForm[key] = '' |
| | | }) |
| | | handleQuery() |
| | | } |
| | | |
| | | // å页åå |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page |
| | | page.size = obj.limit |
| | | getList() |
| | | } |
| | | |
| | | // è¡¨æ ¼éæ©åå |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection |
| | | } |
| | | |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetForm() |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(form, row) |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // å¤çé¢è¦ |
| | | const handleProcess = async (row) => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 300)) |
| | | ElMessage.success(`æ£å¨å¤çé¢è¦ï¼${row.tankName}`) |
| | | getList() |
| | | } catch (error) { |
| | | ElMessage.error('å¤çé¢è¦å¤±è´¥') |
| | | } |
| | | } |
| | | |
| | | // å é¤ |
| | | const handleDelete = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm(`ç¡®å®è¦å é¤é¢è¦è§åï¼${row.tankName}åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 300)) |
| | | ElMessage.success('å 餿å') |
| | | getList() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æ¹éå¤ç |
| | | const handleBatchProcess = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | ElMessage.warning('è¯·éæ©è¦å¤ççé¢è¦') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | ElMessage.success(`æ¹éå¤çäº ${selectedRows.value.length} æ¡é¢è¦`) |
| | | getList() |
| | | } catch (error) { |
| | | ElMessage.error('æ¹éå¤ç失败') |
| | | } |
| | | } |
| | | |
| | | // å¯¼åº |
| | | const handleExport = async () => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 800)) |
| | | |
| | | // çæå¯¼åºæ°æ® |
| | | const exportData = generateMockData().records |
| | | const csvContent = generateCSV(exportData) |
| | | |
| | | // å建ä¸è½½é¾æ¥ |
| | | const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }) |
| | | const url = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = url |
| | | link.download = `卿°ç½é¢è¦æ°æ®_${new Date().getTime()}.csv` |
| | | link.click() |
| | | window.URL.revokeObjectURL(url) |
| | | |
| | | ElMessage.success('å¯¼åºæå') |
| | | } catch (error) { |
| | | ElMessage.error('导åºå¤±è´¥') |
| | | } |
| | | } |
| | | |
| | | // çæCSVå
容 |
| | | const generateCSV = (data) => { |
| | | const headers = [ |
| | | '卿°ç½ç¼ç ', '卿°ç½åç§°', '卿°ç½ç±»å', 'è§æ ¼åå·', '容积(m³)', |
| | | 'å½åæ°ä½é(%)', 'å®å
¨æ°ä½é(%)', 'æä½æ°ä½é(%)', 'æé«æ°ä½é(%)', |
| | | 'å½ååå(MPa)', 'é¢è¦ç±»å', 'é¢è¦çº§å«', 'é¢è¦éå¼', 'æ¯å¦å¯ç¨', |
| | | 'é¢è¦æ¶é´', 'é¢è¦æç»å¤©æ°', 'æåæ´æ°æ¶é´', 'é¢è®¡å
è£
æ¶é´', 'é¢è®¡ç¼ºæ°æ¶é´', 'é¢è¦è§åæè¿°' |
| | | ] |
| | | |
| | | const csvRows = [headers.join(',')] |
| | | |
| | | data.forEach(item => { |
| | | const row = [ |
| | | item.tankCode, |
| | | item.tankName, |
| | | item.tankType, |
| | | item.specificationModel, |
| | | item.volume, |
| | | item.currentGasLevel, |
| | | item.safetyGasLevel, |
| | | item.minGasLevel, |
| | | item.maxGasLevel, |
| | | item.currentPressure, |
| | | item.warningType, |
| | | item.warningLevel, |
| | | item.warningThreshold, |
| | | item.isEnabled ? 'æ¯' : 'å¦', |
| | | item.warningTime, |
| | | item.warningDuration, |
| | | item.lastUpdateTime, |
| | | item.expectedRefillTime, |
| | | item.expectedShortageTime, |
| | | item.warningRule |
| | | ] |
| | | csvRows.push(row.join(',')) |
| | | }) |
| | | |
| | | return csvRows.join('\n') |
| | | } |
| | | |
| | | // å¯ç¨ç¶æåå |
| | | const handleEnableChange = async (row) => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 200)) |
| | | ElMessage.success(`${row.tankName} çå¯ç¨ç¶æå·²æ´æ°`) |
| | | } catch (error) { |
| | | ElMessage.error('ç¶ææ´æ°å¤±è´¥') |
| | | // æ¢å¤åç¶æ |
| | | row.isEnabled = !row.isEnabled |
| | | } |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | |
| | | if (operationType.value === 'add') { |
| | | ElMessage.success('æ°å¢æå') |
| | | } else { |
| | | ElMessage.success('ç¼è¾æå') |
| | | } |
| | | |
| | | closeDialog() |
| | | getList() |
| | | } catch (error) { |
| | | if (!error.errors) { |
| | | ElMessage.error(operationType.value === 'add' ? 'æ°å¢å¤±è´¥' : 'ç¼è¾å¤±è´¥') |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹çª |
| | | const closeDialog = () => { |
| | | dialogFormVisible.value = false |
| | | resetForm() |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | Object.keys(form).forEach(key => { |
| | | if (key === 'isEnabled') { |
| | | form[key] = true |
| | | } else if (typeof form[key] === 'number') { |
| | | form[key] = 0 |
| | | } else { |
| | | form[key] = '' |
| | | } |
| | | }) |
| | | proxy.$refs.formRef?.resetFields() |
| | | } |
| | | |
| | | // è·åæ°ä½éæ ·å¼ç±» |
| | | const getGasLevelClass = (row) => { |
| | | if (row.currentGasLevel < row.minGasLevel) { |
| | | return 'text-danger' |
| | | } else if (row.currentGasLevel > row.maxGasLevel) { |
| | | return 'text-warning' |
| | | } |
| | | return 'text-success' |
| | | } |
| | | |
| | | // è·åé¢è¦ç±»åæ ç¾æ ·å¼ |
| | | const getWarningTypeTag = (type) => { |
| | | const typeMap = { |
| | | 'æ°ä½ä¸è¶³': 'danger', |
| | | 'ååå¼å¸¸': 'warning', |
| | | '温度å¼å¸¸': 'info', |
| | | 'æ³æ¼é¢è¦': 'danger' |
| | | } |
| | | return typeMap[type] || 'info' |
| | | } |
| | | |
| | | // è·åé¢è¦çº§å«æ ç¾æ ·å¼ |
| | | const getWarningLevelTag = (level) => { |
| | | const levelMap = { |
| | | 'ç´§æ¥': 'danger', |
| | | 'éè¦': 'warning', |
| | | 'ä¸è¬': 'info' |
| | | } |
| | | return levelMap[level] || 'info' |
| | | } |
| | | |
| | | // å¯å¨å计æ¶å®æ¶å¨ |
| | | const startCountdownTimer = () => { |
| | | countdownTimer.value = setInterval(() => { |
| | | checkShortageWarnings() |
| | | }, 60000) // æ¯å鿣æ¥ä¸æ¬¡ |
| | | } |
| | | |
| | | // 忢å计æ¶å®æ¶å¨ |
| | | const stopCountdownTimer = () => { |
| | | if (countdownTimer.value) { |
| | | clearInterval(countdownTimer.value) |
| | | countdownTimer.value = null |
| | | } |
| | | } |
| | | |
| | | // 页é¢å è½½ |
| | | onMounted(() => { |
| | | getList() |
| | | startCountdownTimer() |
| | | }) |
| | | |
| | | // 页é¢å¸è½½ |
| | | onUnmounted(() => { |
| | | stopCountdownTimer() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | |
| | | .table-operations { |
| | | text-align: right; |
| | | margin-bottom: 20px; |
| | | |
| | | .el-button { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | background: #fff; |
| | | border-radius: 4px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .text-danger { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .text-warning { |
| | | color: #e6a23c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .text-success { |
| | | color: #67c23a; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | // åè®¡æ¶æ ·å¼ |
| | | .countdown-timer { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .countdown-normal { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .countdown-warning { |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | .countdown-urgent { |
| | | color: #f56c6c; |
| | | animation: blink 1s infinite; |
| | | } |
| | | |
| | | .countdown-expired { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | @keyframes blink { |
| | | 0%, 50% { opacity: 1; } |
| | | 51%, 100% { opacity: 0.5; } |
| | | } |
| | | |
| | | // 缺æ°é¢è¦å¼¹æ¡æ ·å¼ |
| | | .shortage-warning-content { |
| | | text-align: center; |
| | | padding: 20px 0; |
| | | |
| | | .warning-icon { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .warning-message { |
| | | h3 { |
| | | color: #f56c6c; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | p { |
| | | margin-bottom: 10px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .warning-details { |
| | | background: #f5f7fa; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | text-align: left; |
| | | font-size: 14px; |
| | | line-height: 1.6; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |