mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-08-31 01:39:47 +08:00
refactor: migrate charts from echarts to @antv/g2 and drop legacy vite plugins for vite 8
This commit is contained in:
+1
-7
@@ -47,7 +47,7 @@
|
||||
"@tauri-apps/plugin-shell": "^2.3.5",
|
||||
"axios": "^1.15.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"echarts": "^6.0.0",
|
||||
"dayjs": "^1.11.20",
|
||||
"element-plus": "^2.13.7",
|
||||
"highlight.js": "^11.11.1",
|
||||
"js-base64": "^3.7.8",
|
||||
@@ -56,7 +56,6 @@
|
||||
"json-bigint": "^1.0.0",
|
||||
"marked": "^18.0.2",
|
||||
"mitt": "^3.0.1",
|
||||
"moment": "^2.30.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^3.0.4",
|
||||
"screenfull": "^6.0.2",
|
||||
@@ -72,11 +71,8 @@
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
||||
"@typescript-eslint/parser": "^8.59.1",
|
||||
"@vitejs/plugin-legacy": "^8.0.1",
|
||||
"@vitejs/plugin-vue": "^6.0.6",
|
||||
"@vue/eslint-config-typescript": "^14.7.0",
|
||||
"core-js": "^3.49.0",
|
||||
"dotenv": "^17.4.2",
|
||||
"eslint": "^10.2.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
@@ -84,10 +80,8 @@
|
||||
"globals": "^17.5.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.4.0",
|
||||
"minimist": "^1.2.8",
|
||||
"prettier": "^3.8.3",
|
||||
"sass": "^1.99.0",
|
||||
"terser": "^5.46.2",
|
||||
"typescript": "~6.0.3",
|
||||
"unplugin-auto-import": "^21.0.0",
|
||||
"unplugin-vue-components": "^32.0.0",
|
||||
|
||||
Generated
+12
-1455
File diff suppressed because it is too large
Load Diff
@@ -30,16 +30,16 @@
|
||||
</el-menu-item>
|
||||
<template v-for="menusItem in menus">
|
||||
<el-sub-menu v-if="menusItem.children" :key="`${menusItem.path}-submenu`" :index="menusItem.path">
|
||||
<template #title>{{ (menusItem.meta as any).title }}</template>
|
||||
<template #title>{{ menusItem.meta?.title }}</template>
|
||||
<el-menu-item v-for="item in menusItem.children" :key="item.path" :index="item.path">
|
||||
{{ (item.meta as any).title }}
|
||||
{{ item.meta?.title }}
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :key="`${menusItem.path}-menuitem`" :index="menusItem.path">
|
||||
<el-icon>
|
||||
<component :is="(menusItem.meta as any).icon"></component>
|
||||
<component :is="menusItem.meta?.icon"></component>
|
||||
</el-icon>
|
||||
{{ (menusItem.meta as any).title }}
|
||||
{{ menusItem.meta?.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016-present the IoT DC3 original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Augment vue-router's RouteMeta so route definitions under src/config/router/**
|
||||
// can use `meta: { title, icon }` with full type-checking.
|
||||
import 'vue-router';
|
||||
|
||||
declare module 'vue-router' {
|
||||
interface RouteMeta {
|
||||
/** Page title used in document.title and menu labels */
|
||||
title?: string;
|
||||
/** Global Element Plus icon name (e.g. 'Promotion', 'List') used in the nav menu */
|
||||
icon?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -14,11 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/zh-cn';
|
||||
|
||||
moment.locale('zh-cn');
|
||||
|
||||
/**
|
||||
* Format timestamp to date string
|
||||
*
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/zh-cn';
|
||||
|
||||
moment.locale('zh-cn');
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
/**
|
||||
* Log utility with timestamp and color-coded levels
|
||||
@@ -29,7 +26,7 @@ export const log = {
|
||||
* @param message Message to log
|
||||
*/
|
||||
info(message: string) {
|
||||
const now = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
const now = dayjs().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
console.log(now, '%cINFO%c --- :', 'color:#67C23A', message);
|
||||
},
|
||||
|
||||
@@ -39,7 +36,7 @@ export const log = {
|
||||
* @param message Message to log
|
||||
*/
|
||||
warn(message: string) {
|
||||
const now = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
const now = dayjs().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
console.log(now, '%cWARN%c --- :', 'color:#E6A23C', message);
|
||||
},
|
||||
|
||||
@@ -49,7 +46,7 @@ export const log = {
|
||||
* @param message Message to log
|
||||
*/
|
||||
error(message: string) {
|
||||
const now = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
const now = dayjs().format('YYYY-MM-DD HH:mm:ss.SSS');
|
||||
console.log(now, '%cERROR%c --- :', 'color:#F56C6C', message);
|
||||
},
|
||||
};
|
||||
|
||||
+33
-59
@@ -16,7 +16,7 @@
|
||||
|
||||
import { defineComponent, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import * as echarts from 'echarts';
|
||||
import { Chart } from '@antv/g2';
|
||||
|
||||
import TitleCard from '@/components/card/title/TitleCard.vue';
|
||||
import ApplicationCard from '@/views/application/card/ApplicationCard.vue';
|
||||
@@ -238,64 +238,38 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const chart = echarts.init(countDataChartRef.value as HTMLElement);
|
||||
reactiveData.data = reactiveData.data.map((item) => [item[1], item[0], item[2]]);
|
||||
const option = {
|
||||
legend: {
|
||||
data: ['日/时数据量统计'],
|
||||
left: 'right',
|
||||
},
|
||||
tooltip: {
|
||||
position: 'top',
|
||||
formatter: (params) => {
|
||||
return (
|
||||
params.value[2] +
|
||||
' commits in ' +
|
||||
reactiveData.hours[params.value[0]] +
|
||||
' of ' +
|
||||
reactiveData.days[params.value[1]]
|
||||
);
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: 2,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: reactiveData.hours,
|
||||
boundaryGap: false,
|
||||
splitLine: {
|
||||
show: true,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: reactiveData.days,
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '日/时数据量统计',
|
||||
type: 'scatter',
|
||||
symbolSize: (val) => {
|
||||
return val[2] * 2;
|
||||
},
|
||||
data: reactiveData.data,
|
||||
animationDelay: (idx) => {
|
||||
return idx * 5;
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
chart.setOption(option);
|
||||
const el = countDataChartRef.value as HTMLElement | null;
|
||||
if (!el) return;
|
||||
|
||||
// Original data is [dayIndex, hourIndex, count]; turn it into labeled objects
|
||||
const points = reactiveData.data
|
||||
.filter(([dayIdx, hourIdx]: number[]) => dayIdx !== undefined && hourIdx !== undefined)
|
||||
.map(([dayIdx, hourIdx, count]: number[]) => ({
|
||||
hour: reactiveData.hours[hourIdx!],
|
||||
day: reactiveData.days[dayIdx!],
|
||||
count,
|
||||
}));
|
||||
|
||||
const chart = new Chart({ container: el, autoFit: true });
|
||||
|
||||
chart
|
||||
.point()
|
||||
.data(points)
|
||||
.encode('x', 'hour')
|
||||
.encode('y', 'day')
|
||||
.encode('size', 'count')
|
||||
.scale('size', { type: 'sqrt', range: [4, 24] })
|
||||
.scale('x', { padding: 0.5 })
|
||||
.scale('y', { padding: 0.5 })
|
||||
.style('fill', '#409eff')
|
||||
.style('fillOpacity', 0.65)
|
||||
.axis({ x: { title: false }, y: { title: false } })
|
||||
.tooltip({
|
||||
title: (d: { hour: string; day: string }) => `${d.day} ${d.hour}`,
|
||||
items: [{ field: 'count', name: '数据量' }],
|
||||
});
|
||||
|
||||
chart.render();
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-present the IoT DC3 original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, onMounted, reactive } from 'vue';
|
||||
import { CircleClose, Edit, Management, Sunrise, Sunset, Timer, ZoomIn } from '@element-plus/icons-vue';
|
||||
|
||||
import { TinyArea } from '@antv/g2plot';
|
||||
|
||||
import { copy } from '@/utils/CommonUtil';
|
||||
import { timestamp } from '@/utils/DateUtil';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PointValueCard',
|
||||
components: {
|
||||
Edit,
|
||||
Sunset,
|
||||
Timer,
|
||||
Management,
|
||||
Sunrise,
|
||||
ZoomIn,
|
||||
},
|
||||
props: {
|
||||
embedded: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return '';
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
device: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
point: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
historyData: {
|
||||
type: Array<number>,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'images/common/point.png',
|
||||
},
|
||||
},
|
||||
emits: ['show-edit', 'show-detail'],
|
||||
setup(props, { emit }) {
|
||||
// 定义响应式数据
|
||||
const reactiveData = reactive({
|
||||
spRefLineStyles: {
|
||||
stroke: '#54a5ff',
|
||||
strokeOpacity: 0.5,
|
||||
strokeDasharray: '2, 2',
|
||||
},
|
||||
spCurveStyles: {
|
||||
stroke: '#54a5ff',
|
||||
},
|
||||
});
|
||||
|
||||
// 图标
|
||||
const Icon = {
|
||||
CircleClose,
|
||||
};
|
||||
|
||||
const showEdit = (pointValue) => {
|
||||
emit('show-edit', pointValue);
|
||||
};
|
||||
|
||||
const copyValue = (data) => {
|
||||
const content = {
|
||||
deviceId: data.deviceId,
|
||||
pointId: data.pointId,
|
||||
value: data.value,
|
||||
};
|
||||
copy(JSON.stringify(content, null, 2), '位号值');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (props.embedded == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
const tinyArea = new TinyArea(props.data.pointId, {
|
||||
height: 60,
|
||||
data: props.historyData,
|
||||
autoFit: true,
|
||||
smooth: true,
|
||||
});
|
||||
|
||||
tinyArea.render();
|
||||
});
|
||||
|
||||
return {
|
||||
reactiveData,
|
||||
showEdit,
|
||||
copyId: copy,
|
||||
copyValue,
|
||||
timestamp,
|
||||
...Icon,
|
||||
};
|
||||
},
|
||||
});
|
||||
+1
-2
@@ -13,9 +13,8 @@
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
"moduleResolution": "bundler",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"types": ["vite/client", "element-plus/global"],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
+4
-15
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import legacy from '@vitejs/plugin-legacy';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { resolve } from 'path';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
@@ -42,7 +41,6 @@ export default (configEnv: ConfigEnv) => {
|
||||
entryFileNames: `assets/dc3.[name].[hash].js`,
|
||||
chunkFileNames: `assets/dc3.[name].[hash].js`,
|
||||
assetFileNames: `assets/dc3.[name].[hash].[ext]`,
|
||||
compact: true,
|
||||
manualChunks: (id: string) => {
|
||||
if (id.includes('node_modules')) {
|
||||
// Merge vue and element-plus to avoid circular dependency
|
||||
@@ -52,11 +50,8 @@ export default (configEnv: ConfigEnv) => {
|
||||
if (id.includes('vue-router')) {
|
||||
return 'router-vendor';
|
||||
}
|
||||
if (id.includes('echarts')) {
|
||||
return 'echarts-vendor';
|
||||
}
|
||||
if (id.includes('lodash')) {
|
||||
return 'lodash-vendor';
|
||||
if (id.includes('@antv')) {
|
||||
return 'g2-vendor';
|
||||
}
|
||||
return 'vendor';
|
||||
}
|
||||
@@ -85,7 +80,7 @@ export default (configEnv: ConfigEnv) => {
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
chunkSizeWarningLimit: 1500,
|
||||
minify: 'esbuild',
|
||||
// minify defaults to rolldown in Vite 8
|
||||
sourcemap: configEnv.mode === 'production' ? false : true,
|
||||
reportCompressedSize: false,
|
||||
cssCodeSplit: true,
|
||||
@@ -93,12 +88,6 @@ export default (configEnv: ConfigEnv) => {
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
legacy({
|
||||
targets: 'defaults, not ie 11, not op_mini all',
|
||||
additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
|
||||
renderLegacyChunks: true,
|
||||
modernPolyfills: true,
|
||||
}),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
imports: [
|
||||
@@ -119,7 +108,7 @@ export default (configEnv: ConfigEnv) => {
|
||||
}),
|
||||
],
|
||||
optimizeDeps: {
|
||||
include: ['vue', 'vue-router', 'element-plus', '@element-plus/icons-vue', 'echarts'],
|
||||
include: ['vue', 'vue-router', 'element-plus', '@element-plus/icons-vue', '@antv/g2'],
|
||||
exclude: ['@vitejs/plugin-vue'],
|
||||
},
|
||||
css: {
|
||||
|
||||
Reference in New Issue
Block a user