From 563708400e31758d501a9c6ec9273dfb4348cd2e Mon Sep 17 00:00:00 2001 From: dongzp <975303544@qq.com> Date: Tue, 21 Jul 2026 14:47:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E6=9E=B6=E6=9E=84=EF=BC=8CUI=EF=BC=8C=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 8 + .gitignore | 24 + .vscode/extensions.json | 3 + README.md | 35 +- .../plans/2026-07-21-ai-trade-assistant-ui.md | 259 ++ .../2026-07-21-ai-trade-assistant-design.md | 160 ++ index.html | 13 + package-lock.json | 2114 +++++++++++++++++ package.json | 28 + public/favicon.svg | 1 + public/icons.svg | 24 + scripts/fix-encoding-1.mjs | 452 ++++ scripts/fix-encoding-2.mjs | 204 ++ scripts/verify-chinese.mjs | 51 + src/App.vue | 66 + src/api/baidu/mapQuote.ts | 126 + src/api/baidu/quotation.ts | 54 + src/api/baidu/types.ts | 103 + src/api/http.ts | 7 + src/assets/hero.png | Bin 0 -> 13057 bytes src/assets/vite.svg | 1 + src/assets/vue.svg | 1 + src/components/ai/AiAdviceDrawer.vue | 139 ++ src/components/header/AppHeader.vue | 101 + src/components/header/SettingsDialog.vue | 70 + src/components/news/NewsItem.vue | 55 + src/components/news/NewsList.vue | 22 + src/components/position/PositionDonut.vue | 91 + src/components/position/PositionPanel.vue | 72 + src/components/position/PositionTable.vue | 40 + src/components/quote/ChartPanel.vue | 250 ++ src/components/quote/OrderBook.vue | 88 + src/components/quote/QuoteStats.vue | 92 + src/components/quote/TradeTape.vue | 64 + src/composables/useAiAdvice.ts | 31 + src/composables/useNews.ts | 28 + src/composables/usePositions.ts | 28 + src/composables/useQuote.ts | 33 + src/config/contract.ts | 9 + src/env.d.ts | 7 + src/layout/AppLayout.vue | 49 + src/main.ts | 13 + src/mocks/aiAdvice.ts | 15 + src/mocks/news.ts | 49 + src/mocks/positions.ts | 75 + src/mocks/quote.ts | 112 + src/stores/settings.ts | 29 + src/styles/global.css | 49 + src/styles/variables.css | 16 + src/types/index.ts | 104 + tsconfig.app.json | 26 + tsconfig.json | 7 + tsconfig.node.json | 21 + vite.config.ts | 31 + 54 files changed, 5548 insertions(+), 2 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 docs/superpowers/plans/2026-07-21-ai-trade-assistant-ui.md create mode 100644 docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.svg create mode 100644 public/icons.svg create mode 100644 scripts/fix-encoding-1.mjs create mode 100644 scripts/fix-encoding-2.mjs create mode 100644 scripts/verify-chinese.mjs create mode 100644 src/App.vue create mode 100644 src/api/baidu/mapQuote.ts create mode 100644 src/api/baidu/quotation.ts create mode 100644 src/api/baidu/types.ts create mode 100644 src/api/http.ts create mode 100644 src/assets/hero.png create mode 100644 src/assets/vite.svg create mode 100644 src/assets/vue.svg create mode 100644 src/components/ai/AiAdviceDrawer.vue create mode 100644 src/components/header/AppHeader.vue create mode 100644 src/components/header/SettingsDialog.vue create mode 100644 src/components/news/NewsItem.vue create mode 100644 src/components/news/NewsList.vue create mode 100644 src/components/position/PositionDonut.vue create mode 100644 src/components/position/PositionPanel.vue create mode 100644 src/components/position/PositionTable.vue create mode 100644 src/components/quote/ChartPanel.vue create mode 100644 src/components/quote/OrderBook.vue create mode 100644 src/components/quote/QuoteStats.vue create mode 100644 src/components/quote/TradeTape.vue create mode 100644 src/composables/useAiAdvice.ts create mode 100644 src/composables/useNews.ts create mode 100644 src/composables/usePositions.ts create mode 100644 src/composables/useQuote.ts create mode 100644 src/config/contract.ts create mode 100644 src/env.d.ts create mode 100644 src/layout/AppLayout.vue create mode 100644 src/main.ts create mode 100644 src/mocks/aiAdvice.ts create mode 100644 src/mocks/news.ts create mode 100644 src/mocks/positions.ts create mode 100644 src/mocks/quote.ts create mode 100644 src/stores/settings.ts create mode 100644 src/styles/global.css create mode 100644 src/styles/variables.css create mode 100644 src/types/index.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a4b824b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md index 112f168..8215bcc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ -# ai_trade_assistance +# AI 实时交易辅助系统 -基于AI的实时期货交易辅助工具,采用Vue3开发 \ No newline at end of file +基于 Vue 3 的实时期货交易辅助工具(Phase 1:框架 + UI 布局,数据为 Mock)。 + +## 技术栈 + +- Vue 3 + TypeScript +- Vite 7 +- Element Plus +- Pinia +- ECharts / vue-echarts + +## 启动 + +```bash +npm install +npm run dev +``` + +构建: + +```bash +npm run build +``` + +## 功能(本阶段) + +- 行情:报价统计、分时/K 线、五档盘口、成交明细 +- 相关新闻列表 +- 机构持仓(多空前 20 + 圆环图,浅色) +- 底部 AI 建议抽屉(一键刷新,当前返回 Mock) +- 设置:DeepSeek API Key、额外关键词(本地 localStorage) + +数据源与 DeepSeek 真实调用将在后续阶段接入。设计说明见 `docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md`。 diff --git a/docs/superpowers/plans/2026-07-21-ai-trade-assistant-ui.md b/docs/superpowers/plans/2026-07-21-ai-trade-assistant-ui.md new file mode 100644 index 0000000..f99fea4 --- /dev/null +++ b/docs/superpowers/plans/2026-07-21-ai-trade-assistant-ui.md @@ -0,0 +1,259 @@ +# AI 交易辅助系统 Phase1 UI 框架 Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 搭建 Vue3 + Vite7 + Element Plus 单页交易辅助 UI(浅色),含行情/新闻/持仓/AI 抽屉/设置,数据全部 mock。 + +**Architecture:** `AppLayout` 滚动主区 + 固定底栏 AI 抽屉;业务拆为 header/quote/news/position/ai 组件;composable 读 `src/mocks/*`,对外 `{ data, loading, error, refresh }`;设置用 Pinia + localStorage。 + +**Tech Stack:** Vue 3、Vite 7、Element Plus、Pinia、ECharts、vue-echarts + +**Spec:** `docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md` + +--- + +## File Structure + +``` +package.json, vite.config.js, index.html +src/main.js, src/App.vue +src/styles/variables.css, src/styles/global.css +src/layout/AppLayout.vue +src/components/header/AppHeader.vue, SettingsDialog.vue +src/components/quote/QuoteStats.vue, ChartPanel.vue, OrderBook.vue, TradeTape.vue +src/components/news/NewsList.vue, NewsItem.vue +src/components/position/PositionPanel.vue, PositionDonut.vue, PositionTable.vue +src/components/ai/AiAdviceDrawer.vue +src/composables/useQuote.js, useNews.js, usePositions.js, useAiAdvice.js +src/stores/settings.js +src/mocks/quote.js, news.js, positions.js, aiAdvice.js +README.md +``` + +--- + +### Task 1: Scaffold Vite Vue 项目并安装依赖 + +**Files:** +- Create: `package.json`, `vite.config.js`, `index.html`, `src/main.js`(由 create-vite 生成后改) +- Modify: `README.md` + +- [ ] **Step 1: 在仓库根目录用 create-vite 初始化 Vue 模板** + +在 PowerShell、仓库根目录(已有 README,允许非空): + +```powershell +cd e:\Gitea\ai_trade_assistance +npm create vite@latest . -- --template vue +``` + +若提示目录非空,确认继续。期望生成 `package.json`、`vite.config.js`、`src/` 等。 + +- [ ] **Step 2: 安装运行时依赖** + +```powershell +npm install +npm install element-plus @element-plus/icons-vue pinia echarts vue-echarts +``` + +确认 `package.json` 中 `vite` 主版本为 7.x(若为 6.x,执行 `npm install vite@7`)。 + +- [ ] **Step 3: 配置 main.js 接入 Element Plus + Pinia** + +`src/main.js`: + +```js +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import 'element-plus/dist/index.css' +import './styles/variables.css' +import './styles/global.css' +import App from './App.vue' + +const app = createApp(App) +app.use(createPinia()) +app.use(ElementPlus, { locale: zhCn }) +app.mount('#app') +``` + +- [ ] **Step 4: 验证能启动** + +```powershell +npm run dev +``` + +期望:终端出现本地 URL,浏览器可打开默认 Vite 页。 + +- [ ] **Step 5: Commit(仅当用户明确要求时执行;本仓库默认跳过)** + +--- + +### Task 2: 全局样式与 AppLayout 壳 + +**Files:** +- Create: `src/styles/variables.css`, `src/styles/global.css`, `src/layout/AppLayout.vue` +- Modify: `src/App.vue` + +- [ ] **Step 1: 写入主题变量(浅色、红涨绿跌)** + +`src/styles/variables.css`: + +```css +:root { + --bg-page: #f5f6f8; + --bg-card: #ffffff; + --border: #e6e8eb; + --text-primary: #1f2329; + --text-secondary: #8a9199; + --up: #e54545; + --down: #12b37b; + --accent: #1677ff; + --header-height: 56px; + --ai-bar-height: 48px; +} +``` + +`src/styles/global.css`: 重置 body 背景 `--bg-page`、字体、链接色;`.price-up { color: var(--up) }` / `.price-down { color: var(--down) }`。 + +- [ ] **Step 2: AppLayout — 滚动主区 + 底栏插槽** + +`src/layout/AppLayout.vue`:顶部 `#header` 插槽,中间 `.main-scroll` 放默认插槽,底部固定 `.ai-footer` 放 `#ai` 插槽;主区 `padding-bottom` 预留 AI 栏高度。 + +- [ ] **Step 3: App.vue 挂载壳(占位组件可先用空 section)** + +```vue + +``` + +--- + +### Task 3: Mock 数据与 Settings Store + +**Files:** +- Create: `src/mocks/quote.js`, `src/mocks/news.js`, `src/mocks/positions.js`, `src/mocks/aiAdvice.js`, `src/stores/settings.js` +- Create: `src/composables/useQuote.js`, `useNews.js`, `usePositions.js`, `useAiAdvice.js` + +- [ ] **Step 1: quote mock** — 合约 `玻璃2609`/`FG609`,最新价 936、涨跌 -13/-1.37%,开高低结算持仓量内外盘;`intraday` 点数数组;`orderBook` 卖5–买1;`trades` 若干条。 + +- [ ] **Step 2: news / positions / aiAdvice mock** — 新闻 5 条(source/time/title/summary/url);持仓多空各 20 名含 qty/change/percent;AI 建议含 action/confidence/reasons/updatedAt。 + +- [ ] **Step 3: settings store** + +```js +// src/stores/settings.js +import { defineStore } from 'pinia' +import { ref, watch } from 'vue' + +const KEY = 'ai-trade-settings' + +export const useSettingsStore = defineStore('settings', () => { + const saved = JSON.parse(localStorage.getItem(KEY) || '{}') + const apiKey = ref(saved.apiKey || '') + const keywords = ref(saved.keywords || '') + watch([apiKey, keywords], () => { + localStorage.setItem(KEY, JSON.stringify({ apiKey: apiKey.value, keywords: keywords.value })) + }) + return { apiKey, keywords } +}) +``` + +- [ ] **Step 4: composables** — 各 `useX` 返回 `data`(ref mock)、`loading`、`error`、`refresh`(模拟 300ms delay 后重置 mock)。 + +--- + +### Task 4: Header + SettingsDialog + +**Files:** +- Create: `src/components/header/AppHeader.vue`, `src/components/header/SettingsDialog.vue` + +- [ ] **Step 1: AppHeader** — 左:名称+代码;中:现价与涨跌(红绿 class);右:设置按钮打开 dialog。 + +- [ ] **Step 2: SettingsDialog** — `el-dialog`;`el-input` type=password 绑定 apiKey;`el-input` type=textarea 绑定 keywords;保存即关(store 已 watch 持久化)。 + +--- + +### Task 5: 行情区(统计、图表、盘口、成交) + +**Files:** +- Create: `src/components/quote/QuoteStats.vue`, `ChartPanel.vue`, `OrderBook.vue`, `TradeTape.vue` +- Modify: `src/App.vue` 组装行情两栏 + +- [ ] **Step 1: QuoteStats** — 多列网格展示开/高/低/昨结/持仓/量/内外盘等。 + +- [ ] **Step 2: ChartPanel** — `el-tabs`:分时/五日/日K/周K/月K;分时用 ECharts line+area + 成交量 bar;K 线 tab 用 candle + volume(可用简化 mock OHLC)。注册 `CanvasRenderer`、`LineChart`、`BarChart`、`CandlestickChart`。 + +- [ ] **Step 3: OrderBook** — 买卖力度条(红绿 flex 比例);卖5→卖1、买1→买5。 + +- [ ] **Step 4: TradeTape** — 时间/价/量+方向(B/S 着色)。 + +- [ ] **Step 5: 在 App 中布局** — 左 70% 统计+图,右 30% 盘口+成交;卡片白底圆角边框。 + +--- + +### Task 6: 新闻区 + +**Files:** +- Create: `src/components/news/NewsList.vue`, `NewsItem.vue` + +- [ ] **Step 1: NewsItem** — 上行 source+time 与「查看原文」;标题;摘要(多行省略)。 + +- [ ] **Step 2: NewsList** — 标题「相关新闻」+ `v-for` 渲染列表。 + +--- + +### Task 7: 机构持仓区(浅色) + +**Files:** +- Create: `src/components/position/PositionPanel.vue`, `PositionDonut.vue`, `PositionTable.vue` + +- [ ] **Step 1: PositionDonut** — vue-echarts pie(roseType 或标准 doughnut),legend 右侧。 + +- [ ] **Step 2: PositionTable** — 名次/会员简称/数量/增减(正红负青)。 + +- [ ] **Step 3: PositionPanel** — `el-tabs` 总持仓/成交量/净持仓;双列「多单前20」「空单前20」;非总持仓 Tab 复用同结构 mock 并在角标提示「占位数据」。 + +--- + +### Task 8: AI 抽屉 + README 收尾 + +**Files:** +- Create: `src/components/ai/AiAdviceDrawer.vue` +- Modify: `README.md`, `src/App.vue` + +- [ ] **Step 1: AiAdviceDrawer** — 收起:一行摘要 + 展开/刷新;展开:方向、置信度、理由列表、时间;无 apiKey 时刷新用 `ElMessage.warning` 提示打开设置,仍可展示 mock。 + +- [ ] **Step 2: 更新 README** — 启动命令、技术栈、Phase1 范围说明。 + +- [ ] **Step 3: 全量验收** + +```powershell +npm run build +npm run dev +``` + +对照 spec §8 验收清单逐项点检。 + +--- + +## Spec coverage (self-review) + +| Spec 项 | Task | +|---|---| +| 浅色单页滚动 | 2, 5–7 | +| 行情+盘口+成交 | 3, 5 | +| 新闻 | 6 | +| 持仓双列浅色 | 7 | +| AI 底栏抽屉 | 8 | +| DeepSeek Key + 关键词 | 3, 4 | +| Mock composable | 3 | +| Vite7 + Vue3 + Element Plus | 1 | + +无 TBD 占位;提交步骤遵循用户「未要求不 commit」规则。 diff --git a/docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md b/docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md new file mode 100644 index 0000000..b38b34f --- /dev/null +++ b/docs/superpowers/specs/2026-07-21-ai-trade-assistant-design.md @@ -0,0 +1,160 @@ +# AI 实时交易辅助系统 — 框架与 UI 设计 + +**日期:** 2026-07-21 +**阶段:** Phase 1 — 框架搭建 + UI 布局(Mock 数据) +**状态:** 已口头确认,待书面复核 + +--- + +## 1. 背景与目标 + +个人投资者在期货等高频场景中易受情绪影响。本系统提供行情、深度、新闻、机构持仓与 AI 操作建议的统一界面,降低非理性交易。 + +**本阶段目标:** 用 Vue3 搭好可运行的单页布局与组件骨架,数据全部写死;真实数据源与 DeepSeek 调用后续接入。 + +--- + +## 2. 已确认决策 + +| 项 | 选择 | +|---|---| +| 主题 | 统一浅色 | +| AI 建议入口 | 底部可折叠抽屉(默认收起) | +| 页面结构 | 单页分区滚动:行情 → 新闻 → 持仓 | +| 架构风格 | 布局壳 + 业务模块组件 + mock 数据层 | +| 技术栈 | Vue 3、Vite 7、Element Plus、Pinia、ECharts | + +--- + +## 3. 信息架构与布局 + +``` +┌──────────────────────────────────────────────────────────┐ +│ AppHeader:品种名 / 代码 / 现价·涨跌 / 休市状态 / 设置按钮 │ +├────────────────────────────────┬─────────────────────────┤ +│ QuoteSection │ MarketDepthSidebar │ +│ · 报价统计网格 │ · 买卖力度条 │ +│ · 分时/五日/日K/周K/月K Tab │ · 五档盘口 │ +│ · 主图(分时或 K 线)+ 成交量 │ · 分时成交明细 │ +├────────────────────────────────┴─────────────────────────┤ +│ NewsSection:相关新闻列表(来源·时间·标题·摘要·原文链接) │ +├──────────────────────────────────────────────────────────┤ +│ PositionSection:总持仓 | 成交量 | 净持仓 │ +│ · 左:多单前 20(圆环图 + 表格) 右:空单前 20(同构) │ +├──────────────────────────────────────────────────────────┤ +│ AiAdviceDrawer(固定底栏):展开后显示建议/理由/刷新 │ +└──────────────────────────────────────────────────────────┘ +│ SettingsDialog(弹窗):DeepSeek API Key、额外关键词 │ +``` + +- 中文市场惯例:**红涨绿跌**。 +- 持仓页按参考图做浅色改版(多单标题偏红、空单标题偏青,圆环图保留多色段)。 + +--- + +## 4. 目录结构 + +``` +src/ + main.js + App.vue + styles/ + variables.css # 主题色、涨跌色 + global.css + layout/ + AppLayout.vue # 滚动主区 + 底栏抽屉槽位 + components/ + header/ + AppHeader.vue + SettingsDialog.vue + quote/ + QuoteStats.vue + ChartPanel.vue + OrderBook.vue + TradeTape.vue + news/ + NewsList.vue + NewsItem.vue + position/ + PositionPanel.vue + PositionDonut.vue + PositionTable.vue + ai/ + AiAdviceDrawer.vue + composables/ + useQuote.js # 先读 mock,日后换 API + useNews.js + usePositions.js + useAiAdvice.js + stores/ + settings.js # apiKey、keywords(localStorage) + mocks/ + quote.js + news.js + positions.js + aiAdvice.js +``` + +--- + +## 5. 模块职责 + +### 5.1 行情区 +- 展示合约名称、最新价、涨跌额/幅、开高低、持仓量、内外盘等(mock)。 +- ChartPanel:Element Plus Tabs 切换周期;ECharts 渲染分时面积图或蜡烛图 + 成交量柱。 +- 右侧:力度条、卖5–买5、成交明细列表。 + +### 5.2 新闻区 +- 列表项:来源 + 时间、标题、摘要、可选「查看原文」。 +- 数据来自 `mocks/news.js`。 + +### 5.3 机构持仓 +- Tab:总持仓 / 成交量 / 净持仓(首版仅总持仓有完整 mock,其余 Tab 显示同结构占位或同一套 mock 并标注)。 +- 双列:圆环图 + 前 20 名表格(名次、会员简称、数量、增减)。 + +### 5.4 AI 建议抽屉 +- 底栏条:摘要一行 +「展开 / 一键获取建议」。 +- 展开:建议方向(买/卖/观望)、置信度占位、简要理由列表、时间戳。 +- 点击刷新时:若未配置 Key,提示打开设置;有 Key 时本阶段仍返回 mock 文案(真实调用后续)。 + +### 5.5 设置 +- DeepSeek API Key(密码输入框,存 Pinia + localStorage)。 +- 额外关键词(多行或标签输入,供后续新闻/分析过滤)。 +- 不提交到仓库的密钥;仅浏览器本地。 + +--- + +## 6. Mock 数据约定 + +- 默认品种:玻璃 2609 / FG609(与参考图一致,可改)。 +- 分时点、五档、成交、新闻、持仓、AI 建议均静态 JSON/JS 模块。 +- composable 对外统一返回 `{ data, loading, error, refresh }`,便于日后替换实现。 + +--- + +## 7. 非目标(本阶段不做) + +- 真实行情 / WebSocket / 交易所接口 +- 真实新闻、持仓数据源 +- DeepSeek HTTP 调用与流式输出 +- 下单、账户、登录 +- 深色主题切换、移动端专项适配(桌面优先,基础可用即可) + +--- + +## 8. 验收标准 + +1. `npm install && npm run dev` 可启动,无控制台致命错误。 +2. 单页可滚动看到行情、新闻、持仓三块,视觉为统一浅色。 +3. 分时/K 线 Tab 可切换,图表有 mock 曲线/蜡烛。 +4. 五档与成交明细、新闻列表、持仓双列图表明示完整。 +5. 底部 AI 抽屉可展开/收起,刷新有反馈(mock)。 +6. 设置可保存 API Key 与关键词,刷新页面后仍在。 + +--- + +## 9. 后续阶段(备忘) + +- Phase 2:接入行情与深度数据 +- Phase 3:新闻 / 机构持仓 API +- Phase 4:DeepSeek 实调与关键词增强分析 diff --git a/index.html b/index.html new file mode 100644 index 0000000..e902f5d --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + AI 实时交易辅助系统 + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..54bfad3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2114 @@ +{ + "name": "ai-trade-assistance", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ai-trade-assistance", + "version": "0.1.0", + "dependencies": { + "@element-plus/icons-vue": "^2.3.2", + "axios": "^1.18.1", + "echarts": "^6.1.0", + "element-plus": "^2.14.3", + "pinia": "^4.0.2", + "vue": "^3.5.39", + "vue-echarts": "^8.0.1" + }, + "devDependencies": { + "@types/node": "^26.1.1", + "@vitejs/plugin-vue": "^6.0.2", + "typescript": "^5.9.3", + "vite": "^7.3.6", + "vue-tsc": "^3.3.7" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.8", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz", + "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.50", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", + "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", + "integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.50" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.40.tgz", + "integrity": "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.40", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.40.tgz", + "integrity": "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.40.tgz", + "integrity": "sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.40", + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-ssr": "3.5.40", + "@vue/shared": "3.5.40", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.40.tgz", + "integrity": "sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/devtools-api": { + "version": "8.1.5", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-8.1.5.tgz", + "integrity": "sha512-YJipMVAKe5wT5CWf5kTYCaNV7NMNjFVxJkIkJaJ4W/nCxEBzlZzrOsYKeCymdCrFZmBS/+wTWFoUs3Jf/Q6XSQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-kit": "^8.1.5" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "8.1.5", + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.1.5.tgz", + "integrity": "sha512-FcSAxsi4eWuXLCB7Rv9lj0aIVHHPNVQ2BazGf4RJTc2JCqb4BQg0hk87ZFhminCfl+mD5OUI0rX2cgyu4kJOGA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.1.5", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "8.1.5", + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-8.1.5.tgz", + "integrity": "sha512-mhT4zcPFhF+Xk1O4BfhhrbXzpmfqY03fS6xGpcllbQG7lDjhQf8pQHcTIhqQIYx1hfwtHmk/6jM96ele0UxPqQ==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-3.3.7.tgz", + "integrity": "sha512-LzmkKinXAMMoh8Jfi/jMUSDUjuPdv8mynH5WJGKfXyZtDw3hQ6GBaoI6Bcnl/Xqlu32q/0Z6i/trp4VXykzyLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.40.tgz", + "integrity": "sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.40.tgz", + "integrity": "sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.40.tgz", + "integrity": "sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/runtime-core": "3.5.40", + "@vue/shared": "3.5.40", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.40.tgz", + "integrity": "sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.40.tgz", + "integrity": "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "14.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz", + "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.3.0", + "@vueuse/shared": "14.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "14.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz", + "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "14.3.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz", + "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/echarts": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.1.0.tgz", + "integrity": "sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.1.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, + "node_modules/element-plus": { + "version": "2.14.3", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.3.tgz", + "integrity": "sha512-pJcvxcpZjYruNzuJhAeVwnbYjfNgzBKnWHwSVEhwzM2/kcLI3brzmtIBxtPqd4hQWJfD1PRnjoc1WipLw2eBGg==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.2.0", + "@element-plus/icons-vue": "^2.3.2", + "@floating-ui/dom": "^1.7.6", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8", + "@types/lodash": "^4.17.24", + "@types/lodash-es": "^4.17.12", + "@vueuse/core": "14.3.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.20", + "lodash": "^4.18.1", + "lodash-es": "^4.18.1", + "lodash-unified": "^1.0.3", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0", + "vue-component-type-helpers": "^3.3.5" + }, + "peerDependencies": { + "vue": "^3.3.7" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/nostics": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/nostics/-/nostics-1.2.0.tgz", + "integrity": "sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==", + "license": "MIT" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-4.0.2.tgz", + "integrity": "sha512-yKVVA7bSj5oRZFp/Ab9wLlmyb5gPUYEiIm4ryiWTe/xe7PtkRdMVOp1X1ggvq0c6Uj7Q0Du1HnV2mtAwM0Ks1g==", + "license": "MIT", + "dependencies": { + "nostics": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/devtools-api": "^8.1.5", + "typescript": ">=5.6.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "@vue/devtools-api": { + "optional": false + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.20", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.20.tgz", + "integrity": "sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.40", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.40.tgz", + "integrity": "sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-sfc": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/server-renderer": "3.5.40", + "@vue/shared": "3.5.40" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-component-type-helpers": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.7.tgz", + "integrity": "sha512-Skkhw9agYSgsWqv7bxSOGJZa9SaiJbZVGdXuFWnrzKaQYHnw9qbjD630rw6RyMqDbp54nfLCLw5SZA55if7JLg==", + "license": "MIT" + }, + "node_modules/vue-echarts": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/vue-echarts/-/vue-echarts-8.0.1.tgz", + "integrity": "sha512-23rJTFLu1OUEGRWjJGmdGt8fP+8+ja1gVgzMYPIPaHWpXegcO1viIAaeu2H4QHESlVeHzUAHIxKXGrwjsyXAaA==", + "license": "MIT", + "peerDependencies": { + "echarts": "^6.0.0", + "vue": "^3.3.0" + } + }, + "node_modules/vue-tsc": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-3.3.7.tgz", + "integrity": "sha512-+C+rgD49wAQ5bUTl2sp5a8Bzg4YoldMNXM+g7CFe604MYcQ8PrZPMQhIjJSzKXtPBCa+C5ayMipqjbA7splekQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.7" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/zrender": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.1.0.tgz", + "integrity": "sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac84f94 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "ai-trade-assistance", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview", + "typecheck": "vue-tsc -b --pretty false" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.2", + "axios": "^1.18.1", + "echarts": "^6.1.0", + "element-plus": "^2.14.3", + "pinia": "^4.0.2", + "vue": "^3.5.39", + "vue-echarts": "^8.0.1" + }, + "devDependencies": { + "@types/node": "^26.1.1", + "@vitejs/plugin-vue": "^6.0.2", + "typescript": "^5.9.3", + "vite": "^7.3.6", + "vue-tsc": "^3.3.7" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons.svg b/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/fix-encoding-1.mjs b/scripts/fix-encoding-1.mjs new file mode 100644 index 0000000..a96b0cc --- /dev/null +++ b/scripts/fix-encoding-1.mjs @@ -0,0 +1,452 @@ +import { writeFileSync } from 'node:fs' +import { join } from 'node:path' + +const root = 'e:/Gitea/ai_trade_assistance' + +function w(rel, content) { + const path = join(root, rel) + writeFileSync(path, content, 'utf8') + console.log('ok', rel) +} + +// Use unicode escapes so this repair script itself stays ASCII-safe on Windows shells. +const S = { + mai: '\u4e70', + mai2: '\u5356', + shezhi: '\u8bbe\u7f6e', + quxiao: '\u53d6\u6d88', + baocun: '\u4fdd\u5b58', + eci: '\u989d\u5916\u5173\u952e\u8bcd', + eciPh: '\u7528\u4e8e\u65b0\u95fb\u8fc7\u6ee4\u4e0e\u5206\u6790\u589e\u5f3a\uff0c\u591a\u4e2a\u8bcd\u7528\u9017\u53f7\u6216\u6362\u884c\u5206\u9694', + saved: '\u8bbe\u7f6e\u5df2\u4fdd\u5b58\u5230\u672c\u5730', + zongcc: '\u603b\u6301\u4ed3', + cjl: '\u6210\u4ea4\u91cf', + jingcc: '\u51c0\u6301\u4ed3', + placeholder: '\u5f53\u524d\u4e3a\u5360\u4f4d\u6570\u636e\uff08\u7ed3\u6784\u4e0e\u603b\u6301\u4ed3\u4e00\u81f4\uff09', + long20: '\u591a\u5355\u6301\u4ed3\u524d20\u540d', + short20: '\u7a7a\u5355\u6301\u4ed3\u524d20\u540d', + duodan: '\u591a\u5355', + kongdan: '\u7a7a\u5355', + mingci: '\u540d\u6b21', + hyjc: '\u4f1a\u5458\u7b80\u79f0', + zengjian: '\u589e\u51cf', + shuliang: '\u6570\u91cf', + kaipan: '\u5f00\u76d8', + zhangdie: '\u6da8\u8dcc', + junjia: '\u5747\u4ef7', + zuigao: '\u6700\u9ad8', + jiesuan: '\u7ed3\u7b97', + cje: '\u6210\u4ea4\u989d', + yi: '\u4ebf', + ccl: '\u6301\u4ed3\u91cf', + zhenfu: '\u632f\u5e45', + waipan: '\u5916\u76d8', + zuoshou: '\u6628\u6536', + neipan: '\u5185\u76d8', + zuidi: '\u6700\u4f4e', + zuojie: '\u6628\u7ed3', + fenshi: '\u5206\u65f6', + wuri: '\u4e94\u65e5', + riK: '\u65e5K', + zhouK: '\u5468K', + yueK: '\u6708K', + junjia2: '\u5747\u4ef7', + xindu: '\u7f6e\u4fe1\u5ea6', + yijian: '\u4e00\u952e\u83b7\u53d6\u5efa\u8bae', + shouqi: '\u6536\u8d77', + zhankai: '\u5c55\u5f00', + hint: '\u57fa\u4e8e\u884c\u60c5\u3001\u76d8\u53e3\u3001\u65b0\u95fb\u4e0e\u6301\u4ed3\u7684\u7efc\u5408\u5206\u6790\uff08\u5f53\u524d\u4e3a Mock\uff09', + warn: '\u8bf7\u5148\u5728\u8bbe\u7f6e\u4e2d\u914d\u7f6e DeepSeek API Key\uff08\u672c\u9636\u6bb5\u4ecd\u8fd4\u56de Mock \u5efa\u8bae\uff09', + qita: '\u5176\u4ed6', + shuliang2: '\u6570\u91cf', + zhanbi: '\u5360\u6bd4', +} + +w( + 'src/components/quote/OrderBook.vue', + ` + + + + +`, +) + +w( + 'src/components/header/SettingsDialog.vue', + ` + + +`, +) + +w( + 'src/components/position/PositionPanel.vue', + ` + + + + +`, +) + +w( + 'src/components/position/PositionTable.vue', + ` + + + + +`, +) + +w( + 'src/components/quote/QuoteStats.vue', + ` + + + + +`, +) + +console.log('batch1 done') diff --git a/scripts/fix-encoding-2.mjs b/scripts/fix-encoding-2.mjs new file mode 100644 index 0000000..3430a23 --- /dev/null +++ b/scripts/fix-encoding-2.mjs @@ -0,0 +1,204 @@ +import { writeFileSync, readFileSync } from 'node:fs' +import { join } from 'node:path' + +const root = 'e:/Gitea/ai_trade_assistance' + +function w(rel, content) { + writeFileSync(join(root, rel), content, 'utf8') + console.log('ok', rel) +} + +const S = { + fenshi: '\u5206\u65f6', + wuri: '\u4e94\u65e5', + riK: '\u65e5K', + zhouK: '\u5468K', + yueK: '\u6708K', + junjia: '\u5747\u4ef7', + cjl: '\u6210\u4ea4\u91cf', + xindu: '\u7f6e\u4fe1\u5ea6', + yijian: '\u4e00\u952e\u83b7\u53d6\u5efa\u8bae', + shouqi: '\u6536\u8d77', + zhankai: '\u5c55\u5f00', + hint: '\u57fa\u4e8e\u884c\u60c5\u3001\u76d8\u53e3\u3001\u65b0\u95fb\u4e0e\u6301\u4ed3\u7684\u7efc\u5408\u5206\u6790\uff08\u5f53\u524d\u4e3a Mock\uff09', + warn: '\u8bf7\u5148\u5728\u8bbe\u7f6e\u4e2d\u914d\u7f6e DeepSeek API Key\uff08\u672c\u9636\u6bb5\u4ecd\u8fd4\u56de Mock \u5efa\u8bae\uff09', + qita: '\u5176\u4ed6', + shuliang: '\u6570\u91cf', + zengjian: '\u589e\u51cf', + zhanbi: '\u5360\u6bd4', +} + +// Patch ChartPanel: replace garbled labels in existing file structure by rewriting full file from template pieces +const chartPath = join(root, 'src/components/quote/ChartPanel.vue') +let chart = readFileSync(chartPath, 'utf8') +chart = chart + .replace(/label="\?+"/g, (m, offset, str) => m) // noop marker + .replace(/ +
+
+
+ AI + {{ data.action }} + {{ data.summary }} + ${S.xindu} {{ data.confidence }}% \u00b7 {{ data.updatedAt }} +
+
+ ${S.yijian} + + {{ expanded ? '${S.shouqi}' : '${S.zhankai}' }} + +
+
+
+
${S.hint}
+
    +
  • {{ r }}
  • +
+
+
+ + + + + +`, +) + +// Fix PositionDonut Chinese in tooltip/legend if garbled +const donutPath = join(root, 'src/components/position/PositionDonut.vue') +let donut = readFileSync(donutPath, 'utf8') +donut = donut + .replace(/data\.push\(\{ name: '[^']*', value: otherQty \}\)/, `data.push({ name: '${S.qita}', value: otherQty })`) + .replace( + /return `\$\{param\.name\}[^`]+`/, + `return \`\${param.name}
${S.shuliang}: \${param.value}
${S.zengjian}: \${sign}\${change}
${S.zhanbi}: \${param.percent}%\``, + ) +writeFileSync(donutPath, donut, 'utf8') +console.log('ok PositionDonut.vue') + +console.log('batch2 done') diff --git a/scripts/verify-chinese.mjs b/scripts/verify-chinese.mjs new file mode 100644 index 0000000..8eef195 --- /dev/null +++ b/scripts/verify-chinese.mjs @@ -0,0 +1,51 @@ +import { readFileSync, readdirSync } from 'node:fs' +import { join } from 'node:path' + +function walk(d, acc = []) { + for (const e of readdirSync(d, { withFileTypes: true })) { + const p = join(d, e.name) + if (e.isDirectory()) walk(p, acc) + else if (/\.(vue|ts|md)$/.test(e.name)) acc.push(p) + } + return acc +} + +const checks = [ + ['src/components/quote/ChartPanel.vue', ['分时', '五日', '日K', '周K', '月K', '成交量', '均价']], + ['src/components/ai/AiAdviceDrawer.vue', ['置信度', '一键获取建议', '收起', '展开', 'DeepSeek']], + ['src/components/position/PositionPanel.vue', ['总持仓', '成交量', '净持仓', '多单持仓前20名', '空单持仓前20名']], + ['src/components/header/SettingsDialog.vue', ['设置', '额外关键词', '保存', '取消']], + ['src/components/quote/OrderBook.vue', ['买', '卖']], + ['src/components/quote/QuoteStats.vue', ['开盘', '涨跌', '持仓量', '外盘', '内盘']], + ['src/components/position/PositionTable.vue', ['名次', '会员简称', '增减', '数量']], + ['src/components/position/PositionDonut.vue', ['其他', '数量', '增减', '占比']], + ['src/components/quote/TradeTape.vue', ['分时成交', '时间', '价格', '现手']], + ['src/components/news/NewsList.vue', ['相关新闻']], + ['src/components/news/NewsItem.vue', ['查看原文']], + ['src/components/header/AppHeader.vue', ['更新', '设置']], + ['src/mocks/quote.ts', ['玻璃', '郑商所', '休市']], + ['src/mocks/aiAdvice.ts', ['观望']], +] + +let failed = 0 +for (const [f, words] of checks) { + const t = readFileSync(f, 'utf8') + const miss = words.filter((w) => !t.includes(w)) + if (miss.length) { + failed++ + console.log('FAIL', f, miss.join(',')) + } else { + console.log('OK ', f) + } +} + +// detect literal ??? garbled (3+ question marks in a row outside of ??) +for (const f of walk('src')) { + const t = readFileSync(f, 'utf8') + if (/\?{3,}/.test(t)) { + console.log('GARBLED?', f) + failed++ + } +} + +process.exit(failed ? 1 : 0) diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..0efa384 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/src/api/baidu/mapQuote.ts b/src/api/baidu/mapQuote.ts new file mode 100644 index 0000000..608d16f --- /dev/null +++ b/src/api/baidu/mapQuote.ts @@ -0,0 +1,126 @@ +import type { IntradayPoint, QuoteData, TradeTick } from '../../types' +import { contractConfig } from '../../config/contract' +import type { BaiduQuotationResult } from './types' + +function toNum(value: string | number | undefined | null, fallback = 0): number { + if (value == null || value === '' || value === '--') return fallback + if (typeof value === 'number') return Number.isFinite(value) ? value : fallback + const cleaned = value.replace(/[+,%]/g, '').trim() + const n = Number(cleaned) + return Number.isFinite(n) ? n : fallback +} + +/** 将「235.43亿」「77.72万」等转为数值;亿保持为亿元单位 */ +function parseAmountYi(value: string | undefined, rawAmount?: string): number { + if (rawAmount) { + const raw = toNum(rawAmount) + if (raw > 0) return Number((raw / 1e8).toFixed(2)) + } + if (!value || value === '--') return 0 + if (value.includes('亿')) return toNum(value.replace('亿', '')) + if (value.includes('万')) return Number((toNum(value.replace('万', '')) / 1e4).toFixed(4)) + return toNum(value) +} + +function parseIntraday(result: BaiduQuotationResult): IntradayPoint[] { + const days = result.newMarketData?.marketData ?? [] + const points: IntradayPoint[] = [] + + for (const day of days) { + if (!day.p) continue + const chunks = day.p.split(';').filter(Boolean) + for (const chunk of chunks) { + const parts = chunk.split(',') + // timestamp,time,price,avgPrice,range,ratio,volume,amount + if (parts.length < 7) continue + const timeLabel = parts[1] ?? '' + const hhmm = timeLabel.includes(' ') + ? timeLabel.split(' ')[1]!.slice(0, 5) + : timeLabel.slice(0, 5) + points.push({ + time: hhmm, + price: toNum(parts[2]), + avg: toNum(parts[3]), + volume: toNum(parts[6]), + }) + } + } + + return points +} + +function parseTrades(result: BaiduQuotationResult): TradeTick[] { + return (result.detailinfos ?? []).map((t) => ({ + time: t.formatTime, + price: toNum(t.price), + volume: toNum(t.volume), + side: t.bsFlag === 'B' ? 'B' : 'S', + })) +} + +export function mapBaiduQuotationToQuote( + result: BaiduQuotationResult, + fallback?: QuoteData, +): QuoteData { + const op = result.pankouinfos?.origin_pankou + const cur = result.cur + const basic = result.basicinfos + const update = result.update + + const outside = toNum(op?.outside) + const inside = toNum(op?.inside) + const total = outside + inside + const buyRatio = total > 0 ? Math.round((outside / total) * 100) : 50 + const sellRatio = 100 - buyRatio + + const asksRaw = result.askinfos ?? [] + const bidsRaw = result.buyinfos ?? [] + + // 盘口:接口卖档为卖5→卖1,买档为买1→买5,与 UI 一致 + const asks = asksRaw.map((a, i) => ({ + level: asksRaw.length - i, + price: toNum(a.askprice), + volume: toNum(a.askvolume), + })) + + const bids = bidsRaw.map((b, i) => ({ + level: i + 1, + price: toNum(b.bidprice), + volume: toNum(b.bidvolume), + })) + + const amountYi = parseAmountYi( + result.pankouinfos?.list?.find((i) => i.ename === 'amount')?.value, + op?.amount, + ) + + return { + name: basic?.name || contractConfig.name, + code: basic?.code || contractConfig.code, + exchange: basic?.exchange || contractConfig.exchange, + status: update?.stockStatus || '未知', + last: toNum(cur?.price ?? op?.currentPrice), + change: toNum(cur?.increase), + changePercent: toNum(cur?.ratio), + open: toNum(op?.open), + high: toNum(op?.high), + low: toNum(op?.low), + prevClose: toNum(op?.preClose), + settlement: toNum(op?.settlement), + prevSettlement: toNum(op?.prevSettlement), + avg: toNum(cur?.avgPrice ?? op?.currentPrice), + volume: toNum(op?.volume), + amount: amountYi, + openInterest: toNum(op?.holdingAmount), + amplitude: toNum(op?.amplitudeRatio), + outerVol: outside, + innerVol: inside, + updatedAt: update?.text || cur?.datetime || '', + buyRatio, + sellRatio, + intraday: parseIntraday(result), + candles: fallback?.candles ?? { day: [], week: [], month: [] }, + orderBook: { asks, bids }, + trades: parseTrades(result), + } +} diff --git a/src/api/baidu/quotation.ts b/src/api/baidu/quotation.ts new file mode 100644 index 0000000..5f47b45 --- /dev/null +++ b/src/api/baidu/quotation.ts @@ -0,0 +1,54 @@ +import { baiduHttp } from '../http' +import type { BaiduQuotationResponse, BaiduQuotationResult } from './types' + +export interface GetStockQuotationParams { + code: string +} + +/** + * 百度财经 — 期货盘口 / 分时 / 行情快照 + * 仅页面打开时拉取一次;实时更新后续对接 WebSocket。 + */ +export async function getStockQuotation( + params: GetStockQuotationParams, +): Promise { + const { data } = await baiduHttp.get( + '/selfselect/getstockquotation', + { + params: { + all: 1, + isIndex: false, + isBk: false, + isBlock: false, + isStock: false, + isEtf: false, + isFutures: true, + isForeign: false, + code: params.code, + stockType: 'ab', + newFormat: 1, + market_type: 'ab', + group: 'quotation_futures_minute', + finClientType: 'pc', + }, + }, + ) + + if (data.ResultCode !== '0') { + throw new Error(`行情接口失败: ResultCode=${data.ResultCode}`) + } + + const result = data.Result + if (Array.isArray(result)) { + if (!result.length) { + throw new Error('行情接口返回空 Result') + } + return result[0] + } + + if (!result || typeof result !== 'object') { + throw new Error('行情接口返回空 Result') + } + + return result +} diff --git a/src/api/baidu/types.ts b/src/api/baidu/types.ts new file mode 100644 index 0000000..8f1b186 --- /dev/null +++ b/src/api/baidu/types.ts @@ -0,0 +1,103 @@ +export interface BaiduPricePoint { + time: string + price: string + ratio: string + increase: string + volume: string + avgPrice: string + amount: string + totalVolume: string + totalAmount: string + timeKey: string + datetime: string + oriAmount: string + show: string + unit?: string +} + +export interface BaiduPankouItem { + ename: string + name: string + value: string + status?: string +} + +export interface BaiduOriginPankou { + open: string + preClose: string + volume: string + high: string + low: string + inside: string + outside: string + amount: string + amplitudeRatio: string + holdingAmount: string + prevSettlement: string + settlement: string + amountDelta: string + currentPrice: string + [key: string]: string +} + +export interface BaiduAskInfo { + askprice: string + askvolume: string +} + +export interface BaiduBuyInfo { + bidprice: string + bidvolume: string +} + +export interface BaiduDetailInfo { + time: string + volume: string + price: string + type: string + bsFlag: 'B' | 'S' | string + formatTime: string +} + +export interface BaiduMarketDataDay { + date: string + p: string +} + +export interface BaiduQuotationResult { + priceinfo: BaiduPricePoint[] + pankouinfos: { + list: BaiduPankouItem[] + origin_pankou: BaiduOriginPankou + } + basicinfos: { + exchange: string + code: string + name: string + stockStatus: string + stock_market_code: string + } + askinfos: BaiduAskInfo[] + buyinfos: BaiduBuyInfo[] + detailinfos: BaiduDetailInfo[] + update: { + text: string + time: string + stockStatus: string + } + newMarketData: { + headers: string[] + maxPoints: string + cx: string[] + keys: string[] + marketData: BaiduMarketDataDay[] + } + cur: BaiduPricePoint + provider?: string +} + +export interface BaiduQuotationResponse { + QueryID: string + ResultCode: string + Result: BaiduQuotationResult | BaiduQuotationResult[] +} diff --git a/src/api/http.ts b/src/api/http.ts new file mode 100644 index 0000000..338dbc0 --- /dev/null +++ b/src/api/http.ts @@ -0,0 +1,7 @@ +import axios from 'axios' + +/** 开发环境走 Vite 代理 /baidu → https://finance.pae.baidu.com */ +export const baiduHttp = axios.create({ + baseURL: '/baidu', + timeout: 15000, +}) diff --git a/src/assets/hero.png b/src/assets/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..02251f4b956c55af2d76fd0788124d7eee2b45eb GIT binary patch literal 13057 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 P00000NkvXXu0mjft=yBf literal 0 HcmV?d00001 diff --git a/src/assets/vite.svg b/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/src/assets/vue.svg b/src/assets/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/ai/AiAdviceDrawer.vue b/src/components/ai/AiAdviceDrawer.vue new file mode 100644 index 0000000..8d22d85 --- /dev/null +++ b/src/components/ai/AiAdviceDrawer.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/src/components/header/AppHeader.vue b/src/components/header/AppHeader.vue new file mode 100644 index 0000000..d8e0a5f --- /dev/null +++ b/src/components/header/AppHeader.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/components/header/SettingsDialog.vue b/src/components/header/SettingsDialog.vue new file mode 100644 index 0000000..5f3ef39 --- /dev/null +++ b/src/components/header/SettingsDialog.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/components/news/NewsItem.vue b/src/components/news/NewsItem.vue new file mode 100644 index 0000000..5a75e00 --- /dev/null +++ b/src/components/news/NewsItem.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/news/NewsList.vue b/src/components/news/NewsList.vue new file mode 100644 index 0000000..9693619 --- /dev/null +++ b/src/components/news/NewsList.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/position/PositionDonut.vue b/src/components/position/PositionDonut.vue new file mode 100644 index 0000000..02d1b73 --- /dev/null +++ b/src/components/position/PositionDonut.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/components/position/PositionPanel.vue b/src/components/position/PositionPanel.vue new file mode 100644 index 0000000..a9f0414 --- /dev/null +++ b/src/components/position/PositionPanel.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/components/position/PositionTable.vue b/src/components/position/PositionTable.vue new file mode 100644 index 0000000..7a20875 --- /dev/null +++ b/src/components/position/PositionTable.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/quote/ChartPanel.vue b/src/components/quote/ChartPanel.vue new file mode 100644 index 0000000..81c0016 --- /dev/null +++ b/src/components/quote/ChartPanel.vue @@ -0,0 +1,250 @@ + + + + + diff --git a/src/components/quote/OrderBook.vue b/src/components/quote/OrderBook.vue new file mode 100644 index 0000000..668ea78 --- /dev/null +++ b/src/components/quote/OrderBook.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/quote/QuoteStats.vue b/src/components/quote/QuoteStats.vue new file mode 100644 index 0000000..5d28f2e --- /dev/null +++ b/src/components/quote/QuoteStats.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/components/quote/TradeTape.vue b/src/components/quote/TradeTape.vue new file mode 100644 index 0000000..0956173 --- /dev/null +++ b/src/components/quote/TradeTape.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/composables/useAiAdvice.ts b/src/composables/useAiAdvice.ts new file mode 100644 index 0000000..a6a9b6a --- /dev/null +++ b/src/composables/useAiAdvice.ts @@ -0,0 +1,31 @@ +import { ref } from 'vue' +import type { AiAdvice } from '../types' +import { aiAdviceMock } from '../mocks/aiAdvice' + +function delay(ms = 400): Promise { + return new Promise((r) => setTimeout(r, ms)) +} + +export function useAiAdvice() { + const data = ref(structuredClone(aiAdviceMock)) + const loading = ref(false) + const error = ref(null) + + async function refresh() { + loading.value = true + error.value = null + try { + await delay() + data.value = { + ...structuredClone(aiAdviceMock), + updatedAt: new Date().toLocaleString('zh-CN', { hour12: false }), + } + } catch (e) { + error.value = e + } finally { + loading.value = false + } + } + + return { data, loading, error, refresh } +} diff --git a/src/composables/useNews.ts b/src/composables/useNews.ts new file mode 100644 index 0000000..9ce885a --- /dev/null +++ b/src/composables/useNews.ts @@ -0,0 +1,28 @@ +import { ref } from 'vue' +import type { NewsItem } from '../types' +import { newsMock } from '../mocks/news' + +function delay(ms = 300): Promise { + return new Promise((r) => setTimeout(r, ms)) +} + +export function useNews() { + const data = ref(structuredClone(newsMock)) + const loading = ref(false) + const error = ref(null) + + async function refresh() { + loading.value = true + error.value = null + try { + await delay() + data.value = structuredClone(newsMock) + } catch (e) { + error.value = e + } finally { + loading.value = false + } + } + + return { data, loading, error, refresh } +} diff --git a/src/composables/usePositions.ts b/src/composables/usePositions.ts new file mode 100644 index 0000000..ffd3510 --- /dev/null +++ b/src/composables/usePositions.ts @@ -0,0 +1,28 @@ +import { ref } from 'vue' +import type { PositionsData } from '../types' +import { positionsMock } from '../mocks/positions' + +function delay(ms = 300): Promise { + return new Promise((r) => setTimeout(r, ms)) +} + +export function usePositions() { + const data = ref(structuredClone(positionsMock)) + const loading = ref(false) + const error = ref(null) + + async function refresh() { + loading.value = true + error.value = null + try { + await delay() + data.value = structuredClone(positionsMock) + } catch (e) { + error.value = e + } finally { + loading.value = false + } + } + + return { data, loading, error, refresh } +} diff --git a/src/composables/useQuote.ts b/src/composables/useQuote.ts new file mode 100644 index 0000000..d56a6fd --- /dev/null +++ b/src/composables/useQuote.ts @@ -0,0 +1,33 @@ +import { onMounted, ref } from 'vue' +import type { QuoteData } from '../types' +import { quoteMock } from '../mocks/quote' +import { contractConfig } from '../config/contract' +import { getStockQuotation } from '../api/baidu/quotation' +import { mapBaiduQuotationToQuote } from '../api/baidu/mapQuote' + +export function useQuote() { + const data = ref(structuredClone(quoteMock)) + const loading = ref(false) + const error = ref(null) + + async function refresh() { + loading.value = true + error.value = null + try { + const result = await getStockQuotation({ code: contractConfig.code }) + data.value = mapBaiduQuotationToQuote(result, data.value) + } catch (e) { + error.value = e + console.error('[useQuote] 拉取行情失败', e) + } finally { + loading.value = false + } + } + + // 页面打开时请求一次;实时数据后续对接 WebSocket + onMounted(() => { + void refresh() + }) + + return { data, loading, error, refresh } +} diff --git a/src/config/contract.ts b/src/config/contract.ts new file mode 100644 index 0000000..bf42162 --- /dev/null +++ b/src/config/contract.ts @@ -0,0 +1,9 @@ +/** 当前关注的期货合约(后续可改为可切换) */ +export const contractConfig = { + /** 合约代码,对应百度行情接口 code 参数 */ + code: 'FG609', + /** 展示名称;接口未返回 name 时使用 */ + name: '玻璃2609', + /** 交易所展示名 */ + exchange: '郑商所', +} as const diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..65c7311 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,7 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent + export default component +} diff --git a/src/layout/AppLayout.vue b/src/layout/AppLayout.vue new file mode 100644 index 0000000..cfe97cd --- /dev/null +++ b/src/layout/AppLayout.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..055a36c --- /dev/null +++ b/src/main.ts @@ -0,0 +1,13 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import zhCn from 'element-plus/es/locale/lang/zh-cn' +import 'element-plus/dist/index.css' +import './styles/variables.css' +import './styles/global.css' +import App from './App.vue' + +const app = createApp(App) +app.use(createPinia()) +app.use(ElementPlus, { locale: zhCn }) +app.mount('#app') diff --git a/src/mocks/aiAdvice.ts b/src/mocks/aiAdvice.ts new file mode 100644 index 0000000..9d60a60 --- /dev/null +++ b/src/mocks/aiAdvice.ts @@ -0,0 +1,15 @@ +import type { AiAdvice } from '../types' + +export const aiAdviceMock: AiAdvice = { + action: '观望', + direction: 'neutral', + confidence: 62, + summary: '短线偏弱但未破关键支撑,建议观望等待方向确认。', + reasons: [ + '分时均线上方承压,反弹动能不足', + '五档卖压略大于买盘,内外盘接近均衡', + '机构多空头部持仓变动分化,缺乏单边合力', + '相关新闻偏中性,未见明确驱动', + ], + updatedAt: '2026-07-21 11:30:12', +} diff --git a/src/mocks/news.ts b/src/mocks/news.ts new file mode 100644 index 0000000..68b062b --- /dev/null +++ b/src/mocks/news.ts @@ -0,0 +1,49 @@ +import type { NewsItem } from '../types' + +export const newsMock: NewsItem[] = [ + { + id: 1, + source: 'LSEG', + time: '07-16 04:07', + title: 'Precipitate Gold appoints Pelayo Troncoso and John Wenger to the Board', + summary: + 'Precipitate Gold Corp announced the appointment of Pelayo Troncoso and John Wenger as independent directors, strengthening governance ahead of exploration milestones.', + url: 'https://example.com/news/1', + }, + { + id: 2, + source: '路透', + time: '07-16 03:42', + title: '原油短线承压,美油回落关注库存数据', + summary: + '隔夜油价震荡回落,市场等待本周库存与炼厂开工率数据,短线交易者对风险偏好趋于谨慎。', + url: 'https://example.com/news/2', + }, + { + id: 3, + source: '财联社', + time: '07-15 21:18', + title: '玻璃期货日内走弱,期现基差小幅收敛', + summary: + '盘面跟随黑色系情绪回落,现货报价相对坚挺,基差有所收窄;机构提示关注沙河地区库存变化。', + url: 'https://example.com/news/3', + }, + { + id: 4, + source: 'Bloomberg', + time: '07-15 18:05', + title: 'Gold holds near highs as markets await PPI print', + summary: + 'Bullion stayed firm as traders positioned for U.S. producer price data, with real yields and dollar moves still the key drivers.', + url: 'https://example.com/news/4', + }, + { + id: 5, + source: '新华财经', + time: '07-15 15:30', + title: '碳酸锂价格波动加剧,产业链观望情绪升温', + summary: + '下游备货节奏放缓,部分贸易商报价分歧加大,锂盐市场短期或以区间震荡为主。', + url: 'https://example.com/news/5', + }, +] diff --git a/src/mocks/positions.ts b/src/mocks/positions.ts new file mode 100644 index 0000000..c967f78 --- /dev/null +++ b/src/mocks/positions.ts @@ -0,0 +1,75 @@ +import type { PositionRow, PositionsData } from '../types' + +function makeList(names: string[], base: number): PositionRow[] { + return names.map((name, i) => { + const qty = Math.floor(base * (0.22 - i * 0.012) + Math.random() * 2000) + const change = Math.floor((Math.random() - 0.45) * 800) + return { + rank: i + 1, + name, + qty, + change, + percent: 0, + } + }) +} + +function withPercent(list: PositionRow[]): PositionRow[] { + const total = list.reduce((s, x) => s + x.qty, 0) + return list.map((x) => ({ + ...x, + percent: Number(((x.qty / total) * 100).toFixed(2)), + })) +} + +const longNames = [ + '中财期货', + '东证期货', + '恒力期货', + '物产中大期货', + '中信期货', + '国泰君安期货', + '海通期货', + '永安期货', + '银河期货', + '华泰期货', + '南华期货', + '光大期货', + '方正中期', + '申银万国', + '中粮期货', + '浙商期货', + '广发期货', + '兴证期货', + '瑞达期货', + '其他', +] + +const shortNames = [ + '国泰君安期货', + '中信期货', + '永安期货', + '海通期货', + '华泰期货', + '银河期货', + '中财期货', + '东证期货', + '南华期货', + '光大期货', + '恒力期货', + '物产中大期货', + '方正中期', + '申银万国', + '中粮期货', + '浙商期货', + '广发期货', + '兴证期货', + '瑞达期货', + '其他', +] + +export const positionsMock: PositionsData = { + long: withPercent(makeList(longNames, 650000)), + short: withPercent(makeList(shortNames, 640000)), + updatedAt: '2026-07-15', +} diff --git a/src/mocks/quote.ts b/src/mocks/quote.ts new file mode 100644 index 0000000..5593fa5 --- /dev/null +++ b/src/mocks/quote.ts @@ -0,0 +1,112 @@ +import type { Candle, IntradayPoint, QuoteData } from '../types' + +function buildIntraday(): IntradayPoint[] { + const points: IntradayPoint[] = [] + let price = 948 + const slots = [ + { start: '21:00', count: 30 }, + { start: '09:00', count: 40 }, + { start: '10:30', count: 20 }, + { start: '13:30', count: 35 }, + ] + for (const slot of slots) { + const [h, m] = slot.start.split(':').map(Number) + for (let i = 0; i < slot.count; i++) { + const mm = m + i + const hh = h + Math.floor(mm / 60) + const min = mm % 60 + const t = `${String(hh).padStart(2, '0')}:${String(min).padStart(2, '0')}` + price += (Math.random() - 0.55) * 1.2 + points.push({ + time: t, + price: Number(price.toFixed(2)), + avg: Number((price + 0.4).toFixed(2)), + volume: Math.floor(Math.random() * 800 + 50), + }) + } + } + return points +} + +function buildCandles(count = 40): Candle[] { + const candles: Candle[] = [] + let close = 950 + for (let i = 0; i < count; i++) { + const open = close + const change = (Math.random() - 0.5) * 12 + close = Number((open + change).toFixed(2)) + const high = Number((Math.max(open, close) + Math.random() * 4).toFixed(2)) + const low = Number((Math.min(open, close) - Math.random() * 4).toFixed(2)) + candles.push({ + date: `05-${String((i % 28) + 1).padStart(2, '0')}`, + open, + close, + low, + high, + volume: Math.floor(Math.random() * 20000 + 3000), + }) + } + return candles +} + +export const quoteMock: QuoteData = { + name: '玻璃2609', + code: 'FG609', + exchange: '郑商所', + status: '休市', + last: 936.0, + change: -13.0, + changePercent: -1.37, + open: 948.0, + high: 949.0, + low: 934.0, + prevClose: 949.0, + settlement: 949.0, + prevSettlement: 949.0, + avg: 940.0, + volume: 825643, + amount: 77.72, + openInterest: 673892, + amplitude: 1.58, + outerVol: 412331, + innerVol: 413312, + updatedAt: '11:30:00', + buyRatio: 48, + sellRatio: 52, + intraday: buildIntraday(), + candles: { + day: buildCandles(60), + week: buildCandles(40), + month: buildCandles(24), + }, + orderBook: { + asks: [ + { level: 5, price: 938.0, volume: 312 }, + { level: 4, price: 937.0, volume: 198 }, + { level: 3, price: 936.0, volume: 456 }, + { level: 2, price: 935.0, volume: 221 }, + { level: 1, price: 934.0, volume: 178 }, + ], + bids: [ + { level: 1, price: 933.0, volume: 265 }, + { level: 2, price: 932.0, volume: 340 }, + { level: 3, price: 931.0, volume: 189 }, + { level: 4, price: 930.0, volume: 412 }, + { level: 5, price: 929.0, volume: 297 }, + ], + }, + trades: [ + { time: '11:30', price: 936.0, volume: 1, side: 'B' }, + { time: '11:30', price: 936.0, volume: 23, side: 'B' }, + { time: '11:29', price: 935.0, volume: 2, side: 'S' }, + { time: '11:29', price: 935.0, volume: 8, side: 'B' }, + { time: '11:28', price: 936.0, volume: 15, side: 'S' }, + { time: '11:28', price: 936.0, volume: 4, side: 'B' }, + { time: '11:27', price: 937.0, volume: 11, side: 'S' }, + { time: '11:27', price: 936.0, volume: 6, side: 'B' }, + { time: '11:26', price: 935.0, volume: 19, side: 'S' }, + { time: '11:26', price: 934.0, volume: 3, side: 'B' }, + { time: '11:25', price: 935.0, volume: 27, side: 'S' }, + { time: '11:25', price: 936.0, volume: 9, side: 'B' }, + ], +} diff --git a/src/stores/settings.ts b/src/stores/settings.ts new file mode 100644 index 0000000..a5bb3a6 --- /dev/null +++ b/src/stores/settings.ts @@ -0,0 +1,29 @@ +import { defineStore } from 'pinia' +import { ref, watch } from 'vue' +import type { AppSettings } from '../types' + +const STORAGE_KEY = 'ai-trade-settings' + +function load(): Partial { + try { + return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}') as Partial + } catch { + return {} + } +} + +export const useSettingsStore = defineStore('settings', () => { + const saved = load() + const apiKey = ref(saved.apiKey || '') + const keywords = ref(saved.keywords || '') + + watch([apiKey, keywords], () => { + const payload: AppSettings = { + apiKey: apiKey.value, + keywords: keywords.value, + } + localStorage.setItem(STORAGE_KEY, JSON.stringify(payload)) + }) + + return { apiKey, keywords } +}) diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 0000000..9755c69 --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,49 @@ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body, +#app { + margin: 0; + min-height: 100%; +} + +body { + font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; + background: var(--bg-page); + color: var(--text-primary); + -webkit-font-smoothing: antialiased; +} + +a { + color: var(--accent); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +.price-up { + color: var(--up); +} + +.price-down { + color: var(--down); +} + +.card { + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: var(--shadow); +} + +.section-title { + margin: 0 0 12px; + font-size: 16px; + font-weight: 600; +} diff --git a/src/styles/variables.css b/src/styles/variables.css new file mode 100644 index 0000000..b729f51 --- /dev/null +++ b/src/styles/variables.css @@ -0,0 +1,16 @@ +:root { + --bg-page: #f5f6f8; + --bg-card: #ffffff; + --border: #e6e8eb; + --text-primary: #1f2329; + --text-secondary: #8a9199; + --up: #e54545; + --down: #12b37b; + --accent: #1677ff; + --long: #e54545; + --short: #0ea5a0; + --header-height: 56px; + --ai-bar-height: 48px; + --radius: 8px; + --shadow: 0 1px 2px rgba(0, 0, 0, 0.04); +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..5fc964d --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,104 @@ +export interface IntradayPoint { + time: string + price: number + avg: number + volume: number +} + +export interface Candle { + date: string + open: number + close: number + low: number + high: number + volume: number +} + +export interface OrderLevel { + level: number + price: number + volume: number +} + +export interface TradeTick { + time: string + price: number + volume: number + side: 'B' | 'S' +} + +export interface QuoteData { + name: string + code: string + exchange: string + status: string + last: number + change: number + changePercent: number + open: number + high: number + low: number + prevClose: number + settlement: number + prevSettlement: number + avg: number + volume: number + amount: number + openInterest: number + amplitude: number + outerVol: number + innerVol: number + updatedAt: string + buyRatio: number + sellRatio: number + intraday: IntradayPoint[] + candles: { + day: Candle[] + week: Candle[] + month: Candle[] + } + orderBook: { + asks: OrderLevel[] + bids: OrderLevel[] + } + trades: TradeTick[] +} + +export interface NewsItem { + id: number + source: string + time: string + title: string + summary: string + url?: string +} + +export interface PositionRow { + rank: number + name: string + qty: number + change: number + percent: number +} + +export interface PositionsData { + long: PositionRow[] + short: PositionRow[] + updatedAt: string +} + +export type AdviceDirection = 'long' | 'short' | 'neutral' + +export interface AiAdvice { + action: string + direction: AdviceDirection + confidence: number + summary: string + reasons: string[] + updatedAt: string +} + +export interface AppSettings { + apiKey: string + keywords: string +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..23a72a7 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..953116c --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..6dc6607 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { fileURLToPath, URL } from 'node:url' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + server: { + proxy: { + '/baidu': { + target: 'https://finance.pae.baidu.com', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/baidu/, ''), + headers: { + Referer: 'https://gushitong.baidu.com/', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + }, + }, + '/jqka': { + target: 'https://fupage.10jqka.com.cn', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/jqka/, ''), + }, + }, + }, +})