Merge branch 'dev' into ywx
| | |
| | | # 页颿 é¢
|
| | | VITE_APP_TITLE = æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»
|
| | | VITE_APP_TITLE = æµè¯è¿éå管çç³»ç»
|
| | |
|
| | | # å¼åç¯å¢é
ç½®
|
| | | VITE_APP_ENV = 'development'
|
| | |
|
| | | # æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»/å¼åç¯å¢
|
| | | # æµè¯è¿éå管çç³»ç»/å¼åç¯å¢
|
| | | VITE_APP_BASE_API = '/dev-api'
|
| | |
| | | # 页颿 é¢
|
| | | VITE_APP_TITLE = æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»
|
| | | VITE_APP_TITLE = æµè¯è¿éå管çç³»ç»
|
| | |
|
| | | # ç产ç¯å¢é
ç½®
|
| | | VITE_APP_ENV = 'production'
|
| | |
|
| | | # æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»/ç产ç¯å¢
|
| | | # æµè¯è¿éå管çç³»ç»/ç产ç¯å¢
|
| | | VITE_APP_BASE_API = '/prod-api'
|
| | |
|
| | | # æ¯å¦å¨æå
æ¶å¼å¯åç¼©ï¼æ¯æ gzip å brotli
|
| | |
| | | # 页颿 é¢
|
| | | VITE_APP_TITLE = æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»
|
| | | VITE_APP_TITLE = æµè¯è¿éå管çç³»ç»
|
| | |
|
| | | # ç产ç¯å¢é
ç½®
|
| | | VITE_APP_ENV = 'staging'
|
| | |
|
| | | # æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»/ç产ç¯å¢
|
| | | # æµè¯è¿éå管çç³»ç»/ç产ç¯å¢
|
| | | VITE_APP_BASE_API = '/stage-api'
|
| | |
|
| | | # æ¯å¦å¨æå
æ¶å¼å¯åç¼©ï¼æ¯æ gzip å brotli
|
| | |
| | | name="viewport"
|
| | | content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
|
| | | />
|
| | | <link rel="icon" href="/DHDCico.ico" />
|
| | | <title>æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»</title>
|
| | | <link rel="icon" href="/ZQHXico.ico" />
|
| | | <title>æµè¯è¿éå管çç³»ç»</title>
|
| | | <!--[if lt IE 11
|
| | | ]><script>
|
| | | window.location.href = "/html/ie.html";
|
| | |
| | | { |
| | | "name": "ruoyi", |
| | | "version": "3.8.9", |
| | | "description": "æ¦ç
é¼è¯ç®¡çä¿¡æ¯ç³»ç»", |
| | | "description": "æµè¯è¿éå管çç³»ç»", |
| | | "author": "è¥ä¾", |
| | | "license": "MIT", |
| | | "type": "module", |
| | |
| | | "@vue-office/excel": "^1.7.14", |
| | | "@vueup/vue-quill": "1.2.0", |
| | | "@vueuse/core": "10.11.0", |
| | | "autofit.js": "^3.2.8", |
| | | "axios": "0.28.1", |
| | | "clipboard": "2.0.11", |
| | | "dayjs": "^1.11.13", |
| | |
| | | params, |
| | | }); |
| | | }; |
| | | export const listPageAnalysis = (params) => { |
| | | return request({ |
| | | url: "/account/accountExpense/report/analysis", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢ |
| | | export function add(data) { |
| | |
| | | type: Array, |
| | | default: () => [] |
| | | }, |
| | | visualMap: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | option: { |
| | | type: Object, |
| | | default: () => ({}) |
| | |
| | | const option = { |
| | | color: props.color.length ? props.color : undefined, |
| | | backgroundColor: props.options.backgroundColor || '#fff', |
| | | textStyle: props.options.textStyle || { color: '#333' }, |
| | | xAxis: props.xAxis, |
| | | yAxis: props.yAxis, |
| | | dataset: props.dataset, |
| | |
| | | grid: props.grid, |
| | | legend: props.legend, |
| | | tooltip: props.tooltip, |
| | | visualMap: Object.keys(props.visualMap).length ? props.visualMap : undefined, |
| | | } |
| | | |
| | | chartInstance.clear() |
| | |
| | | |
| | | // Watch all reactive props that affect the chart |
| | | watch( |
| | | () => [props.xAxis, props.series, props.legend, props.tooltip], |
| | | () => [props.xAxis, props.yAxis, props.series, props.legend, props.tooltip, props.visualMap], |
| | | () => { |
| | | if (chartInstance) { |
| | | renderChart() |
| | |
| | | <script setup>
|
| | | import { ref, computed, onMounted, watch } from 'vue'
|
| | | import useUserStore from '@/store/modules/user'
|
| | | import defaultLogo from '@/assets/logo/æ¦ç
é¼è¯.png' // 导å
¥é»è®¤logo
|
| | | import defaultLogo from '@/assets/indexViews/ZQHXLogo.png' // 导å
¥é»è®¤logo
|
| | |
|
| | | defineProps({
|
| | | collapse: {
|
| | |
| | | import { createApp } from "vue";
|
| | |
|
| | | import Cookies from "js-cookie";
|
| | |
|
| | | import ElementPlus from "element-plus";
|
| | | import "element-plus/dist/index.css";
|
| | | import "element-plus/theme-chalk/dark/css-vars.css";
|
| | | import locale from "element-plus/es/locale/lang/zh-cn";
|
| | |
|
| | | import "@/assets/styles/index.scss"; // global css
|
| | |
|
| | | import App from "./App";
|
| | | import store from "./store";
|
| | | import router from "./router";
|
| | | import directive from "./directive"; // directive
|
| | |
|
| | | // 注åæä»¤
|
| | | import plugins from "./plugins"; // plugins
|
| | | import { download } from "@/utils/request";
|
| | |
|
| | | // svg徿
|
| | | import "virtual:svg-icons-register";
|
| | | import SvgIcon from "@/components/SvgIcon";
|
| | | import elementIcons from "@/components/SvgIcon/svgicon";
|
| | | import "./assets/fonts/font.css";
|
| | |
|
| | | import "./permission"; // permission control
|
| | |
|
| | | import { useDict } from "@/utils/dict";
|
| | | import {
|
| | | parseTime,
|
| | | resetForm,
|
| | | addDateRange,
|
| | | handleTree,
|
| | | selectDictLabel,
|
| | | selectDictLabels,
|
| | | } from "@/utils/ruoyi";
|
| | |
|
| | | // å页ç»ä»¶
|
| | | import Pagination from "@/components/Pagination";
|
| | | // èªå®ä¹è¡¨æ ¼å·¥å
·ç»ä»¶
|
| | | import RightToolbar from "@/components/RightToolbar";
|
| | | // 坿æ¬ç»ä»¶
|
| | | import Editor from "@/components/Editor";
|
| | | // æä»¶ä¸ä¼ ç»ä»¶
|
| | | import FileUpload from "@/components/FileUpload";
|
| | | // å¾çä¸ä¼ ç»ä»¶
|
| | | import ImageUpload from "@/components/ImageUpload";
|
| | | // å¾çé¢è§ç»ä»¶
|
| | | import ImagePreview from "@/components/ImagePreview";
|
| | | // åå
¸æ ç¾ç»ä»¶
|
| | | import DictTag from "@/components/DictTag";
|
| | | // è¡¨æ ¼ç»ä»¶
|
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue";
|
| | |
|
| | | import { getToken } from "@/utils/auth";
|
| | | import {
|
| | | calculateTaxExclusiveTotalPrice,
|
| | | summarizeTable,
|
| | | calculateTaxIncludeTotalPrice,
|
| | | } from "@/utils/summarizeTable.js";
|
| | |
|
| | | const app = createApp(App);
|
| | |
|
| | | // å
¨å±æ¹æ³æè½½
|
| | | app.config.globalProperties.useDict = useDict;
|
| | | app.config.globalProperties.download = download;
|
| | | app.config.globalProperties.parseTime = parseTime;
|
| | | app.config.globalProperties.resetForm = resetForm;
|
| | | app.config.globalProperties.summarizeTable = summarizeTable;
|
| | | app.config.globalProperties.calculateTaxExclusiveTotalPrice =
|
| | | calculateTaxExclusiveTotalPrice;
|
| | | app.config.globalProperties.calculateTaxIncludeTotalPrice =
|
| | | calculateTaxIncludeTotalPrice;
|
| | | app.config.globalProperties.handleTree = handleTree;
|
| | | app.config.globalProperties.addDateRange = addDateRange;
|
| | | app.config.globalProperties.selectDictLabel = selectDictLabel;
|
| | | app.config.globalProperties.selectDictLabels = selectDictLabels;
|
| | | app.config.globalProperties.javaApi = "http://114.132.189.42:9033";
|
| | | app.config.globalProperties.HaveJson = (val) => {
|
| | | return JSON.parse(JSON.stringify(val));
|
| | | };
|
| | | app.config.globalProperties.uploadHeader = {
|
| | | Authorization: "Bearer " + getToken(),
|
| | | };
|
| | |
|
| | | // å
¨å±ç»ä»¶æè½½
|
| | | app.component("DictTag", DictTag);
|
| | | app.component("Pagination", Pagination);
|
| | | app.component("FileUpload", FileUpload);
|
| | | app.component("ImageUpload", ImageUpload);
|
| | | app.component("ImagePreview", ImagePreview);
|
| | | app.component("RightToolbar", RightToolbar);
|
| | | app.component("Editor", Editor);
|
| | | app.component("PIMTable", PIMTable);
|
| | |
|
| | | app.use(router);
|
| | | app.use(store);
|
| | | app.use(plugins);
|
| | | app.use(elementIcons);
|
| | | app.component("svg-icon", SvgIcon);
|
| | |
|
| | | directive(app);
|
| | |
|
| | | // 使ç¨element-plus å¹¶ä¸è®¾ç½®å
¨å±ç大å°
|
| | | app.use(ElementPlus, {
|
| | | locale: locale,
|
| | | // æ¯æ largeãdefaultãsmall
|
| | | size: Cookies.get("size") || "default",
|
| | | });
|
| | | app._context.components.ElDialog.props.closeOnClickModal.default = false;
|
| | |
|
| | | app.mount("#app");
|
| | | import { createApp } from "vue"; |
| | | |
| | | import Cookies from "js-cookie"; |
| | | |
| | | import ElementPlus from "element-plus"; |
| | | import "element-plus/dist/index.css"; |
| | | import "element-plus/theme-chalk/dark/css-vars.css"; |
| | | import locale from "element-plus/es/locale/lang/zh-cn"; |
| | | |
| | | import "@/assets/styles/index.scss"; // global css |
| | | |
| | | import App from "./App"; |
| | | import store from "./store"; |
| | | import router from "./router"; |
| | | import directive from "./directive"; // directive |
| | | |
| | | // 注åæä»¤ |
| | | import plugins from "./plugins"; // plugins |
| | | import { download } from "@/utils/request"; |
| | | |
| | | // svg徿 |
| | | import "virtual:svg-icons-register"; |
| | | import SvgIcon from "@/components/SvgIcon"; |
| | | import elementIcons from "@/components/SvgIcon/svgicon"; |
| | | import "./assets/fonts/font.css"; |
| | | |
| | | import "./permission"; // permission control |
| | | |
| | | import { useDict } from "@/utils/dict"; |
| | | import { |
| | | parseTime, |
| | | resetForm, |
| | | addDateRange, |
| | | handleTree, |
| | | selectDictLabel, |
| | | selectDictLabels, |
| | | } from "@/utils/ruoyi"; |
| | | |
| | | // å页ç»ä»¶ |
| | | import Pagination from "@/components/Pagination"; |
| | | // èªå®ä¹è¡¨æ ¼å·¥å
·ç»ä»¶ |
| | | import RightToolbar from "@/components/RightToolbar"; |
| | | // 坿æ¬ç»ä»¶ |
| | | import Editor from "@/components/Editor"; |
| | | // æä»¶ä¸ä¼ ç»ä»¶ |
| | | import FileUpload from "@/components/FileUpload"; |
| | | // å¾çä¸ä¼ ç»ä»¶ |
| | | import ImageUpload from "@/components/ImageUpload"; |
| | | // å¾çé¢è§ç»ä»¶ |
| | | import ImagePreview from "@/components/ImagePreview"; |
| | | // åå
¸æ ç¾ç»ä»¶ |
| | | import DictTag from "@/components/DictTag"; |
| | | // è¡¨æ ¼ç»ä»¶ |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | |
| | | import { getToken } from "@/utils/auth"; |
| | | import { |
| | | calculateTaxExclusiveTotalPrice, |
| | | summarizeTable, |
| | | calculateTaxIncludeTotalPrice, |
| | | } from "@/utils/summarizeTable.js"; |
| | | |
| | | const app = createApp(App); |
| | | |
| | | // å
¨å±æ¹æ³æè½½ |
| | | app.config.globalProperties.useDict = useDict; |
| | | app.config.globalProperties.download = download; |
| | | app.config.globalProperties.parseTime = parseTime; |
| | | app.config.globalProperties.resetForm = resetForm; |
| | | app.config.globalProperties.summarizeTable = summarizeTable; |
| | | app.config.globalProperties.calculateTaxExclusiveTotalPrice = |
| | | calculateTaxExclusiveTotalPrice; |
| | | app.config.globalProperties.calculateTaxIncludeTotalPrice = |
| | | calculateTaxIncludeTotalPrice; |
| | | app.config.globalProperties.handleTree = handleTree; |
| | | app.config.globalProperties.addDateRange = addDateRange; |
| | | app.config.globalProperties.selectDictLabel = selectDictLabel; |
| | | app.config.globalProperties.selectDictLabels = selectDictLabels; |
| | | app.config.globalProperties.javaApi = "http://114.132.189.42:9037"; |
| | | app.config.globalProperties.HaveJson = (val) => { |
| | | return JSON.parse(JSON.stringify(val)); |
| | | }; |
| | | app.config.globalProperties.uploadHeader = { |
| | | Authorization: "Bearer " + getToken(), |
| | | }; |
| | | |
| | | // å
¨å±ç»ä»¶æè½½ |
| | | app.component("DictTag", DictTag); |
| | | app.component("Pagination", Pagination); |
| | | app.component("FileUpload", FileUpload); |
| | | app.component("ImageUpload", ImageUpload); |
| | | app.component("ImagePreview", ImagePreview); |
| | | app.component("RightToolbar", RightToolbar); |
| | | app.component("Editor", Editor); |
| | | app.component("PIMTable", PIMTable); |
| | | |
| | | app.use(router); |
| | | app.use(store); |
| | | app.use(plugins); |
| | | app.use(elementIcons); |
| | | app.component("svg-icon", SvgIcon); |
| | | |
| | | directive(app); |
| | | |
| | | // 使ç¨element-plus å¹¶ä¸è®¾ç½®å
¨å±çå¤§å° |
| | | app.use(ElementPlus, { |
| | | locale: locale, |
| | | // æ¯æ largeãdefaultãsmall |
| | | size: Cookies.get("size") || "default", |
| | | }); |
| | | app._context.components.ElDialog.props.closeOnClickModal.default = false; |
| | | |
| | | app.mount("#app"); |
| | |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | path: '/main/MobileChat', |
| | | component: Layout, |
| | | redirect: '', |
| | | hidden: true, |
| | | children: [ |
| | | { |
| | | path: '', |
| | | component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'), |
| | | name: 'MobileChat', |
| | | meta: { title: 'AI对è¯', icon: 'dashboard', affix: true} |
| | | } |
| | | ] |
| | | }, |
| | | // { |
| | | // path: '/main/MobileChat', |
| | | // component: Layout, |
| | | // redirect: '', |
| | | // hidden: true, |
| | | // children: [ |
| | | // { |
| | | // path: '', |
| | | // component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'), |
| | | // name: 'MobileChat', |
| | | // meta: { title: 'AI对è¯', icon: 'dashboard', affix: true} |
| | | // } |
| | | // ] |
| | | // }, |
| | | { |
| | | path: '/user', |
| | | component: Layout, |
| | |
| | | name: "DeviceInfo", |
| | | meta: { title: "设å¤ä¿¡æ¯", icon: "monitor" }, |
| | | }, |
| | | { |
| | | path: "/data-dashboard", |
| | | component: () => import("@/views/reportAnalysis/dataDashboard/index.vue"), |
| | | hidden: true, |
| | | name: "DataDashboard", |
| | | meta: { title: "æ°æ®å¤§å±", icon: "dashboard" }, |
| | | }, |
| | | ]; |
| | | |
| | | // å¨æè·¯ç±ï¼åºäºç¨æ·æé卿å»å è½½ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="carbon-management"> |
| | | <!-- 页é¢å¤´é¨ --> |
| | | <div class="page-header"> |
| | | <div class="header-content"> |
| | | <h1 class="page-title">ç¢³ææ¾ç®¡çç³»ç»</h1> |
| | | <p class="page-subtitle">åºäºISO 14064æ å · GHG Protocolæ ¸ç®æ å</p> |
| | | </div> |
| | | <div class="header-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ»ç¢³ææ¾é</span> |
| | | <span class="stat-value">{{totalEmissions}} tCOâe</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ¬æåæ</span> |
| | | <span class="stat-value reduction">-{{monthlyReduction}}%</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">碳ä¸åè¿åº¦</span> |
| | | <span class="stat-value">{{neutralProgress}}%</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 主è¦å
容åºå --> |
| | | <div class="dashboard-content"> |
| | | <!-- 顶鍿°æ®é¢æ¿ --> |
| | | <div class="top-panels"> |
| | | <div class="data-panel top-left"> |
| | | <div class="panel-title">å½åç¢³ææ¾</div> |
| | | <div class="panel-value">{{carbonData.scope1}} <span class="unit">tCOâe</span></div> |
| | | <div class="panel-subtitle">èå´1ç´æ¥ææ¾</div> |
| | | </div> |
| | | <div class="data-panel top-center"> |
| | | <div class="panel-title">è½èçæµ</div> |
| | | <div class="panel-value">{{carbonData.scope2}} <span class="unit">tCOâe</span></div> |
| | | <div class="panel-subtitle">èå´2é´æ¥ææ¾</div> |
| | | </div> |
| | | <div class="data-panel top-right"> |
| | | <div class="panel-title">ä¾åºé¾ææ¾</div> |
| | | <div class="panel-value">{{carbonData.scope3}} <span class="unit">tCOâe</span></div> |
| | | <div class="panel-subtitle">èå´3ä¾åºé¾ææ¾</div> |
| | | </div> |
| | | <div class="data-panel top-far-right"> |
| | | <div class="panel-title">åæè¿åº¦</div> |
| | | <div class="panel-value">{{neutralProgress}} <span class="unit">%</span></div> |
| | | <div class="panel-subtitle">碳ä¸åç®æ </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ä¸å¿ä¸»è§å¾åºå --> |
| | | <div class="center-main-view"> |
| | | <!-- 左侧æ§å¶é¢æ¿ --> |
| | | <div class="left-control-panel"> |
| | | <div class="control-section"> |
| | | <div class="section-title">ç¢³ææ¾èå´</div> |
| | | <el-radio-group v-model="selectedScope" @change="updateScopeData" class="vertical-radio"> |
| | | <el-radio-button :value="'all'">å
¨é¨èå´</el-radio-button> |
| | | <el-radio-button :value="'scope1'">èå´1</el-radio-button> |
| | | <el-radio-button :value="'scope2'">èå´2</el-radio-button> |
| | | <el-radio-button :value="'scope3'">èå´3</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | <div class="control-section"> |
| | | <div class="section-title">çæµå±çº§</div> |
| | | <el-radio-group v-model="heatmapLevel" @change="updateHeatmapLevel" class="vertical-radio"> |
| | | <el-radio-button :value="'device'">设å¤çº§</el-radio-button> |
| | | <el-radio-button :value="'line'">产线级</el-radio-button> |
| | | <el-radio-button :value="'enterprise'">ä¼ä¸çº§</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ä¸å¿çåå¾ --> |
| | | <div class="main-heatmap"> |
| | | <div class="heatmap-header"> |
| | | <h2 class="main-title">碳足迹çåå¾åæ</h2> |
| | | <div class="date-selector"> |
| | | <el-date-picker |
| | | v-model="selectedDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | size="small" |
| | | @change="updateHeatmapData" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div class="heatmap-view"> |
| | | <Echarts ref="heatmapChart" |
| | | :series="heatmapSeries" |
| | | :xAxis="heatmapXAxis" |
| | | :yAxis="heatmapYAxis" |
| | | :tooltip="heatmapTooltip" |
| | | :visualMap="heatmapVisualMap" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 450px"></Echarts> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å³ä¾§æ°æ®é¢æ¿ --> |
| | | <div class="right-data-panel"> |
| | | <div class="data-section"> |
| | | <div class="section-title">宿¶çæ§</div> |
| | | <div class="mini-chart"> |
| | | <Echarts ref="realtimeChart" |
| | | :series="realtimeSeries" |
| | | :xAxis="realtimeXAxis" |
| | | :chartStyle="chartStyle" |
| | | :yAxis="realtimeYAxis" |
| | | :tooltip="realtimeTooltip" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 300px"></Echarts> |
| | | </div> |
| | | </div> |
| | | <div class="data-section"> |
| | | <div class="section-title">è¶å¿åæ</div> |
| | | <div class="trend-controls"> |
| | | <el-radio-group v-model="trendPeriod" size="small" @change="updateTrendData"> |
| | | <el-radio-button :value="'week'">å¨</el-radio-button> |
| | | <el-radio-button :value="'month'">æ</el-radio-button> |
| | | <el-radio-button :value="'year'">å¹´</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | <div class="mini-chart"> |
| | | <Echarts ref="trendChart" |
| | | :series="trendSeries" |
| | | :xAxis="trendXAxis" |
| | | :yAxis="trendYAxis" |
| | | :tooltip="trendTooltip" |
| | | :chartStyle="chartStyle" |
| | | :legend="trendLegend" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 200px"></Echarts> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åºé¨è¿åº¦é¢æ¿ --> |
| | | <div class="bottom-progress-panel"> |
| | | <div class="progress-section"> |
| | | <div class="progress-title">2024å¹´åæç®æ </div> |
| | | <div class="progress-data"> |
| | | <span class="current">{{reductionTarget.current}}</span> |
| | | <span class="separator">/</span> |
| | | <span class="target">{{reductionTarget.target}} tCOâe</span> |
| | | </div> |
| | | <el-progress :percentage="reductionTarget.percentage" :stroke-width="6" color="#00E676"/> |
| | | </div> |
| | | <div class="progress-section"> |
| | | <div class="progress-title">碳ä¸åè¿åº¦</div> |
| | | <div class="progress-data"> |
| | | <span class="current">{{neutralTarget.current}}</span> |
| | | <span class="separator">/</span> |
| | | <span class="target">{{neutralTarget.target}} tCOâe</span> |
| | | </div> |
| | | <el-progress :percentage="neutralTarget.percentage" :stroke-width="6" color="#00D4FF"/> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åºé¨æ°æ®è¡¨æ ¼ --> |
| | | <div class="bottom-data-table"> |
| | | <div class="table-panel"> |
| | | <div class="table-header"> |
| | | <h3 class="table-title">ç¢³ææ¾è¯¦ç»æ°æ®</h3> |
| | | <div class="table-controls"> |
| | | <el-input |
| | | v-model="searchKeyword" |
| | | placeholder="æç´¢è®¾å¤æäº§çº¿" |
| | | size="small" |
| | | style="width: 200px; margin-right: 10px;" |
| | | /> |
| | | <el-button type="primary" size="small" @click="exportData">å¯¼åºæ°æ®</el-button> |
| | | </div> |
| | | </div> |
| | | <el-table :data="filteredTableData" style="width: 100%" height="180"> |
| | | <el-table-column prop="name" label="设å¤/产线" width="150"/> |
| | | <el-table-column prop="type" label="ç±»å" width="100"/> |
| | | <el-table-column prop="scope1" label="èå´1ææ¾" width="120"/> |
| | | <el-table-column prop="scope2" label="èå´2ææ¾" width="120"/> |
| | | <el-table-column prop="scope3" label="èå´3ææ¾" width="120"/> |
| | | <el-table-column prop="total" label="æ»ææ¾é" width="120"/> |
| | | <el-table-column prop="efficiency" label="碳æç" width="100"/> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)">{{scope.row.status}}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, onBeforeUnmount, computed } from 'vue' |
| | | import * as echarts from 'echarts' |
| | | import Echarts from '@/components/Echarts/echarts.vue' |
| | | |
| | | // ååºå¼æ°æ® |
| | | const selectedScope = ref('all') |
| | | const heatmapLevel = ref('device') |
| | | const selectedDate = ref(new Date()) |
| | | const trendPeriod = ref('week') |
| | | const searchKeyword = ref('') |
| | | |
| | | // ç¢³ææ¾æ°æ® |
| | | const carbonData = ref({ |
| | | scope1: 125.6, |
| | | scope2: 89.3, |
| | | scope3: 234.7 |
| | | }) |
| | | const chartStyle = { |
| | | width: '96%', |
| | | height: '110%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | // 计ç®å±æ§ |
| | | const totalEmissions = computed(() => { |
| | | return (carbonData.value.scope1 + carbonData.value.scope2 + carbonData.value.scope3).toFixed(1) |
| | | }) |
| | | |
| | | const monthlyReduction = ref(8.5) |
| | | |
| | | // 计ç®ç¢³ä¸åè¿åº¦ç¾åæ¯ |
| | | const neutralProgress = computed(() => { |
| | | return Math.round(neutralTarget.value.percentage) |
| | | }) |
| | | |
| | | // åæç®æ æ°æ® |
| | | const reductionTarget = ref({ |
| | | current: 320.5, |
| | | target: 500, |
| | | percentage: 64.1 |
| | | }) |
| | | |
| | | const neutralTarget = ref({ |
| | | current: 1250, |
| | | target: 3800, |
| | | percentage: 32.9 |
| | | }) |
| | | |
| | | // 宿¶çæ§å¾è¡¨é
ç½® |
| | | const realtimeSeries = ref([ |
| | | { |
| | | name: '宿¶ç¢³ææ¾', |
| | | type: 'line', |
| | | smooth: true, |
| | | data: generateRealtimeData(), |
| | | itemStyle: { |
| | | color: '#FF6B6B' |
| | | }, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(255, 107, 107, 0.3)' }, |
| | | { offset: 1, color: 'rgba(255, 107, 107, 0.1)' } |
| | | ]) |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | const realtimeXAxis = [{ |
| | | type: 'category', |
| | | data: Array.from({length: 24}, (_, i) => `${i.toString().padStart(2, '0')}:00`), |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const realtimeYAxis = [{ |
| | | type: 'value', |
| | | name: 'tCOâe/h', |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | nameTextStyle: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const realtimeTooltip = { |
| | | trigger: 'axis', |
| | | formatter: '{b}: {c} tCOâe/h' |
| | | } |
| | | |
| | | // çåå¾é
ç½® |
| | | const heatmapSeries = ref([ |
| | | { |
| | | name: 'ç¢³ææ¾é', |
| | | type: 'heatmap', |
| | | data: generateHeatmapData(), |
| | | label: { |
| | | show: false |
| | | }, |
| | | emphasis: { |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowColor: 'rgba(0, 0, 0, 0.5)' |
| | | } |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | const heatmapXAxis = [{ |
| | | type: 'category', |
| | | data: Array.from({length: 24}, (_, i) => `${i}:00`), |
| | | splitArea: { show: true }, |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const heatmapYAxis = [{ |
| | | type: 'category', |
| | | data: ['设å¤A', '设å¤B', '设å¤C', '设å¤D', '设å¤E', '设å¤F', '设å¤G'], |
| | | splitArea: { show: true }, |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const heatmapTooltip = { |
| | | trigger: 'item', |
| | | formatter: function (params) { |
| | | const [hour, device] = params.data |
| | | const value = params.value[2] |
| | | return `设å¤: ${heatmapYAxis[0].data[device]}<br/>æ¶é´: ${hour}:00<br/>ç¢³ææ¾é: ${value} tCOâe` |
| | | } |
| | | } |
| | | |
| | | const heatmapVisualMap = ref({ |
| | | min: 0, |
| | | max: 50, |
| | | calculable: true, |
| | | orient: 'horizontal', |
| | | left: 'center', |
| | | bottom: '5%', |
| | | inRange: { |
| | | color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026'] |
| | | }, |
| | | textStyle: { color: '#B8C8E0' } |
| | | }) |
| | | |
| | | // è¶å¿åæå¾è¡¨é
ç½® |
| | | const trendSeries = ref([ |
| | | { |
| | | name: 'èå´1', |
| | | type: 'line', |
| | | data: [120, 132, 101, 134, 90, 230, 210], |
| | | itemStyle: { color: '#FF6B6B' } |
| | | }, |
| | | { |
| | | name: 'èå´2', |
| | | type: 'line', |
| | | data: [220, 182, 191, 234, 290, 330, 310], |
| | | itemStyle: { color: '#4ECDC4' } |
| | | }, |
| | | { |
| | | name: 'èå´3', |
| | | type: 'line', |
| | | data: [150, 232, 201, 154, 190, 330, 410], |
| | | itemStyle: { color: '#45B7D1' } |
| | | } |
| | | ]) |
| | | |
| | | const trendXAxis = [{ |
| | | type: 'category', |
| | | data: ['å¨ä¸', 'å¨äº', 'å¨ä¸', 'å¨å', 'å¨äº', 'å¨å
', '卿¥'], |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const trendYAxis = [{ |
| | | type: 'value', |
| | | name: 'tCOâe', |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | nameTextStyle: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | const trendTooltip = { |
| | | trigger: 'axis' |
| | | } |
| | | |
| | | const trendLegend = { |
| | | data: ['èå´1', 'èå´2', 'èå´3'], |
| | | textStyle: { color: '#B8C8E0' } |
| | | } |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const carbonTableData = ref([ |
| | | { name: 'ç产线A', type: '产线', scope1: 45.2, scope2: 32.1, scope3: 18.7, total: 96.0, efficiency: 'è¯å¥½', status: 'æ£å¸¸' }, |
| | | { name: '设å¤B-01', type: '设å¤', scope1: 12.5, scope2: 8.3, scope3: 5.2, total: 26.0, efficiency: 'ä¼ç§', status: 'æ£å¸¸' }, |
| | | { name: 'ç产线C', type: '产线', scope1: 38.7, scope2: 28.9, scope3: 15.4, total: 83.0, efficiency: 'è¯å¥½', status: 'åè¦' }, |
| | | { name: '设å¤D-02', type: '设å¤', scope1: 15.8, scope2: 11.2, scope3: 7.1, total: 34.1, efficiency: 'ä¸è¬', status: 'æ£å¸¸' }, |
| | | { name: 'ç产线E', type: '产线', scope1: 52.3, scope2: 39.6, scope3: 22.8, total: 114.7, efficiency: 'å¾
ä¼å', status: 'åè¦' } |
| | | ]) |
| | | |
| | | // çæå®æ¶æ°æ® |
| | | function generateRealtimeData() { |
| | | return Array.from({length: 24}, () => (Math.random() * 20 + 10).toFixed(1)) |
| | | } |
| | | |
| | | // çæçå徿°æ® |
| | | function generateHeatmapData() { |
| | | const data = [] |
| | | let yAxisLength = 7 // é»è®¤è®¾å¤çº§ |
| | | let baseMultiplier = 1 // åºç¡åæ° |
| | | |
| | | // æ ¹æ®å±çº§ç¡®å®Yè½´é¿åº¦åæ°æ®èå´ |
| | | if (heatmapLevel.value === 'line') { |
| | | yAxisLength = 5 |
| | | baseMultiplier = 2 // äº§çº¿çº§æ°æ®æ´å¤§ |
| | | } else if (heatmapLevel.value === 'enterprise') { |
| | | yAxisLength = 3 |
| | | baseMultiplier = 4 // ä¼ä¸çº§æ°æ®æå¤§ |
| | | } |
| | | |
| | | for (let i = 0; i < yAxisLength; i++) { |
| | | for (let j = 0; j < 24; j++) { |
| | | let value |
| | | // ç®åçæ¶é´æ®µé»è¾ |
| | | if (j >= 8 && j <= 18) { |
| | | // 工使¶é´ææ¾éè¾é« |
| | | value = Math.random() * 30 + 20 |
| | | } else if (j >= 19 && j <= 22) { |
| | | // æé´ææ¾éä¸ç |
| | | value = Math.random() * 20 + 10 |
| | | } else { |
| | | // æ·±å¤ååæ¨ææ¾éè¾ä½ |
| | | value = Math.random() * 10 + 2 |
| | | } |
| | | |
| | | // æ·»å 设å¤å·®å¼åå±çº§åæ° |
| | | value *= (0.8 + i * 0.1) * baseMultiplier |
| | | |
| | | data.push([j, i, Math.round(value * 10) / 10]) |
| | | } |
| | | } |
| | | return data |
| | | } |
| | | |
| | | // æ´æ°èå´æ°æ® |
| | | function updateScopeData() { |
| | | // æ ¹æ®éæ©çèå´æ´æ°ææç¸å
³å¾è¡¨æ°æ® |
| | | const scopeMultiplier = { |
| | | 'all': 1, |
| | | 'scope1': 0.3, |
| | | 'scope2': 0.4, |
| | | 'scope3': 0.3 |
| | | } |
| | | |
| | | const multiplier = scopeMultiplier[selectedScope.value] || 1 |
| | | |
| | | // æ´æ°ç¢³ææ¾æ°æ®æ¾ç¤º |
| | | if (selectedScope.value === 'all') { |
| | | carbonData.value = { |
| | | scope1: 125.6, |
| | | scope2: 89.3, |
| | | scope3: 234.7 |
| | | } |
| | | } else { |
| | | const baseTotal = 125.6 + 89.3 + 234.7 |
| | | carbonData.value = { |
| | | scope1: selectedScope.value === 'scope1' ? 125.6 : 0, |
| | | scope2: selectedScope.value === 'scope2' ? 89.3 : 0, |
| | | scope3: selectedScope.value === 'scope3' ? 234.7 : 0 |
| | | } |
| | | } |
| | | |
| | | // æ´æ°çå徿°æ® |
| | | heatmapSeries.value[0].data = generateHeatmapData().map(item => [ |
| | | item[0], item[1], Math.round(item[2] * multiplier * 10) / 10 |
| | | ]) |
| | | |
| | | // æ´æ°å®æ¶çæ§æ°æ® |
| | | realtimeSeries.value[0].data = generateRealtimeData().map(val => |
| | | Math.round(parseFloat(val) * multiplier * 10) / 10 |
| | | ) |
| | | } |
| | | |
| | | // æ´æ°çåå¾å±çº§ |
| | | function updateHeatmapLevel() { |
| | | // æ ¹æ®å±çº§æ´æ°Yè½´æ°æ®åvisualMapèå´ |
| | | if (heatmapLevel.value === 'device') { |
| | | heatmapYAxis[0].data = ['é
çA', 'å缩æºB', 'å·å´å¡C', '飿ºD', 'æ³µE', 'ååå¨F', 'çµæºG'] |
| | | heatmapVisualMap.value.max = 50 |
| | | } else if (heatmapLevel.value === 'line') { |
| | | heatmapYAxis[0].data = ['ç产线1', 'ç产线2', 'ç产线3', 'ç产线4', 'ç产线5'] |
| | | heatmapVisualMap.value.max = 100 |
| | | } else { |
| | | heatmapYAxis[0].data = ['ååºA', 'ååºB', 'ååºC'] |
| | | heatmapVisualMap.value.max = 200 |
| | | } |
| | | |
| | | // æ´æ°çå徿°æ® |
| | | heatmapSeries.value[0].data = generateHeatmapData() |
| | | |
| | | // æ´æ°è¡¨æ ¼æ°æ®ä»¥å¹é
å½åå±çº§ |
| | | updateTableDataForLevel() |
| | | } |
| | | |
| | | // æ ¹æ®å±çº§æ´æ°è¡¨æ ¼æ°æ® |
| | | function updateTableDataForLevel() { |
| | | const levelConfigs = { |
| | | device: [ |
| | | { name: 'é
çA', type: '设å¤', scope1: 45.2, scope2: 32.1, scope3: 18.7, total: 96.0, efficiency: 'è¯å¥½', status: 'æ£å¸¸' }, |
| | | { name: 'å缩æºB', type: '设å¤', scope1: 38.5, scope2: 28.3, scope3: 15.2, total: 82.0, efficiency: 'ä¼ç§', status: 'æ£å¸¸' }, |
| | | { name: 'å·å´å¡C', type: '设å¤', scope1: 22.8, scope2: 18.9, scope3: 12.3, total: 54.0, efficiency: 'è¯å¥½', status: 'åè¦' }, |
| | | { name: '飿ºD', type: '设å¤', scope1: 15.6, scope2: 12.4, scope3: 8.1, total: 36.1, efficiency: 'ä¸è¬', status: 'æ£å¸¸' }, |
| | | { name: 'æ³µE', type: '设å¤', scope1: 12.3, scope2: 9.8, scope3: 6.4, total: 28.5, efficiency: 'ä¼ç§', status: 'æ£å¸¸' } |
| | | ], |
| | | line: [ |
| | | { name: 'ç产线1', type: '产线', scope1: 125.6, scope2: 89.3, scope3: 56.8, total: 271.7, efficiency: 'è¯å¥½', status: 'æ£å¸¸' }, |
| | | { name: 'ç产线2', type: '产线', scope1: 98.4, scope2: 72.1, scope3: 45.2, total: 215.7, efficiency: 'ä¼ç§', status: 'æ£å¸¸' }, |
| | | { name: 'ç产线3', type: '产线', scope1: 87.2, scope2: 65.8, scope3: 41.6, total: 194.6, efficiency: 'è¯å¥½', status: 'åè¦' }, |
| | | { name: 'ç产线4', type: '产线', scope1: 76.9, scope2: 58.3, scope3: 37.1, total: 172.3, efficiency: 'ä¸è¬', status: 'æ£å¸¸' }, |
| | | { name: 'ç产线5', type: '产线', scope1: 65.7, scope2: 49.2, scope3: 31.8, total: 146.7, efficiency: 'å¾
ä¼å', status: 'åè¦' } |
| | | ], |
| | | enterprise: [ |
| | | { name: 'ååºA', type: 'ååº', scope1: 456.8, scope2: 334.7, scope3: 212.5, total: 1004.0, efficiency: 'è¯å¥½', status: 'æ£å¸¸' }, |
| | | { name: 'ååºB', type: 'ååº', scope1: 387.2, scope2: 289.6, scope3: 184.3, total: 861.1, efficiency: 'ä¼ç§', status: 'æ£å¸¸' }, |
| | | { name: 'ååºC', type: 'ååº', scope1: 298.5, scope2: 223.8, scope3: 142.7, total: 665.0, efficiency: 'è¯å¥½', status: 'åè¦' } |
| | | ] |
| | | } |
| | | |
| | | carbonTableData.value = levelConfigs[heatmapLevel.value] || levelConfigs.device |
| | | } |
| | | |
| | | // æ´æ°çå徿°æ®ï¼æ¥æååæ¶ï¼ |
| | | function updateHeatmapData() { |
| | | heatmapSeries.value[0].data = generateHeatmapData() |
| | | |
| | | // åæ¶æ´æ°å
¶ä»ç¸å
³æ°æ® |
| | | updateScopeData() |
| | | } |
| | | |
| | | // æ´æ°è¶å¿æ°æ® |
| | | function updateTrendData() { |
| | | const trendDataConfigs = { |
| | | week: { |
| | | xAxisData: ['å¨ä¸', 'å¨äº', 'å¨ä¸', 'å¨å', 'å¨äº', 'å¨å
', '卿¥'], |
| | | scope1Data: [120, 132, 101, 134, 90, 80, 75], |
| | | scope2Data: [220, 182, 191, 234, 190, 150, 140], |
| | | scope3Data: [150, 232, 201, 154, 190, 120, 110] |
| | | }, |
| | | month: { |
| | | xAxisData: ['1æ', '2æ', '3æ', '4æ', '5æ', '6æ', '7æ', '8æ', '9æ', '10æ', '11æ', '12æ'], |
| | | scope1Data: [1200, 1150, 1300, 1250, 1180, 1320, 1280, 1350, 1220, 1290, 1160, 1100], |
| | | scope2Data: [2200, 2100, 2350, 2280, 2150, 2400, 2320, 2450, 2180, 2380, 2120, 2050], |
| | | scope3Data: [1800, 1750, 1950, 1880, 1820, 2000, 1920, 2100, 1850, 1980, 1780, 1720] |
| | | }, |
| | | year: { |
| | | xAxisData: ['2019', '2020', '2021', '2022', '2023', '2024'], |
| | | scope1Data: [14500, 14200, 13800, 13500, 13100, 12800], |
| | | scope2Data: [26800, 26200, 25600, 25000, 24400, 23800], |
| | | scope3Data: [22400, 21800, 21200, 20600, 20000, 19400] |
| | | } |
| | | } |
| | | |
| | | const config = trendDataConfigs[trendPeriod.value] || trendDataConfigs.week |
| | | |
| | | // æ´æ°Xè½´æ°æ® |
| | | trendXAxis[0].data = config.xAxisData |
| | | |
| | | // æ´æ°ç³»åæ°æ® |
| | | trendSeries.value = [ |
| | | { |
| | | name: 'èå´1', |
| | | type: 'line', |
| | | data: config.scope1Data, |
| | | itemStyle: { color: '#FF6B6B' }, |
| | | smooth: true |
| | | }, |
| | | { |
| | | name: 'èå´2', |
| | | type: 'line', |
| | | data: config.scope2Data, |
| | | itemStyle: { color: '#4ECDC4' }, |
| | | smooth: true |
| | | }, |
| | | { |
| | | name: 'èå´3', |
| | | type: 'line', |
| | | data: config.scope3Data, |
| | | itemStyle: { color: '#45B7D1' }, |
| | | smooth: true |
| | | } |
| | | ] |
| | | } |
| | | |
| | | // è·åç¶æç±»å |
| | | function getStatusType(status) { |
| | | switch (status) { |
| | | case 'æ£å¸¸': return 'success' |
| | | case 'åè¦': return 'warning' |
| | | case 'å¼å¸¸': return 'danger' |
| | | default: return 'info' |
| | | } |
| | | } |
| | | |
| | | // å¯¼åºæ°æ® |
| | | function exportData() { |
| | | // åå¤å¯¼åºæ°æ® |
| | | const exportDataSet = { |
| | | åºæ¬ä¿¡æ¯: { |
| | | å¯¼åºæ¶é´: new Date().toLocaleString('zh-CN'), |
| | | æ°æ®å±çº§: heatmapLevel.value === 'device' ? '设å¤çº§' : heatmapLevel.value === 'line' ? '产线级' : 'ä¼ä¸çº§', |
| | | éæ©èå´: selectedScope.value === 'all' ? 'å
¨é¨èå´' : `èå´${selectedScope.value.slice(-1)}`, |
| | | éæ©æ¥æ: selectedDate.value ? selectedDate.value.toLocaleDateString('zh-CN') : '仿¥' |
| | | }, |
| | | ç¢³ææ¾ç»è®¡: { |
| | | èå´1ç´æ¥ææ¾: carbonData.value.scope1 + ' tCOâe', |
| | | èå´2é´æ¥ææ¾: carbonData.value.scope2 + ' tCOâe', |
| | | èå´3ä¾åºé¾ææ¾: carbonData.value.scope3 + ' tCOâe', |
| | | æ»ææ¾é: totalEmissions.value + ' tCOâe' |
| | | }, |
| | | è¯¦ç»æ°æ®: carbonTableData.value, |
| | | çå徿°æ®: heatmapSeries.value[0].data.map(item => ({ |
| | | æ¶é´: `${item[0]}:00`, |
| | | 设å¤åºå·: item[1], |
| | | 设å¤åç§°: heatmapYAxis.data[item[1]], |
| | | ç¢³ææ¾é: item[2] + ' tCOâe' |
| | | })) |
| | | } |
| | | |
| | | // å建CSVå
容 |
| | | let csvContent = '\uFEFF' // BOM for UTF-8 |
| | | |
| | | // åºæ¬ä¿¡æ¯ |
| | | csvContent += 'åºæ¬ä¿¡æ¯\n' |
| | | Object.entries(exportDataSet.åºæ¬ä¿¡æ¯).forEach(([key, value]) => { |
| | | csvContent += `${key},${value}\n` |
| | | }) |
| | | csvContent += '\n' |
| | | |
| | | // ç¢³ææ¾ç»è®¡ |
| | | csvContent += 'ç¢³ææ¾ç»è®¡\n' |
| | | Object.entries(exportDataSet.ç¢³ææ¾ç»è®¡).forEach(([key, value]) => { |
| | | csvContent += `${key},${value}\n` |
| | | }) |
| | | csvContent += '\n' |
| | | |
| | | // è¯¦ç»æ°æ®è¡¨æ ¼ |
| | | csvContent += 'è¯¦ç»æ°æ®\n' |
| | | csvContent += 'åç§°,ç±»å,èå´1ææ¾,èå´2ææ¾,èå´3ææ¾,æ»ææ¾é,碳æç,ç¶æ\n' |
| | | exportDataSet.è¯¦ç»æ°æ®.forEach(row => { |
| | | csvContent += `${row.name},${row.type},${row.scope1},${row.scope2},${row.scope3},${row.total},${row.efficiency},${row.status}\n` |
| | | }) |
| | | csvContent += '\n' |
| | | |
| | | // çå徿°æ®ï¼å50æ¡ï¼ |
| | | csvContent += 'çå徿°æ®ï¼å50æ¡ï¼\n' |
| | | csvContent += 'æ¶é´,设å¤åç§°,ç¢³ææ¾é\n' |
| | | exportDataSet.çå徿°æ®.slice(0, 50).forEach(row => { |
| | | csvContent += `${row.æ¶é´},${row.设å¤åç§°},${row.ç¢³ææ¾é}\n` |
| | | }) |
| | | |
| | | // å建ä¸è½½é¾æ¥ |
| | | const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }) |
| | | const link = document.createElement('a') |
| | | const url = URL.createObjectURL(blob) |
| | | link.setAttribute('href', url) |
| | | link.setAttribute('download', `ç¢³ææ¾æ°æ®_${new Date().toISOString().slice(0, 10)}.csv`) |
| | | link.style.visibility = 'hidden' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | document.body.removeChild(link) |
| | | |
| | | // æ¾ç¤ºæåæ¶æ¯ |
| | | console.log('ç¢³ææ¾æ°æ®å¯¼åºæå') |
| | | } |
| | | |
| | | // æç´¢è¿æ»¤åè½ |
| | | const filteredTableData = computed(() => { |
| | | if (!searchKeyword.value) { |
| | | return carbonTableData.value |
| | | } |
| | | return carbonTableData.value.filter(item => |
| | | item.name.toLowerCase().includes(searchKeyword.value.toLowerCase()) || |
| | | item.type.toLowerCase().includes(searchKeyword.value.toLowerCase()) |
| | | ) |
| | | }) |
| | | |
| | | // çåå¾ç¹å»äºä»¶å¤ç |
| | | function handleHeatmapClick(params) { |
| | | if (params.componentType === 'series') { |
| | | const [hour, deviceIndex, value] = params.data |
| | | const deviceName = heatmapYAxis.data[deviceIndex] |
| | | console.log(`ç¹å»äºè®¾å¤: ${deviceName}, æ¶é´: ${hour}:00, ææ¾é: ${value} tCOâe`) |
| | | |
| | | // å¯ä»¥å¨è¿éæ·»å 详ç»ä¿¡æ¯å¼¹çªæè·³è½¬å°è¯¦ç»é¡µé¢ |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½å®æåçåå§åæä½ |
| | | console.log('碳管ç页é¢å·²å è½½') |
| | | |
| | | // åå§åçå徿°æ® |
| | | updateHeatmapLevel() |
| | | |
| | | // åå§åè¶å¿æ°æ® |
| | | updateTrendData() |
| | | |
| | | // åå§åèå´æ°æ® |
| | | updateScopeData() |
| | | |
| | | // è®¾ç½®å®æ¶å¨ï¼æ¯30ç§æ´æ°ä¸æ¬¡å®æ¶æ°æ® |
| | | const timer = setInterval(() => { |
| | | realtimeSeries.value[0].data = generateRealtimeData() |
| | | }, 30000) |
| | | |
| | | // æ¸
ç宿¶å¨ |
| | | onBeforeUnmount(() => { |
| | | clearInterval(timer) |
| | | }) |
| | | }) |
| | | |
| | | // æ·»å çåå¾ç¹å»äºä»¶ç»å® |
| | | function bindHeatmapEvents() { |
| | | // è¿ä¸ªå½æ°å¯ä»¥ç¨æ¥ç»å®çåå¾çç¹å»äºä»¶ |
| | | // å¨å®é
使ç¨ä¸ï¼å¯ä»¥éè¿EChartsçäºä»¶ç³»ç»æ¥å®ç° |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .carbon-management { |
| | | min-height: 100vh; |
| | | background: |
| | | radial-gradient(ellipse at top, rgba(29, 78, 216, 0.15), transparent 50%), |
| | | radial-gradient(ellipse at bottom, rgba(139, 92, 246, 0.15), transparent 50%), |
| | | linear-gradient(135deg, #0a0f1c 0%, #1e293b 25%, #0f172a 50%, #1e293b 75%, #0a0f1c 100%); |
| | | padding: 20px; |
| | | font-family: 'Inter', 'Microsoft YaHei', sans-serif; |
| | | overflow: hidden; |
| | | position: relative; |
| | | } |
| | | |
| | | .carbon-management::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: |
| | | radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.1) 0%, transparent 50%), |
| | | radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.1) 0%, transparent 50%), |
| | | radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.05) 0%, transparent 50%); |
| | | pointer-events: none; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .page-header { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%), |
| | | radial-gradient(circle at top right, rgba(59, 130, 246, 0.1), transparent 50%); |
| | | border: 1px solid rgba(148, 163, 184, 0.2); |
| | | border-radius: 20px; |
| | | padding: 40px; |
| | | margin-bottom: 30px; |
| | | box-shadow: |
| | | 0 25px 50px -12px rgba(0, 0, 0, 0.4), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05), |
| | | inset 0 1px 0 rgba(255, 255, 255, 0.1); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | position: relative; |
| | | overflow: hidden; |
| | | backdrop-filter: blur(20px); |
| | | |
| | | } |
| | | |
| | | .page-header:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: |
| | | 0 32px 64px -12px rgba(0, 0, 0, 0.5), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.1), |
| | | inset 0 1px 0 rgba(255, 255, 255, 0.15); |
| | | } |
| | | |
| | | .page-header::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: |
| | | linear-gradient(45deg, rgba(59, 130, 246, 0.08) 0%, rgba(147, 51, 234, 0.08) 50%, rgba(236, 72, 153, 0.08) 100%); |
| | | pointer-events: none; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | .header-content { |
| | | flex: 1; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .page-title { |
| | | font-size: 28px; |
| | | font-weight: bold; |
| | | color: #ffffff; |
| | | margin: 0 0 8px 0; |
| | | text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); |
| | | } |
| | | |
| | | .page-subtitle { |
| | | font-size: 14px; |
| | | color: #B8C8E0; |
| | | margin: 0; |
| | | } |
| | | |
| | | .header-stats { |
| | | display: flex; |
| | | gap: 40px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: |
| | | linear-gradient(135deg, rgba(59, 130, 246, 0.15) 0%, rgba(147, 51, 234, 0.15) 100%), |
| | | radial-gradient(circle at center, rgba(255, 255, 255, 0.05), transparent 70%); |
| | | border-radius: 12px; |
| | | border: 1px solid rgba(148, 163, 184, 0.2); |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | backdrop-filter: blur(10px); |
| | | } |
| | | |
| | | .stat-item:hover { |
| | | transform: translateY(-2px) scale(1.05); |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(59, 130, 246, 0.3), |
| | | 0 10px 10px -5px rgba(59, 130, 246, 0.2); |
| | | } |
| | | |
| | | .stat-item::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: -100%; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); |
| | | |
| | | } |
| | | |
| | | .stat-item:hover::before { |
| | | left: 100%; |
| | | } |
| | | |
| | | .stat-label { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #94A3B8; |
| | | margin-bottom: 8px; |
| | | font-weight: 500; |
| | | letter-spacing: 0.5px; |
| | | text-transform: uppercase; |
| | | } |
| | | |
| | | .stat-value { |
| | | display: block; |
| | | font-size: 28px; |
| | | font-weight: 700; |
| | | color: #00D4FF; |
| | | text-shadow: |
| | | 0 0 20px rgba(0, 212, 255, 0.6), |
| | | 0 0 40px rgba(0, 212, 255, 0.3); |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .stat-value.reduction { |
| | | color: #00E676; |
| | | text-shadow: |
| | | 0 0 20px rgba(0, 230, 118, 0.6), |
| | | 0 0 40px rgba(0, 230, 118, 0.3); |
| | | } |
| | | |
| | | .dashboard-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | min-height: calc(100vh - 200px); |
| | | } |
| | | |
| | | .top-panels { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr 1fr 1fr; |
| | | gap: 20px; |
| | | height: 120px; |
| | | } |
| | | |
| | | .data-panel { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%), |
| | | radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 10px 10px -5px rgba(0, 0, 0, 0.2), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05); |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | text-align: center; |
| | | } |
| | | |
| | | .panel-title { |
| | | font-size: 12px; |
| | | color: #94A3B8; |
| | | margin-bottom: 8px; |
| | | font-weight: 500; |
| | | letter-spacing: 0.5px; |
| | | text-transform: uppercase; |
| | | } |
| | | |
| | | .panel-value { |
| | | font-size: 24px; |
| | | font-weight: 700; |
| | | color: #00D4FF; |
| | | text-shadow: |
| | | 0 0 20px rgba(0, 212, 255, 0.6), |
| | | 0 0 40px rgba(0, 212, 255, 0.3); |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .panel-subtitle { |
| | | font-size: 11px; |
| | | color: #B8C8E0; |
| | | font-weight: 400; |
| | | } |
| | | |
| | | .unit { |
| | | font-size: 16px; |
| | | color: #94A3B8; |
| | | } |
| | | |
| | | .center-main-view { |
| | | display: grid; |
| | | grid-template-columns: 200px 1fr 300px; |
| | | gap: 20px; |
| | | flex: 1; |
| | | } |
| | | |
| | | .left-control-panel { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05); |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .control-section { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .vertical-radio { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .main-heatmap { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05); |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .heatmap-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid rgba(148, 163, 184, 0.2); |
| | | } |
| | | |
| | | .main-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #ffffff; |
| | | margin: 0; |
| | | } |
| | | |
| | | .date-selector { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .heatmap-view { |
| | | flex: 1; |
| | | } |
| | | |
| | | .right-data-panel { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05); |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .data-section { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .mini-chart { |
| | | width: 100%; |
| | | } |
| | | |
| | | .trend-controls { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .bottom-progress-panel { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 40px; |
| | | height: 100px; |
| | | } |
| | | |
| | | .progress-section { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05); |
| | | backdrop-filter: blur(16px); |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .progress-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .progress-data { |
| | | display: flex; |
| | | align-items: baseline; |
| | | gap: 4px; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .progress-data .current { |
| | | font-size: 20px; |
| | | font-weight: 700; |
| | | color: #00D4FF; |
| | | } |
| | | |
| | | .progress-data .separator { |
| | | font-size: 16px; |
| | | color: #94A3B8; |
| | | } |
| | | |
| | | .progress-data .target { |
| | | font-size: 14px; |
| | | color: #B8C8E0; |
| | | } |
| | | |
| | | .bottom-data-table { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .table-panel { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%), |
| | | radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 20px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 10px 10px -5px rgba(0, 0, 0, 0.2), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05), |
| | | inset 0 1px 0 rgba(255, 255, 255, 0.1); |
| | | backdrop-filter: blur(16px); |
| | | } |
| | | |
| | | .table-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid rgba(148, 163, 184, 0.2); |
| | | } |
| | | |
| | | .table-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #ffffff; |
| | | margin: 0; |
| | | } |
| | | |
| | | .table-controls { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .panel-card { |
| | | background: |
| | | linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%), |
| | | radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%); |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | border-radius: 16px; |
| | | padding: 24px; |
| | | box-shadow: |
| | | 0 20px 25px -5px rgba(0, 0, 0, 0.3), |
| | | 0 10px 10px -5px rgba(0, 0, 0, 0.2), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.05), |
| | | inset 0 1px 0 rgba(255, 255, 255, 0.1); |
| | | position: relative; |
| | | overflow: hidden; |
| | | backdrop-filter: blur(16px); |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | } |
| | | |
| | | |
| | | |
| | | .heatmap-card { |
| | | height: 500px; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid rgba(81, 129, 219, 0.3); |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #ffffff; |
| | | margin: 0; |
| | | text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); |
| | | } |
| | | |
| | | .heatmap-controls { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .scope-stats { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .scope-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20px; |
| | | border-radius: 12px; |
| | | background: |
| | | linear-gradient(135deg, rgba(59, 130, 246, 0.12) 0%, rgba(147, 51, 234, 0.12) 100%), |
| | | radial-gradient(circle at top, rgba(255, 255, 255, 0.05), transparent 60%); |
| | | border-left: 4px solid #00D4FF; |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | backdrop-filter: blur(8px); |
| | | } |
| | | |
| | | .scope-item:hover { |
| | | transform: translateY(-3px); |
| | | box-shadow: |
| | | 0 15px 30px -5px rgba(59, 130, 246, 0.25), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.1); |
| | | } |
| | | |
| | | .scope-item::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | height: 2px; |
| | | background: linear-gradient(90deg, #3B82F6, #8B5CF6, #EC4899); |
| | | opacity: 0; |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | .scope-item:hover::after { |
| | | opacity: 1; |
| | | } |
| | | |
| | | /* ç¢³ææ¾ç»è®¡æ ·å¼ */ |
| | | .carbon-stats { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 20px; |
| | | gap: 15px; |
| | | } |
| | | |
| | | .carbon-stat-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 20px; |
| | | background: |
| | | linear-gradient(135deg, rgba(59, 130, 246, 0.12) 0%, rgba(147, 51, 234, 0.12) 100%), |
| | | radial-gradient(circle at top, rgba(255, 255, 255, 0.05), transparent 60%); |
| | | border-radius: 12px; |
| | | border: 1px solid rgba(148, 163, 184, 0.15); |
| | | flex: 1; |
| | | position: relative; |
| | | overflow: hidden; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | backdrop-filter: blur(8px); |
| | | } |
| | | |
| | | .carbon-stat-item:hover { |
| | | transform: translateY(-3px); |
| | | box-shadow: |
| | | 0 15px 30px -5px rgba(59, 130, 246, 0.25), |
| | | 0 0 0 1px rgba(255, 255, 255, 0.1); |
| | | } |
| | | |
| | | .carbon-stat-item::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | height: 2px; |
| | | background: linear-gradient(90deg, #3B82F6, #8B5CF6, #EC4899); |
| | | opacity: 0; |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | .carbon-stat-item:hover::after { |
| | | opacity: 1; |
| | | } |
| | | |
| | | .carbon-label { |
| | | color: #94A3B8; |
| | | font-size: 11px; |
| | | text-align: center; |
| | | font-weight: 500; |
| | | letter-spacing: 0.5px; |
| | | text-transform: uppercase; |
| | | } |
| | | |
| | | .carbon-value { |
| | | color: #00D4FF; |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | text-shadow: |
| | | 0 0 15px rgba(0, 212, 255, 0.6), |
| | | 0 0 30px rgba(0, 212, 255, 0.3); |
| | | position: relative; |
| | | } |
| | | |
| | | .scope-item.scope1 { |
| | | border-left-color: #FF6B6B; |
| | | } |
| | | |
| | | .scope-item.scope2 { |
| | | border-left-color: #FFD93D; |
| | | } |
| | | |
| | | .scope-item.scope3 { |
| | | border-left-color: #6BCF7F; |
| | | } |
| | | |
| | | .scope-icon { |
| | | font-size: 24px; |
| | | margin-right: 15px; |
| | | } |
| | | |
| | | .scope-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .scope-name { |
| | | display: block; |
| | | font-weight: bold; |
| | | color: #ffffff; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .scope-value { |
| | | display: block; |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | color: #00D4FF; |
| | | margin-bottom: 3px; |
| | | text-shadow: 0 0 8px rgba(0, 212, 255, 0.5); |
| | | } |
| | | |
| | | .scope-desc { |
| | | display: block; |
| | | font-size: 12px; |
| | | color: #B8C8E0; |
| | | } |
| | | |
| | | .target-progress { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | position: relative; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .progress-item { |
| | | padding: 15px; |
| | | background: rgba(81, 129, 219, 0.1); |
| | | border-radius: 8px; |
| | | border: 1px solid rgba(81, 129, 219, 0.2); |
| | | } |
| | | |
| | | .progress-info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .progress-label { |
| | | font-weight: bold; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .progress-value { |
| | | color: #B8C8E0; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .bottom-panel { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .table-controls { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | /* Element Plus ç»ä»¶æ·±è²ä¸»é¢æ ·å¼ */ |
| | | :deep(.el-table) { |
| | | background: transparent !important; |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background: rgba(81, 129, 219, 0.2) !important; |
| | | color: #ffffff !important; |
| | | border-bottom: 1px solid rgba(81, 129, 219, 0.3) !important; |
| | | } |
| | | |
| | | :deep(.el-table td) { |
| | | background: transparent !important; |
| | | color: #B8C8E0 !important; |
| | | border-bottom: 1px solid rgba(81, 129, 219, 0.1) !important; |
| | | } |
| | | |
| | | :deep(.el-table tr:hover > td) { |
| | | background: rgba(81, 129, 219, 0.1) !important; |
| | | } |
| | | |
| | | :deep(.el-input__wrapper) { |
| | | background: rgba(15, 27, 46, 0.8) !important; |
| | | border: 1px solid rgba(81, 129, 219, 0.3) !important; |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.el-button--primary) { |
| | | background: linear-gradient(135deg, #5181DB, #D369E0) !important; |
| | | border: none !important; |
| | | box-shadow: 0 0 10px rgba(81, 129, 219, 0.5) !important; |
| | | } |
| | | |
| | | /* åç´åéæé®ç»æ ·å¼ */ |
| | | :deep(.vertical-radio) { |
| | | display: flex !important; |
| | | flex-direction: column !important; |
| | | gap: 6px !important; |
| | | } |
| | | |
| | | :deep(.vertical-radio .el-radio-button) { |
| | | margin: 0 !important; |
| | | width: 100% !important; |
| | | } |
| | | |
| | | :deep(.vertical-radio .el-radio-button__inner) { |
| | | background: rgba(59, 130, 246, 0.1) !important; |
| | | border: 1px solid rgba(148, 163, 184, 0.2) !important; |
| | | color: #B8C8E0 !important; |
| | | border-radius: 8px !important; |
| | | padding: 10px 16px !important; |
| | | width: 100% !important; |
| | | text-align: center !important; |
| | | font-size: 12px !important; |
| | | font-weight: 500 !important; |
| | | } |
| | | |
| | | :deep(.vertical-radio .el-radio-button__inner:hover) { |
| | | background: rgba(59, 130, 246, 0.2) !important; |
| | | border-color: rgba(59, 130, 246, 0.4) !important; |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.vertical-radio .el-radio-button.is-active .el-radio-button__inner) { |
| | | background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; |
| | | border-color: #3B82F6 !important; |
| | | color: #ffffff !important; |
| | | box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important; |
| | | } |
| | | |
| | | :deep(.vertical-radio .el-radio-button:first-child .el-radio-button__inner) { |
| | | border-left: 1px solid rgba(148, 163, 184, 0.2) !important; |
| | | } |
| | | |
| | | :deep(.el-radio-group .el-radio-button__inner) { |
| | | background: rgba(59, 130, 246, 0.1) !important; |
| | | border: 1px solid rgba(148, 163, 184, 0.2) !important; |
| | | color: #B8C8E0 !important; |
| | | border-radius: 6px !important; |
| | | padding: 6px 12px !important; |
| | | margin: 0 2px !important; |
| | | font-size: 12px !important; |
| | | } |
| | | |
| | | :deep(.el-radio-group .el-radio-button__inner:hover) { |
| | | background: rgba(59, 130, 246, 0.2) !important; |
| | | border-color: rgba(59, 130, 246, 0.4) !important; |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.el-radio-group .el-radio-button.is-active .el-radio-button__inner) { |
| | | background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important; |
| | | border-color: #3B82F6 !important; |
| | | color: #ffffff !important; |
| | | box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important; |
| | | } |
| | | |
| | | :deep(.el-date-editor .el-input__wrapper) { |
| | | background: rgba(15, 27, 46, 0.8) !important; |
| | | border: 1px solid rgba(81, 129, 219, 0.3) !important; |
| | | } |
| | | |
| | | :deep(.el-progress-bar__outer) { |
| | | background: rgba(81, 129, 219, 0.2) !important; |
| | | } |
| | | |
| | | :deep(.el-tag) { |
| | | background: rgba(81, 129, 219, 0.2) !important; |
| | | border: 1px solid rgba(81, 129, 219, 0.3) !important; |
| | | color: #ffffff !important; |
| | | } |
| | | |
| | | :deep(.el-tag.el-tag--success) { |
| | | background: rgba(0, 230, 118, 0.2) !important; |
| | | border-color: rgba(0, 230, 118, 0.3) !important; |
| | | color: #00E676 !important; |
| | | } |
| | | |
| | | :deep(.el-tag.el-tag--warning) { |
| | | background: rgba(255, 193, 7, 0.2) !important; |
| | | border-color: rgba(255, 193, 7, 0.3) !important; |
| | | color: #FFC107 !important; |
| | | } |
| | | |
| | | :deep(.el-tag.el-tag--danger) { |
| | | background: rgba(244, 67, 54, 0.2) !important; |
| | | border-color: rgba(244, 67, 54, 0.3) !important; |
| | | color: #F44336 !important; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 1200px) { |
| | | .main-content { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .header-stats { |
| | | gap: 20px; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .page-header { |
| | | flex-direction: column; |
| | | text-align: center; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .header-stats { |
| | | justify-content: center; |
| | | } |
| | | |
| | | .carbon-management { |
| | | padding: 10px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | } |
| | | // åºä»åºæ¶ç»è®¡ |
| | | const statisticsReceivable = (type) => { |
| | | console.log(type) |
| | | statisticsReceivablePayable({type: radio1.value}).then((res) => { |
| | | barSeries.value[0].data = [ |
| | | // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } }, |
| | |
| | | <style lang='scss' scoped>
|
| | | .login {
|
| | | height: 100%;
|
| | | background-image: url("../assets/indexViews/DHDCView.png");
|
| | | background-size: 100% 100%;
|
| | | background-image: url("../assets/indexViews/JZYJView.png");
|
| | | background-size: cover;
|
| | | position: relative;
|
| | | }
|
| | | .title {
|
| | |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢å
¥è' : 'ç¼è¾äººå'" |
| | | :title="operationType === 'add' ? 'æ°å¢èªèµ' : 'ç¼è¾èªèµ'" |
| | | width="50%" |
| | | @close="closeDia" |
| | | > |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="data-dashboard"> |
| | | <!-- å
¨å±æé® - ç§»å¨å°å·¦ä¸è§ --> |
| | | <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? 'éåºå
¨å±' : 'å
¨å±æ¾ç¤º'"> |
| | | <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/> |
| | | </svg> |
| | | <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| | | <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/> |
| | | </svg> |
| | | </button> |
| | | |
| | | <!-- 顶鍿 颿 --> |
| | | <div class="dashboard-header"> |
| | | </div> |
| | | |
| | | <!-- 主è¦å
容åºå --> |
| | | <div class="dashboard-content"> |
| | | <!-- 左侧åºå --> |
| | | <div class="left-panel"> |
| | | <!-- 客æ·ä¿¡æ¯ç»è®¡åæ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">客æ·ä¿¡æ¯ç»è®¡åæ</span> |
| | | </div> |
| | | <div class="panel-item-customers"> |
| | | <div class="panel-title-second"> |
| | | <div class="panel-title-icon"></div> |
| | | <div class="total-customers"> |
| | | <span class="label">æ»ååéé¢(å
)</span> |
| | | <span class="value">{{sum}}</span> |
| | | </div> |
| | | <!-- <div class="jiantou"></div>--> |
| | | </div> |
| | | <!-- 饼å¾åºå --> |
| | | <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 82%;margin-top: 20px"> |
| | | <div style="width: 240px; height: 240px; background-image: url('/src/assets/BI/zonghetongbingtubiankuang@2x.png'); background-size: contain; background-position: center; background-repeat: no-repeat; display: flex; align-items: center; justify-content: center;"> |
| | | <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" |
| | | :series="materialPieSeries" |
| | | :tooltip="pieTooltip" |
| | | :options="{backgroundColor: 'transparent'}" |
| | | style="margin-left: 5px;"></Echarts> |
| | | </div> |
| | | <ul class="contract-list" style="margin: 0; padding: 0; display: flex; flex-direction: column;justify-content: space-around; height: 100%; overflow-y: auto; scroll-behavior: smooth;" ref="refContractList"> |
| | | <li v-for="item in materialPieSeries[0].data" :key="item.name" style="list-style: none; margin-bottom: 12px;"> |
| | | <div style="display: flex;align-items: center;justify-content: space-between;width: 100%"> |
| | | <div class="line" :style="{color: item.itemStyle.color}">â {{item.name}}</div> |
| | | <div style="font-weight: 700;font-size: 16px;color: #85B1E4;">ï¿¥{{item.value}}</div> |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- è´¨éç»è®¡ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">è´¨éç»è®¡</span> |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | | <div class="quality-cards"> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card one"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>åææå·²æ£æµæ°</div> |
| | | <div>{{qualityStatisticsObject.supplierNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card two"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>è¿ç¨æ£éªæ°é</div> |
| | | <div>{{qualityStatisticsObject.processNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | <div class="quality-cardSec"> |
| | | <div class="quality-card three"></div> |
| | | <div class="quality-cardTitle"> |
| | | <div>åºåå·²æ£æ°é</div> |
| | | <div>{{qualityStatisticsObject.factoryNum}}ä»¶</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="barLegend" |
| | | :series="barSeries1" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis1" |
| | | :yAxis="yAxis1" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 260px"></Echarts> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ä¸é´åºå --> |
| | | <div class="center-panel"> |
| | | <!-- é¡¶é¨ç»è®¡å¡ç --> |
| | | <div class="stats-cards"> |
| | | <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="徿 " class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">åå·¥æ»æ°</span> |
| | | <span class="card-value">{{totalStaff}}</span> |
| | | </div> |
| | | </div> |
| | | <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="徿 " class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">å®¢æ·æ»æ°</span> |
| | | <span class="card-value">{{totalCustomers}}</span> |
| | | </div> |
| | | </div> |
| | | <div class="stat-card"> |
| | | <img src="@/assets/BI/icon@2x.png" alt="徿 " class="card-icon" /> |
| | | <div class="card-content"> |
| | | <span class="card-label">ä¾åºåæ»æ°</span> |
| | | <span class="card-value">{{totalSuppliers}}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 设å¤ç»è®¡ --> |
| | | <div class="equipment-stats"> |
| | | <div class="equipment-header"> |
| | | <img src="@/assets/BI/shujutongjiicon@2x.png" alt="徿 " class="equipment-icon" /> |
| | | <span class="equipment-title">设å¤ç»è®¡</span> |
| | | </div> |
| | | <div class="equipment-items"> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentNum}}</span> |
| | | <span class="equipment-label">è®¾å¤æ»æ°</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentRepair}}</span> |
| | | <span class="equipment-label">å¾
维修设å¤</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentMaintain}}</span> |
| | | <span class="equipment-label">å¾
ä¿å
»è®¾å¤</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{totalMeasuring}}</span> |
| | | <span class="equipment-label">计éå¨å
·æ»æ°</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- äºä»¶åç§° --> |
| | | <div class="event-info"> |
| | | <div class="event-header"> |
| | | <img src="@/assets/BI/shijianmingxiicon@2x.png" alt="徿 " class="event-icon" /> |
| | | <span class="event-title">äºä»¶åç§°</span> |
| | | </div> |
| | | <div class="event-content"> |
| | | <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> |
| | | <li v-for="item in todoList" :key="item.id"> |
| | | <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;"> |
| | | <div class="todo-title">å¾
åç¼å·ï¼{{item.approveId}}</div> |
| | | <div class="todo-division">é¨é¨ï¼{{item.approveDeptName}}</div> |
| | | <div class="todo-time">{{item.approveTime}}</div> |
| | | </div> |
| | | <div class="todo-division">å¾
åäºç±ï¼{{item.approveReason}}</div> |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <div v-else style="text-align: center"> |
| | | ææ æ°æ® |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="financial-header"> |
| | | <span class="financial-title">è´¢å¡åæ</span> |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | | <div class="event-header"> |
| | | <img src="@/assets/BI/shijianmingxiicon@2x.png" alt="徿 " class="event-icon" /> |
| | | <span class="event-title">ç»è¥ææåæ</span> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="barLegend1" |
| | | :series="barSeries11" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis3" |
| | | :yAxis="yAxis3" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 300px"></Echarts> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å³ä¾§åºå --> |
| | | <div class="right-panel"> |
| | | <!-- åºæ¶åºä»ç»è®¡ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">åºæ¶åºä»ç»è®¡</span> |
| | | </div> |
| | | <div class="panel-item-customers"> |
| | | <div style="display: flex;justify-content: space-between;margin-bottom: 20px;"> |
| | | <div class="section-title">åºæ¶åºä»ç»è®¡</div> |
| | | <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group"> |
| | | <el-radio-button label="æå¨" :value="1" /> |
| | | <el-radio-button label="ææ" :value="2" /> |
| | | <el-radio-button label="æå£åº¦" :value="3" /> |
| | | </el-radio-group> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :color="barColors2" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="barLegend2" |
| | | :series="barSeries" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis" |
| | | :yAxis="yAxis" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 260px"></Echarts> |
| | | </div> |
| | | |
| | | <!-- 忬¾ä¸å¼ç¥¨åæ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">忬¾ä¸å¼ç¥¨åæ</span> |
| | | </div> |
| | | <div class="panel-item-customers" style="padding-top: 60px;"> |
| | | <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries" |
| | | :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" :options="{backgroundColor: 'transparent', textStyle: {color: '#FFFFFF'}}" style="height: 270px;"></Echarts> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import * as echarts from 'echarts' |
| | | import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue' |
| | | import autofit from 'autofit.js' |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { |
| | | analysisCustomerContractAmounts, getAmountHalfYear, |
| | | homeTodos, |
| | | qualityStatistics, |
| | | statisticsReceivablePayable |
| | | } from "@/api/viewIndex.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {listCustomer} from "@/api/basicData/customerFile.js"; |
| | | import {listSupplier} from "@/api/basicData/supplierManageFile.js"; |
| | | import {getLedgerPage} from "@/api/equipmentManagement/ledger.js"; |
| | | import {getRepairPage} from "@/api/equipmentManagement/repair.js"; |
| | | import {getUpkeepPage} from "@/api/equipmentManagement/upkeep.js"; |
| | | import {measuringInstrumentListPage} from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import {listPageAnalysis} from "@/api/financialManagement/expenseManagement.js"; |
| | | |
| | | // å
¨å±ç¸å
³ç¶æ |
| | | const isFullscreen = ref(false); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const currentTime = ref('') |
| | | const currentDate = ref('') |
| | | const timer = ref(null) |
| | | const charts = ref([]) |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | const customerPieChartRef = ref(null) |
| | | const salesBarChartRef = ref(null) |
| | | const dataBarChartRef = ref(null) |
| | | const financialAreaChartRef = ref(null) |
| | | const realtimeLineChartRef = ref(null) |
| | | const refContractList = ref(null) |
| | | const refTodoList = ref(null) |
| | | const timerScroll = ref(null) |
| | | |
| | | const chartStylePie = { |
| | | width: '140%', |
| | | height: '140%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | const materialPieSeries = ref([ |
| | | { |
| | | type: 'pie', |
| | | radius: ['0%', '90%'], |
| | | avoidLabelOverlap: false, |
| | | itemStyle: { |
| | | borderColor: '#fff', |
| | | borderWidth: 0 |
| | | }, |
| | | label: { |
| | | show: false |
| | | }, |
| | | data: [] |
| | | } |
| | | ]) |
| | | const pieLegend = reactive({ |
| | | show: false, |
| | | }) |
| | | const sum = ref(0) |
| | | const totalStaff = ref(0) |
| | | const totalCustomers = ref(0) |
| | | const totalSuppliers = ref(0) |
| | | const yny = ref(0) |
| | | const chain = ref(0) |
| | | const equipmentNum = ref(0) |
| | | const equipmentRepair = ref(0) |
| | | const equipmentMaintain = ref(0) |
| | | const totalMeasuring = ref(0) |
| | | const pieTooltip = reactive({ |
| | | trigger: 'item', |
| | | formatter: function (params) { |
| | | // å¨æçææç¤ºä¿¡æ¯ï¼åºäºæ°æ®é¡¹ç name 屿§ |
| | | const description = params.name === 'æ¬æåæ¬¾éé¢' ? 'æ¬æåæ¬¾éé¢' : 'åºæ¶æ¬¾éé¢'; |
| | | return `<div style="color: #B8C8E0">${description} ${params.value}å
${params.percent}%</div>`; |
| | | }, |
| | | position: 'right' |
| | | }) |
| | | |
| | | const qualityStatisticsObject = ref({ |
| | | supplierNum: 0, |
| | | processNum: 0, |
| | | factoryNum: 0, |
| | | }) |
| | | const chartStyle = { |
| | | width: '100%', |
| | | height: '150%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | const barSeries = ref([ |
| | | { |
| | | name: 'åºä»éé¢', |
| | | type: 'bar', |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | | }, |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#00A4ED' }, |
| | | { offset: 1, color: '#4EE4FF' } |
| | | ]) |
| | | } |
| | | }, |
| | | { |
| | | name: 'åºæ¶éé¢', |
| | | type: 'bar', |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | | }, |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: '#537EF5' }, |
| | | { offset: 1, color: '#9061F8' } |
| | | ]) |
| | | } |
| | | } |
| | | ]) |
| | | const radio1 = ref(1) |
| | | const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8'] |
| | | const grid = { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | } |
| | | const lineLegend = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['å¼ç¥¨', '忬¾'] |
| | | } |
| | | const lineSeries = ref([ |
| | | { |
| | | type: 'line', |
| | | data: [], |
| | | label: { |
| | | show: true |
| | | }, |
| | | showSymbol: true, // æ¾ç¤ºåç¹ |
| | | }, |
| | | ]) |
| | | const tooltipLine = { |
| | | trigger: 'axis', |
| | | } |
| | | const yAxis2 = ref([ |
| | | { |
| | | type: 'value', |
| | | } |
| | | ]) |
| | | const xAxis2 = ref([ |
| | | { |
| | | type: 'category', |
| | | data: [], |
| | | axisLabel: { |
| | | interval: 0, |
| | | formatter: function(value) { |
| | | return value.replace(/~/g, '\n'); |
| | | }, |
| | | } |
| | | } |
| | | ]) |
| | | const barLegend2 = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['åºä»éé¢', 'åºæ¶éé¢'] |
| | | } |
| | | const barLegend = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['åææä¸åæ ¼æ°', 'è¿ç¨ä¸åæ ¼æ°', 'åºåä¸åæ ¼æ°'] |
| | | } |
| | | const barLegend1 = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['æ»æ¶å
¥', 'æ»æ¯åº', 'åæ¶å
¥'] |
| | | } |
| | | const barSeries11 = ref([ |
| | | { |
| | | name: 'æ»æ¶å
¥', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#00A4ED' }, |
| | | { offset: 0, color: '#4EE4FF' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'æ»æ¯åº', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#3378FF' }, |
| | | { offset: 0, color: '#4E8AFF' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'åæ¶å
¥', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#537EF5' }, |
| | | { offset: 0, color: '#9061F8' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | ]) |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: 'åææä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#00A4ED' }, |
| | | { offset: 0, color: '#4EE4FF' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'è¿ç¨ä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#3378FF' }, |
| | | { offset: 0, color: '#4E8AFF' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'åºåä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | itemStyle: { |
| | | color: { |
| | | type: 'linear', |
| | | x: 0, |
| | | y: 0, |
| | | x2: 0, |
| | | y2: 1, |
| | | colorStops: [ |
| | | { offset: 1, color: '#537EF5' }, |
| | | { offset: 0, color: '#9061F8' } |
| | | ] |
| | | } |
| | | }, |
| | | data: [] |
| | | }, |
| | | ]) |
| | | const tooltip = { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | }, |
| | | formatter: function (params) { |
| | | let result = params[0].axisValueLabel + '<br/>'; |
| | | params.forEach(item => { |
| | | result += `<div style="color: #B8C8E0">${item.marker} ${item.seriesName}: ${item.value}</div>`; |
| | | }); |
| | | return result; |
| | | } |
| | | } |
| | | const xAxis = [{ |
| | | type: 'value', |
| | | }] |
| | | const yAxis = [{ |
| | | type: 'category', |
| | | data: ['åºæ¶åºä»ç»è®¡'] |
| | | }] |
| | | const xAxis1 = ref([{ |
| | | type: 'category', |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | data: [] |
| | | }]) |
| | | const yAxis1 = [{ |
| | | type: 'value', |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | const xAxis3 = ref([{ |
| | | type: 'category', |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | data: [] |
| | | }]) |
| | | const yAxis3 = [{ |
| | | type: 'value', |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }] |
| | | |
| | | // å¾
åäºé¡¹ |
| | | const todoList = ref([]) |
| | | |
| | | // çªå£å¤§å°ååå¤ç |
| | | const handleResize = () => { |
| | | charts.value.forEach(chart => { |
| | | if (chart && chart.resize) { |
| | | chart.resize() |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // 鿝å¾è¡¨å®ä¾ |
| | | const disposeCharts = () => { |
| | | charts.value.forEach(chart => { |
| | | if (chart && chart.dispose) { |
| | | chart.dispose() |
| | | } |
| | | }) |
| | | charts.value = [] |
| | | } |
| | | // ååéé¢ |
| | | const analysisCustomer = () => { |
| | | analysisCustomerContractAmounts().then((res) => { |
| | | sum.value = res.data.sum |
| | | yny.value = res.data.yny |
| | | chain.value = res.data.chain |
| | | // 为æ¯ä¸ªæ°æ®é¡¹åé
éæºé¢è² |
| | | materialPieSeries.value[0].data = res.data.item.map(item => ({ |
| | | ...item, |
| | | itemStyle: { color: getRandomColor() } |
| | | })) |
| | | }) |
| | | } |
| | | // è´¨æ£ç»è®¡ |
| | | const qualityStatisticsInfo = () => { |
| | | qualityStatistics().then((res) => { |
| | | res.data.item.forEach(item => { |
| | | xAxis1.value[0].data.push(item.date) |
| | | barSeries1.value[0].data.push(item.supplierNum) |
| | | barSeries1.value[1].data.push(item.processNum) |
| | | barSeries1.value[2].data.push(item.factoryNum) |
| | | }) |
| | | qualityStatisticsObject.value.supplierNum = res.data.supplierNum |
| | | qualityStatisticsObject.value.processNum = res.data.processNum |
| | | qualityStatisticsObject.value.factoryNum = res.data.factoryNum |
| | | }) |
| | | } |
| | | // è´¢å¡ç»è®¡ |
| | | const accountStatisticsInfo = () => { |
| | | listPageAnalysis().then((res) => { |
| | | xAxis3.value[0].data = res.data.days |
| | | barSeries11.value[0].data = res.data.totalIncome |
| | | barSeries11.value[1].data = res.data.totalExpense |
| | | barSeries11.value[2].data = res.data.netIncome |
| | | }) |
| | | } |
| | | const getNum = () => { |
| | | const params = { |
| | | pageNum: -1, |
| | | pageSize: -1, |
| | | } |
| | | staffOnJobListPage({...params, staffState: 1}).then(res => { |
| | | totalStaff.value = res.data.total |
| | | }) |
| | | listCustomer(params).then((res) => { |
| | | totalCustomers.value = res.total; |
| | | }); |
| | | listSupplier(params).then((res) => { |
| | | totalSuppliers.value = res.data.total |
| | | }); |
| | | } |
| | | const getLedgerNum = () => { |
| | | const params = { |
| | | pageNum: -1, |
| | | pageSize: -1, |
| | | } |
| | | getLedgerPage(params).then((res) => { |
| | | equipmentNum.value = res.data.total |
| | | }); |
| | | getRepairPage(params).then((res) => { |
| | | equipmentRepair.value = res.data.total |
| | | }); |
| | | getUpkeepPage(params).then((res) => { |
| | | equipmentMaintain.value = res.data.total |
| | | }); |
| | | measuringInstrumentListPage(params).then((res) => { |
| | | totalMeasuring.value = res.data.total |
| | | }); |
| | | } |
| | | // å¾
åäºé¡¹ |
| | | const todoInfoS = () => { |
| | | homeTodos().then((res) => { |
| | | todoList.value = res.data |
| | | // å¨è·åå°å¾
åäºé¡¹æ°æ®åï¼åå§åæ»å¨åè½ |
| | | nextTick(() => { |
| | | initTodoListScroll() |
| | | }) |
| | | }) |
| | | } |
| | | // åºä»åºæ¶ç»è®¡ |
| | | const statisticsReceivable = (type) => { |
| | | statisticsReceivablePayable({type: radio1.value}).then((res) => { |
| | | // 设置åºä»é颿°æ® |
| | | barSeries.value[0].data = [ |
| | | { value: res.data.payableMoney } |
| | | ] |
| | | // è®¾ç½®åºæ¶é颿°æ® |
| | | barSeries.value[1].data = [ |
| | | { value: res.data.receivableMoney } |
| | | ] |
| | | }) |
| | | } |
| | | const getAmountHalfYearNum = async () => { |
| | | const res = await getAmountHalfYear() |
| | | console.log(res) |
| | | const monthName = [] |
| | | const receiptAmount = [] |
| | | const invoiceAmount = [] |
| | | res.data.forEach(item => { |
| | | monthName.push(item.month) |
| | | receiptAmount.push(item.receiptAmount) |
| | | invoiceAmount.push(item.invoiceAmount) |
| | | }) |
| | | // æ£ç¡®ååºå¼èµå¼ï¼å建æ°ç xAxis å series 对象 |
| | | xAxis2.value[0].data = monthName |
| | | xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~')); |
| | | lineSeries.value = [ |
| | | { |
| | | name: 'å¼ç¥¨', |
| | | type: 'line', |
| | | data: receiptAmount, |
| | | stack: 'Total', |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: 'rgba(131, 207, 255, 1)' |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: 'rgba(186, 228, 255, 1)' |
| | | } |
| | | ]) |
| | | }, |
| | | itemStyle: { |
| | | color: '#2D99FF', |
| | | borderColor: '#2D99FF' |
| | | }, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | lineStyle: { |
| | | width: 0 |
| | | }, |
| | | showSymbol: true, |
| | | }, |
| | | { |
| | | name: '忬¾', |
| | | type: 'line', |
| | | data: invoiceAmount, |
| | | stack: 'Total', |
| | | lineStyle: { |
| | | width: 0 |
| | | }, |
| | | itemStyle: { |
| | | color: '#83CFFF', |
| | | borderColor: '#83CFFF' |
| | | }, |
| | | showSymbol: true, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: 'rgba(54, 153, 255, 1)' |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: 'rgba(89, 169, 254, 1)' |
| | | } |
| | | ]) |
| | | }, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | } |
| | | ] |
| | | } |
| | | |
| | | // èªå¨è½®æ¢å¨ãæãå£åº¦ç宿¶å¨ |
| | | const autoSwitchTimer = ref(null) |
| | | // åå§åå¾
åäºé¡¹å表æ»å¨åè½ |
| | | const initTodoListScroll = () => { |
| | | const todoList = refTodoList.value |
| | | // 强å¶å¯ç¨æ»å¨ï¼ä¸æ£æ¥ä»»ä½æ¡ä»¶ |
| | | if (todoList) { |
| | | // å建ä¸ä¸ªå
é项ï¼ç¨äºå®ç°æ ç¼æ»å¨ |
| | | const scrollItems = Array.from(todoList.querySelectorAll('li')) |
| | | if (scrollItems.length > 0) { |
| | | // ç¡®ä¿æè¶³å¤ç项ç®ç¨äºæ»å¨ |
| | | // 妿项ç®å¤ªå°ï¼å¤å¤å¶å æ¬¡ä»¥ç¡®ä¿æ»å¨ææ |
| | | if (scrollItems.length < 4) { |
| | | const originalItems = [...scrollItems] |
| | | for (let i = 0; i < 4; i++) { |
| | | originalItems.forEach(item => { |
| | | const clone = item.cloneNode(true) |
| | | todoList.appendChild(clone) |
| | | }) |
| | | } |
| | | // éæ°è·åææé¡¹ç® |
| | | scrollItems.push(...Array.from(todoList.querySelectorAll('li')).slice(scrollItems.length)); |
| | | } |
| | | const itemHeight = scrollItems[0]?.offsetHeight || 0 |
| | | const containerHeight = todoList.clientHeight |
| | | const cloneCount = Math.ceil(containerHeight / itemHeight) + 2 |
| | | |
| | | // å
éåå 个项ç®å¹¶æ·»å å°å表æ«å°¾ï¼å®ç°æ ç¼æ»å¨ |
| | | for (let i = 0; i < cloneCount; i++) { |
| | | const clone = scrollItems[i % scrollItems.length].cloneNode(true) |
| | | todoList.appendChild(clone) |
| | | } |
| | | |
| | | let scrollPosition = 0 |
| | | const scrollSpeed = 1.5 // å¢å æ»å¨é度ï¼ä½¿æ»å¨æ´å ææ¾ |
| | | const pauseTime = 3000 // æ»å¨æåæ¶é´ |
| | | let isPaused = false |
| | | let lastTimestamp = 0 |
| | | |
| | | // è¿ç»æ»å¨å¨ç»å½æ° |
| | | function scrollAnimation(timestamp) { |
| | | if (!lastTimestamp) lastTimestamp = timestamp |
| | | const deltaTime = timestamp - lastTimestamp |
| | | lastTimestamp = timestamp |
| | | |
| | | if (!isPaused) { |
| | | scrollPosition += scrollSpeed * (deltaTime / 16) // æ åå为60fpsçé度 |
| | | |
| | | // 彿»å¨è¶
è¿åå§å
容é¿åº¦æ¶ï¼éç½®ä½ç½®å®ç°æ ç¼æ»å¨ |
| | | const maxScroll = Math.max(todoList.scrollHeight - containerHeight - cloneCount * itemHeight, itemHeight * scrollItems.length) |
| | | if (scrollPosition >= maxScroll) { |
| | | scrollPosition = 0 |
| | | todoList.scrollTop = 0 |
| | | } else { |
| | | todoList.scrollTop = scrollPosition |
| | | } |
| | | } |
| | | |
| | | todoList._animationFrame = requestAnimationFrame(scrollAnimation) |
| | | } |
| | | |
| | | // å¯å¨æ»å¨å¨ç» |
| | | todoList._animationFrame = requestAnimationFrame(scrollAnimation) |
| | | |
| | | // 设置æ»å¨-æå-æ»å¨çå¾ªç¯ææ |
| | | const pauseTimer = setInterval(() => { |
| | | isPaused = !isPaused |
| | | }, pauseTime) |
| | | |
| | | // æ¸
ç宿¶å¨ |
| | | todoList._pauseTimer = pauseTimer |
| | | } |
| | | } |
| | | } |
| | | const getRandomColor = () => { |
| | | // çææµ
è²ï¼RãGãB åéé½å¨ 150-255 ä¹é´ |
| | | const r = Math.floor(Math.random() * 106) + 150; // 150-255 |
| | | const g = Math.floor(Math.random() * 106) + 150; // 150-255 |
| | | const b = Math.floor(Math.random() * 106) + 150; // 150-255 |
| | | // å° RGB 转æ¢ä¸ºåå
è¿å¶é¢è² |
| | | return '#' + r.toString(16).padStart(2, '0') + g.toString(16).padStart(2, '0') + b.toString(16).padStart(2, '0'); |
| | | } |
| | | |
| | | // æ´æ°æ¶é´ |
| | | const updateTime = () => { |
| | | const now = new Date() |
| | | currentTime.value = now.toLocaleTimeString('zh-CN', { hour12: false }) |
| | | currentDate.value = now.toLocaleDateString('zh-CN', { |
| | | year: 'numeric', |
| | | month: '2-digit', |
| | | day: '2-digit', |
| | | weekday: 'long' |
| | | }) |
| | | } |
| | | |
| | | // åå§åæ¶é´ |
| | | const initTime = () => { |
| | | updateTime() |
| | | timer.value = setInterval(updateTime, 1000) |
| | | } |
| | | // å
¨å±åè½å®ç° - é对data-dashboardå
ç´ |
| | | const toggleFullscreen = () => { |
| | | const element = document.querySelector('.data-dashboard') |
| | | |
| | | if (!element) return |
| | | |
| | | if (!isFullscreen.value) { |
| | | if (element.requestFullscreen) { |
| | | element.requestFullscreen() |
| | | } else if (element.webkitRequestFullscreen) { |
| | | element.webkitRequestFullscreen() |
| | | } else if (element.msRequestFullscreen) { |
| | | element.msRequestFullscreen() |
| | | } |
| | | } else { |
| | | if (document.exitFullscreen) { |
| | | document.exitFullscreen() |
| | | } else if (document.webkitExitFullscreen) { |
| | | document.webkitExitFullscreen() |
| | | } else if (document.msExitFullscreen) { |
| | | document.msExitFullscreen() |
| | | } |
| | | } |
| | | } |
| | | |
| | | // çå¬å
¨å±ååäºä»¶ |
| | | const handleFullscreenChange = () => { |
| | | const fullscreenElement = document.fullscreenElement || |
| | | document.webkitFullscreenElement || |
| | | document.msFullscreenElement |
| | | isFullscreen.value = fullscreenElement && fullscreenElement.classList.contains('data-dashboard') |
| | | } |
| | | |
| | | // çå½å¨æé©å |
| | | onMounted(() => { |
| | | initTime() |
| | | // 使ç¨nextTickç¡®ä¿DOMå®å
¨æ¸²æåååå§åå¾è¡¨ |
| | | nextTick(() => { |
| | | // åå§åautofitèªéåº |
| | | autofit.init({ dh: 1440, dw: 2560, el: '.data-dashboard', resize: true }, false) |
| | | |
| | | // æ·»å èªå¨æ»å¨å¨ç»ææ - 客æ·ä¿¡æ¯å表 |
| | | const contractList = refContractList.value |
| | | if (contractList && contractList.scrollHeight > contractList.clientHeight) { |
| | | // å建ä¸ä¸ªå
é项ï¼ç¨äºå®ç°æ ç¼æ»å¨ |
| | | const scrollItems = Array.from(contractList.querySelectorAll('li')) |
| | | const itemHeight = scrollItems[0]?.offsetHeight || 0 |
| | | const containerHeight = contractList.clientHeight |
| | | const cloneCount = Math.ceil(containerHeight / itemHeight) + 2 |
| | | |
| | | // å
éåå 个项ç®å¹¶æ·»å å°å表æ«å°¾ï¼å®ç°æ ç¼æ»å¨ |
| | | for (let i = 0; i < cloneCount; i++) { |
| | | const clone = scrollItems[i % scrollItems.length].cloneNode(true) |
| | | contractList.appendChild(clone) |
| | | } |
| | | |
| | | let scrollPosition = 0 |
| | | const scrollSpeed = 1.5 // å¢å æ»å¨é度ï¼ä½¿æ»å¨æ´å ææ¾ |
| | | const pauseTime = 3000 // æ»å¨æåæ¶é´ |
| | | let isPaused = false |
| | | let lastTimestamp = 0 |
| | | |
| | | // è¿ç»æ»å¨å¨ç»å½æ° |
| | | function scrollAnimation(timestamp) { |
| | | if (!lastTimestamp) lastTimestamp = timestamp |
| | | const deltaTime = timestamp - lastTimestamp |
| | | lastTimestamp = timestamp |
| | | |
| | | if (!isPaused) { |
| | | scrollPosition += scrollSpeed * (deltaTime / 16) // æ åå为60fpsçé度 |
| | | |
| | | // 彿»å¨è¶
è¿åå§å
容é¿åº¦æ¶ï¼éç½®ä½ç½®å®ç°æ ç¼æ»å¨ |
| | | if (scrollPosition >= contractList.scrollHeight - containerHeight - cloneCount * itemHeight) { |
| | | scrollPosition = 0 |
| | | contractList.scrollTop = 0 |
| | | } else { |
| | | contractList.scrollTop = scrollPosition |
| | | } |
| | | } |
| | | |
| | | timerScroll.value = requestAnimationFrame(scrollAnimation) |
| | | } |
| | | |
| | | // å¯å¨æ»å¨å¨ç» |
| | | timerScroll.value = requestAnimationFrame(scrollAnimation) |
| | | |
| | | // 设置æ»å¨-æå-æ»å¨çå¾ªç¯ææ |
| | | const pauseTimer = setInterval(() => { |
| | | isPaused = !isPaused |
| | | }, pauseTime) |
| | | |
| | | // æ¸
ç宿¶å¨ |
| | | contractList._pauseTimer = pauseTimer |
| | | } |
| | | |
| | | // å¾
åäºé¡¹å表æ»å¨åè½å·²ç§»è³todoInfoS彿°ä¸ï¼å¨è·åæ°æ®ååå§å |
| | | }) |
| | | |
| | | window.addEventListener('resize', handleResize) |
| | | analysisCustomer() |
| | | qualityStatisticsInfo() |
| | | accountStatisticsInfo() |
| | | getNum() |
| | | getLedgerNum() |
| | | todoInfoS() |
| | | statisticsReceivable() |
| | | getAmountHalfYearNum() |
| | | |
| | | // 设置èªå¨è½®æ¢å¨ãæãå£åº¦ç宿¶å¨ï¼æ¯10ç§åæ¢ä¸æ¬¡ |
| | | autoSwitchTimer.value = setInterval(() => { |
| | | // 循ç¯åæ¢ï¼1(å¨) -> 2(æ) -> 3(å£åº¦) -> 1(å¨) |
| | | radio1.value = radio1.value === 3 ? 1 : radio1.value + 1 |
| | | statisticsReceivable() |
| | | }, 10000) // 10ç§åæ¢ä¸æ¬¡ |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | if (timer.value) { |
| | | clearInterval(timer.value) |
| | | } |
| | | if (timerScroll.value) { |
| | | cancelAnimationFrame(timerScroll.value) |
| | | } |
| | | // æ¸
çæ»å¨å表çæå宿¶å¨ |
| | | const contractList = refContractList.value |
| | | if (contractList && contractList._pauseTimer) { |
| | | clearInterval(contractList._pauseTimer) |
| | | } |
| | | |
| | | // æ¸
çå¾
åäºé¡¹å表çå¨ç»å宿¶å¨ |
| | | const todoList = refTodoList.value |
| | | if (todoList) { |
| | | if (todoList._animationFrame) { |
| | | cancelAnimationFrame(todoList._animationFrame) |
| | | todoList._animationFrame = null |
| | | } |
| | | if (todoList._pauseTimer) { |
| | | clearInterval(todoList._pauseTimer) |
| | | todoList._pauseTimer = null |
| | | } |
| | | } |
| | | |
| | | // æ¸
çèªå¨è½®æ¢å¨ãæãå£åº¦ç宿¶å¨ |
| | | if (autoSwitchTimer.value) { |
| | | clearInterval(autoSwitchTimer.value) |
| | | autoSwitchTimer.value = null |
| | | } |
| | | |
| | | window.removeEventListener('resize', handleResize) |
| | | window.removeEventListener('fullscreenchange', handleFullscreenChange) |
| | | window.removeEventListener('webkitfullscreenchange', handleFullscreenChange) |
| | | window.removeEventListener('MSFullscreenChange', handleFullscreenChange) |
| | | // ç§»é¤æä»¬æ·»å çautofitå¨æè°æ´çå¬å¨ |
| | | if (window._autofitUpdateHandler) { |
| | | window.removeEventListener('resize', window._autofitUpdateHandler) |
| | | delete window._autofitUpdateHandler |
| | | } |
| | | disposeCharts() |
| | | // å
³éautofit |
| | | autofit.off() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .data-dashboard { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | overflow: hidden; |
| | | background-image: url("@/assets/BI/backImage@2x.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | /* å
¨å±ç¶æçæ ·å¼ */ |
| | | .data-dashboard:fullscreen { |
| | | width: 100%; |
| | | height: 100%; |
| | | margin: 0; |
| | | padding: 0; |
| | | background-color: inherit; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | /* Webkitæµè§å¨åç¼ */ |
| | | .data-dashboard:-webkit-full-screen { |
| | | width: 100%; |
| | | height: 100%; |
| | | margin: 0; |
| | | padding: 0; |
| | | background-color: inherit; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | /* MSæµè§å¨åç¼ */ |
| | | .data-dashboard:-ms-fullscreen { |
| | | width: 100%; |
| | | height: 100%; |
| | | margin: 0; |
| | | padding: 0; |
| | | background-color: inherit; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | |
| | | .dashboard-header { |
| | | position: relative; |
| | | z-index: 1; |
| | | height: 170px; |
| | | background-image: url("@/assets/BI/biaoti.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .fullscreen-btn { |
| | | position: absolute; |
| | | top: 10px; |
| | | left: 20px; |
| | | width: 40px; |
| | | height: 40px; |
| | | background: rgba(0, 20, 60, 0.8); |
| | | border: 1px solid rgba(0, 212, 255, 0.3); |
| | | border-radius: 6px; |
| | | color: #00d4ff; |
| | | cursor: pointer; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: all 0.3s; |
| | | z-index: 10000; |
| | | } |
| | | |
| | | .fullscreen-btn:hover { |
| | | background: rgba(0, 30, 90, 0.9); |
| | | border-color: rgba(0, 212, 255, 0.5); |
| | | } |
| | | |
| | | .dashboard-content { |
| | | position: relative; |
| | | z-index: 1; |
| | | display: flex; |
| | | gap: 30px; |
| | | padding: 0 30px; |
| | | height: calc(100% - 120px); |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* ç¡®ä¿å颿¿è½å¤æ£ç¡®æ¾ç¤º */ |
| | | .left-panel, .center-panel, .right-panel { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 24px; |
| | | width: 520px; |
| | | } |
| | | |
| | | .center-panel { |
| | | flex: 1.5; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | .panel-item-customers { |
| | | border: 1px solid #1A58B0; |
| | | padding: 18px; |
| | | width: 100%; |
| | | height: 540px; |
| | | } |
| | | .panel-title-second { |
| | | height: 60px; |
| | | display: flex; |
| | | gap: 12px; |
| | | margin-bottom: 20px; |
| | | align-items: center; |
| | | } |
| | | .quality-cards { |
| | | display: flex; |
| | | gap: 12px; |
| | | width: 100%; |
| | | height: 94px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .quality-cardSec { |
| | | display: flex; |
| | | } |
| | | .quality-cardTitle { |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #FFFFFF; |
| | | display: flex; |
| | | align-items: flex-start; |
| | | flex-direction: column; |
| | | } |
| | | .quality-card { |
| | | width: 80px; |
| | | height: 60px; |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .quality-card.one { |
| | | background-image: url("@/assets/BI/yuancailiaoyijianicon@2x.png"); |
| | | } |
| | | .quality-card.two { |
| | | background-image: url("@/assets/BI/guochengyijianicon@2x.png"); |
| | | } |
| | | .quality-card.three { |
| | | background-image: url("@/assets/BI/chuchangyijianicon@2x.png"); |
| | | |
| | | } |
| | | .panel-title-icon { |
| | | width: 60px; |
| | | height: 60px; |
| | | background-image: url("@/assets/BI/hetongicon.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .panel-header { |
| | | background-image: url("@/assets/BI/kehuhetongback@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .panel-title { |
| | | width: 100%; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #D9ECFF; |
| | | padding-left: 46px; |
| | | line-height: 36px; |
| | | } |
| | | .total-customers { |
| | | background-image: url("@/assets/BI/hetongjineback@2x.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | width: 90%; |
| | | height: 60px; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 0 20px; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .total-customers .label { |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | .total-customers .value { |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | |
| | | .contract-list { |
| | | margin-top: 16px; |
| | | font-size: 14px; |
| | | color: #666; |
| | | list-style: none; |
| | | padding: 0; |
| | | height: 82%; |
| | | overflow-y: auto; |
| | | width: 460px; |
| | | /* éèæ»å¨æ¡ä½ä¿çæ»å¨åè½ */ |
| | | scrollbar-width: none; /* Firefox */ |
| | | -ms-overflow-style: none; /* IEåEdge */ |
| | | } |
| | | |
| | | /* ChromeãSafariåOpera */ |
| | | .contract-list::-webkit-scrollbar { |
| | | display: none; |
| | | } |
| | | .line { |
| | | position: relative; |
| | | width: 230px; |
| | | } |
| | | .line::after { |
| | | content: ''; |
| | | position: absolute; |
| | | right: 2px; |
| | | top: 0; |
| | | bottom: 0; |
| | | width: 1px; |
| | | background-color: #C9C5C5; |
| | | border-radius: 2px; |
| | | } |
| | | .contract-list li { |
| | | margin-top: 10px; |
| | | } |
| | | .stats-cards { |
| | | display: flex; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | background-image: url("@/assets/BI/border@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | height: 142px; |
| | | } |
| | | |
| | | .card-icon { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin: 20px 20px 0 10px; |
| | | } |
| | | |
| | | .card-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .card-value { |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | background: linear-gradient(360deg, #008BFD 0%, #FFFFFF 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | } |
| | | |
| | | .card-label { |
| | | font-weight: 400; |
| | | font-size: 19px; |
| | | color: rgba(208,231,255,0.7); |
| | | } |
| | | |
| | | .equipment-stats { |
| | | border: 1px solid #1A58B0; |
| | | padding: 18px; |
| | | height: 240px; |
| | | } |
| | | .equipment-header { |
| | | font-weight: 500; |
| | | font-size: 21px; |
| | | display: flex; |
| | | border-bottom: 1px solid; |
| | | border-image: linear-gradient( 270deg, rgba(0,126,255,0) 0%, rgba(0,126,255,0.4549) 35%, #007EFF 78%, #007EFF 100%) 1; |
| | | padding-bottom: 2px; |
| | | } |
| | | .equipment-title { |
| | | font-weight: 500; |
| | | font-size: 21px; |
| | | background: linear-gradient(360deg, #056DFF 0%, #43E8FC 100%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | background-clip: text; |
| | | line-height: 50px; |
| | | } |
| | | .equipment-icon { |
| | | width: 50px; |
| | | height: 50px; |
| | | } |
| | | .equipment-items { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .equipment-item { |
| | | text-align: center; |
| | | } |
| | | |
| | | .equipment-value { |
| | | display: block; |
| | | font-weight: 500; |
| | | font-size: 40px; |
| | | color: #FFFFFF; |
| | | width: 120px; |
| | | height: 110px; |
| | | line-height: 110px; |
| | | background-image: url("@/assets/BI/shujutongji@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .equipment-label { |
| | | font-weight: 500; |
| | | font-size: 21px; |
| | | color: #FFFFFE; |
| | | } |
| | | |
| | | .event-info { |
| | | background-image: url("@/assets/BI/shijianmingchengbeijing@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | padding: 20px; |
| | | height: 186px; |
| | | } |
| | | .event-header { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .event-icon { |
| | | width: 40px; |
| | | height: 40px; |
| | | } |
| | | .event-title { |
| | | font-weight: 500; |
| | | font-size: 24px; |
| | | color: #FFFFFE; |
| | | line-height: 30px; |
| | | } |
| | | .todo-list { |
| | | list-style: none; |
| | | padding: 0; |
| | | margin: 0; |
| | | height: 120px; /* æç¨æ·è¦æ±è°æ´é«åº¦ */ |
| | | overflow: hidden; |
| | | font-size: 15px; |
| | | } |
| | | .todo-list li { |
| | | border-radius: 8px; |
| | | margin-bottom: 12px; |
| | | padding: 12px 40px; |
| | | height: 74px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .todo-title { |
| | | font-weight: 400; |
| | | font-size: 20px; |
| | | color: #FFFFFE; |
| | | position: relative; |
| | | } |
| | | .todo-title::before { |
| | | content: ''; /* å¿
éï¼è¡¨ç¤ºè¿éæä¸ä¸ªå
容 */ |
| | | position: absolute; |
| | | left: -10px; /* å®ä½å°å·¦ä¾§ */ |
| | | top: 50%; /* åç´å±
ä¸ */ |
| | | transform: translateY(-50%); /* å¾®è°åç´å±
ä¸ */ |
| | | width: 6px; /* åçç´å¾ */ |
| | | height: 6px; /* åçç´å¾ */ |
| | | background: #498CEB; |
| | | border-radius: 50%; /* 让å
¶åæåå½¢ */ |
| | | } |
| | | .todo-division { |
| | | font-weight: 400; |
| | | font-size: 20px; |
| | | color: #FFFFFE; |
| | | } |
| | | .todo-time { |
| | | font-weight: 400; |
| | | font-size: 20px; |
| | | color: #FFFFFE; |
| | | } |
| | | .financial-header { |
| | | background-image: url("@/assets/BI/caiwufenxiback@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .financial-title { |
| | | width: 100%; |
| | | font-weight: 500; |
| | | font-size: 16px; |
| | | color: #D9ECFF; |
| | | padding-left: 46px; |
| | | line-height: 36px; |
| | | } |
| | | |
| | | /* èªå®ä¹åéæé®ç»æ ·å¼ */ |
| | | .custom-radio-group :deep(.el-radio-button__inner) { |
| | | background-color: transparent; |
| | | color: white; |
| | | border-color: rgba(255, 255, 255, 0.3); |
| | | } |
| | | |
| | | .custom-radio-group :deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) { |
| | | background-color: rgba(255, 255, 255, 0.2); |
| | | color: white; |
| | | border-color: rgba(255, 255, 255, 0.5); |
| | | box-shadow: -1px 0 0 0 rgba(255, 255, 255, 0.5); |
| | | } |
| | | </style> |
| | |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="æ°å¢å票å·é¡µé¢" |
| | | title="æ°å¢å款页é¢" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°äººï¼" prop="registrant"> |
| | | <el-input |
| | | v-model="form.registrant" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="忬¾æ¥æï¼" prop="receiptPaymentDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.receiptPaymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥æ¬¾æ¥æï¼" prop="receiptPaymentDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.receiptPaymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°äººï¼" prop="registrant"> |
| | | <el-input |
| | | v-model="form.registrant" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | import { defineConfig, loadEnv } from "vite";
|
| | | import path from "path";
|
| | | import createVitePlugins from "./vite/plugins";
|
| | |
|
| | | // https://vitejs.dev/config/
|
| | | export default defineConfig(({ mode, command }) => {
|
| | | const env = loadEnv(mode, process.cwd());
|
| | | const { VITE_APP_ENV } = env;
|
| | | const baseUrl =
|
| | | VITE_APP_ENV == "development"
|
| | | ? "http://114.132.189.42:8089" // å¼åç¯å¢å端æ¥å£
|
| | | : "http://114.132.189.42:9032"; // ç产ç¯å¢å端æ¥å£
|
| | |
|
| | | return {
|
| | | // é¨ç½²ç产ç¯å¢åå¼åç¯å¢ä¸çURLã
|
| | | // é»è®¤æ
åµä¸ï¼vite ä¼åè®¾ä½ çåºç¨æ¯è¢«é¨ç½²å¨ä¸ä¸ªååçæ ¹è·¯å¾ä¸
|
| | | // ä¾å¦ https://www.ruoyi.vip/ã妿åºç¨è¢«é¨ç½²å¨ä¸ä¸ªåè·¯å¾ä¸ï¼ä½ å°±éè¦ç¨è¿ä¸ªé项æå®è¿ä¸ªåè·¯å¾ãä¾å¦ï¼å¦æä½ çåºç¨è¢«é¨ç½²å¨ https://www.ruoyi.vip/admin/ï¼å设置 baseUrl 为 /admin/ã
|
| | | base: VITE_APP_ENV === "production" ? "/" : "/",
|
| | | plugins: createVitePlugins(env, command === "build"),
|
| | | resolve: {
|
| | | // https://cn.vitejs.dev/config/#resolve-alias
|
| | | alias: {
|
| | | // 设置路å¾
|
| | | "~": path.resolve(__dirname, "./"),
|
| | | // 设置å«å
|
| | | "@": path.resolve(__dirname, "./src"),
|
| | | },
|
| | | // https://cn.vitejs.dev/config/#resolve-extensions
|
| | | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
|
| | | },
|
| | | // æå
é
ç½®
|
| | | build: {
|
| | | // https://vite.dev/config/build-options.html
|
| | | sourcemap: command === "build" ? false : "inline",
|
| | | outDir: "dist",
|
| | | assetsDir: "assets",
|
| | | chunkSizeWarningLimit: 2000,
|
| | | rollupOptions: {
|
| | | output: {
|
| | | chunkFileNames: "static/js/[name]-[hash].js",
|
| | | entryFileNames: "static/js/[name]-[hash].js",
|
| | | assetFileNames: "static/[ext]/[name]-[hash].[ext]",
|
| | | },
|
| | | },
|
| | | },
|
| | | // vite ç¸å
³é
ç½®
|
| | | server: {
|
| | | port: 8001,
|
| | | host: true,
|
| | | open: true,
|
| | | proxy: {
|
| | | // https://cn.vitejs.dev/config/#server-proxy
|
| | | "/dev-api": {
|
| | | target: baseUrl,
|
| | | changeOrigin: true,
|
| | | rewrite: (p) => p.replace(/^\/dev-api/, ""),
|
| | | },
|
| | | // springdoc proxy
|
| | | "^/v3/api-docs/(.*)": {
|
| | | target: baseUrl,
|
| | | changeOrigin: true,
|
| | | },
|
| | | },
|
| | | },
|
| | | css: {
|
| | | postcss: {
|
| | | plugins: [
|
| | | {
|
| | | postcssPlugin: "internal:charset-removal",
|
| | | AtRule: {
|
| | | charset: (atRule) => {
|
| | | if (atRule.name === "charset") {
|
| | | atRule.remove();
|
| | | }
|
| | | },
|
| | | },
|
| | | },
|
| | | ],
|
| | | },
|
| | | },
|
| | | };
|
| | | });
|
| | | import { defineConfig, loadEnv } from "vite"; |
| | | import path from "path"; |
| | | import createVitePlugins from "./vite/plugins"; |
| | | |
| | | // https://vitejs.dev/config/ |
| | | export default defineConfig(({ mode, command }) => { |
| | | const env = loadEnv(mode, process.cwd()); |
| | | const { VITE_APP_ENV } = env; |
| | | const baseUrl = |
| | | VITE_APP_ENV == "development" |
| | | ? "http://114.132.189.42:9036" // å¼åç¯å¢å端æ¥å£ |
| | | : "http://114.132.189.42:9036"; // ç产ç¯å¢å端æ¥å£ |
| | | |
| | | return { |
| | | // é¨ç½²ç产ç¯å¢åå¼åç¯å¢ä¸çURLã |
| | | // é»è®¤æ
åµä¸ï¼vite ä¼åè®¾ä½ çåºç¨æ¯è¢«é¨ç½²å¨ä¸ä¸ªååçæ ¹è·¯å¾ä¸ |
| | | // ä¾å¦ https://www.ruoyi.vip/ã妿åºç¨è¢«é¨ç½²å¨ä¸ä¸ªåè·¯å¾ä¸ï¼ä½ å°±éè¦ç¨è¿ä¸ªé项æå®è¿ä¸ªåè·¯å¾ãä¾å¦ï¼å¦æä½ çåºç¨è¢«é¨ç½²å¨ https://www.ruoyi.vip/admin/ï¼å设置 baseUrl 为 /admin/ã |
| | | base: VITE_APP_ENV === "production" ? "/" : "/", |
| | | plugins: createVitePlugins(env, command === "build"), |
| | | resolve: { |
| | | // https://cn.vitejs.dev/config/#resolve-alias |
| | | alias: { |
| | | // è®¾ç½®è·¯å¾ |
| | | "~": path.resolve(__dirname, "./"), |
| | | // 设置å«å |
| | | "@": path.resolve(__dirname, "./src"), |
| | | }, |
| | | // https://cn.vitejs.dev/config/#resolve-extensions |
| | | extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"], |
| | | }, |
| | | // æå
é
ç½® |
| | | build: { |
| | | // https://vite.dev/config/build-options.html |
| | | sourcemap: command === "build" ? false : "inline", |
| | | outDir: "dist", |
| | | assetsDir: "assets", |
| | | chunkSizeWarningLimit: 2000, |
| | | rollupOptions: { |
| | | output: { |
| | | chunkFileNames: "static/js/[name]-[hash].js", |
| | | entryFileNames: "static/js/[name]-[hash].js", |
| | | assetFileNames: "static/[ext]/[name]-[hash].[ext]", |
| | | }, |
| | | }, |
| | | }, |
| | | // vite ç¸å
³é
ç½® |
| | | server: { |
| | | port: 80, |
| | | host: true, |
| | | open: true, |
| | | proxy: { |
| | | // https://cn.vitejs.dev/config/#server-proxy |
| | | "/dev-api": { |
| | | target: baseUrl, |
| | | changeOrigin: true, |
| | | rewrite: (p) => p.replace(/^\/dev-api/, ""), |
| | | }, |
| | | // springdoc proxy |
| | | "^/v3/api-docs/(.*)": { |
| | | target: baseUrl, |
| | | changeOrigin: true, |
| | | }, |
| | | }, |
| | | }, |
| | | css: { |
| | | postcss: { |
| | | plugins: [ |
| | | { |
| | | postcssPlugin: "internal:charset-removal", |
| | | AtRule: { |
| | | charset: (atRule) => { |
| | | if (atRule.name === "charset") { |
| | | atRule.remove(); |
| | | } |
| | | }, |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | }; |
| | | }); |