From 64adb432af57444f42c6b6b8236dad80d05927dd Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 13 八月 2025 16:19:52 +0800 Subject: [PATCH] 完成用气管理 --- src/views/energyManagement/gasManagement/index.vue | 624 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 624 insertions(+), 0 deletions(-) diff --git a/src/views/energyManagement/gasManagement/index.vue b/src/views/energyManagement/gasManagement/index.vue new file mode 100644 index 0000000..fbbd9f4 --- /dev/null +++ b/src/views/energyManagement/gasManagement/index.vue @@ -0,0 +1,624 @@ +<template> + <div class="app-container"> + <!-- 椤甸潰鏍囬 --> + <div class="page-header"> + <h2>鐢ㄦ皵绠$悊绯荤粺</h2> + <div class="header-info"> + <span class="update-time">鏈�鍚庢洿鏂帮細{{ lastUpdateTime }}</span> + <el-button type="primary" size="small" @click="refreshData"> + <el-icon><Refresh /></el-icon> + 鍒锋柊鏁版嵁 + </el-button> + </div> + </div> + + <!-- 缁熻鍗$墖鍖哄煙 --> + <div class="stats-cards"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-card class="stat-card"> + <div class="stat-content"> + <div class="stat-icon gas-device"> + <el-icon size="32"><Box /></el-icon> + </div> + <div class="stat-info"> + <div class="stat-value">{{ totalDevices }}</div> + <div class="stat-label">鍦ㄧ敤璁惧</div> + </div> + </div> + </el-card> + </el-col> + <el-col :span="6"> + <el-card class="stat-card"> + <div class="stat-content"> + <div class="stat-icon daily-consumption"> + <el-icon size="32"><TrendCharts /></el-icon> + </div> + <div class="stat-info"> + <div class="stat-value">{{ dailyConsumption }} m鲁</div> + <div class="stat-label">鏃ヨ�楅噺</div> + </div> + </div> + </el-card> + </el-col> + <el-col :span="6"> + <el-card class="stat-card"> + <div class="stat-content"> + <div class="stat-icon monthly-consumption"> + <el-icon size="32"><DataLine /></el-icon> + </div> + <div class="stat-info"> + <div class="stat-value">{{ monthlyConsumption }} m鲁</div> + <div class="stat-label">鏈堣�楅噺</div> + </div> + </div> + </el-card> + </el-col> + <el-col :span="6"> + <el-card class="stat-card"> + <div class="stat-content"> + <div class="stat-icon gas-price"> + <el-icon size="32"><Money /></el-icon> + </div> + <div class="stat-info"> + <div class="stat-value">楼{{ gasUnitPrice }}</div> + <div class="stat-label">姘斾綋鍗曚环</div> + </div> + </div> + </el-card> + </el-col> + </el-row> + </div> + + <!-- 璐圭敤缁熻鍖哄煙 --> + <div class="cost-stats"> + <el-row :gutter="20"> + <el-col :span="12"> + <el-card class="cost-card"> + <template #header> + <div class="card-header"> + <span>鏃ヨ垂鐢ㄧ粺璁�</span> + <el-tag type="success" size="small">浠婃棩</el-tag> + </div> + </template> + <div class="cost-content"> + <div class="cost-main"> + <span class="cost-amount">楼{{ dailyTotalCost.toFixed(2) }}</span> + <span class="cost-unit">鍏�</span> + </div> + <div class="cost-details"> + <div class="cost-item"> + <span>娑堣�楅噺锛�</span> + <span>{{ dailyConsumption }} m鲁</span> + </div> + <div class="cost-item"> + <span>鍗曚环锛�</span> + <span>楼{{ gasUnitPrice }}/m鲁</span> + </div> + </div> + </div> + </el-card> + </el-col> + <el-col :span="12"> + <el-card class="cost-card"> + <template #header> + <div class="card-header"> + <span>鏈堣垂鐢ㄧ粺璁�</span> + <el-tag type="primary" size="small">鏈湀</el-tag> + </div> + </template> + <div class="cost-content"> + <div class="cost-main"> + <span class="cost-amount">楼{{ monthlyTotalCost.toFixed(2) }}</span> + <span class="cost-unit">鍏�</span> + </div> + <div class="cost-details"> + <div class="cost-item"> + <span>娑堣�楅噺锛�</span> + <span>{{ monthlyConsumption }} m鲁</span> + </div> + <div class="cost-item"> + <span>骞冲潎鍗曚环锛�</span> + <span>楼{{ gasUnitPrice }}/m鲁</span> + </div> + </div> + </div> + </el-card> + </el-col> + </el-row> + </div> + + <!-- 璁惧鍒楄〃鍖哄煙 --> + <div class="device-section"> + <el-card> + <template #header> + <div class="card-header"> + <span>璁惧鐩戞帶</span> + <div class="header-actions"> + <el-button type="primary" size="small" @click="addDevice"> + <el-icon><Plus /></el-icon> + 娣诲姞璁惧 + </el-button> + </div> + </div> + </template> + + <el-table :data="deviceList" border style="width: 100%" v-loading="tableLoading"> + <el-table-column align="center" label="搴忓彿" type="index" width="60" /> + <el-table-column label="璁惧缂栧彿" prop="deviceCode" width="120" show-overflow-tooltip /> + <el-table-column label="璁惧鍚嶇О" prop="deviceName" width="150" show-overflow-tooltip /> + <el-table-column label="璁惧绫诲瀷" prop="deviceType" width="120" show-overflow-tooltip /> + <el-table-column label="瑙勬牸鍨嬪彿" prop="specification" width="150" show-overflow-tooltip /> + <el-table-column label="褰撳墠鍘嬪姏(MPa)" prop="currentPressure" width="130" show-overflow-tooltip> + <template #default="scope"> + <span :class="getPressureClass(scope.row.currentPressure)"> + {{ scope.row.currentPressure }} + </span> + </template> + </el-table-column> + <el-table-column label="褰撳墠娓╁害(鈩�)" prop="currentTemperature" width="130" show-overflow-tooltip> + <template #default="scope"> + <span :class="getTemperatureClass(scope.row.currentTemperature)"> + {{ scope.row.currentTemperature }} + </span> + </template> + </el-table-column> + <el-table-column label="姘斾綋娴撳害(ppm)" prop="gasConcentration" width="140" show-overflow-tooltip> + <template #default="scope"> + <span :class="getConcentrationClass(scope.row.gasConcentration)"> + {{ scope.row.gasConcentration }} + </span> + </template> + </el-table-column> + <el-table-column label="杩愯鐘舵��" prop="status" width="100" show-overflow-tooltip> + <template #default="scope"> + <el-tag :type="getStatusType(scope.row.status)" size="small"> + {{ getStatusText(scope.row.status) }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鏈�鍚庢洿鏂�" prop="lastUpdate" width="160" show-overflow-tooltip /> + <el-table-column label="鎿嶄綔" align="center" width="100" fixed="right"> + <template #default="scope"> + <el-button link size="small" @click="editDevice(scope.row)"> + 缂栬緫 + </el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </div> + + <!-- 娣诲姞/缂栬緫璁惧寮圭獥 --> + <el-dialog v-model="deviceDialogVisible" :title="dialogTitle" width="600px"> + <el-form :model="deviceForm" :rules="deviceRules" ref="deviceFormRef" label-width="120px"> + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="璁惧缂栧彿" prop="deviceCode"> + <el-input v-model="deviceForm.deviceCode" placeholder="璇疯緭鍏ヨ澶囩紪鍙�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="璁惧鍚嶇О" prop="deviceName"> + <el-input v-model="deviceForm.deviceName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="璁惧绫诲瀷" prop="deviceType"> + <el-select v-model="deviceForm.deviceType" placeholder="璇烽�夋嫨璁惧绫诲瀷" style="width: 100%"> + <el-option label="娑插寲姘斿偍缃�" value="娑插寲姘斿偍缃�" /> + <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="specification"> + <el-input v-model="deviceForm.specification" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="璁捐鍘嬪姏(MPa)" prop="designPressure"> + <el-input-number v-model="deviceForm.designPressure" :min="0" :precision="2" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="瀹圭Н(m鲁)" prop="volume"> + <el-input-number v-model="deviceForm.volume" :min="0" :precision="2" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <el-button @click="deviceDialogVisible = false">鍙栨秷</el-button> + <el-button type="primary" @click="saveDevice">淇濆瓨</el-button> + </template> + </el-dialog> + </div> +</template> + +<script setup> +import { ref, reactive, onMounted, onUnmounted } from 'vue' +import { ElMessage, ElMessageBox } from 'element-plus' +import { + Refresh, + Box, + TrendCharts, + DataLine, + Money, + Plus +} from '@element-plus/icons-vue' + +// 鍝嶅簲寮忔暟鎹� +const lastUpdateTime = ref('') +const totalDevices = ref(0) +const dailyConsumption = ref(0) +const monthlyConsumption = ref(0) +const gasUnitPrice = ref(0) +const dailyTotalCost = ref(0) +const monthlyTotalCost = ref(0) +const deviceList = ref([]) +const tableLoading = ref(false) +const deviceDialogVisible = ref(false) +const dialogTitle = ref('') +const deviceFormRef = ref() + +// 璁惧琛ㄥ崟鏁版嵁 +const deviceForm = reactive({ + deviceCode: '', + deviceName: '', + deviceType: '', + specification: '', + designPressure: 0, + volume: 0 +}) + +// 琛ㄥ崟楠岃瘉瑙勫垯 +const deviceRules = { + deviceCode: [{ required: true, message: '璇疯緭鍏ヨ澶囩紪鍙�', trigger: 'blur' }], + deviceName: [{ required: true, message: '璇疯緭鍏ヨ澶囧悕绉�', trigger: 'blur' }], + deviceType: [{ required: true, message: '璇烽�夋嫨璁惧绫诲瀷', trigger: 'change' }], + specification: [{ required: true, message: '璇疯緭鍏ヨ鏍煎瀷鍙�', trigger: 'blur' }], + designPressure: [{ required: true, message: '璇疯緭鍏ヨ璁″帇鍔�', trigger: 'blur' }], + volume: [{ required: true, message: '璇疯緭鍏ュ绉�', trigger: 'blur' }] +} + +// 瀹氭椂鍣� +let updateTimer = null + +// 妯℃嫙鏁版嵁鐢熸垚 +const generateMockData = () => { + // 鏇存柊缁熻鏁版嵁 + totalDevices.value = Math.floor(Math.random() * 10) + 15 // 15-25鍙拌澶� + dailyConsumption.value = Math.floor(Math.random() * 100) + 200 // 200-300 m鲁 + monthlyConsumption.value = Math.floor(Math.random() * 2000) + 5000 // 5000-7000 m鲁 + gasUnitPrice.value = (Math.random() * 2 + 3).toFixed(2) // 3-5鍏�/m鲁 + + // 璁$畻璐圭敤 + dailyTotalCost.value = dailyConsumption.value * gasUnitPrice.value + monthlyTotalCost.value = monthlyConsumption.value * gasUnitPrice.value + + // 鏇存柊璁惧鍒楄〃鏁版嵁 + deviceList.value = Array.from({ length: totalDevices.value }, (_, index) => ({ + id: index + 1, + deviceCode: `GT${String(index + 1).padStart(3, '0')}`, + deviceName: `鍌ㄦ皵缃�${index + 1}`, + deviceType: ['娑插寲姘斿偍缃�', '鍘嬬缉姘斿偍缃�', '澶╃劧姘斿偍缃�', '姘ф皵鍌ㄧ綈'][Math.floor(Math.random() * 4)], + specification: `${Math.floor(Math.random() * 50) + 50}m鲁`, + currentPressure: (Math.random() * 2 + 0.5).toFixed(2), + currentTemperature: (Math.random() * 20 + 15).toFixed(1), + gasConcentration: (Math.random() * 10).toFixed(2), + status: ['running', 'stopped', 'warning', 'error'][Math.floor(Math.random() * 4)], + lastUpdate: new Date().toLocaleString() + })) + + // 鏇存柊鏈�鍚庢洿鏂版椂闂� + lastUpdateTime.value = new Date().toLocaleString() +} + +// 鑾峰彇鍘嬪姏鐘舵�佹牱寮� +const getPressureClass = (pressure) => { + const p = parseFloat(pressure) + if (p < 0.8) return 'pressure-low' + if (p > 1.5) return 'pressure-high' + return 'pressure-normal' +} + +// 鑾峰彇娓╁害鐘舵�佹牱寮� +const getTemperatureClass = (temperature) => { + const t = parseFloat(temperature) + if (t < 10 || t > 35) return 'temperature-warning' + return 'temperature-normal' +} + +// 鑾峰彇娴撳害鐘舵�佹牱寮� +const getConcentrationClass = (concentration) => { + const c = parseFloat(concentration) + if (c > 5) return 'concentration-warning' + return 'concentration-normal' +} + +// 鑾峰彇鐘舵�佺被鍨� +const getStatusType = (status) => { + const statusMap = { + running: 'success', + stopped: 'info', + warning: 'warning', + error: 'danger' + } + return statusMap[status] || 'info' +} + +// 鑾峰彇鐘舵�佹枃鏈� +const getStatusText = (status) => { + const statusMap = { + running: '杩愯涓�', + stopped: '宸插仠姝�', + warning: '璀﹀憡', + error: '鏁呴殰' + } + return statusMap[status] || '鏈煡' +} + +// 鍒锋柊鏁版嵁 +const refreshData = () => { + generateMockData() + ElMessage.success('鏁版嵁宸插埛鏂�') +} + +// 娣诲姞璁惧 +const addDevice = () => { + dialogTitle.value = '娣诲姞璁惧' + Object.keys(deviceForm).forEach(key => { + deviceForm[key] = key === 'designPressure' || key === 'volume' ? 0 : '' + }) + deviceDialogVisible.value = true +} + +// 缂栬緫璁惧 +const editDevice = (row) => { + dialogTitle.value = '缂栬緫璁惧' + Object.keys(deviceForm).forEach(key => { + if (row[key] !== undefined) { + deviceForm[key] = row[key] + } + }) + deviceDialogVisible.value = true +} + + + +// 淇濆瓨璁惧 +const saveDevice = () => { + deviceFormRef.value.validate((valid) => { + if (valid) { + ElMessage.success('淇濆瓨鎴愬姛') + deviceDialogVisible.value = false + refreshData() + } + }) +} + + + +// 鍚姩瀹氭椂鏇存柊 +const startAutoUpdate = () => { + updateTimer = setInterval(() => { + generateMockData() + }, 60000) // 姣忓垎閽熸洿鏂颁竴娆� +} + +// 鍋滄瀹氭椂鏇存柊 +const stopAutoUpdate = () => { + if (updateTimer) { + clearInterval(updateTimer) + updateTimer = null + } +} + +// 缁勪欢鎸傝浇 +onMounted(() => { + generateMockData() + startAutoUpdate() +}) + +// 缁勪欢鍗歌浇 +onUnmounted(() => { + stopAutoUpdate() +}) +</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; + font-size: 24px; + } + + .header-info { + display: flex; + align-items: center; + gap: 15px; + + .update-time { + color: #909399; + font-size: 14px; + } + } +} + +.stats-cards { + margin-bottom: 20px; + + .stat-card { + .stat-content { + display: flex; + align-items: center; + padding: 10px; + + .stat-icon { + width: 60px; + height: 60px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; + + &.gas-device { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + } + + &.daily-consumption { + background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); + color: white; + } + + &.monthly-consumption { + background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); + color: white; + } + + &.gas-price { + background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); + color: white; + } + } + + .stat-info { + .stat-value { + font-size: 24px; + font-weight: bold; + color: #303133; + line-height: 1; + } + + .stat-label { + font-size: 14px; + color: #909399; + margin-top: 5px; + } + } + } + } +} + +.cost-stats { + margin-bottom: 20px; + + .cost-card { + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + } + + .cost-content { + text-align: center; + padding: 20px 0; + + .cost-main { + margin-bottom: 15px; + + .cost-amount { + font-size: 36px; + font-weight: bold; + color: #409eff; + } + + .cost-unit { + font-size: 16px; + color: #909399; + margin-left: 5px; + } + } + + .cost-details { + .cost-item { + display: flex; + justify-content: space-between; + margin-bottom: 8px; + font-size: 14px; + color: #606266; + + &:last-child { + margin-bottom: 0; + } + } + } + } + } +} + +.device-section { + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + .header-actions { + display: flex; + gap: 10px; + } + } +} + +// 鐘舵�佹牱寮� +.pressure-low { + color: #e6a23c; + font-weight: bold; +} + +.pressure-normal { + color: #67c23a; + font-weight: bold; +} + +.pressure-high { + color: #f56c6c; + font-weight: bold; +} + +.temperature-normal { + color: #67c23a; + font-weight: bold; +} + +.temperature-warning { + color: #e6a23c; + font-weight: bold; +} + +.concentration-normal { + color: #67c23a; + font-weight: bold; +} + +.concentration-warning { + color: #f56c6c; + font-weight: bold; +} +</style> -- Gitblit v1.9.3