From 108a4fb5ce13ed06596f7e125e59632e76aafa58 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 10 三月 2026 18:00:37 +0800
Subject: [PATCH] 能耗管理模块
---
src/api/productionPlan/productionPlan.js | 11
src/api/energyManagement/energyType.js | 53
src/views/energyManagement/energyType/index2.vue | 697 +++++++++++
src/views/productionPlan/productionPlan/index.vue | 735 ++++++++---
src/views/energyManagement/officeEnergyConsumption/index.vue | 696 +++++++++++
src/views/energyManagement/energyConsumptionStatistical/index.vue | 874 +++++++++++++
src/views/energyManagement/productionEnergyConsumption/index.vue | 696 +++++++++++
7 files changed, 3,556 insertions(+), 206 deletions(-)
diff --git a/src/api/energyManagement/energyType.js b/src/api/energyManagement/energyType.js
new file mode 100644
index 0000000..43b8066
--- /dev/null
+++ b/src/api/energyManagement/energyType.js
@@ -0,0 +1,53 @@
+// 鑳借�楃被鍨�
+import request from "@/utils/request";
+
+// 鑳借�楃被鍨�-鍒嗛〉鏌ヨ
+export function energyTypeListPage(query) {
+ return request({
+ url: "/energy/page",
+ method: "get",
+ params: query,
+ });
+}
+// 鑳借�楃被鍨�-鏂板淇敼
+export function energyTypeAdd(query) {
+ return request({
+ url: "/energy",
+ method: "post",
+ data: query,
+ });
+}
+
+// 鑳借�楃被鍨�-鍒犻櫎
+export function energyTypeDelete(ids) {
+ return request({
+ url: "/energy/" + ids,
+ method: "delete",
+ });
+}
+
+// 鑳借�楁妱琛ㄦ槑缁�
+export function energyConsumptionDetailListPage(query) {
+ return request({
+ url: "/energyConsumptionDetail/page",
+ method: "get",
+ params: query,
+ });
+}
+// 鑳借�楁妱琛ㄦ槑缁�-鏂板淇敼
+export function energyConsumptionDetailAdd(query) {
+ return request({
+ url: "/energyConsumptionDetail",
+ method: "post",
+ data: query,
+ });
+}
+
+
+// 鑳借�楁妱琛ㄦ槑缁�-鍒犻櫎
+export function energyConsumptionDetailDelete(ids) {
+ return request({
+ url: "/energyConsumptionDetail/" + ids,
+ method: "delete",
+ });
+}
\ No newline at end of file
diff --git a/src/api/productionPlan/productionPlan.js b/src/api/productionPlan/productionPlan.js
new file mode 100644
index 0000000..2b08129
--- /dev/null
+++ b/src/api/productionPlan/productionPlan.js
@@ -0,0 +1,11 @@
+// 鐢熶骇璁㈠崟椤甸潰鎺ュ彛
+import request from "@/utils/request";
+
+
+export function productionPlanListPage(query) {
+ return request({
+ url: "/productionPlan/listPage",
+ method: "get",
+ params: query,
+ });
+}
diff --git a/src/views/energyManagement/energyConsumptionStatistical/index.vue b/src/views/energyManagement/energyConsumptionStatistical/index.vue
new file mode 100644
index 0000000..9363511
--- /dev/null
+++ b/src/views/energyManagement/energyConsumptionStatistical/index.vue
@@ -0,0 +1,874 @@
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储鍖哄煙 -->
+ <div class="search_form">
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="缁熻缁村害:">
+ <el-radio-group v-model="statisticsType"
+ @change="handleTypeChange">
+ <el-radio-button label="day">鎸夋棩缁熻</el-radio-button>
+ <el-radio-button label="month">鎸夋湀缁熻</el-radio-button>
+ <el-radio-button label="year">鎸夊勾缁熻</el-radio-button>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="鑳借�楃敤閫�:">
+ <el-select v-model="searchForm.energyType"
+ placeholder="鍏ㄩ儴"
+ clearable
+ style="width: 120px;"
+ @change="handleQuery">
+ <el-option label="鍏ㄩ儴"
+ value="鍏ㄩ儴" />
+ <el-option label="鍔炲叕"
+ value="鍔炲叕" />
+ <el-option label="鐢熶骇"
+ value="鐢熶骇" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏃堕棿鑼冨洿:">
+ <el-date-picker v-if="statisticsType === 'day'"
+ v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;"
+ @change="handleQuery" />
+ <el-date-picker v-else-if="statisticsType === 'month'"
+ v-model="searchForm.monthRange"
+ type="monthrange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫湀浠�"
+ end-placeholder="缁撴潫鏈堜唤"
+ value-format="YYYY-MM"
+ style="width: 240px;"
+ @change="handleQuery" />
+ <el-select v-else
+ v-model="searchForm.year"
+ placeholder="閫夋嫨骞翠唤"
+ style="width: 140px;"
+ @change="handleQuery">
+ <el-option v-for="year in yearOptions"
+ :key="year"
+ :label="year + '骞�'"
+ :value="year" />
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery">鏌ヨ</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ <div>
+ <el-button type="success"
+ @click="handleExport">瀵煎嚭鎶ヨ〃</el-button>
+ </div>
+ </div>
+ <!-- 缁熻姒傝鍗$墖 -->
+ <div class="statistics-overview">
+ <el-row :gutter="20">
+ <el-col :span="6">
+ <div class="overview-card total-consumption">
+ <div class="overview-icon">
+ <el-icon>
+ <DataLine />
+ </el-icon>
+ </div>
+ <div class="overview-info">
+ <div class="overview-label">鎬昏兘鑰楃敤閲�</div>
+ <div class="overview-value">{{ overview.totalConsumption }} <span class="unit">鍚�/搴�/m鲁</span></div>
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="6">
+ <div class="overview-card total-amount">
+ <div class="overview-icon">
+ <el-icon>
+ <Money />
+ </el-icon>
+ </div>
+ <div class="overview-info">
+ <div class="overview-label">鎬昏兘鑰楄垂鐢�</div>
+ <div class="overview-value">楼{{ overview.totalAmount }}</div>
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="6">
+ <div class="overview-card avg-consumption">
+ <div class="overview-icon">
+ <el-icon>
+ <TrendCharts />
+ </el-icon>
+ </div>
+ <div class="overview-info">
+ <div class="overview-label">骞冲潎鐢ㄩ噺</div>
+ <div class="overview-value">{{ overview.avgConsumption }} <span class="unit">/{{ statisticsType === 'day' ? '鏃�' : statisticsType === 'month' ? '鏈�' : '骞�' }}</span></div>
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="6">
+ <div class="overview-card compare-last">
+ <div class="overview-icon">
+ <el-icon>
+ <Histogram />
+ </el-icon>
+ </div>
+ <div class="overview-info">
+ <div class="overview-label">鐜瘮鍙樺寲</div>
+ <div class="overview-value"
+ :class="overview.compareRate >= 0 ? 'up' : 'down'">
+ <el-icon v-if="overview.compareRate >= 0">
+ <ArrowUp />
+ </el-icon>
+ <el-icon v-else>
+ <ArrowDown />
+ </el-icon>
+ {{ Math.abs(overview.compareRate) }}%
+ </div>
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ <!-- 鍥捐〃鍖哄煙 -->
+ <div class="charts-container">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <div class="chart-card">
+ <div class="chart-title">鑳借�楃敤閲忚秼鍔�</div>
+ <div ref="consumptionChart"
+ class="chart-content"></div>
+ </div>
+ </el-col>
+ <el-col :span="12">
+ <div class="chart-card">
+ <div class="chart-title">鑳借�楄垂鐢ㄨ秼鍔�</div>
+ <div ref="amountChart"
+ class="chart-content"></div>
+ </div>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20"
+ style="margin-top: 20px;">
+ <el-col :span="12">
+ <div class="chart-card">
+ <div class="chart-title">鑳借�楃被鍨嬪崰姣�</div>
+ <div ref="typeChart"
+ class="chart-content"></div>
+ </div>
+ </el-col>
+ <el-col :span="12">
+ <div class="chart-card">
+ <div class="chart-title">鑳借�楃被鍨嬭垂鐢ㄥ崰姣�</div>
+ <div ref="amountTypeChart"
+ class="chart-content"></div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ <!-- 鏁版嵁琛ㄦ牸 -->
+ <div class="table-section">
+ <div class="section-title">璇︾粏鏁版嵁</div>
+ <el-table :data="tableData"
+ v-loading="tableLoading"
+ border
+ stripe>
+ <el-table-column type="index"
+ label="搴忓彿"
+ width="60"
+ align="center" />
+ <el-table-column prop="timePeriod"
+ :label="timeColumnLabel"
+ align="center" />
+ <el-table-column prop="waterConsumption"
+ label="鐢ㄦ按閲�(鍚�)"
+ align="right">
+ <template #default="scope">
+ <span class="consumption-value">{{ scope.row.waterConsumption }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="waterAmount"
+ label="姘磋垂(鍏�)"
+ align="right">
+ <template #default="scope">
+ <span class="amount-value">{{ scope.row.waterAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="electricityConsumption"
+ label="鐢ㄧ數閲�(搴�)"
+ align="right">
+ <template #default="scope">
+ <span class="consumption-value">{{ scope.row.electricityConsumption }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="electricityAmount"
+ label="鐢佃垂(鍏�)"
+ align="right">
+ <template #default="scope">
+ <span class="amount-value">{{ scope.row.electricityAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="gasConsumption"
+ label="鐢ㄦ皵閲�(m鲁)"
+ align="right">
+ <template #default="scope">
+ <span class="consumption-value">{{ scope.row.gasConsumption }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="gasAmount"
+ label="姘旇垂(鍏�)"
+ align="right">
+ <template #default="scope">
+ <span class="amount-value">{{ scope.row.gasAmount }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="totalConsumption"
+ label="鍚堣鐢ㄩ噺"
+ align="right">
+ <template #default="scope">
+ <span class="total-value">{{ scope.row.totalConsumption }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="totalAmount"
+ label="鍚堣璐圭敤(鍏�)"
+ align="right"
+ fixed="right">
+ <template #default="scope">
+ <span class="total-amount-value">楼{{ scope.row.totalAmount }}</span>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <!-- 鍒嗛〉 -->
+ <div class="pagination-container">
+ <el-pagination v-model:current-page="page.current"
+ v-model:page-size="page.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange" />
+ </div>
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, onMounted, computed, nextTick } from "vue";
+ import { ElMessage } from "element-plus";
+ import {
+ DataLine,
+ Money,
+ TrendCharts,
+ Histogram,
+ ArrowUp,
+ ArrowDown,
+ } from "@element-plus/icons-vue";
+ import * as echarts from "echarts";
+
+ // 缁熻缁村害锛歞ay-鎸夋棩锛宮onth-鎸夋湀锛寉ear-鎸夊勾
+ const statisticsType = ref("day");
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ energyType: "",
+ dateRange: [],
+ monthRange: [],
+ year: new Date().getFullYear(),
+ });
+
+ // 骞翠唤閫夐」
+ const yearOptions = computed(() => {
+ const currentYear = new Date().getFullYear();
+ const years = [];
+ for (let i = currentYear - 5; i <= currentYear; i++) {
+ years.push(i);
+ }
+ return years.reverse();
+ });
+
+ // 鏃堕棿鍒楁爣绛�
+ const timeColumnLabel = computed(() => {
+ const labels = {
+ day: "鏃ユ湡",
+ month: "鏈堜唤",
+ year: "骞翠唤",
+ };
+ return labels[statisticsType.value];
+ });
+
+ // 缁熻姒傝
+ const overview = reactive({
+ totalConsumption: "25,680.5",
+ totalAmount: "45,280.60",
+ avgConsumption: "856.0",
+ compareRate: -5.2,
+ });
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鍒嗛〉
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 鍥捐〃寮曠敤
+ const consumptionChart = ref(null);
+ const amountChart = ref(null);
+ const typeChart = ref(null);
+ const amountTypeChart = ref(null);
+
+ // 鍥捐〃瀹炰緥
+ let consumptionChartInstance = null;
+ let amountChartInstance = null;
+ let typeChartInstance = null;
+ let amountTypeChartInstance = null;
+
+ // 鐢熸垚妯℃嫙鏁版嵁
+ const generateMockData = () => {
+ const data = [];
+ const count =
+ statisticsType.value === "day"
+ ? 30
+ : statisticsType.value === "month"
+ ? 12
+ : 5;
+
+ for (let i = 0; i < count; i++) {
+ const waterConsumption = (Math.random() * 100 + 50).toFixed(2);
+ const waterAmount = (waterConsumption * 2.5).toFixed(2);
+ const electricityConsumption = (Math.random() * 500 + 200).toFixed(2);
+ const electricityAmount = (electricityConsumption * 0.8).toFixed(2);
+ const gasConsumption = (Math.random() * 200 + 100).toFixed(2);
+ const gasAmount = (gasConsumption * 3.0).toFixed(2);
+
+ let timePeriod;
+ if (statisticsType.value === "day") {
+ const date = new Date();
+ date.setDate(date.getDate() - i);
+ timePeriod = date.toISOString().split("T")[0];
+ } else if (statisticsType.value === "month") {
+ const date = new Date();
+ date.setMonth(date.getMonth() - i);
+ timePeriod = date.toISOString().slice(0, 7);
+ } else {
+ timePeriod = (new Date().getFullYear() - i).toString();
+ }
+
+ data.push({
+ timePeriod,
+ waterConsumption,
+ waterAmount,
+ electricityConsumption,
+ electricityAmount,
+ gasConsumption,
+ gasAmount,
+ totalConsumption: (
+ parseFloat(waterConsumption) +
+ parseFloat(electricityConsumption) +
+ parseFloat(gasConsumption)
+ ).toFixed(2),
+ totalAmount: (
+ parseFloat(waterAmount) +
+ parseFloat(electricityAmount) +
+ parseFloat(gasAmount)
+ ).toFixed(2),
+ });
+ }
+ return data.reverse();
+ };
+
+ // 鍒濆鍖栧浘琛�
+ const initCharts = () => {
+ nextTick(() => {
+ // 鑳借�楃敤閲忚秼鍔垮浘
+ if (consumptionChart.value) {
+ consumptionChartInstance = echarts.init(consumptionChart.value);
+ updateConsumptionChart();
+ }
+ // 鑳借�楄垂鐢ㄨ秼鍔垮浘
+ if (amountChart.value) {
+ amountChartInstance = echarts.init(amountChart.value);
+ updateAmountChart();
+ }
+ // 鑳借�楃被鍨嬪崰姣斿浘
+ if (typeChart.value) {
+ typeChartInstance = echarts.init(typeChart.value);
+ updateTypeChart();
+ }
+ // 鑳借�楃被鍨嬭垂鐢ㄥ崰姣斿浘
+ if (amountTypeChart.value) {
+ amountTypeChartInstance = echarts.init(amountTypeChart.value);
+ updateAmountTypeChart();
+ }
+ });
+ };
+
+ // 鏇存柊鑳借�楃敤閲忚秼鍔垮浘
+ const updateConsumptionChart = () => {
+ const data = tableData.value;
+ const option = {
+ tooltip: {
+ trigger: "axis",
+ axisPointer: { type: "cross" },
+ },
+ legend: {
+ data: ["鐢ㄦ按閲�", "鐢ㄧ數閲�", "鐢ㄦ皵閲�"],
+ bottom: 0,
+ },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "15%",
+ containLabel: true,
+ },
+ xAxis: {
+ type: "category",
+ data: data.map(item => item.timePeriod),
+ axisLabel: { rotate: statisticsType.value === "day" ? 45 : 0 },
+ },
+ yAxis: {
+ type: "value",
+ name: "鐢ㄩ噺",
+ },
+ series: [
+ {
+ name: "鐢ㄦ按閲�",
+ type: "bar",
+ data: data.map(item => item.waterConsumption),
+ itemStyle: { color: "#409EFF" },
+ },
+ {
+ name: "鐢ㄧ數閲�",
+ type: "bar",
+ data: data.map(item => item.electricityConsumption),
+ itemStyle: { color: "#E6A23C" },
+ },
+ {
+ name: "鐢ㄦ皵閲�",
+ type: "bar",
+ data: data.map(item => item.gasConsumption),
+ itemStyle: { color: "#67C23A" },
+ },
+ ],
+ };
+ consumptionChartInstance.setOption(option);
+ };
+
+ // 鏇存柊鑳借�楄垂鐢ㄨ秼鍔垮浘
+ const updateAmountChart = () => {
+ const data = tableData.value;
+ const option = {
+ tooltip: {
+ trigger: "axis",
+ axisPointer: { type: "cross" },
+ },
+ legend: {
+ data: ["姘磋垂", "鐢佃垂", "姘旇垂"],
+ bottom: 0,
+ },
+ grid: {
+ left: "3%",
+ right: "4%",
+ bottom: "15%",
+ containLabel: true,
+ },
+ xAxis: {
+ type: "category",
+ data: data.map(item => item.timePeriod),
+ axisLabel: { rotate: statisticsType.value === "day" ? 45 : 0 },
+ },
+ yAxis: {
+ type: "value",
+ name: "璐圭敤(鍏�)",
+ },
+ series: [
+ {
+ name: "姘磋垂",
+ type: "line",
+ data: data.map(item => item.waterAmount),
+ smooth: true,
+ itemStyle: { color: "#409EFF" },
+ },
+ {
+ name: "鐢佃垂",
+ type: "line",
+ data: data.map(item => item.electricityAmount),
+ smooth: true,
+ itemStyle: { color: "#E6A23C" },
+ },
+ {
+ name: "姘旇垂",
+ type: "line",
+ data: data.map(item => item.gasAmount),
+ smooth: true,
+ itemStyle: { color: "#67C23A" },
+ },
+ ],
+ };
+ amountChartInstance.setOption(option);
+ };
+
+ // 鏇存柊鑳借�楃被鍨嬪崰姣斿浘
+ const updateTypeChart = () => {
+ const data = tableData.value;
+ const totalWater = data.reduce(
+ (sum, item) => sum + parseFloat(item.waterConsumption),
+ 0
+ );
+ const totalElectricity = data.reduce(
+ (sum, item) => sum + parseFloat(item.electricityConsumption),
+ 0
+ );
+ const totalGas = data.reduce(
+ (sum, item) => sum + parseFloat(item.gasConsumption),
+ 0
+ );
+
+ const option = {
+ tooltip: {
+ trigger: "item",
+ formatter: "{a} <br/>{b}: {c} ({d}%)",
+ },
+ legend: {
+ orient: "vertical",
+ left: "left",
+ },
+ series: [
+ {
+ name: "鑳借�楃敤閲�",
+ type: "pie",
+ radius: ["40%", "70%"],
+ avoidLabelOverlap: false,
+ itemStyle: {
+ borderRadius: 10,
+ borderColor: "#fff",
+ borderWidth: 2,
+ },
+ label: {
+ show: true,
+ formatter: "{b}: {d}%",
+ },
+ data: [
+ {
+ value: totalWater.toFixed(2),
+ name: "姘�",
+ itemStyle: { color: "#409EFF" },
+ },
+ {
+ value: totalElectricity.toFixed(2),
+ name: "鐢�",
+ itemStyle: { color: "#E6A23C" },
+ },
+ {
+ value: totalGas.toFixed(2),
+ name: "姘�",
+ itemStyle: { color: "#67C23A" },
+ },
+ ],
+ },
+ ],
+ };
+ typeChartInstance.setOption(option);
+ };
+
+ // 鏇存柊鑳借�楃被鍨嬭垂鐢ㄥ崰姣斿浘
+ const updateAmountTypeChart = () => {
+ const data = tableData.value;
+ const totalWaterAmount = data.reduce(
+ (sum, item) => sum + parseFloat(item.waterAmount),
+ 0
+ );
+ const totalElectricityAmount = data.reduce(
+ (sum, item) => sum + parseFloat(item.electricityAmount),
+ 0
+ );
+ const totalGasAmount = data.reduce(
+ (sum, item) => sum + parseFloat(item.gasAmount),
+ 0
+ );
+
+ const option = {
+ tooltip: {
+ trigger: "item",
+ formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
+ },
+ legend: {
+ orient: "vertical",
+ left: "left",
+ },
+ series: [
+ {
+ name: "鑳借�楄垂鐢�",
+ type: "pie",
+ radius: "60%",
+ data: [
+ {
+ value: totalWaterAmount.toFixed(2),
+ name: "姘磋垂",
+ itemStyle: { color: "#409EFF" },
+ },
+ {
+ value: totalElectricityAmount.toFixed(2),
+ name: "鐢佃垂",
+ itemStyle: { color: "#E6A23C" },
+ },
+ {
+ value: totalGasAmount.toFixed(2),
+ name: "姘旇垂",
+ itemStyle: { color: "#67C23A" },
+ },
+ ],
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: "rgba(0, 0, 0, 0.5)",
+ },
+ },
+ },
+ ],
+ };
+ amountTypeChartInstance.setOption(option);
+ };
+
+ // 缁熻缁村害鍒囨崲
+ const handleTypeChange = () => {
+ // 閲嶇疆鏃堕棿鑼冨洿
+ searchForm.dateRange = [];
+ searchForm.monthRange = [];
+ searchForm.year = new Date().getFullYear();
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 鏌ヨ
+ const handleQuery = () => {
+ tableLoading.value = true;
+ setTimeout(() => {
+ const data = generateMockData();
+ tableData.value = data;
+ page.total = data.length;
+ tableLoading.value = false;
+ updateCharts();
+ }, 300);
+ };
+
+ // 鏇存柊鎵�鏈夊浘琛�
+ const updateCharts = () => {
+ nextTick(() => {
+ if (consumptionChartInstance) updateConsumptionChart();
+ if (amountChartInstance) updateAmountChart();
+ if (typeChartInstance) updateTypeChart();
+ if (amountTypeChartInstance) updateAmountTypeChart();
+ });
+ };
+
+ // 閲嶇疆
+ const handleReset = () => {
+ searchForm.energyType = "";
+ searchForm.dateRange = [];
+ searchForm.monthRange = [];
+ searchForm.year = new Date().getFullYear();
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 瀵煎嚭
+ const handleExport = () => {
+ ElMessage.success("鎶ヨ〃瀵煎嚭鎴愬姛");
+ };
+
+ // 鍒嗛〉澶у皬鍙樺寲
+ const handleSizeChange = val => {
+ page.size = val;
+ };
+
+ // 椤电爜鍙樺寲
+ const handleCurrentChange = val => {
+ page.current = val;
+ };
+
+ // 绐楀彛澶у皬鍙樺寲鏃堕噸鏂版覆鏌撳浘琛�
+ const handleResize = () => {
+ consumptionChartInstance && consumptionChartInstance.resize();
+ amountChartInstance && amountChartInstance.resize();
+ typeChartInstance && typeChartInstance.resize();
+ amountTypeChartInstance && amountTypeChartInstance.resize();
+ };
+
+ onMounted(() => {
+ handleQuery();
+ initCharts();
+ window.addEventListener("resize", handleResize);
+ });
+</script>
+
+<style scoped lang="scss">
+ .app-container {
+ padding: 20px;
+ }
+
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 15px;
+ background-color: #f5f7fa;
+ border-radius: 8px;
+ }
+
+ .statistics-overview {
+ margin-bottom: 20px;
+ }
+
+ .overview-card {
+ display: flex;
+ align-items: center;
+ padding: 20px;
+ border-radius: 8px;
+ background: #fff;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+
+ &.total-consumption {
+ border-left: 4px solid #409eff;
+ }
+
+ &.total-amount {
+ border-left: 4px solid #67c23a;
+ }
+
+ &.avg-consumption {
+ border-left: 4px solid #e6a23c;
+ }
+
+ &.compare-last {
+ border-left: 4px solid #909399;
+ }
+
+ .overview-icon {
+ width: 50px;
+ height: 50px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #f5f7fa;
+ border-radius: 50%;
+ margin-right: 15px;
+
+ .el-icon {
+ font-size: 24px;
+ color: #409eff;
+ }
+ }
+
+ .overview-info {
+ flex: 1;
+
+ .overview-label {
+ font-size: 14px;
+ color: #909399;
+ margin-bottom: 5px;
+ }
+
+ .overview-value {
+ font-size: 24px;
+ font-weight: bold;
+ color: #303133;
+
+ .unit {
+ font-size: 14px;
+ font-weight: normal;
+ color: #909399;
+ }
+
+ &.up {
+ color: #67c23a;
+ }
+
+ &.down {
+ color: #f56c6c;
+ }
+
+ .el-icon {
+ font-size: 16px;
+ vertical-align: middle;
+ }
+ }
+ }
+ }
+
+ .charts-container {
+ margin-bottom: 20px;
+ }
+
+ .chart-card {
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ padding: 20px;
+
+ .chart-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #303133;
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ .chart-content {
+ height: 300px;
+ }
+ }
+
+ .table-section {
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ padding: 20px;
+ margin-bottom: 20px;
+
+ .section-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #303133;
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #ebeef5;
+ }
+ }
+
+ .consumption-value {
+ font-weight: bold;
+ color: #409eff;
+ }
+
+ .amount-value {
+ font-weight: bold;
+ color: #67c23a;
+ }
+
+ .total-value {
+ font-weight: bold;
+ color: #e6a23c;
+ }
+
+ .total-amount-value {
+ font-weight: bold;
+ color: #f56c6c;
+ font-size: 14px;
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ }
+</style>
diff --git a/src/views/energyManagement/energyType/index2.vue b/src/views/energyManagement/energyType/index2.vue
new file mode 100644
index 0000000..88296a1
--- /dev/null
+++ b/src/views/energyManagement/energyType/index2.vue
@@ -0,0 +1,697 @@
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储鍖哄煙 -->
+ <div class="search_form">
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="鑳芥簮绫诲瀷:">
+ <el-select v-model="searchForm.energyTyep"
+ placeholder="鍏ㄩ儴"
+ clearable
+ style="width: 120px;"
+ @change="handleQuery">
+ <el-option label="姘�"
+ value="gas" />
+ <el-option label="鐢�"
+ value="electricity" />
+ <el-option label="姘�"
+ value="water" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鑳芥簮鍚嶇О:">
+ <el-input v-model="searchForm.energyName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ style="width: 160px;"
+ @keyup.enter="handleQuery" />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery">鏌ヨ</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ <div>
+ <el-button type="primary"
+ @click="handleAdd">鏂板</el-button>
+ <!-- <el-button type="success"
+ @click="handleImport">瀵煎叆</el-button> -->
+ <el-button type="warning"
+ @click="handleExport">瀵煎嚭</el-button>
+ </div>
+ </div>
+ <!-- 鏁版嵁琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table :data="tableData"
+ v-loading="tableLoading"
+ border
+ height="calc(100vh - 350px)"
+ stripe>
+ <el-table-column type="selection"
+ width="55"
+ align="center" />
+ <el-table-column prop="energyTyep"
+ label="鑳芥簮绫诲瀷"
+ width="100"
+ align="center">
+ <template #default="scope">
+ <el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
+ {{ scope.row.energyTyep }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="energyName"
+ label="鑳芥簮鍚嶇О"
+ align="center" />
+ <el-table-column prop="unitPrice"
+ label="鍗曚环"
+ sortable
+ align="right">
+ <template #default="scope">
+ <span>{{ scope.row.unitPrice }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="澶囨敞"
+ prop="remark"
+ align="center" />
+ <el-table-column prop="unit"
+ label="鍗曚綅"
+ align="center" />
+ <el-table-column prop="createUserName"
+ label="鍒涘缓浜�"
+ align="center" />
+ <el-table-column prop="createTime"
+ label="鍒涘缓鏃堕棿"
+ sortable
+ align="center" />
+ <el-table-column label="鎿嶄綔"
+ align="center"
+ fixed="right">
+ <template #default="scope">
+ <el-button type="primary"
+ link
+ @click="handleDetail(scope.row)">璇︽儏</el-button>
+ <el-button type="danger"
+ link
+ @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ <el-button type="primary"
+ link
+ @click="handleEdit(scope.row)">缂栬緫</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <!-- 鍒嗛〉 -->
+ <div class="pagination-container">
+ <el-pagination v-model:current-page="page.current"
+ v-model:page-size="page.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange" />
+ </div>
+ </div>
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="600px">
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ label-width="100px">
+ <el-form-item label="鑳芥簮鍚嶇О"
+ prop="energyName">
+ <el-input v-model="form.energyName"
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="鑳芥簮绫诲瀷"
+ prop="energyTyep">
+ <el-select v-model="form.energyTyep"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%;">
+ <el-option label="姘�"
+ value="姘�" />
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="姘�"
+ value="姘�" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ rows="3" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="form.unit"
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="鍗曚环"
+ prop="unitPrice">
+ <el-input-number v-model="form.unitPrice"
+ :precision="2"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button type="primary"
+ @click="handleSubmit">纭畾</el-button>
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 璇︽儏寮圭獥 -->
+ <el-dialog v-model="detailDialogVisible"
+ title="鑳芥簮绫诲瀷璇︽儏"
+ width="600px">
+ <el-form :model="detailForm"
+ label-width="100px"
+ disabled>
+ <el-form-item label="鑳芥簮绫诲瀷">
+ <el-tag :type="getEnergyTypeType(detailForm.energyTyep)">
+ {{ detailForm.energyTyep }}
+ </el-tag>
+ </el-form-item>
+ <el-form-item label="鑳芥簮鍚嶇О">
+ <el-input v-model="detailForm.energyName" />
+ </el-form-item>
+ <el-form-item label="鍗曚环">
+ <el-input v-model="detailForm.unitPrice" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅">
+ <el-input v-model="detailForm.unit" />
+ </el-form-item>
+ <el-form-item label="澶囨敞">
+ <el-input v-model="detailForm.remark"
+ type="textarea"
+ rows="3" />
+ </el-form-item>
+ <el-form-item label="鍒涘缓浜�">
+ <el-input v-model="detailForm.createUserName" />
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-input v-model="detailForm.createTime" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="detailDialogVisible = false">鍏抽棴</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import {
+ energyTypeListPage,
+ energyTypeAdd,
+ energyTypeDelete,
+ } from "@/api/energyManagement/energyType";
+
+ import { More } from "@element-plus/icons-vue";
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ energyTyep: "",
+ energyName: "",
+ });
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鍒嗛〉
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 寮圭獥鎺у埗
+ const dialogVisible = ref(false);
+ const dialogTitle = ref("鏂板鑳芥簮绫诲瀷");
+ const formRef = ref(null);
+ const isEdit = ref(false);
+ const currentId = ref(null);
+
+ // 琛ㄥ崟鏁版嵁
+ const form = reactive({
+ energyName: "",
+ energyTyep: "",
+ id: "",
+ remark: "",
+ unit: "",
+ unitPrice: 0,
+ });
+ const { proxy } = getCurrentInstance();
+ // 琛ㄥ崟鏍¢獙瑙勫垯
+ const rules = {
+ energyTyep: [
+ { required: true, message: "璇烽�夋嫨鑳芥簮绫诲瀷", trigger: "change" },
+ ],
+ energyName: [{ required: true, message: "璇疯緭鍏ヨ兘婧愬悕绉�", trigger: "blur" }],
+ unitPrice: [{ required: true, message: "璇疯緭鍏ュ崟浠�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇疯緭鍏ュ崟浣�", trigger: "blur" }],
+ };
+
+ // 璇︽儏寮圭獥
+ const detailDialogVisible = ref(false);
+ const detailForm = reactive({
+ energyTyep: "",
+ energyName: "",
+ unitPrice: "",
+ unit: "",
+ remark: "",
+ createUserName: "",
+ createUserNameOrganization: "",
+ createTime: "",
+ updateTime: "",
+ });
+
+ // 鑾峰彇鑳芥簮绫诲瀷鏍峰紡
+ const getEnergyTypeType = type => {
+ const typeMap = {
+ 姘�: "success",
+ 鐢�: "warning",
+ 姘�: "primary",
+ };
+ return typeMap[type] || "info";
+ };
+
+ // 鐢熸垚妯℃嫙鏁版嵁
+ const generateMockData = () => {
+ const data = [
+ {
+ id: 1,
+ energyTyep: "姘�",
+ energyName: "钂告苯",
+ unitPrice: "0.00",
+ unit: "T",
+ createUserName: "鐧芥礇宸茬棿鐢�",
+ createUserNameOrganization: "瀹佸涓摱缁掍笟瀹炰笟闆嗗洟鏈夐檺鍏徃",
+ createTime: "2022-11-09 14:14:05",
+ updateTime: "2022-11-10 18:14:48",
+ remark: "",
+ },
+ {
+ id: 2,
+ energyTyep: "鐢�",
+ energyName: "鐢甸噺",
+ unitPrice: "0.00",
+ unit: "搴�",
+ createUserName: "鐜嬬惇宸茬棿鐢�",
+ createUserNameOrganization: "瀹佸涓摱缁掍笟瀹炰笟闆嗗洟鏈夐檺鍏徃",
+ createTime: "2022-10-08 17:27:27",
+ updateTime: "2022-11-10 18:14:40",
+ remark: "",
+ },
+ {
+ id: 3,
+ energyTyep: "姘�",
+ energyName: "涓按",
+ unitPrice: "0.00",
+ unit: "m鲁",
+ createUserName: "鐜嬬惇宸茬棿鐢�",
+ createUserNameOrganization: "瀹佸涓摱缁掍笟瀹炰笟闆嗗洟鏈夐檺鍏徃",
+ createTime: "2022-10-08 10:03:03",
+ updateTime: "2022-11-10 18:10:31",
+ remark: "",
+ },
+ ];
+ return data;
+ };
+
+ // 鏌ヨ
+ const handleQuery = () => {
+ tableLoading.value = true;
+ let params = {
+ current: page.current,
+ size: page.size,
+ energyTyep: searchForm.energyTyep,
+ energyName: searchForm.energyName,
+ };
+ energyTypeListPage(params)
+ .then(res => {
+ if (res.code === 200) {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ tableLoading.value = false;
+ } else {
+ ElMessage.error(res.message || "鏌ヨ澶辫触");
+ tableLoading.value = false;
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ tableLoading.value = false;
+ });
+ };
+
+ // 閲嶇疆
+ const handleReset = () => {
+ searchForm.energyTyep = "";
+ searchForm.energyName = "";
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 鏂板
+ const handleAdd = () => {
+ isEdit.value = false;
+ currentId.value = null;
+ dialogTitle.value = "鏂板鑳芥簮绫诲瀷";
+ resetForm();
+ dialogVisible.value = true;
+ };
+
+ // 缂栬緫
+ const handleEdit = row => {
+ isEdit.value = true;
+ currentId.value = row.id;
+ dialogTitle.value = "缂栬緫鑳芥簮绫诲瀷";
+ Object.assign(form, row);
+ dialogVisible.value = true;
+ };
+
+ // 璇︽儏
+ const handleDetail = row => {
+ Object.assign(detailForm, row);
+ detailDialogVisible.value = true;
+ };
+
+ // 鍒犻櫎
+ const handleDelete = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鑳芥簮绫诲瀷鍚楋紵", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ tableLoading.value = true;
+ energyTypeDelete([row.id])
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ });
+ };
+
+ // 澶嶅埗
+ const handleCopy = row => {
+ isEdit.value = false;
+ currentId.value = null;
+ dialogTitle.value = "澶嶅埗鑳芥簮绫诲瀷";
+ Object.assign(form, row);
+ delete form.id;
+ dialogVisible.value = true;
+ ElMessage.success("宸插鍒跺埌琛ㄥ崟");
+ };
+
+ // 閲嶇疆琛ㄥ崟
+ const resetForm = () => {
+ form.energyName = "";
+ form.energyTyep = "";
+ form.id = "";
+ form.remark = "";
+ form.unit = "";
+ form.unitPrice = 0;
+ };
+
+ // 鎻愪氦琛ㄥ崟
+ const handleSubmit = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ tableLoading.value = true;
+ energyTypeAdd(form)
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ dialogVisible.value = false;
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鎿嶄綔澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ }
+ });
+ };
+
+ // 瀵煎叆
+ const handleImport = () => {
+ ElMessage.success("瀵煎叆鎴愬姛");
+ };
+
+ // 瀵煎嚭
+ const handleExport = () => {
+ // proxy.download("/energy/export", { ...searchForm.value }, "鑳借�楃被鍨�.xlsx");
+ proxy.download("/energy/export", {}, "鑳借�楃被鍨�.xlsx");
+ };
+
+ // 鍒嗛〉澶у皬鍙樺寲
+ const handleSizeChange = val => {
+ page.size = val;
+ handleQuery();
+ };
+
+ // 椤电爜鍙樺寲
+ const handleCurrentChange = val => {
+ page.current = val;
+ handleQuery();
+ };
+
+ onMounted(() => {
+ handleQuery();
+ });
+</script>
+<style scoped lang="scss">
+ .app-container {
+ padding: 24px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 48px);
+ }
+
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+ }
+ }
+
+ .table_list {
+ // margin-bottom: 24px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ height: calc(100vh - 250px);
+ }
+
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-table__header-wrapper {
+ background-color: #fafafa;
+
+ th {
+ background-color: #fafafa;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #ebeef5;
+ padding: 14px 0;
+ }
+ }
+
+ .el-table__body-wrapper {
+ tr {
+ transition: all 0.3s ease;
+
+ &:hover {
+ background-color: #f5f7fa;
+ }
+
+ td {
+ border-bottom: 1px solid #ebeef5;
+ padding: 12px 0;
+ }
+ }
+
+ tr.current-row {
+ background-color: #ecf5ff;
+ }
+ }
+
+ .el-table__empty-block {
+ padding: 40px 0;
+ }
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #ffffff;
+ border-top: 1px solid #ebeef5;
+ border-radius: 0 0 12px 12px;
+ }
+
+ :deep(.el-button) {
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ }
+
+ :deep(.el-dialog) {
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-dialog__header {
+ background-color: #fafafa;
+ border-bottom: 1px solid #ebeef5;
+ padding: 20px 24px;
+
+ .el-dialog__title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .el-dialog__body {
+ padding: 24px;
+ }
+
+ .el-dialog__footer {
+ padding: 16px 24px;
+ border-top: 1px solid #ebeef5;
+ background-color: #fafafa;
+ }
+ }
+
+ :deep(.el-form) {
+ .el-form-item {
+ margin-bottom: 20px;
+
+ .el-form-item__label {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .el-input,
+ .el-select,
+ .el-date-picker,
+ .el-input-number {
+ width: 100%;
+
+ // .el-input__inner {
+ // border-radius: 6px;
+ // border: 1px solid #dcdfe6;
+ // transition: all 0.3s ease;
+
+ // &:focus {
+ // border-color: #409eff;
+ // box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+ // }
+ // }
+ }
+ }
+ }
+
+ :deep(.el-tag) {
+ border-radius: 4px;
+ padding: 2px 8px;
+ font-size: 12px;
+ }
+
+ @media (max-width: 768px) {
+ .app-container {
+ padding: 16px;
+ }
+
+ .search_form {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .el-form {
+ width: 100%;
+
+ .el-form-item {
+ width: 100%;
+ }
+ }
+
+ > div {
+ width: 100%;
+ display: flex;
+ gap: 12px;
+
+ .el-button {
+ flex: 1;
+ }
+ }
+ }
+
+ :deep(.el-table) {
+ th,
+ td {
+ padding: 10px 0;
+ font-size: 12px;
+ }
+ }
+
+ :deep(.el-dialog) {
+ width: 90% !important;
+ margin: 20px auto !important;
+ }
+ }
+ .consumption-value {
+ font-weight: bold;
+ color: #409eff;
+ }
+
+ .consumption-unit {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 4px;
+ }
+ .search_form {
+ :deep(.el-form-item) {
+ margin-bottom: 0px !important;
+ }
+ }
+</style>
diff --git a/src/views/energyManagement/officeEnergyConsumption/index.vue b/src/views/energyManagement/officeEnergyConsumption/index.vue
new file mode 100644
index 0000000..c3fbf82
--- /dev/null
+++ b/src/views/energyManagement/officeEnergyConsumption/index.vue
@@ -0,0 +1,696 @@
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储鍖哄煙 -->
+ <div class="search_form">
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="鑳借�楃被鍨�:">
+ <el-select v-model="searchForm.energyType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 140px;"
+ @change="handleQuery">
+ <el-option label="姘�"
+ value="water" />
+ <el-option label="鐢�"
+ value="electricity" />
+ <el-option label="姘�"
+ value="gas" />
+ </el-select>
+ </el-form-item>
+ <!-- <el-form-item label="鏃ユ湡鑼冨洿:">
+ <el-date-picker v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;"
+ @change="handleQuery" />
+ </el-form-item> -->
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery">鎼滅储</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ <div>
+ <!-- <el-button type="primary"
+ @click="handleAdd">鏂板</el-button> -->
+ <el-button type="success"
+ @click="handleExport">瀵煎嚭</el-button>
+ </div>
+ </div>
+ <!-- 鏁版嵁琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table :data="tableData"
+ v-loading="tableLoading"
+ border
+ height="calc(100vh - 350px)"
+ stripe>
+ <el-table-column type="index"
+ label="搴忓彿"
+ width="60"
+ align="center" />
+ <el-table-column prop="meterReadingDate"
+ label="鎶勮〃鏃ユ湡"
+ width="120"
+ sortable
+ align="center" />
+ <el-table-column prop="energyType"
+ label="鑳芥簮绫诲瀷"
+ width="100"
+ align="center">
+ <template #default="scope">
+ <el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
+ {{ scope.row.energyTyep }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="energyName"
+ label="鑳芥簮鍚嶇О"
+ align="center" />
+ <el-table-column prop="meterReadingLocation"
+ label="鎶勮〃浣嶇疆"
+ align="center" />
+ <el-table-column prop="startCode"
+ label="璧风爜"
+ sortable
+ align="right" />
+ <el-table-column prop="stopCode"
+ label="姝㈢爜"
+ sortable
+ align="right" />
+ <el-table-column prop="dosage"
+ label="鐢ㄩ噺"
+ sortable
+ align="right">
+ <template #default="scope">
+ <span class="consumption-value">{{ scope.row.dosage }}</span>
+ <span class="consumption-unit">{{ scope.row.unit }}</span>
+ </template>
+ </el-table-column>
+ <!-- <el-table-column prop="unit"
+ label="鍗曚綅"
+ width="80"
+ align="center" /> -->
+ <!-- <el-table-column prop="energyId"
+ label="鑳芥簮绫诲瀷ID"
+ width="120"
+ align="center" /> -->
+ <el-table-column prop="remark"
+ label="澶囨敞"
+ min-width="150"
+ show-overflow-tooltip />
+ <!-- <el-table-column label="鎿嶄綔"
+ width="180"
+ align="center"
+ fixed="right">
+ <template #default="scope">
+ <el-button type="primary"
+ link
+ @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <el-button type="danger"
+ link
+ @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column> -->
+ </el-table>
+ <div class="pagination-container">
+ <el-pagination v-model:current-page="page.current"
+ v-model:page-size="page.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange" />
+ </div>
+ </div>
+ <!-- 鍒嗛〉 -->
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="600px">
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ label-width="120px">
+ <el-form-item label="鎶勮〃鏃ユ湡"
+ prop="meterReadingDate">
+ <el-date-picker v-model="form.meterReadingDate"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鑳芥簮绫诲瀷"
+ prop="energyType">
+ <el-select v-model="form.energyType"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%;"
+ @change="handleEnergyTypeChange">
+ <el-option v-for="item in energyTypeList"
+ :key="item.id"
+ :label="item.energyName"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鎶勮〃浣嶇疆"
+ prop="meterReadingLocation">
+ <el-input v-model="form.meterReadingLocation"
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="璧风爜"
+ prop="startCode">
+ <el-input-number v-model="form.startCode"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="姝㈢爜"
+ prop="stopCode">
+ <el-input-number v-model="form.stopCode"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鐢ㄩ噺"
+ prop="dosage">
+ <el-input-number v-model="form.dosage"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="form.unit"
+ disabled
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ rows="3" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Watermelon, Lightning } from "@element-plus/icons-vue";
+ import {
+ energyConsumptionDetailListPage,
+ energyConsumptionDetailAdd,
+ energyConsumptionDetailDelete,
+ energyTypeListPage,
+ } from "@/api/energyManagement/energyType";
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ energyType: "",
+ dateRange: [],
+ });
+ const { proxy } = getCurrentInstance();
+
+ // 缁熻鏁版嵁
+ const statistics = reactive({
+ waterTotal: 1256.8,
+ waterAmount: "3,142.00",
+ electricityTotal: 8520.5,
+ electricityAmount: "6,816.40",
+ gasTotal: 3200.6,
+ gasAmount: "9,601.80",
+ });
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鍒嗛〉
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 寮圭獥鎺у埗
+ const dialogVisible = ref(false);
+ const dialogTitle = ref("鏂板鑳借�楄褰�");
+ const formRef = ref(null);
+ const isEdit = ref(false);
+ const currentId = ref(null);
+
+ // 琛ㄥ崟鏁版嵁
+ const form = reactive({
+ meterReadingDate: "",
+ energyType: "",
+ energyName: "",
+ energyId: "",
+ meterReadingLocation: "",
+ startCode: 0,
+ stopCode: 0,
+ dosage: 0,
+ unit: "",
+ remark: "",
+ type: "鍔炲叕",
+ });
+
+ // 琛ㄥ崟鏍¢獙瑙勫垯
+ const rules = {
+ meterReadingDate: [
+ { required: true, message: "璇烽�夋嫨鎶勮〃鏃ユ湡", trigger: "change" },
+ ],
+ energyType: [
+ { required: true, message: "璇烽�夋嫨鑳芥簮绫诲瀷", trigger: "change" },
+ ],
+ energyName: [
+ { required: true, message: "璇烽�夋嫨鑳芥簮鍚嶇О", trigger: "change" },
+ ],
+ energyId: [{ required: true, message: "璇烽�夋嫨鑳芥簮绫诲瀷", trigger: "change" }],
+ meterReadingLocation: [
+ { required: true, message: "璇疯緭鍏ユ妱琛ㄤ綅缃�", trigger: "blur" },
+ ],
+ startCode: [{ required: true, message: "璇疯緭鍏ヨ捣鐮�", trigger: "blur" }],
+ stopCode: [{ required: true, message: "璇疯緭鍏ユ鐮�", trigger: "blur" }],
+ dosage: [{ required: true, message: "璇疯緭鍏ョ敤閲�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇疯緭鍏ュ崟浣�", trigger: "blur" }],
+ };
+
+ // 鑾峰彇鑳借�楃被鍨嬫牱寮�
+ const getEnergyTypeType = type => {
+ const typeMap = {
+ 姘�: "primary",
+ 鐢�: "warning",
+ 姘�: "success",
+ water: "primary",
+ electricity: "warning",
+ gas: "success",
+ };
+ return typeMap[type] || "info";
+ };
+
+ // 鑾峰彇鑳借�楃被鍨嬫枃鏈�
+ const getEnergyTypeText = type => {
+ const textMap = {
+ water: "姘�",
+ electricity: "鐢�",
+ gas: "姘�",
+ };
+ return textMap[type] || type;
+ };
+
+ // 鏌ヨ
+ const handleQuery = () => {
+ tableLoading.value = true;
+ const params = {
+ current: page.current,
+ size: page.size,
+ type: "鍔炲叕",
+ // energyType: searchForm.energyType,
+ // startDate:
+ // searchForm.dateRange && searchForm.dateRange.length === 2
+ // ? searchForm.dateRange[0]
+ // : null,
+ // endDate:
+ // searchForm.dateRange && searchForm.dateRange.length === 2
+ // ? searchForm.dateRange[1]
+ // : null,
+ };
+ energyConsumptionDetailListPage(params)
+ .then(res => {
+ if (res.code === 200) {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ } else {
+ ElMessage.error(res.message || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+ const energyTypeList = ref([]);
+ const getEnergyTypeList = () => {
+ energyTypeListPage({ current: -1, size: -1 })
+ .then(res => {
+ if (res.code === 200) {
+ energyTypeList.value = res.data.records;
+ } else {
+ ElMessage.error(res.message || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ });
+ };
+
+ // 閲嶇疆
+ const handleReset = () => {
+ searchForm.energyType = "";
+ searchForm.dateRange = [];
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 瀵煎嚭
+ const handleExport = () => {
+ proxy.download(
+ "/energyConsumptionDetail/export",
+ { type: "鍔炲叕" },
+ "鑳借�楁槑缁�.xlsx"
+ );
+ };
+
+ // 鍒嗛〉澶у皬鍙樺寲
+ const handleSizeChange = val => {
+ page.size = val;
+ handleQuery();
+ };
+
+ // 椤电爜鍙樺寲
+ const handleCurrentChange = val => {
+ page.current = val;
+ handleQuery();
+ };
+
+ // 澶勭悊鑳芥簮绫诲瀷鍙樺寲
+ const handleEnergyTypeChange = value => {
+ const selectedType = energyTypeList.value.find(item => item.id === value);
+ if (selectedType) {
+ form.energyName = selectedType.energyName;
+ form.energyId = selectedType.id;
+ form.unit = selectedType.unit;
+ }
+ };
+
+ // 鏂板
+ const handleAdd = () => {
+ isEdit.value = false;
+ currentId.value = null;
+ dialogTitle.value = "鏂板鑳借�楄褰�";
+ resetForm();
+ dialogVisible.value = true;
+ };
+
+ // 缂栬緫
+ const handleEdit = row => {
+ isEdit.value = true;
+ currentId.value = row.id;
+ dialogTitle.value = "缂栬緫鑳借�楄褰�";
+ Object.assign(form, row);
+ dialogVisible.value = true;
+ };
+
+ // 鍒犻櫎
+ const handleDelete = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鑳借�楄褰曞悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ tableLoading.value = true;
+ energyConsumptionDetailDelete([row.id])
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ });
+ };
+
+ // 閲嶇疆琛ㄥ崟
+ const resetForm = () => {
+ form.meterReadingDate = "";
+ form.energyType = "";
+ form.energyName = "";
+ form.energyId = "";
+ form.meterReadingLocation = "";
+ form.startCode = 0;
+ form.stopCode = 0;
+ form.dosage = 0;
+ form.unit = "";
+ form.remark = "";
+ form.type = "鍔炲叕";
+ };
+
+ // 鎻愪氦琛ㄥ崟
+ const handleSubmit = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ tableLoading.value = true;
+ energyConsumptionDetailAdd(form)
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ dialogVisible.value = false;
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鎿嶄綔澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ }
+ });
+ };
+
+ onMounted(() => {
+ getEnergyTypeList();
+ handleQuery();
+ });
+</script>
+
+<style scoped lang="scss">
+ .app-container {
+ padding: 24px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 48px);
+ }
+
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+ }
+ }
+
+ .table_list {
+ // margin-bottom: 24px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ height: calc(100vh - 250px);
+ }
+
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-table__header-wrapper {
+ background-color: #fafafa;
+
+ th {
+ background-color: #fafafa;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #ebeef5;
+ padding: 14px 0;
+ }
+ }
+
+ .el-table__body-wrapper {
+ tr {
+ transition: all 0.3s ease;
+
+ &:hover {
+ background-color: #f5f7fa;
+ }
+
+ td {
+ border-bottom: 1px solid #ebeef5;
+ padding: 12px 0;
+ }
+ }
+
+ tr.current-row {
+ background-color: #ecf5ff;
+ }
+ }
+
+ .el-table__empty-block {
+ padding: 40px 0;
+ }
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #ffffff;
+ border-top: 1px solid #ebeef5;
+ border-radius: 0 0 12px 12px;
+ }
+
+ :deep(.el-button) {
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ }
+
+ :deep(.el-dialog) {
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-dialog__header {
+ background-color: #fafafa;
+ border-bottom: 1px solid #ebeef5;
+ padding: 20px 24px;
+
+ .el-dialog__title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .el-dialog__body {
+ padding: 24px;
+ }
+
+ .el-dialog__footer {
+ padding: 16px 24px;
+ border-top: 1px solid #ebeef5;
+ background-color: #fafafa;
+ }
+ }
+
+ :deep(.el-form) {
+ .el-form-item {
+ margin-bottom: 20px;
+
+ .el-form-item__label {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .el-input,
+ .el-select,
+ .el-date-picker,
+ .el-input-number {
+ width: 100%;
+
+ // .el-input__inner {
+ // border-radius: 6px;
+ // border: 1px solid #dcdfe6;
+ // transition: all 0.3s ease;
+
+ // &:focus {
+ // border-color: #409eff;
+ // box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+ // }
+ // }
+ }
+ }
+ }
+
+ :deep(.el-tag) {
+ border-radius: 4px;
+ padding: 2px 8px;
+ font-size: 12px;
+ }
+
+ @media (max-width: 768px) {
+ .app-container {
+ padding: 16px;
+ }
+
+ .search_form {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .el-form {
+ width: 100%;
+
+ .el-form-item {
+ width: 100%;
+ }
+ }
+
+ > div {
+ width: 100%;
+ display: flex;
+ gap: 12px;
+
+ .el-button {
+ flex: 1;
+ }
+ }
+ }
+
+ :deep(.el-table) {
+ th,
+ td {
+ padding: 10px 0;
+ font-size: 12px;
+ }
+ }
+
+ :deep(.el-dialog) {
+ width: 90% !important;
+ margin: 20px auto !important;
+ }
+ }
+ .consumption-value {
+ font-weight: bold;
+ color: #409eff;
+ }
+
+ .consumption-unit {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 4px;
+ }
+ .search_form {
+ :deep(.el-form-item) {
+ margin-bottom: 0px !important;
+ }
+ }
+</style>
diff --git a/src/views/energyManagement/productionEnergyConsumption/index.vue b/src/views/energyManagement/productionEnergyConsumption/index.vue
new file mode 100644
index 0000000..7a69ec2
--- /dev/null
+++ b/src/views/energyManagement/productionEnergyConsumption/index.vue
@@ -0,0 +1,696 @@
+<template>
+ <div class="app-container">
+ <!-- 鎼滅储鍖哄煙 -->
+ <div class="search_form">
+ <el-form :model="searchForm"
+ :inline="true">
+ <el-form-item label="鑳借�楃被鍨�:">
+ <el-select v-model="searchForm.energyType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 140px;"
+ @change="handleQuery">
+ <el-option label="姘�"
+ value="water" />
+ <el-option label="鐢�"
+ value="electricity" />
+ <el-option label="姘�"
+ value="gas" />
+ </el-select>
+ </el-form-item>
+ <!-- <el-form-item label="鏃ユ湡鑼冨洿:">
+ <el-date-picker v-model="searchForm.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 240px;"
+ @change="handleQuery" />
+ </el-form-item> -->
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleQuery">鎼滅储</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ <div>
+ <el-button type="primary"
+ @click="handleAdd">鏂板</el-button>
+ <el-button type="success"
+ @click="handleExport">瀵煎嚭</el-button>
+ </div>
+ </div>
+ <!-- 鏁版嵁琛ㄦ牸 -->
+ <div class="table_list">
+ <el-table :data="tableData"
+ v-loading="tableLoading"
+ border
+ height="calc(100vh - 350px)"
+ stripe>
+ <el-table-column type="index"
+ label="搴忓彿"
+ width="60"
+ align="center" />
+ <el-table-column prop="meterReadingDate"
+ label="鎶勮〃鏃ユ湡"
+ width="120"
+ sortable
+ align="center" />
+ <el-table-column prop="energyType"
+ label="鑳芥簮绫诲瀷"
+ width="100"
+ align="center">
+ <template #default="scope">
+ <el-tag :type="getEnergyTypeType(scope.row.energyTyep)">
+ {{ scope.row.energyTyep }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="energyName"
+ label="鑳芥簮鍚嶇О"
+ align="center" />
+ <el-table-column prop="meterReadingLocation"
+ label="鎶勮〃浣嶇疆"
+ align="center" />
+ <el-table-column prop="startCode"
+ label="璧风爜"
+ sortable
+ align="right" />
+ <el-table-column prop="stopCode"
+ label="姝㈢爜"
+ sortable
+ align="right" />
+ <el-table-column prop="dosage"
+ label="鐢ㄩ噺"
+ sortable
+ align="right">
+ <template #default="scope">
+ <span class="consumption-value">{{ scope.row.dosage }}</span>
+ <span class="consumption-unit">{{ scope.row.unit }}</span>
+ </template>
+ </el-table-column>
+ <!-- <el-table-column prop="unit"
+ label="鍗曚綅"
+ width="80"
+ align="center" /> -->
+ <!-- <el-table-column prop="energyId"
+ label="鑳芥簮绫诲瀷ID"
+ width="120"
+ align="center" /> -->
+ <el-table-column prop="remark"
+ label="澶囨敞"
+ min-width="150"
+ show-overflow-tooltip />
+ <el-table-column label="鎿嶄綔"
+ width="180"
+ align="center"
+ fixed="right">
+ <template #default="scope">
+ <el-button type="primary"
+ link
+ @click="handleEdit(scope.row)">缂栬緫</el-button>
+ <el-button type="danger"
+ link
+ @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <div class="pagination-container">
+ <el-pagination v-model:current-page="page.current"
+ v-model:page-size="page.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="page.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange" />
+ </div>
+ </div>
+ <!-- 鍒嗛〉 -->
+ <!-- 鏂板/缂栬緫寮圭獥 -->
+ <el-dialog v-model="dialogVisible"
+ :title="dialogTitle"
+ width="600px">
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ label-width="120px">
+ <el-form-item label="鎶勮〃鏃ユ湡"
+ prop="meterReadingDate">
+ <el-date-picker v-model="form.meterReadingDate"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鑳芥簮绫诲瀷"
+ prop="energyType">
+ <el-select v-model="form.energyType"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%;"
+ @change="handleEnergyTypeChange">
+ <el-option v-for="item in energyTypeList"
+ :key="item.id"
+ :label="item.energyName"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鎶勮〃浣嶇疆"
+ prop="meterReadingLocation">
+ <el-input v-model="form.meterReadingLocation"
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="璧风爜"
+ prop="startCode">
+ <el-input-number v-model="form.startCode"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="姝㈢爜"
+ prop="stopCode">
+ <el-input-number v-model="form.stopCode"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鐢ㄩ噺"
+ prop="dosage">
+ <el-input-number v-model="form.dosage"
+ :min="0"
+ style="width: 100%;" />
+ </el-form-item>
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="form.unit"
+ disabled
+ placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ rows="3" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary"
+ @click="handleSubmit">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Watermelon, Lightning } from "@element-plus/icons-vue";
+ import {
+ energyConsumptionDetailListPage,
+ energyConsumptionDetailAdd,
+ energyConsumptionDetailDelete,
+ energyTypeListPage,
+ } from "@/api/energyManagement/energyType";
+
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ energyType: "",
+ dateRange: [],
+ });
+ const { proxy } = getCurrentInstance();
+
+ // 缁熻鏁版嵁
+ const statistics = reactive({
+ waterTotal: 1256.8,
+ waterAmount: "3,142.00",
+ electricityTotal: 8520.5,
+ electricityAmount: "6,816.40",
+ gasTotal: 3200.6,
+ gasAmount: "9,601.80",
+ });
+
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鍒嗛〉
+ const page = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+
+ // 寮圭獥鎺у埗
+ const dialogVisible = ref(false);
+ const dialogTitle = ref("鏂板鑳借�楄褰�");
+ const formRef = ref(null);
+ const isEdit = ref(false);
+ const currentId = ref(null);
+
+ // 琛ㄥ崟鏁版嵁
+ const form = reactive({
+ meterReadingDate: "",
+ energyType: "",
+ energyName: "",
+ energyId: "",
+ meterReadingLocation: "",
+ startCode: 0,
+ stopCode: 0,
+ dosage: 0,
+ unit: "",
+ remark: "",
+ type: "鐢熶骇",
+ });
+
+ // 琛ㄥ崟鏍¢獙瑙勫垯
+ const rules = {
+ meterReadingDate: [
+ { required: true, message: "璇烽�夋嫨鎶勮〃鏃ユ湡", trigger: "change" },
+ ],
+ energyType: [
+ { required: true, message: "璇烽�夋嫨鑳芥簮绫诲瀷", trigger: "change" },
+ ],
+ energyName: [
+ { required: true, message: "璇烽�夋嫨鑳芥簮鍚嶇О", trigger: "change" },
+ ],
+ energyId: [{ required: true, message: "璇烽�夋嫨鑳芥簮绫诲瀷", trigger: "change" }],
+ meterReadingLocation: [
+ { required: true, message: "璇疯緭鍏ユ妱琛ㄤ綅缃�", trigger: "blur" },
+ ],
+ startCode: [{ required: true, message: "璇疯緭鍏ヨ捣鐮�", trigger: "blur" }],
+ stopCode: [{ required: true, message: "璇疯緭鍏ユ鐮�", trigger: "blur" }],
+ dosage: [{ required: true, message: "璇疯緭鍏ョ敤閲�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇疯緭鍏ュ崟浣�", trigger: "blur" }],
+ };
+
+ // 鑾峰彇鑳借�楃被鍨嬫牱寮�
+ const getEnergyTypeType = type => {
+ const typeMap = {
+ 姘�: "primary",
+ 鐢�: "warning",
+ 姘�: "success",
+ water: "primary",
+ electricity: "warning",
+ gas: "success",
+ };
+ return typeMap[type] || "info";
+ };
+
+ // 鑾峰彇鑳借�楃被鍨嬫枃鏈�
+ const getEnergyTypeText = type => {
+ const textMap = {
+ water: "姘�",
+ electricity: "鐢�",
+ gas: "姘�",
+ };
+ return textMap[type] || type;
+ };
+
+ // 鏌ヨ
+ const handleQuery = () => {
+ tableLoading.value = true;
+ const params = {
+ current: page.current,
+ size: page.size,
+ type: "鐢熶骇",
+ // energyType: searchForm.energyType,
+ // startDate:
+ // searchForm.dateRange && searchForm.dateRange.length === 2
+ // ? searchForm.dateRange[0]
+ // : null,
+ // endDate:
+ // searchForm.dateRange && searchForm.dateRange.length === 2
+ // ? searchForm.dateRange[1]
+ // : null,
+ };
+ energyConsumptionDetailListPage(params)
+ .then(res => {
+ if (res.code === 200) {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ } else {
+ ElMessage.error(res.message || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+ const energyTypeList = ref([]);
+ const getEnergyTypeList = () => {
+ energyTypeListPage({ current: -1, size: -1 })
+ .then(res => {
+ if (res.code === 200) {
+ energyTypeList.value = res.data.records;
+ } else {
+ ElMessage.error(res.message || "鏌ヨ澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ });
+ };
+
+ // 閲嶇疆
+ const handleReset = () => {
+ searchForm.energyType = "";
+ searchForm.dateRange = [];
+ page.current = 1;
+ handleQuery();
+ };
+
+ // 瀵煎嚭
+ const handleExport = () => {
+ proxy.download(
+ "/energyConsumptionDetail/export",
+ { type: "鐢熶骇" },
+ "鑳借�楁槑缁�.xlsx"
+ );
+ };
+
+ // 鍒嗛〉澶у皬鍙樺寲
+ const handleSizeChange = val => {
+ page.size = val;
+ handleQuery();
+ };
+
+ // 椤电爜鍙樺寲
+ const handleCurrentChange = val => {
+ page.current = val;
+ handleQuery();
+ };
+
+ // 澶勭悊鑳芥簮绫诲瀷鍙樺寲
+ const handleEnergyTypeChange = value => {
+ const selectedType = energyTypeList.value.find(item => item.id === value);
+ if (selectedType) {
+ form.energyName = selectedType.energyName;
+ form.energyId = selectedType.id;
+ form.unit = selectedType.unit;
+ }
+ };
+
+ // 鏂板
+ const handleAdd = () => {
+ isEdit.value = false;
+ currentId.value = null;
+ dialogTitle.value = "鏂板鑳借�楄褰�";
+ resetForm();
+ dialogVisible.value = true;
+ };
+
+ // 缂栬緫
+ const handleEdit = row => {
+ isEdit.value = true;
+ currentId.value = row.id;
+ dialogTitle.value = "缂栬緫鑳借�楄褰�";
+ Object.assign(form, row);
+ dialogVisible.value = true;
+ };
+
+ // 鍒犻櫎
+ const handleDelete = row => {
+ ElMessageBox.confirm("纭畾瑕佸垹闄よ鑳借�楄褰曞悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ tableLoading.value = true;
+ energyConsumptionDetailDelete([row.id])
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ });
+ };
+
+ // 閲嶇疆琛ㄥ崟
+ const resetForm = () => {
+ form.meterReadingDate = "";
+ form.energyType = "";
+ form.energyName = "";
+ form.energyId = "";
+ form.meterReadingLocation = "";
+ form.startCode = 0;
+ form.stopCode = 0;
+ form.dosage = 0;
+ form.unit = "";
+ form.remark = "";
+ form.type = "鐢熶骇";
+ };
+
+ // 鎻愪氦琛ㄥ崟
+ const handleSubmit = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ tableLoading.value = true;
+ energyConsumptionDetailAdd(form)
+ .then(res => {
+ if (res.code === 200) {
+ ElMessage.success(isEdit.value ? "缂栬緫鎴愬姛" : "鏂板鎴愬姛");
+ dialogVisible.value = false;
+ handleQuery();
+ } else {
+ ElMessage.error(res.message || "鎿嶄綔澶辫触");
+ }
+ })
+ .catch(error => {
+ ElMessage.error("缃戠粶閿欒锛岃绋嶅悗閲嶈瘯");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ }
+ });
+ };
+
+ onMounted(() => {
+ getEnergyTypeList();
+ handleQuery();
+ });
+</script>
+
+<style scoped lang="scss">
+ .app-container {
+ padding: 24px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 48px);
+ }
+
+ .search_form {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+ }
+ }
+
+ .table_list {
+ // margin-bottom: 24px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ height: calc(100vh - 250px);
+ }
+
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-table__header-wrapper {
+ background-color: #fafafa;
+
+ th {
+ background-color: #fafafa;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #ebeef5;
+ padding: 14px 0;
+ }
+ }
+
+ .el-table__body-wrapper {
+ tr {
+ transition: all 0.3s ease;
+
+ &:hover {
+ background-color: #f5f7fa;
+ }
+
+ td {
+ border-bottom: 1px solid #ebeef5;
+ padding: 12px 0;
+ }
+ }
+
+ tr.current-row {
+ background-color: #ecf5ff;
+ }
+ }
+
+ .el-table__empty-block {
+ padding: 40px 0;
+ }
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #ffffff;
+ border-top: 1px solid #ebeef5;
+ border-radius: 0 0 12px 12px;
+ }
+
+ :deep(.el-button) {
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ }
+
+ :deep(.el-dialog) {
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-dialog__header {
+ background-color: #fafafa;
+ border-bottom: 1px solid #ebeef5;
+ padding: 20px 24px;
+
+ .el-dialog__title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .el-dialog__body {
+ padding: 24px;
+ }
+
+ .el-dialog__footer {
+ padding: 16px 24px;
+ border-top: 1px solid #ebeef5;
+ background-color: #fafafa;
+ }
+ }
+
+ :deep(.el-form) {
+ .el-form-item {
+ margin-bottom: 20px;
+
+ .el-form-item__label {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .el-input,
+ .el-select,
+ .el-date-picker,
+ .el-input-number {
+ width: 100%;
+
+ // .el-input__inner {
+ // border-radius: 6px;
+ // border: 1px solid #dcdfe6;
+ // transition: all 0.3s ease;
+
+ // &:focus {
+ // border-color: #409eff;
+ // box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+ // }
+ // }
+ }
+ }
+ }
+
+ :deep(.el-tag) {
+ border-radius: 4px;
+ padding: 2px 8px;
+ font-size: 12px;
+ }
+
+ @media (max-width: 768px) {
+ .app-container {
+ padding: 16px;
+ }
+
+ .search_form {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .el-form {
+ width: 100%;
+
+ .el-form-item {
+ width: 100%;
+ }
+ }
+
+ > div {
+ width: 100%;
+ display: flex;
+ gap: 12px;
+
+ .el-button {
+ flex: 1;
+ }
+ }
+ }
+
+ :deep(.el-table) {
+ th,
+ td {
+ padding: 10px 0;
+ font-size: 12px;
+ }
+ }
+
+ :deep(.el-dialog) {
+ width: 90% !important;
+ margin: 20px auto !important;
+ }
+ }
+ .consumption-value {
+ font-weight: bold;
+ color: #409eff;
+ }
+
+ .consumption-unit {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 4px;
+ }
+ .search_form {
+ :deep(.el-form-item) {
+ margin-bottom: 0px !important;
+ }
+ }
+</style>
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index 15c1fa9..7c475ce 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -50,6 +50,7 @@
:column="tableColumn"
:tableData="tableData"
:page="page"
+ height="calc(100vh - 350px)"
:tableLoading="tableLoading"
:isSelection="true"
:selectable="isSelectable"
@@ -63,12 +64,12 @@
width="500px">
<el-form :model="mergeForm"
label-width="120px">
- <el-form-item label="鐢熶骇璁″垝鍙�">
- <el-input v-model="mergeForm.productionPlanNo"
+ <el-form-item label="搴忓垪鍙�">
+ <el-input v-model="mergeForm.serialNo"
disabled />
</el-form-item>
<el-form-item label="鐢熶骇璁″垝鏁伴噺">
- <el-input-number v-model="mergeForm.totalManufactureQuantity"
+ <el-input-number v-model="mergeForm.totalquantity"
:min="1"
:step="1"
style="width: 100%" />
@@ -93,17 +94,83 @@
<el-table :data="categorySummary"
border
style="width: 100%">
- <el-table-column prop="productCategory"
+ <el-table-column prop="materialCategory"
label="浜у搧绫诲埆"
align="center"
width="150" />
- <el-table-column prop="totalManufactureQuantity"
+ <el-table-column prop="totalquantity"
label="鎬诲埗閫犳暟閲�"
align="center" />
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button @click="showCategorySummaryDialog = false">鍏抽棴</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ <!-- 杩借釜杩涘害寮圭獥 -->
+ <el-dialog v-model="showTrackProgressDialog"
+ :title="`杩借釜杩涘害 - ${trackProgressForm.serialNo || ''}`"
+ width="600px">
+ <el-form :model="trackProgressForm"
+ label-width="120px">
+ <el-form-item label="搴忓垪鍙�">
+ <el-input v-model="trackProgressForm.serialNo"
+ disabled />
+ </el-form-item>
+ <el-form-item label="褰撳墠鐘舵��">
+ <el-select v-model="trackProgressForm.currentStatus"
+ placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="寰呭鐞�"
+ value="pending" />
+ <el-option label="杩涜涓�"
+ value="processing" />
+ <el-option label="宸插畬鎴�"
+ value="completed" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="瀹屾垚杩涘害">
+ <el-progress :percentage="trackProgressForm.completionRate"
+ :status="trackProgressForm.completionRate === 100 ? 'success' : ''" />
+ </el-form-item>
+ <el-form-item label="杩涘害璇︽儏">
+ <el-table :data="trackProgressForm.progressDetails"
+ border
+ style="width: 100%">
+ <el-table-column prop="step"
+ label="姝ラ"
+ align="center"
+ width="100" />
+ <el-table-column prop="status"
+ label="鐘舵��"
+ align="center"
+ width="100">
+ <template #default="scope">
+ <el-tag :type="scope.row.status === 'completed' ? 'success' : scope.row.status === 'processing' ? 'warning' : 'info'">
+ {{ scope.row.status === 'completed' ? '宸插畬鎴�' : scope.row.status === 'processing' ? '杩涜涓�' : '寰呭紑濮�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="startTime"
+ label="寮�濮嬫椂闂�"
+ align="center"
+ width="180" />
+ <el-table-column prop="endTime"
+ label="缁撴潫鏃堕棿"
+ align="center"
+ width="180" />
+ </el-table>
+ </el-form-item>
+ <el-form-item label="澶囨敞">
+ <el-input v-model="trackProgressForm.remark"
+ type="textarea" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="showTrackProgressDialog = false">鍏抽棴</el-button>
+ <el-button type="primary"
+ @click="handleUpdateProgress">鏇存柊杩涘害</el-button>
</span>
</template>
</el-dialog>
@@ -114,7 +181,7 @@
import { onMounted, ref } from "vue";
import { ElMessage } from "element-plus";
import dayjs from "dayjs";
- import { productOrderListPage } from "@/api/productionManagement/productionOrder.js";
+ import { productionPlanListPage } from "@/api/productionPlan/productionPlan.js";
import PIMTable from "./components/PIMTable.vue";
const tableColumn = ref([
@@ -139,8 +206,8 @@
width: "120px",
},
{
- label: "鐢熶骇璁″垝鍙�",
- prop: "productionPlanNo",
+ label: "搴忓垪鍙�",
+ prop: "serialNo",
width: "140px",
},
{
@@ -155,7 +222,7 @@
},
{
label: "浜у搧绫诲埆",
- prop: "productCategory",
+ prop: "materialCategory",
width: "100px",
},
{
@@ -171,7 +238,7 @@
},
{
label: "鍒堕�犳暟閲�",
- prop: "manufactureQuantity",
+ prop: "quantity",
width: "100px",
align: "right",
},
@@ -237,8 +304,8 @@
clickFun: row => {
// 鍗曠嫭涓嬪彂鎿嶄綔
// 璁剧疆琛ㄥ崟鏁版嵁
- mergeForm.productionPlanNo = row.productionPlanNo;
- mergeForm.totalManufactureQuantity = row.manufactureQuantity;
+ mergeForm.serialNo = row.serialNo;
+ mergeForm.totalquantity = row.quantity;
mergeForm.remark = "";
// 鎵撳紑寮圭獥
@@ -249,8 +316,7 @@
name: "杩借釜杩涘害",
type: "text",
clickFun: row => {
- // 杩借釜杩涘害鎿嶄綔
- ElMessage.warning("杩借釜杩涘害鍔熻兘寰呭紑鍙�");
+ handleTrackProgress(row);
},
},
],
@@ -274,17 +340,118 @@
const isShowNewModal = ref(false);
// 鍚堝苟涓嬪彂琛ㄥ崟鏁版嵁
const mergeForm = reactive({
- productionPlanNo: "",
- totalManufactureQuantity: 0,
+ serialNo: "",
+ totalquantity: 0,
remark: "",
});
+
+ // 杩借釜杩涘害寮圭獥鎺у埗
+ const showTrackProgressDialog = ref(false);
+ // 杩借釜杩涘害琛ㄥ崟鏁版嵁
+ const trackProgressForm = reactive({
+ serialNo: "",
+ currentStatus: "",
+ completionRate: 0,
+ progressDetails: [],
+ remark: "",
+ });
+
+ // 澶勭悊杩借釜杩涘害鎸夐挳鐐瑰嚮
+ const handleTrackProgress = row => {
+ // 璁剧疆琛ㄥ崟鏁版嵁
+ trackProgressForm.serialNo = row.serialNo;
+ trackProgressForm.currentStatus = row.status;
+
+ // 鐢熸垚妯℃嫙杩涘害鏁版嵁
+ trackProgressForm.progressDetails = generateProgressDetails(row.status);
+
+ // 璁$畻瀹屾垚鐜�
+ trackProgressForm.completionRate = calculateCompletionRate(
+ trackProgressForm.progressDetails
+ );
+ trackProgressForm.remark = "";
+
+ // 鎵撳紑寮圭獥
+ showTrackProgressDialog.value = true;
+ };
+
+ // 鐢熸垚妯℃嫙杩涘害璇︽儏鏁版嵁
+ const generateProgressDetails = status => {
+ const details = [
+ {
+ step: "璁″垝纭",
+ status: "completed",
+ startTime: "2026-03-01 09:00:00",
+ endTime: "2026-03-01 10:00:00",
+ },
+ {
+ step: "鐗╂枡鍑嗗",
+ status:
+ status === "completed"
+ ? "completed"
+ : status === "processing"
+ ? "completed"
+ : "pending",
+ startTime:
+ status === "completed" || status === "processing"
+ ? "2026-03-01 10:30:00"
+ : "",
+ endTime:
+ status === "completed" || status === "processing"
+ ? "2026-03-02 16:00:00"
+ : "",
+ },
+ {
+ step: "鐢熶骇鍔犲伐",
+ status:
+ status === "completed"
+ ? "completed"
+ : status === "processing"
+ ? "processing"
+ : "pending",
+ startTime:
+ status === "completed" || status === "processing"
+ ? "2026-03-03 08:00:00"
+ : "",
+ endTime: status === "completed" ? "2026-03-08 17:00:00" : "",
+ },
+ {
+ step: "璐ㄩ噺妫�楠�",
+ status: status === "completed" ? "completed" : "pending",
+ startTime: status === "completed" ? "2026-03-09 09:00:00" : "",
+ endTime: status === "completed" ? "2026-03-09 15:00:00" : "",
+ },
+ {
+ step: "鍏ュ簱",
+ status: status === "completed" ? "completed" : "pending",
+ startTime: status === "completed" ? "2026-03-10 10:00:00" : "",
+ endTime: status === "completed" ? "2026-03-10 11:00:00" : "",
+ },
+ ];
+ return details;
+ };
+
+ // 璁$畻瀹屾垚鐜�
+ const calculateCompletionRate = details => {
+ const completedSteps = details.filter(
+ step => step.status === "completed"
+ ).length;
+ return Math.round((completedSteps / details.length) * 100);
+ };
+
+ // 澶勭悊杩涘害鏇存柊
+ const handleUpdateProgress = () => {
+ // 杩欓噷鍙互娣诲姞鏇存柊杩涘害鐨勯�昏緫
+ ElMessage.success("杩涘害鏇存柊鎴愬姛");
+ showTrackProgressDialog.value = false;
+ };
const data = reactive({
searchForm: {
customerName: "",
salesContractNo: "",
projectName: "",
- productCategory: "",
+ materialCategory: "",
specificationModel: "",
},
});
@@ -307,14 +474,14 @@
// 閬嶅巻琛ㄦ牸鏁版嵁锛屾寜浜у搧绫诲埆姹囨��
tableData.value.forEach(row => {
- const category = row.productCategory;
+ const category = row.materialCategory;
if (!summary[category]) {
summary[category] = {
- productCategory: category,
- totalManufactureQuantity: 0,
+ materialCategory: category,
+ totalquantity: 0,
};
}
- summary[category].totalManufactureQuantity += row.manufactureQuantity;
+ summary[category].totalquantity += row.quantity;
});
// 杞崲涓烘暟缁勬牸寮�
@@ -326,164 +493,164 @@
// 鏋勯�犱竴涓柊鐨勫璞★紝涓嶅寘鍚玡ntryDate瀛楁
const params = { ...searchForm.value, ...page };
params.entryDate = undefined;
- tableData.value = [
- {
- id: 1,
- source: "閿�鍞鍗�",
- status: "寰呭鐞�",
- auditStatus: "宸插鏍�",
- orderNo: "SO20260301001",
- productionPlanNo: "PP20260301001",
- partNo: "P001",
- partName: "闆朵欢A",
- productCategory: "绫诲埆1",
- processFileNo: "PF20260301001",
- salesQuantity: 100,
- manufactureQuantity: 105,
- partUnit: "涓�",
- mainPlanDemandDate: "2026-03-15",
- commitmentDate: "2026-03-10",
- manufactureProperty: "甯歌",
- remark: "",
- updateTime: "2026-03-01",
- updateBy: "admin",
- createTime: "2026-03-01",
- createBy: "admin",
- },
- {
- id: 2,
- source: "閿�鍞鍗�",
- status: "寰呭鐞�",
- auditStatus: "宸插鏍�",
- orderNo: "SO20260301002",
- productionPlanNo: "PP20260301001",
- partNo: "P002",
- partName: "闆朵欢B",
- productCategory: "绫诲埆1",
- processFileNo: "PF20260301002",
- salesQuantity: 200,
- manufactureQuantity: 210,
- partUnit: "涓�",
- mainPlanDemandDate: "2026-03-15",
- commitmentDate: "2026-03-10",
- manufactureProperty: "甯歌",
- remark: "",
- updateTime: "2026-03-01",
- updateBy: "admin",
- createTime: "2026-03-01",
- createBy: "admin",
- },
- {
- id: 3,
- source: "閿�鍞鍗�",
- status: "杩涜涓�",
- auditStatus: "宸插鏍�",
- orderNo: "SO20260301003",
- productionPlanNo: "PP20260301002",
- partNo: "P003",
- partName: "闆朵欢C",
- productCategory: "绫诲埆2",
- processFileNo: "PF20260301003",
- salesQuantity: 150,
- manufactureQuantity: 155,
- partUnit: "涓�",
- mainPlanDemandDate: "2026-03-20",
- commitmentDate: "2026-03-15",
- manufactureProperty: "甯歌",
- remark: "",
- updateTime: "2026-03-01",
- updateBy: "admin",
- createTime: "2026-03-01",
- createBy: "admin",
- },
- {
- id: 4,
- source: "閿�鍞鍗�",
- status: "杩涜涓�",
- auditStatus: "宸插鏍�",
- orderNo: "SO20260301004",
- productionPlanNo: "PP20260301002",
- partNo: "P004",
- partName: "闆朵欢D",
- productCategory: "绫诲埆2",
- processFileNo: "PF20260301004",
- salesQuantity: 300,
- manufactureQuantity: 315,
- partUnit: "涓�",
- mainPlanDemandDate: "2026-03-20",
- commitmentDate: "2026-03-15",
- manufactureProperty: "甯歌",
- remark: "",
- updateTime: "2026-03-01",
- updateBy: "admin",
- createTime: "2026-03-01",
- createBy: "admin",
- },
- {
- id: 5,
- source: "閿�鍞鍗�",
- status: "宸插畬鎴�",
- auditStatus: "宸插鏍�",
- orderNo: "SO20260301005",
- productionPlanNo: "PP20260301003",
- partNo: "P005",
- partName: "闆朵欢E",
- productCategory: "绫诲埆3",
- processFileNo: "PF20260301005",
- salesQuantity: 250,
- manufactureQuantity: 260,
- partUnit: "涓�",
- mainPlanDemandDate: "2026-03-10",
- commitmentDate: "2026-03-05",
- manufactureProperty: "甯歌",
- remark: "",
- updateTime: "2026-03-01",
- updateBy: "admin",
- createTime: "2026-03-01",
- createBy: "admin",
- },
- ];
- tableLoading.value = false;
- page.total = tableData.value.length;
- // 璁$畻浜у搧绫诲埆姹囨�荤粺璁�
- calculateCategorySummary();
- // productOrderListPage(params)
- // .then(res => {
- // tableLoading.value = false;
+ // tableData.value = [
+ // {
+ // id: 1,
+ // source: "閿�鍞鍗�",
+ // status: "寰呭鐞�",
+ // auditStatus: "宸插鏍�",
+ // orderNo: "SO20260301001",
+ // serialNo: "PP20260301001",
+ // partNo: "P001",
+ // partName: "闆朵欢A",
+ // materialCategory: "绫诲埆1",
+ // processFileNo: "PF20260301001",
+ // salesQuantity: 100,
+ // quantity: 105,
+ // partUnit: "涓�",
+ // mainPlanDemandDate: "2026-03-15",
+ // commitmentDate: "2026-03-10",
+ // manufactureProperty: "甯歌",
+ // remark: "",
+ // updateTime: "2026-03-01",
+ // updateBy: "admin",
+ // createTime: "2026-03-01",
+ // createBy: "admin",
+ // },
+ // {
+ // id: 2,
+ // source: "閿�鍞鍗�",
+ // status: "寰呭鐞�",
+ // auditStatus: "宸插鏍�",
+ // orderNo: "SO20260301002",
+ // serialNo: "PP20260301001",
+ // partNo: "P002",
+ // partName: "闆朵欢B",
+ // materialCategory: "绫诲埆1",
+ // processFileNo: "PF20260301002",
+ // salesQuantity: 200,
+ // quantity: 210,
+ // partUnit: "涓�",
+ // mainPlanDemandDate: "2026-03-15",
+ // commitmentDate: "2026-03-10",
+ // manufactureProperty: "甯歌",
+ // remark: "",
+ // updateTime: "2026-03-01",
+ // updateBy: "admin",
+ // createTime: "2026-03-01",
+ // createBy: "admin",
+ // },
+ // {
+ // id: 3,
+ // source: "閿�鍞鍗�",
+ // status: "杩涜涓�",
+ // auditStatus: "宸插鏍�",
+ // orderNo: "SO20260301003",
+ // serialNo: "PP20260301002",
+ // partNo: "P003",
+ // partName: "闆朵欢C",
+ // materialCategory: "绫诲埆2",
+ // processFileNo: "PF20260301003",
+ // salesQuantity: 150,
+ // quantity: 155,
+ // partUnit: "涓�",
+ // mainPlanDemandDate: "2026-03-20",
+ // commitmentDate: "2026-03-15",
+ // manufactureProperty: "甯歌",
+ // remark: "",
+ // updateTime: "2026-03-01",
+ // updateBy: "admin",
+ // createTime: "2026-03-01",
+ // createBy: "admin",
+ // },
+ // {
+ // id: 4,
+ // source: "閿�鍞鍗�",
+ // status: "杩涜涓�",
+ // auditStatus: "宸插鏍�",
+ // orderNo: "SO20260301004",
+ // serialNo: "PP20260301002",
+ // partNo: "P004",
+ // partName: "闆朵欢D",
+ // materialCategory: "绫诲埆2",
+ // processFileNo: "PF20260301004",
+ // salesQuantity: 300,
+ // quantity: 315,
+ // partUnit: "涓�",
+ // mainPlanDemandDate: "2026-03-20",
+ // commitmentDate: "2026-03-15",
+ // manufactureProperty: "甯歌",
+ // remark: "",
+ // updateTime: "2026-03-01",
+ // updateBy: "admin",
+ // createTime: "2026-03-01",
+ // createBy: "admin",
+ // },
+ // {
+ // id: 5,
+ // source: "閿�鍞鍗�",
+ // status: "宸插畬鎴�",
+ // auditStatus: "宸插鏍�",
+ // orderNo: "SO20260301005",
+ // serialNo: "PP20260301003",
+ // partNo: "P005",
+ // partName: "闆朵欢E",
+ // materialCategory: "绫诲埆3",
+ // processFileNo: "PF20260301005",
+ // salesQuantity: 250,
+ // quantity: 260,
+ // partUnit: "涓�",
+ // mainPlanDemandDate: "2026-03-10",
+ // commitmentDate: "2026-03-05",
+ // manufactureProperty: "甯歌",
+ // remark: "",
+ // updateTime: "2026-03-01",
+ // updateBy: "admin",
+ // createTime: "2026-03-01",
+ // createBy: "admin",
+ // },
+ // ];
+ // tableLoading.value = false;
+ // page.total = tableData.value.length;
+ // // 璁$畻浜у搧绫诲埆姹囨�荤粺璁�
+ // calculateCategorySummary();
+ productionPlanListPage(params)
+ .then(res => {
+ tableLoading.value = false;
- // tableData.value = res.data.records;
- // page.total = res.data.total;
- // // 璁$畻浜у搧绫诲埆姹囨�荤粺璁�
- // calculateCategorySummary();
- // })
- // .catch(() => {
- // tableLoading.value = false;
- // });
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ // 璁$畻浜у搧绫诲埆姹囨�荤粺璁�
+ calculateCategorySummary();
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
};
- // 閫変腑鐨勭敓浜ц鍒掑彿
- const selectedProductionPlanNo = ref("");
+ // 閫変腑鐨勫簭鍒楀彿
+ const selectedserialNo = ref("");
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = selection => {
selectedRows.value = selection;
- // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑鐢熶骇璁″垝鍙�
+ // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑搴忓垪鍙�
if (selection.length > 0) {
- selectedProductionPlanNo.value = selection[0].productionPlanNo;
+ selectedserialNo.value = selection[0].serialNo;
} else {
- // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌虹敓浜ц鍒掑彿
- selectedProductionPlanNo.value = "";
+ // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌哄簭鍒楀彿
+ selectedserialNo.value = "";
}
};
// 鍒ゆ柇琛屾槸鍚﹀彲閫夋嫨
const isSelectable = row => {
// 濡傛灉娌℃湁閫変腑鐨勮锛屾墍鏈夎閮藉彲閫夋嫨
- if (!selectedProductionPlanNo.value) {
+ if (!selectedserialNo.value) {
return true;
}
- // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈夌敓浜ц鍒掑彿鐩稿悓鐨勮鎵嶅彲閫夋嫨
- return row.productionPlanNo === selectedProductionPlanNo.value;
+ // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈夊簭鍒楀彿鐩稿悓鐨勮鎵嶅彲閫夋嫨
+ return row.serialNo === selectedserialNo.value;
};
// 澶勭悊鍚堝苟涓嬪彂鎸夐挳鐐瑰嚮
@@ -495,12 +662,12 @@
// 璁$畻鎬诲埗閫犳暟閲�
const totalQuantity = selectedRows.value.reduce((sum, row) => {
- return sum + row.manufactureQuantity;
+ return sum + row.quantity;
}, 0);
// 璁剧疆琛ㄥ崟鏁版嵁
- mergeForm.productionPlanNo = selectedProductionPlanNo.value;
- mergeForm.totalManufactureQuantity = totalQuantity;
+ mergeForm.serialNo = selectedserialNo.value;
+ mergeForm.totalquantity = totalQuantity;
mergeForm.remark = "";
// 鎵撳紑寮圭獥
@@ -521,56 +688,212 @@
</script>
<style scoped lang="scss">
+ .app-container {
+ padding: 24px;
+ background-color: #f0f2f5;
+ min-height: calc(100vh - 48px);
+ }
+
.search_form {
- align-items: start;
- }
-
- .summary-section {
- margin-bottom: 16px;
- }
-
- .horizontal-summary {
display: flex;
- flex-wrap: wrap;
- gap: 20px;
- padding: 10px 0;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+ padding: 20px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.08);
+ }
}
- .summary-item {
- flex: 1;
- min-width: 120px;
- text-align: center;
- padding: 10px;
- background-color: #f5f7fa;
+ .table_list {
+ // margin-bottom: 24px;
+ background-color: #ffffff;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ height: calc(100vh - 250px);
+ }
+
+ :deep(.el-table) {
+ border: none;
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-table__header-wrapper {
+ background-color: #fafafa;
+
+ th {
+ background-color: #fafafa;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #ebeef5;
+ padding: 14px 0;
+ }
+ }
+
+ .el-table__body-wrapper {
+ tr {
+ transition: all 0.3s ease;
+
+ &:hover {
+ background-color: #f5f7fa;
+ }
+
+ td {
+ border-bottom: 1px solid #ebeef5;
+ padding: 12px 0;
+ }
+ }
+
+ tr.current-row {
+ background-color: #ecf5ff;
+ }
+ }
+
+ .el-table__empty-block {
+ padding: 40px 0;
+ }
+ }
+
+ .pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px 20px;
+ background-color: #ffffff;
+ border-top: 1px solid #ebeef5;
+ border-radius: 0 0 12px 12px;
+ }
+
+ :deep(.el-button) {
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ }
+
+ :deep(.el-dialog) {
+ border-radius: 6px;
+ overflow: hidden;
+
+ .el-dialog__header {
+ background-color: #fafafa;
+ border-bottom: 1px solid #ebeef5;
+ padding: 20px 24px;
+
+ .el-dialog__title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ }
+
+ .el-dialog__body {
+ padding: 24px;
+ }
+
+ .el-dialog__footer {
+ padding: 16px 24px;
+ border-top: 1px solid #ebeef5;
+ background-color: #fafafa;
+ }
+ }
+
+ :deep(.el-form) {
+ .el-form-item {
+ margin-bottom: 20px;
+
+ .el-form-item__label {
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .el-input,
+ .el-select,
+ .el-date-picker,
+ .el-input-number {
+ width: 100%;
+
+ // .el-input__inner {
+ // border-radius: 6px;
+ // border: 1px solid #dcdfe6;
+ // transition: all 0.3s ease;
+
+ // &:focus {
+ // border-color: #409eff;
+ // box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
+ // }
+ // }
+ }
+ }
+ }
+
+ :deep(.el-tag) {
border-radius: 4px;
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+ padding: 2px 8px;
+ font-size: 12px;
}
- .summary-label {
- font-size: 14px;
- color: #606266;
- margin-bottom: 5px;
+ @media (max-width: 768px) {
+ .app-container {
+ padding: 16px;
+ }
+
+ .search_form {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .el-form {
+ width: 100%;
+
+ .el-form-item {
+ width: 100%;
+ }
+ }
+
+ > div {
+ width: 100%;
+ display: flex;
+ gap: 12px;
+
+ .el-button {
+ flex: 1;
+ }
+ }
+ }
+
+ :deep(.el-table) {
+ th,
+ td {
+ padding: 10px 0;
+ font-size: 12px;
+ }
+ }
+
+ :deep(.el-dialog) {
+ width: 90% !important;
+ margin: 20px auto !important;
+ }
+ }
+ .consumption-value {
+ font-weight: bold;
+ color: #409eff;
}
- .summary-value {
- font-size: 18px;
- font-weight: 600;
- color: #303133;
+ .consumption-unit {
+ font-size: 12px;
+ color: #909399;
+ margin-left: 4px;
}
-
- ::v-deep .yellow {
- background-color: #faf0de;
- }
-
- ::v-deep .pink {
- background-color: #fae1de;
- }
-
- ::v-deep .red {
- background-color: #f80202;
- }
-
- ::v-deep .purple {
- background-color: #f4defa;
+ .search_form {
+ :deep(.el-form-item) {
+ margin-bottom: 0px !important;
+ }
}
</style>
--
Gitblit v1.9.3