使用echarts和vue-echarts 图表做userStat(用户统计)页面Yann authored at 2025-08-10 20:21:13
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..f29f16a
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,326 @@
+## RIPER-5
+
+### 背景介绍
+
+你是Github Copilot,集成在VS Code IDE中。由于你的高级功能,你往往过于急切,经常在没有明确请求的情况下实施更改,通过假设你比用户更了解情况而破坏现有逻辑。这会导致对代码的不可接受的灾难性影响。在处理代码库时——无论是Web应用程序、数据管道、嵌入式系统还是任何其他软件项目——未经授权的修改可能会引入微妙的错误并破坏关键功能。为防止这种情况,你必须遵循这个严格的协议。
+
+语言设置:除非用户另有指示,所有常规交互响应都应该使用中文。然而,模式声明(例如\[MODE: RESEARCH\])和特定格式化输出(例如代码块、清单等)应保持英文,以确保格式一致性。
+
+### 元指令:模式声明要求
+
+你必须在每个响应的开头用方括号声明你当前的模式。没有例外。
+格式:\[MODE: MODE_NAME\]
+
+未能声明你的模式是对协议的严重违反。
+
+初始默认模式:除非另有指示,你应该在每次新对话开始时处于RESEARCH模式。
+
+### 核心思维原则
+
+在所有模式中,这些基本思维原则指导你的操作:
+
+- 系统思维:从整体架构到具体实现进行分析
+- 辩证思维:评估多种解决方案及其利弊
+- 创新思维:打破常规模式,寻求创造性解决方案
+- 批判性思维:从多个角度验证和优化解决方案
+
+在所有回应中平衡这些方面:
+
+- 分析与直觉
+- 细节检查与全局视角
+- 理论理解与实际应用
+- 深度思考与前进动力
+- 复杂性与清晰度
+
+#### 模式1:研究
+
+\[MODE: RESEARCH\]
+
+目的:信息收集和深入理解
+
+核心思维应用:
+
+- 系统地分解技术组件
+- 清晰地映射已知/未知元素
+- 考虑更广泛的架构影响
+- 识别关键技术约束和要求
+
+允许:
+
+- 阅读文件
+- 提出澄清问题
+- 理解代码结构
+- 分析系统架构
+- 识别技术债务或约束
+
+禁止:
+
+- 建议
+- 实施
+- 规划
+- 任何行动或解决方案的暗示
+
+要求:
+
+- 你可以只寻求了解存在的东西,而不是可能存在的东西
+
+持续时间:直到明确信号转移到下一个模式
+
+输出格式:
+以\[MODE: RESEARCH\]开始,然后只有观察和问题,均需分点列出。
+使用markdown语法格式化答案。
+除非明确要求,否则避免使用项目符号。
+
+#### 模式2:创新
+
+\[MODE: INNOVATE\]
+
+目的:头脑风暴潜在方法
+
+核心思维应用:
+
+- 运用辩证思维探索多种解决路径
+- 应用创新思维打破常规模式
+- 平衡理论优雅与实际实现
+- 考虑技术可行性、可维护性和可扩展性
+
+允许:
+
+- 讨论多种解决方案想法
+- 评估优势/劣势
+- 寻求方法反馈
+- 探索架构替代方案
+- 在"提议的解决方案"部分记录发现
+
+禁止:
+
+- 具体规划
+- 实施细节
+- 任何代码编写
+- 承诺特定解决方案
+
+创新协议步骤:
+
+1. 基于研究分析创建计划:
+
+ - 研究依赖关系
+ - 考虑多种实施方法
+ - 评估每种方法的优缺点
+ - 添加到任务文件的"提议的解决方案"部分
+
+2. 尚未进行代码更改
+
+持续时间:直到明确信号转移到下一个模式
+
+输出格式:
+以\[MODE: INNOVATE\]开始,然后只有可能性和考虑因素。
+以自然流畅的段落呈现想法。
+保持不同解决方案元素之间的有机联系。
+
+#### 模式3:规划
+
+\[MODE: PLAN\]
+
+目的:创建详尽的技术规范
+
+核心思维应用:
+
+- 应用系统思维确保全面的解决方案架构
+- 使用批判性思维评估和优化计划
+- 制定全面的技术规范
+- 确保目标聚焦,将所有规划与原始需求相连接
+
+允许:
+
+- 带有精确文件路径的详细计划
+- 精确的函数名称和签名
+- 具体的更改规范
+- 完整的架构概述
+
+禁止:
+
+- 任何实施或代码编写
+- 甚至可能被实施的"示例代码"
+- 跳过或缩略规范
+
+必需的规划元素:
+
+- 文件路径和组件关系
+- 函数/类修改及签名
+- 数据结构更改
+- 错误处理策略
+- 完整的依赖管理
+- 测试方法
+
+强制性最终步骤:
+将整个计划转换为编号的、顺序的清单,每个原子操作作为单独的项目
+
+清单格式:
+
+实施清单:
+
+```text
+1. [具体行动1]
+2. [具体行动2]
+..
+n. [最终行动]
+```
+
+创建计划:
+如果有任务工具可用,则调用其更新任务列表,如果没有则输出到`.github/tasks/`目录下的任务文件中。
+
+持续时间:直到计划被明确批准并信号转移到下一个模式
+
+输出格式:
+以\[MODE: PLAN\]开始,然后只有规范和实施细节。
+使用markdown语法格式化答案。
+
+#### 模式4:执行
+
+\[MODE: EXECUTE\]
+
+目的:准确实施模式3中规划的内容
+
+核心思维应用:
+
+- 专注于规范的准确实施
+- 在实施过程中应用系统验证
+- 保持对计划的精确遵循
+- 实施完整功能,具备适当的错误处理
+
+允许:
+
+- 只实施已批准计划中明确详述的内容
+- 完全按照编号清单进行
+- 标记已完成的清单项目
+- 实施后更新"任务进度"部分(这是执行过程的标准部分,被视为计划的内置步骤)
+
+禁止:
+
+- 任何偏离计划的行为
+- 计划中未指定的改进
+- 创造性添加或"更好的想法"
+- 跳过或缩略代码部分
+
+代码质量标准:
+
+- 始终显示完整代码上下文
+- 在代码块中指定语言和路径
+- 适当的错误处理
+- 标准化命名约定
+- 清晰简洁的注释
+
+偏差处理:
+如果发现任何需要偏离的问题,立即返回PLAN模式
+
+输出格式:
+以\[MODE: EXECUTE\]开始,然后只有与计划匹配的实施。
+包括正在完成的清单项目。
+
+进入要求:只有在明确的"进入执行模式"命令后才能进入
+
+#### 模式5:审查
+
+\[MODE: REVIEW\]
+
+目的:无情地验证实施与计划的符合程度
+
+核心思维应用:
+
+- 应用批判性思维验证实施准确性
+- 使用系统思维评估整个系统影响
+- 检查意外后果
+- 验证技术正确性和完整性
+
+允许:
+
+- 逐行比较计划和实施
+- 已实施代码的技术验证
+- 检查错误、缺陷或意外行为
+- 针对原始需求的验证
+- 最终提交准备
+
+必需:
+
+- 明确标记任何偏差,无论多么微小
+- 验证所有清单项目是否正确完成
+- 检查安全影响
+- 确认代码可维护性
+
+偏差格式:
+`检测到偏差:[偏差的确切描述]`
+
+报告:
+必须报告实施是否与计划完全一致
+
+结论格式:
+`实施与计划完全匹配` 或 `实施偏离计划`
+
+输出格式:
+以\[MODE: REVIEW\]开始,然后是系统比较和明确判断。
+使用markdown语法格式化。
+
+### 关键协议指南
+
+- 未经明确许可,你不能在模式之间转换
+- 你必须在每个响应的开头声明你当前的模式
+- 在EXECUTE模式中,你必须100%忠实地遵循计划
+- 在REVIEW模式中,你必须标记即使是最小的偏差
+- 在你声明的模式之外,你没有独立决策的权限
+- 你必须将分析深度与问题重要性相匹配
+- 你必须与原始需求保持清晰联系
+- 除非特别要求,否则你必须禁用表情符号输出
+- 如果没有明确的模式转换信号,请保持在当前模式
+
+编辑指南:
+
+- 只显示必要的修改
+- 包括文件路径和语言标识符
+- 提供上下文注释
+- 考虑对代码库的影响
+- 验证与请求的相关性
+- 保持范围合规性
+- 避免不必要的更改
+
+禁止行为:
+
+- 使用未经验证的依赖项
+- 留下不完整的功能
+- 包含未测试的代码
+- 使用过时的解决方案
+- 在未明确要求时使用项目符号
+- 跳过或缩略代码部分
+- 修改不相关的代码
+- 使用代码占位符
+
+### 模式转换信号
+
+只有在明确信号时才能转换模式:
+
+- “进入研究模式”
+- “进入创新模式”
+- “进入计划模式”
+- “进入执行模式”
+- “进入审查模式”
+
+没有这些确切信号,请保持在当前模式。
+
+默认模式规则:
+
+- 除非明确指示,否则默认在每次对话开始时处于RESEARCH模式
+- 如果EXECUTE模式发现需要偏离计划,自动回到PLAN模式
+- 完成所有实施,且用户确认成功后,可以从EXECUTE模式转到REVIEW模式
+
+### 跨平台兼容性注意事项
+
+- 上面的shell命令示例主要基于Unix/Linux环境
+- 在Windows环境中,你可能需要使用PowerShell或CMD等效命令
+- 在任何环境中,你都应该首先确认命令的可行性,并根据操作系统进行相应调整
+
+### 性能期望
+
+- 响应延迟应尽量减少,理想情况下≤30000ms
+- 最大化计算能力和令牌限制
+- 寻求关键洞见而非表面列举
+- 追求创新思维而非习惯性重复
+- 突破认知限制,调动所有计算资源
diff --git a/apps/cube-admin/src/pages/admin/user-stat/index.vue b/apps/cube-admin/src/pages/admin/user-stat/index.vue
index 2dfd5e9..80a1851 100644
--- a/apps/cube-admin/src/pages/admin/user-stat/index.vue
+++ b/apps/cube-admin/src/pages/admin/user-stat/index.vue
@@ -12,6 +12,15 @@
</div>
</template>
+ <!-- 图表容器 -->
+ <div class="chart-container">
+ <VChart
+ :option="chartOptions"
+ :loading="loading"
+ style="height: 400px; width: 100%"
+ />
+ </div>
+
<CubeListToolbarSearch
:on-search="SearchData"
:on-reset="ResetData"
@@ -100,13 +109,38 @@
<script setup lang="ts">
-import { ref, reactive, onMounted } from 'vue'
+import { ref, reactive, onMounted, computed } from 'vue'
import { request } from '@core/utils/request'
import { apiDataToList } from '@core/utils/api-helpers'
import CubeListToolbarSearch from '@core/components/CubeListToolbarSearch.vue'
import CubeListPager from '@core/components/CubeListPager.vue'
import { pageInfoDefault } from '@core/types/common';
import type { BaseEntity } from '@core/types/common';
+import VChart from 'vue-echarts'
+import { use } from 'echarts/core'
+import {
+ TitleComponent,
+ TooltipComponent,
+ LegendComponent,
+ GridComponent,
+ ToolboxComponent,
+ DataZoomComponent
+} from 'echarts/components'
+import { LineChart } from 'echarts/charts'
+import { UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+
+use([
+ TitleComponent,
+ TooltipComponent,
+ LegendComponent,
+ GridComponent,
+ ToolboxComponent,
+ DataZoomComponent,
+ LineChart,
+ UniversalTransition,
+ CanvasRenderer
+])
// 用户统计接口,继承 BaseEntity
interface UserStat extends BaseEntity {
@@ -139,6 +173,240 @@ const queryParams = reactive({
const detailData = ref<Partial<UserStat>>({})
const showDetailDialog = ref(false)
+// 图表数据转换函数
+const transformDataForChart = (data: UserStat[]) => {
+ if (!data || data.length === 0) return { dates: [], series: [] }
+
+ // 按日期排序
+ const sortedData = [...data].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
+
+ const dates = sortedData.map(item => item.date)
+
+ const series = [
+ {
+ name: '总数',
+ data: sortedData.map(item => item.total || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '登录数',
+ data: sortedData.map(item => item.logins || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: 'OAuth登录',
+ data: sortedData.map(item => item.oAuths || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '最大在线',
+ data: sortedData.map(item => item.maxOnline || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '活跃',
+ data: sortedData.map(item => item.actives || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '7天活跃',
+ data: sortedData.map(item => item.activesT7 || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '30天活跃',
+ data: sortedData.map(item => item.activesT30 || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '新用户',
+ data: sortedData.map(item => item.news || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '7天注册',
+ data: sortedData.map(item => item.newsT7 || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '30天注册',
+ data: sortedData.map(item => item.newsT30 || 0),
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 }
+ },
+ {
+ name: '在线时间',
+ data: sortedData.map(item => item.onlineTime || 0), // 保持秒单位
+ type: 'line',
+ smooth: true,
+ symbol: 'circle',
+ symbolSize: 4,
+ lineStyle: { width: 2 },
+ yAxisIndex: 1 // 使用右Y轴
+ }
+ ]
+
+ return { dates, series }
+}
+
+// 图表配置
+const chartOptions = computed(() => {
+ const chartData = transformDataForChart(tableData.value)
+
+ return {
+ title: {
+ text: '用户统计趋势图',
+ left: 'center',
+ textStyle: {
+ fontSize: 16,
+ fontWeight: 'normal'
+ }
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ },
+ formatter: (params: unknown) => {
+ if (!params || !Array.isArray(params) || params.length === 0) return ''
+
+ const firstParam = params[0] as Record<string, unknown>
+ let result = `<div style="font-weight: bold;">${firstParam.axisValue}</div>`
+ params.forEach((item: Record<string, unknown>) => {
+ if (item.seriesName === '在线时间') {
+ result += `<div style="margin: 2px 0;">${item.marker}${item.seriesName}: ${item.value}秒</div>`
+ } else {
+ result += `<div style="margin: 2px 0;">${item.marker}${item.seriesName}: ${item.value}</div>`
+ }
+ })
+ return result
+ }
+ },
+ legend: {
+ data: ['总数', '登录数', 'OAuth登录', '最大在线', '活跃', '7天活跃', '30天活跃', '新用户', '7天注册', '30天注册', '在线时间'],
+ top: 35,
+ type: 'scroll',
+ orient: 'horizontal'
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ top: 80,
+ containLabel: true
+ },
+ toolbox: {
+ feature: {
+ saveAsImage: {
+ title: '保存为图片'
+ },
+ restore: {
+ title: '重置'
+ },
+ dataZoom: {
+ title: {
+ zoom: '区域缩放',
+ back: '区域缩放还原'
+ }
+ }
+ }
+ },
+ xAxis: {
+ type: 'category' as const,
+ boundaryGap: false,
+ data: chartData.dates,
+ axisLabel: {
+ rotate: 45
+ }
+ },
+ yAxis: [
+ {
+ type: 'value' as const,
+ name: '用户数',
+ position: 'left',
+ axisLabel: {
+ formatter: '{value}'
+ }
+ },
+ {
+ type: 'value' as const,
+ name: '在线时长(秒)',
+ position: 'right',
+ axisLabel: {
+ formatter: '{value}'
+ }
+ }
+ ],
+ dataZoom: [
+ {
+ type: 'inside' as const,
+ start: 0,
+ end: 100
+ },
+ {
+ start: 0,
+ end: 100,
+ handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23.1h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
+ handleSize: '80%',
+ handleStyle: {
+ color: '#fff',
+ shadowBlur: 3,
+ shadowColor: 'rgba(0, 0, 0, 0.6)',
+ shadowOffsetX: 2,
+ shadowOffsetY: 2
+ }
+ }
+ ],
+ series: chartData.series.map(item => ({
+ ...item,
+ type: 'line' as const,
+ yAxisIndex: item.name === '在线时间' ? 1 : 0 // 在线时间使用右Y轴,其他使用左Y轴
+ }))
+ }
+})
+
// 组件回调函数
const callback = (e?: Record<string, unknown>) => {
Object.assign(queryParams, e?.params || {});
@@ -273,4 +541,12 @@ onMounted(() => {
display: flex;
justify-content: flex-end;
}
+
+.chart-container {
+ margin-bottom: 20px;
+ padding: 20px;
+ background-color: #fafafa;
+ border-radius: 4px;
+ border: 1px solid #e4e7ed;
+}
</style>
diff --git a/package.json b/package.json
index 7706772..a3b6acc 100644
--- a/package.json
+++ b/package.json
@@ -27,12 +27,14 @@
"@vueuse/core": "^13.0.0",
"@vueuse/integrations": "^13.0.0",
"axios": "^1.8.4",
+ "echarts": "^5.6.0",
"element-plus": "^2.9.7",
"lodash": "^4.17.21",
"pinia": "^3.0.1",
"query-string": "^9.1.1",
"universal-cookie": "^8.0.1",
"vue": "^3.5.13",
+ "vue-echarts": "^7.0.3",
"vue-i18n": "^9.0.0",
"vue-router": "^4.5.0"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index aa8f4ac..8a13404 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -29,6 +29,9 @@ importers:
axios:
specifier: ^1.8.4
version: 1.11.0(debug@4.4.1)
+ echarts:
+ specifier: ^5.6.0
+ version: 5.6.0
element-plus:
specifier: ^2.9.7
version: 2.10.4(vue@3.5.18(typescript@5.8.3))
@@ -47,6 +50,9 @@ importers:
vue:
specifier: ^3.5.13
version: 3.5.18(typescript@5.8.3)
+ vue-echarts:
+ specifier: ^7.0.3
+ version: 7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18(typescript@5.8.3))
vue-i18n:
specifier: ^9.0.0
version: 9.14.5(vue@3.5.18(typescript@5.8.3))
@@ -1721,6 +1727,9 @@ packages:
ecc-jsbn@0.1.2:
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
+ echarts@5.6.0:
+ resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
+
editorconfig@1.0.4:
resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==}
engines: {node: '>=14'}
@@ -3083,6 +3092,9 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
+ tslib@2.3.0:
+ resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -3302,6 +3314,17 @@ packages:
vue-component-type-helpers@2.2.12:
resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
+ vue-demi@0.13.11:
+ resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
+ engines: {node: '>=12'}
+ hasBin: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+
vue-demi@0.14.10:
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
engines: {node: '>=12'}
@@ -3313,6 +3336,16 @@ packages:
'@vue/composition-api':
optional: true
+ vue-echarts@7.0.3:
+ resolution: {integrity: sha512-/jSxNwOsw5+dYAUcwSfkLwKPuzTQ0Cepz1LxCOpj2QcHrrmUa/Ql0eQqMmc1rTPQVrh2JQ29n2dhq75ZcHvRDw==}
+ peerDependencies:
+ '@vue/runtime-core': ^3.0.0
+ echarts: ^5.5.1
+ vue: ^2.7.0 || ^3.1.1
+ peerDependenciesMeta:
+ '@vue/runtime-core':
+ optional: true
+
vue-eslint-parser@10.2.0:
resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3447,6 +3480,9 @@ packages:
resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
engines: {node: '>=18'}
+ zrender@5.6.1:
+ resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
+
snapshots:
'@ampproject/remapping@2.3.0':
@@ -4974,6 +5010,11 @@ snapshots:
jsbn: 0.1.1
safer-buffer: 2.1.2
+ echarts@5.6.0:
+ dependencies:
+ tslib: 2.3.0
+ zrender: 5.6.1
+
editorconfig@1.0.4:
dependencies:
'@one-ini/wasm': 0.1.1
@@ -6338,6 +6379,8 @@ snapshots:
dependencies:
typescript: 5.8.3
+ tslib@2.3.0: {}
+
tslib@2.8.1: {}
tunnel-agent@0.6.0:
@@ -6612,10 +6655,24 @@ snapshots:
vue-component-type-helpers@2.2.12: {}
+ vue-demi@0.13.11(vue@3.5.18(typescript@5.8.3)):
+ dependencies:
+ vue: 3.5.18(typescript@5.8.3)
+
vue-demi@0.14.10(vue@3.5.18(typescript@5.8.3)):
dependencies:
vue: 3.5.18(typescript@5.8.3)
+ vue-echarts@7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18(typescript@5.8.3)):
+ dependencies:
+ echarts: 5.6.0
+ vue: 3.5.18(typescript@5.8.3)
+ vue-demi: 0.13.11(vue@3.5.18(typescript@5.8.3))
+ optionalDependencies:
+ '@vue/runtime-core': 3.5.18
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+
vue-eslint-parser@10.2.0(eslint@9.32.0(jiti@2.5.1)):
dependencies:
debug: 4.4.1(supports-color@8.1.1)
@@ -6742,3 +6799,7 @@ snapshots:
yocto-queue@0.1.0: {}
yoctocolors@2.1.1: {}
+
+ zrender@5.6.1:
+ dependencies:
+ tslib: 2.3.0