| | |
| | | <el-form :model="searchForm" |
| | | :inline="true" |
| | | class="filter-form"> |
| | | <el-form-item label="能耗类型"> |
| | | <!-- <el-form-item label="能耗类型"> |
| | | <el-select v-model="searchForm.energyType" |
| | | placeholder="全部" |
| | | clearable |
| | |
| | | <el-option label="气" |
| | | value="气" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form-item> --> |
| | | <el-form-item label="能耗用途"> |
| | | <el-select v-model="searchForm.energyPurpose" |
| | | placeholder="全部" |
| | | <el-select v-model="searchForm.type" |
| | | placeholder="" |
| | | clearable |
| | | class="w-140" |
| | | @change="handleQuery"> |
| | | <el-option label="全部" |
| | | value="全部" /> |
| | | <el-option label="生产" |
| | | value="生产" /> |
| | | <el-option label="办公" |
| | |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="energyPurpose" |
| | | <el-table-column prop="type" |
| | | label="能耗用途" |
| | | width="100" |
| | | align="center" |
| | |
| | | :filter-method="filterEnergyPurpose" |
| | | filter-placement="bottom-end"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.energyPurpose === '生产' ? 'primary' : 'info'"> |
| | | {{ scope.row.energyPurpose }} |
| | | <el-tag :type="scope.row.type === '生产' ? 'primary' : 'info'"> |
| | | {{ scope.row.type }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | |
| | | // 搜索表单 |
| | | const searchForm = reactive({ |
| | | energyType: "", |
| | | energyPurpose: "", |
| | | // energyType: "", |
| | | type: "", |
| | | dateRange: (() => { |
| | | // 默认最近7天 |
| | | const end = new Date(); |
| | |
| | | const c = Number.parseFloat(r?.cost); |
| | | const cost = Number.isFinite(c) ? c : 0; |
| | | bucket.total += cost; |
| | | if (r?.energyPurpose === "生产") bucket.production += cost; |
| | | if (r?.energyPurpose === "办公") bucket.office += cost; |
| | | if (r?.type === "生产") bucket.production += cost; |
| | | if (r?.type === "办公") bucket.office += cost; |
| | | } |
| | | const times = Array.from(byTime.keys()).sort((a, b) => String(a).localeCompare(String(b))); |
| | | const total = times.map(t => byTime.get(t).total); |
| | |
| | | |
| | | const handleKpiClick = key => { |
| | | selectedKpi.value = key; |
| | | if (key === "all") searchForm.energyPurpose = ""; |
| | | if (key === "production") searchForm.energyPurpose = "生产"; |
| | | if (key === "office") searchForm.energyPurpose = "办公"; |
| | | if (key === "all") searchForm.type = ""; |
| | | if (key === "production") searchForm.type = "生产"; |
| | | if (key === "office") searchForm.type = "办公"; |
| | | page.current = 1; |
| | | handleQuery(); |
| | | }; |
| | |
| | | const a = document.createElement("a"); |
| | | a.href = url; |
| | | const typePart = searchForm.energyType ? `_${searchForm.energyType}` : ""; |
| | | const purposePart = searchForm.energyPurpose ? `_${searchForm.energyPurpose}` : ""; |
| | | const purposePart = searchForm.type ? `_${searchForm.type}` : ""; |
| | | let rangePart = ""; |
| | | if (statisticsType.value === "day") { |
| | | if (searchForm.dateRange?.length === 2) rangePart = `_${searchForm.dateRange[0]}~${searchForm.dateRange[1]}`; |
| | |
| | | ]; |
| | | |
| | | const filterEnergyType = (value, row) => row.energyType === value; |
| | | const filterEnergyPurpose = (value, row) => row.energyPurpose === value; |
| | | const filterEnergyPurpose = (value, row) => row.type === value; |
| | | |
| | | // 分页 |
| | | const page = reactive({ |
| | |
| | | { |
| | | name: "生产能耗成本", |
| | | type: "bar", |
| | | data: data.map(item => (item.energyPurpose === "生产" ? item.cost : 0)), |
| | | data: data.map(item => (item.type === "生产" ? item.cost : 0)), |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: "#409EFF" }, |
| | |
| | | { |
| | | name: "办公能耗成本", |
| | | type: "bar", |
| | | data: data.map(item => (item.energyPurpose === "办公" ? item.cost : 0)), |
| | | data: data.map(item => (item.type === "办公" ? item.cost : 0)), |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: "#67C23A" }, |
| | |
| | | }; |
| | | |
| | | data.forEach(item => { |
| | | if (purposeCosts.hasOwnProperty(item.energyPurpose)) { |
| | | purposeCosts[item.energyPurpose] += parseFloat(item.cost); |
| | | if (purposeCosts.hasOwnProperty(item.type)) { |
| | | purposeCosts[item.type] += parseFloat(item.cost); |
| | | } |
| | | }); |
| | | |
| | |
| | | 办公: 0, |
| | | }; |
| | | } |
| | | if (priceData[item.energyType].hasOwnProperty(item.energyPurpose)) { |
| | | priceData[item.energyType][item.energyPurpose] = parseFloat(item.price); |
| | | if (priceData[item.energyType].hasOwnProperty(item.type)) { |
| | | priceData[item.energyType][item.type] = parseFloat(item.price); |
| | | } |
| | | }); |
| | | |
| | |
| | | |
| | | // 构造请求参数 |
| | | const params = { |
| | | type: statisticsType.value, |
| | | energyType: searchForm.energyType || undefined, |
| | | energyPurpose: searchForm.energyPurpose || undefined, |
| | | days: 0, |
| | | // energyType: searchForm.energyType || undefined, |
| | | type: searchForm.type || undefined, |
| | | // 项目内常用分页参数命名 |
| | | pageNum: page.current, |
| | | pageSize: page.size, |
| | |
| | | } else { |
| | | if (searchForm.monthRange && searchForm.monthRange.length === 2) { |
| | | params.startDate = searchForm.monthRange[0] + "-01"; |
| | | params.endDate = searchForm.monthRange[1] + "-01"; |
| | | |
| | | // 结束时间需要取结束月份的最后一天(例如 2026-03 -> 2026-03-31) |
| | | const [endYearStr, endMonthStr] = String(searchForm.monthRange[1]).split("-"); |
| | | const endYear = Number(endYearStr); |
| | | const endMonth = Number(endMonthStr); // 1-12 |
| | | if (!Number.isNaN(endYear) && !Number.isNaN(endMonth) && endMonth >= 1 && endMonth <= 12) { |
| | | const lastDay = new Date(endYear, endMonth, 0).getDate(); // 下个月第0天 = 本月最后一天 |
| | | params.endDate = `${endYearStr}-${endMonthStr}-${String(lastDay).padStart(2, "0")}`; |
| | | } else { |
| | | params.endDate = searchForm.monthRange[1] + "-01"; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 计算开始到结束的天数(包含起止两天) |
| | | if (params.startDate && params.endDate) { |
| | | const start = new Date(params.startDate); |
| | | const end = new Date(params.endDate); |
| | | if (!Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime())) { |
| | | const diffTime = end.getTime() - start.getTime(); |
| | | const diffDays = Math.floor(diffTime / (24 * 60 * 60 * 1000)) + 1; |
| | | params.days = diffDays > 0 ? diffDays : 0; |
| | | } |
| | | } |
| | | |
| | |
| | | mockData.push({ |
| | | timePeriod: dateStr, |
| | | energyType: "电", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 1000 + 500).toFixed(2), |
| | | unit: "kWh", |
| | | price: "0.85", |
| | |
| | | mockData.push({ |
| | | timePeriod: dateStr, |
| | | energyType: "水", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 500 + 200).toFixed(2), |
| | | unit: "m³", |
| | | price: "3.50", |
| | |
| | | mockData.push({ |
| | | timePeriod: dateStr, |
| | | energyType: "气", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 300 + 100).toFixed(2), |
| | | unit: "m³", |
| | | price: "2.80", |
| | |
| | | mockData.push({ |
| | | timePeriod: dateStr, |
| | | energyType: "电", |
| | | energyPurpose: "办公", |
| | | type: "办公", |
| | | consumption: (Math.random() * 200 + 100).toFixed(2), |
| | | unit: "kWh", |
| | | price: "0.85", |
| | |
| | | mockData.push({ |
| | | timePeriod: dateStr, |
| | | energyType: "水", |
| | | energyPurpose: "办公", |
| | | type: "办公", |
| | | consumption: (Math.random() * 50 + 20).toFixed(2), |
| | | unit: "m³", |
| | | price: "3.50", |
| | |
| | | mockData.push({ |
| | | timePeriod: monthStr, |
| | | energyType: "电", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 30000 + 15000).toFixed(2), |
| | | unit: "kWh", |
| | | price: "0.85", |
| | |
| | | mockData.push({ |
| | | timePeriod: monthStr, |
| | | energyType: "水", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 15000 + 6000).toFixed(2), |
| | | unit: "m³", |
| | | price: "3.50", |
| | |
| | | mockData.push({ |
| | | timePeriod: monthStr, |
| | | energyType: "气", |
| | | energyPurpose: "生产", |
| | | type: "生产", |
| | | consumption: (Math.random() * 9000 + 3000).toFixed(2), |
| | | unit: "m³", |
| | | price: "2.80", |
| | |
| | | mockData.push({ |
| | | timePeriod: monthStr, |
| | | energyType: "电", |
| | | energyPurpose: "办公", |
| | | type: "办公", |
| | | consumption: (Math.random() * 6000 + 3000).toFixed(2), |
| | | unit: "kWh", |
| | | price: "0.85", |
| | |
| | | mockData.push({ |
| | | timePeriod: monthStr, |
| | | energyType: "水", |
| | | energyPurpose: "办公", |
| | | type: "办公", |
| | | consumption: (Math.random() * 1500 + 600).toFixed(2), |
| | | unit: "m³", |
| | | price: "3.50", |
| | |
| | | tableData.value.forEach(item => { |
| | | const cost = parseFloat(item.cost); |
| | | totalCost += cost; |
| | | if (item.energyPurpose === "生产") { |
| | | if (item.type === "生产") { |
| | | productionCost += cost; |
| | | } else if (item.energyPurpose === "办公") { |
| | | } else if (item.type === "办公") { |
| | | officeCost += cost; |
| | | } |
| | | }); |
| | |
| | | |
| | | // 重置 |
| | | const handleReset = () => { |
| | | searchForm.energyType = ""; |
| | | searchForm.energyPurpose = ""; |
| | | // searchForm.energyType = ""; |
| | | searchForm.type = ""; |
| | | if (statisticsType.value === "day") { |
| | | const end = new Date(); |
| | | const start = new Date(); |