diff --git a/.cursor/rules/doc-sync.mdc b/.cursor/rules/doc-sync.mdc new file mode 100644 index 0000000..1272c61 --- /dev/null +++ b/.cursor/rules/doc-sync.mdc @@ -0,0 +1,37 @@ +--- +description: 修改或新增 src/ 代码时同步更新 docs/ 技术文档 +globs: src/**/* +alwaysApply: false +--- + +# 文档同步规则 + +当你在 `src/` 下**新增或修改**任何文件时,必须同步更新 `docs/` 中对应的技术文档。 + +## 文件映射关系 + +| 源文件 | 文档路径 | +|--------|----------| +| `src/api/*.ts` | `docs/api/*.md` | +| `src/stores/*.ts` | `docs/stores/*.md` | +| `src/composables/*.ts` | `docs/composables/*.md` | +| `src/views/*.vue` | `docs/views/*.md` | +| `src/components/*.vue` | `docs/components/*.md` | +| `src/main.ts` | `docs/core/main.md` | +| `src/App.vue` | `docs/core/App.md` | +| `src/router/index.ts` | `docs/core/router.md` | +| `src/plugins/*.ts` | `docs/core/*.md`(如 vuetify.md) | + +## 文档结构要求 + +每个文档需包含以下三部分: + +1. **功能用途**:该文件/模块的职责与核心能力 +2. **使用方式**:调用示例、Props/Events、API 用法 +3. **扩展方式**:如何修改、新增功能 + +API 与组件文档需补充类型说明、Props、Events 等。 + +## 示例 + +修改 `src/api/event.ts` 后,需更新 `docs/api/event.md`;新增 `src/api/order.ts` 时,需新建 `docs/api/order.md`。 diff --git a/docs/FEATURES.md b/docs/FEATURES.md new file mode 100644 index 0000000..00af240 --- /dev/null +++ b/docs/FEATURES.md @@ -0,0 +1,143 @@ +# 功能实现状态 + +本文档列出项目中**已实现**与**未实现**的功能,便于开发与迭代时参考。 + +--- + +## 已实现功能 + +### 认证与用户 + +| 功能 | 说明 | +|------|------| +| 钱包登录 (SIWE) | 通过 MetaMask 等钱包签名,调用 `/base/walletLogin` 获取 token,存入 userStore | +| 用户信息 | `getUserInfo` 获取头像、昵称等,登录后自动拉取 | +| USDC 余额 | `getUsdcBalance` 获取余额,除以 1_000_000 后展示 | +| 登出 | 清空 token、user,移除 localStorage | + +### 首页 (Home) + +| 功能 | 说明 | +|------|------| +| 分类 Tab | 调用 `getPmTagMain` 获取分类树,支持三层;接口失败时回退 `MOCK_CATEGORY_TREE` | +| 事件列表 | `getPmEventPublic` 分页获取,支持 keyword、tagSlug、tagId 等筛选 | +| 搜索 | 关键词搜索、搜索历史(localStorage,最多 10 条) | +| 下拉刷新 | VPullToRefresh 组件 | +| 无限滚动 | 滚动到底部加载更多 | +| 列表缓存 | 切换页面时复用 `eventListCache`,下拉刷新时清空 | +| 单一/多选项卡片 | MarketCard 支持 single(Yes/No)与 multi(轮播多选项) | + +### 交易详情 (TradeDetail) + +| 功能 | 说明 | +|------|------| +| 事件详情 | `findPmEvent` 按 id/slug 获取,需鉴权 | +| 分时图 | ECharts 渲染,时间粒度 1H/6H/1D/1W/1M/ALL,**当前为本地生成 mock 数据** | +| 交易组件 | Buy/Sell、Market 模式、Merge、Split | +| 下单 | `pmOrderPlace` 调用 CLOB 下单接口 | +| Split | `pmMarketSplit` 用 USDC 兑换 Yes+No | +| Merge | `pmMarketMerge` 合并 Yes+No 得 USDC | +| 移动端适配 | 底部 Yes/No 栏 + 弹窗交易组件 | +| 多市场切换 | 支持 query.marketId 指定当前 market | + +### 钱包 (Wallet) + +| 功能 | 说明 | +|------|------| +| Portfolio 卡片 | 展示 userStore.balance | +| Deposit/Withdraw 弹窗 | UI 完整,Deposit 展示固定地址与二维码;Withdraw 支持金额、网络、目标地址选择 | +| 取消订单 | `pmCancelOrder` 调用真实接口,**但 Positions/Open orders/History 数据为 mock** | +| Profit/Loss 图表 | ECharts 展示,**数据为 mock** | +| Positions/Orders/History Tab | 表格与移动端列表,**数据为 mock** | +| 搜索、分页 | 对 mock 数据生效 | + +### 事件市场列表 (EventMarkets) + +| 功能 | 说明 | +|------|------| +| 事件详情 | `findPmEvent` 获取,失败时用 `getMockEventById` 兜底 | +| 市场列表 | 展示该 Event 下多个 Market,可点击跳转交易详情 | + +### API 层 + +| 模块 | 已实现 | +|------|--------| +| request | get、post,支持 BASE_URL、自定义 headers | +| event | getPmEventPublic、findPmEvent、mapEventItemToCard、缓存 | +| category | getPmTagMain、enrichWithIcons、MOCK_CATEGORY_TREE | +| categoryIcons | resolveCategoryIcon、resolveCategoryIconColor | +| market | pmOrderPlace、pmCancelOrder、pmMarketSplit、pmMarketMerge | +| user | getUserInfo、getUsdcBalance、formatUsdcBalance | +| constants | OrderType、Side | + +### 其他 + +| 功能 | 说明 | +|------|------| +| 路由 | 6 个页面,createWebHistory | +| Keep-alive | Home 页面缓存 | +| 多语言 | 当前中英混用,无 i18n | + +--- + +## 未实现 / Mock 功能 + +### 认证 + +| 功能 | 状态 | +|------|------| +| 邮箱密码登录 | 仅前端校验,无真实 API 调用,直接跳转首页 | + +### 首页 + +| 功能 | 状态 | +|------|------| +| 分类接口失败兜底 | 使用 MOCK_CATEGORY_TREE,非真实数据 | + +### 交易详情 + +| 功能 | 状态 | +|------|------| +| 分时图数据 | 本地 `generateData()` 生成随机曲线,未对接 WebSocket 或历史接口 | +| Comments | 占位文案 "No comments yet." | +| Top Holders | 占位文案 "Top holders will appear here." | +| Activity | 使用硬编码 mock 数据,未对接交易活动接口 | + +### 订单簿 (OrderBook) + +| 功能 | 状态 | +|------|------| +| Asks/Bids | 硬编码 mock 数据,定时随机变化模拟 | +| Last/Spread | mock | +| 真实订单簿 | 需对接 CLOB 或 WebSocket | + +### 钱包 + +| 功能 | 状态 | +|------|------| +| Positions | mock 数据 | +| Open orders | mock 数据,取消订单调用真实 API 但列表为 mock | +| History | mock 数据 | +| Profit/Loss 图表 | mock 数据 | +| Portfolio 余额 | 来自 userStore(真实),非 mock | +| Deposit 实际充值 | 仅展示地址与二维码,未对接链上或托管充值 | +| Withdraw 实际提现 | 仅 UI 流程,未对接提现接口 | +| Close Losses | TODO,未实现 | +| Export | TODO,未实现 | +| 筛选/排序 | 部分按钮为占位,未实现逻辑 | + +### 其他 + +| 功能 | 状态 | +|------|------| +| 注册页 | 路由未配置,Login 中链接指向 `/register` | +| Limit 单 | TradeComponent 有 Limit 选项,下单逻辑以 Market 为主 | +| 订单簿点击下单 | 点击某行价格填入 TradeComponent 未实现 | + +--- + +## 实现优先级建议 + +1. **高**:订单簿真实数据、分时图真实数据、Positions/Orders/History 真实接口 +2. **中**:Comments、Top Holders、Activity 接口;Deposit/Withdraw 实际流程 +3. **低**:邮箱密码登录、注册页、Limit 单完善 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..8043d1d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,70 @@ +# PolyClientVuetify 开发文档 + +本目录包含项目各模块的详细开发文档,每个文件对应一份文档,说明其功能用途、使用方式及扩展方法。 + +## 功能实现状态 + +**[FEATURES.md](./FEATURES.md)**:已实现功能与未实现/Mock 功能清单,含实现优先级建议。 + +## 文档结构 + +``` +docs/ +├── README.md # 本索引文件 +├── api/ # API 层 +│ ├── request.md +│ ├── event.md +│ ├── category.md +│ ├── categoryIcons.md +│ ├── market.md +│ ├── user.md +│ ├── constants.md +│ └── mockEventList.md +├── stores/ # Pinia 状态 +│ ├── user.md +│ └── counter.md +├── composables/ # 组合式函数 +│ └── useSearchHistory.md +├── views/ # 页面视图 +│ ├── Home.md +│ ├── Trade.md +│ ├── TradeDetail.md +│ ├── EventMarkets.md +│ ├── Login.md +│ └── Wallet.md +├── components/ # 可复用组件 +│ ├── MarketCard.md +│ ├── TradeComponent.md +│ ├── OrderBook.md +│ ├── HorizontalProgressBar.md +│ ├── DepositDialog.md +│ └── WithdrawDialog.md +├── core/ # 核心入口与配置 +│ ├── main.md +│ ├── App.md +│ ├── router.md +│ └── vuetify.md +└── config/ # 构建与工具配置 + ├── vite.md + └── package.md +``` + +## 技术栈概览 + +- **框架**:Vue 3(Composition API)+ TypeScript +- **构建**:Vite 7,路径别名 `@/*` → `./src/*` +- **UI**:Vuetify 4 +- **状态**:Pinia +- **路由**:Vue Router 5 + +## 快速导航 + +| 模块 | 说明 | +|------|------| +| [API 层](./api/) | 请求封装、接口函数、类型定义 | +| [Stores](./stores/) | 全局状态管理 | +| [Composables](./composables/) | 组合式函数 | +| [Views](./views/) | 页面级视图,对应路由 | +| [Components](./components/) | 可复用 UI 组件 | +| [Core](./core/) | 入口、路由、插件 | +| [Config](./config/) | 构建与工具配置 | diff --git a/docs/api/category.md b/docs/api/category.md new file mode 100644 index 0000000..c476868 --- /dev/null +++ b/docs/api/category.md @@ -0,0 +1,39 @@ +# category.ts + +**路径**:`src/api/category.ts` + +## 功能用途 + +分类(Tag)相关接口与数据结构,对接 `/PmTag/getPmTagList`,获取首页顶部分类 Tab 数据。支持树形结构、图标自动匹配、按 sort 排序。 + +## 核心能力 + +- `getPmTagMain`:获取主分类树,返回 `CategoryTreeNode[]` +- `enrichWithIcons`:递归为节点补充 MDI 图标(无 icon 时自动匹配) +- `MOCK_CATEGORY_TREE`:模拟分类数据,用于开发/测试 + +## 类型说明 + +| 类型 | 说明 | +|------|------| +| `PmTagMainItem` | 接口返回的 PmTag 结构,含 children | +| `CategoryTreeNode` | 前端使用的树节点,含 id、label、slug、icon、sectionTitle、children | + +## 使用方式 + +```typescript +import { getPmTagMain, enrichWithIcons, MOCK_CATEGORY_TREE } from '@/api/category' + +// 获取分类 +const res = await getPmTagMain() +const tree = res.data // 已包含图标、排序 + +// 开发时使用 mock +const mockTree = enrichWithIcons(MOCK_CATEGORY_TREE) +``` + +## 扩展方式 + +1. **新增分类层级**:在 `CategoryTreeNode` 中扩展字段,`getPmTagMain` 的 `mapPmTagToTreeNode` 中映射 +2. **自定义图标**:在 `categoryIcons.ts` 中扩展 `ICON_MAP`,`enrichWithIcons` 会自动使用 +3. **过滤逻辑**:在 `getPmTagMain` 中根据 `forceShow`/`forceHide` 过滤节点 diff --git a/docs/api/categoryIcons.md b/docs/api/categoryIcons.md new file mode 100644 index 0000000..d0d2f8f --- /dev/null +++ b/docs/api/categoryIcons.md @@ -0,0 +1,42 @@ +# categoryIcons.ts + +**路径**:`src/api/categoryIcons.ts` + +## 功能用途 + +根据分类的 label/slug 自动解析 MDI 图标名和颜色,供首页分类 Tab 使用。项目已引入 `@mdi/font`,图标名为 `mdi-xxx` 格式。 + +## 核心能力 + +- `resolveCategoryIcon`:根据 label/slug 返回 MDI 图标名,无匹配时返回 `DEFAULT_CATEGORY_ICON` +- `resolveCategoryIconColor`:返回 Vuetify 颜色名或 CSS 颜色 +- `DEFAULT_CATEGORY_ICON`:默认图标 `mdi-tag-outline` + +## 匹配优先级 + +1. 节点已有 `icon` 且以 `mdi-` 开头 → 直接使用 +2. 精确匹配 slug +3. 精确匹配 label +4. 关键词匹配 label(`LABEL_KEYWORDS`) +5. 默认图标 + +## 使用方式 + +```typescript +import { + resolveCategoryIcon, + resolveCategoryIconColor, + DEFAULT_CATEGORY_ICON, +} from '@/api/categoryIcons' + +// 在模板中 + + {{ item.icon || resolveCategoryIcon(item) || DEFAULT_CATEGORY_ICON }} + +``` + +## 扩展方式 + +1. **新增分类图标**:在 `ICON_MAP` 中增加 `slug -> mdi-xxx` 映射 +2. **新增颜色**:在 `ICON_COLOR_MAP` 或 `LABEL_COLOR_KEYWORDS` 中增加 +3. **正则匹配**:在 `LABEL_KEYWORDS` 中使用 RegExp,如 `/^\d+[mhd]$/i` diff --git a/docs/api/constants.md b/docs/api/constants.md new file mode 100644 index 0000000..823e5b3 --- /dev/null +++ b/docs/api/constants.md @@ -0,0 +1,44 @@ +# constants.ts + +**路径**:`src/api/constants.ts` + +## 功能用途 + +交易相关常量:订单类型(OrderType)、交易方向(Side),用于 market 接口入参。 + +## 常量说明 + +### OrderType + +| 值 | 常量 | 说明 | +|----|------|------| +| 0 | GTC | Good Till Cancelled,一直有效直到取消 | +| 1 | GTD | Good Till Date,指定时间内有效 | +| 2 | FOK | Fill Or Kill,全部成交或立即取消 | +| 3 | FAK | Fill And Kill (IOC),立即成交,剩余取消 | +| 4 | Market | 市价单 | + +### Side + +| 值 | 常量 | 说明 | +|----|------|------| +| 1 | Buy | 买入 | +| 2 | Sell | 卖出 | + +## 使用方式 + +```typescript +import { OrderType, Side } from '@/api/constants' + +// 下单时 +await pmOrderPlace({ + orderType: OrderType.GTC, + side: Side.Buy, + // ... +}) +``` + +## 扩展方式 + +1. **新增订单类型**:在 `OrderType` 中增加,并同步后端定义 +2. **业务枚举**:可在此文件或新建 `enums.ts` 中集中管理 diff --git a/docs/api/event.md b/docs/api/event.md new file mode 100644 index 0000000..db4e20b --- /dev/null +++ b/docs/api/event.md @@ -0,0 +1,51 @@ +# event.ts + +**路径**:`src/api/event.ts` + +## 功能用途 + +Event(预测市场事件)相关接口与类型定义,对接 XTrader API 的 `/PmEvent/*` 接口。提供事件列表、详情查询,以及将接口数据映射为首页卡片所需结构的工具函数。 + +## 核心能力 + +- `getPmEventPublic`:分页获取公开事件列表(无需鉴权) +- `findPmEvent`:按 id/slug 查询事件详情(需鉴权) +- `mapEventItemToCard`:将 `PmEventListItem` 转为 `EventCardItem`(供 MarketCard 使用) +- 内存缓存:`getEventListCache`、`setEventListCache`、`clearEventListCache`,用于列表切换页面时复用 + +## 类型说明 + +| 类型 | 说明 | +|------|------| +| `PmEventListItem` | 接口返回的事件项 | +| `PmEventMarketItem` | 市场项,含 outcomes、outcomePrices、clobTokenIds | +| `EventCardItem` | 首页卡片所需结构,含 displayType(single/multi) | +| `EventCardOutcome` | 多选项卡片中单个选项 | +| `PageResult` | 分页结果 | + +## 使用方式 + +```typescript +import { + getPmEventPublic, + findPmEvent, + mapEventItemToCard, + clearEventListCache, +} from '@/api/event' + +// 获取列表 +const res = await getPmEventPublic({ page: 1, pageSize: 10, tagSlug: 'crypto' }) +const cards = res.data.list.map(mapEventItemToCard) + +// 获取详情(需鉴权) +const detail = await findPmEvent({ id: 123 }, { headers: authHeaders }) + +// 下拉刷新时清空缓存 +clearEventListCache() +``` + +## 扩展方式 + +1. **新增筛选参数**:在 `GetPmEventListParams` 中增加字段,并在 `getPmEventPublic` 的 query 中传入 +2. **缓存策略**:可改为 sessionStorage 或带 TTL 的缓存 +3. **多选项展示**:`mapEventItemToCard` 已支持 multi 类型,可扩展 `EventCardOutcome` 字段 diff --git a/docs/api/market.md b/docs/api/market.md new file mode 100644 index 0000000..43485b3 --- /dev/null +++ b/docs/api/market.md @@ -0,0 +1,63 @@ +# market.ts + +**路径**:`src/api/market.ts` + +## 功能用途 + +交易与市场相关接口:下单、取消订单、Split(USDC 换 Yes+No)、Merge(Yes+No 换 USDC)。对接 CLOB Gateway 与 PmMarket 接口。 + +## 核心能力 + +- `pmOrderPlace`:下单(买入/卖出 Yes 或 No) +- `pmCancelOrder`:取消订单 +- `pmMarketSplit`:用 USDC 兑换 Yes+No 份额 +- `pmMarketMerge`:合并 Yes+No 份额得到 USDC + +## 类型说明 + +| 类型 | 说明 | +|------|------| +| `ClobSubmitOrderRequest` | 下单请求体,含 tokenID、price、size、side 等 | +| `ClobCancelOrderRequest` | 取消订单请求体 | +| `PmMarketSplitRequest` | Split 请求体,marketID、usdcAmount | +| `PmMarketMergeRequest` | Merge 请求体,marketID、amount | + +## 使用方式 + +```typescript +import { + pmOrderPlace, + pmCancelOrder, + pmMarketSplit, + pmMarketMerge, +} from '@/api/market' +import { useUserStore } from '@/stores/user' + +const userStore = useUserStore() +const headers = userStore.getAuthHeaders() +if (!headers) return + +// 下单 +await pmOrderPlace( + { + tokenID: clobTokenId, + price: 3700, // 37¢ = 3700 + size: 100, + side: Side.Buy, + // ... 其他字段 + }, + { headers } +) + +// Split +await pmMarketSplit({ marketID: '123', usdcAmount: '10' }, { headers }) + +// Merge +await pmMarketMerge({ marketID: '123', amount: '5' }, { headers }) +``` + +## 扩展方式 + +1. **批量下单**:封装 `pmOrderPlace` 循环或对接批量接口 +2. **订单状态查询**:新增 `getOpenOrders`、`getOrderHistory` 等接口 +3. **价格/数量校验**:在调用前增加业务校验逻辑 diff --git a/docs/api/mockEventList.md b/docs/api/mockEventList.md new file mode 100644 index 0000000..44ef0c4 --- /dev/null +++ b/docs/api/mockEventList.md @@ -0,0 +1,27 @@ +# mockEventList.ts + +**路径**:`src/api/mockEventList.ts` + +## 功能用途 + +模拟事件列表数据 `MOCK_EVENT_LIST`,用于本地开发、测试,覆盖单一 market(Up/Down、Yes/No)、多 markets 轮播等场景。 + +## 核心能力 + +- 提供 `PmEventListItem[]` 格式的 mock 数据 +- 包含单一 market、多 market 等多种结构 +- 可与 `mapEventItemToCard` 配合使用 + +## 使用方式 + +```typescript +import { MOCK_EVENT_LIST } from '@/api/mockEventList' +import { mapEventItemToCard } from '@/api/event' + +const cards = MOCK_EVENT_LIST.map(mapEventItemToCard) +``` + +## 扩展方式 + +1. **新增 mock 项**:在 `MOCK_EVENT_LIST` 中追加符合 `PmEventListItem` 结构的对象 +2. **环境切换**:在 Home 等视图中根据 `import.meta.env.DEV` 选择使用 mock 或真实接口 diff --git a/docs/api/request.md b/docs/api/request.md new file mode 100644 index 0000000..e0b2f14 --- /dev/null +++ b/docs/api/request.md @@ -0,0 +1,40 @@ +# request.ts + +**路径**:`src/api/request.ts` + +## 功能用途 + +HTTP 请求基础封装,提供 `get` 和 `post` 方法,支持自定义请求头(如鉴权 `x-token`、`x-user-id`)。所有 API 模块均通过此文件发起请求。 + +## 核心能力 + +- 统一 BASE_URL:默认 `https://api.xtrader.vip`,可通过环境变量 `VITE_API_BASE_URL` 覆盖 +- GET 请求:支持 query 参数,自动序列化 +- POST 请求:支持 JSON body +- 自定义 headers:通过 `RequestConfig.headers` 传入 + +## 使用方式 + +```typescript +import { get, post } from '@/api/request' + +// GET 请求 +const data = await get('/path', { page: 1, keyword: 'x' }) + +// 带鉴权 +const data = await get('/path', undefined, { + headers: { 'x-token': token, 'x-user-id': userId }, +}) + +// POST 请求 +const res = await post('/path', { key: 'value' }, { + headers: { 'x-token': token }, +}) +``` + +## 扩展方式 + +1. **添加 PUT/DELETE**:仿照 `get`/`post` 实现 `put`、`del` 函数 +2. **统一错误处理**:在 `get`/`post` 内对 `!res.ok` 做统一 toast 或错误上报 +3. **请求/响应拦截**:在 fetch 前后加入拦截逻辑(如 loading、日志) +4. **超时控制**:使用 `AbortController` 实现超时取消 diff --git a/docs/api/user.md b/docs/api/user.md new file mode 100644 index 0000000..6a651ac --- /dev/null +++ b/docs/api/user.md @@ -0,0 +1,41 @@ +# user.ts + +**路径**:`src/api/user.ts` + +## 功能用途 + +用户相关接口:获取用户信息、USDC 余额。对接 `/user/getUserInfo`、`/user/getUsdcBalance`,均需鉴权。 + +## 核心能力 + +- `getUserInfo`:获取当前用户信息(头像、昵称等) +- `getUsdcBalance`:查询 USDC 余额(amount、available、locked 需除以 1_000_000) +- `formatUsdcBalance`:将原始数值转为显示用字符串(如 "0.00") + +## 类型说明 + +| 类型 | 说明 | +|------|------| +| `UserInfoData` | 用户信息结构 | +| `UsdcBalanceData` | 余额结构,amount/available/locked 为原始值 | + +## 使用方式 + +```typescript +import { getUserInfo, getUsdcBalance, formatUsdcBalance } from '@/api/user' + +const headers = { 'x-token': token, 'x-user-id': userId } + +const userRes = await getUserInfo(headers) +const balanceRes = await getUsdcBalance(headers) + +if (balanceRes.data) { + const display = formatUsdcBalance(balanceRes.data.available) +} +``` + +## 扩展方式 + +1. **更新个人信息**:新增 `updateUserInfo` 接口 +2. **交易记录**:新增 `getUserTrades` 等接口 +3. **多币种**:扩展 `UsdcBalanceData` 支持其他资产 diff --git a/docs/components/DepositDialog.md b/docs/components/DepositDialog.md new file mode 100644 index 0000000..5f36052 --- /dev/null +++ b/docs/components/DepositDialog.md @@ -0,0 +1,30 @@ +# DepositDialog.vue + +**路径**:`src/components/DepositDialog.vue` + +## 功能用途 + +充值弹窗,支持 Transfer Crypto、Connect Exchange 等方式。展示充值地址、网络选择、二维码等。 + +## Props + +| 属性 | 类型 | 说明 | +|------|------|------| +| modelValue | boolean | v-model 控制显隐 | +| balance | string | 当前余额展示 | + +## 事件 + +- `update:modelValue`:关闭时更新 + +## 使用方式 + +```vue + +``` + +## 扩展方式 + +1. **真实充值**:对接链上或托管充值接口 +2. **多链**:扩展 networks 列表,支持更多网络 +3. **历史记录**:展示最近充值记录 diff --git a/docs/components/HorizontalProgressBar.md b/docs/components/HorizontalProgressBar.md new file mode 100644 index 0000000..d6bb2c0 --- /dev/null +++ b/docs/components/HorizontalProgressBar.md @@ -0,0 +1,34 @@ +# HorizontalProgressBar.vue + +**路径**:`src/components/HorizontalProgressBar.vue` + +## 功能用途 + +横向进度条,用于订单簿深度展示等场景。根据 `value`/`max` 计算百分比宽度,支持自定义轨道与填充样式。 + +## Props + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| max | number | 100 | 最大值 | +| value | number | 0 | 当前值 | +| className | string | '' | 自定义类名 | +| trackStyle | object | {} | 轨道样式 | +| fillStyle | object | {} | 填充样式 | + +## 使用方式 + +```vue + +``` + +## 扩展方式 + +1. **动画**:增加 `transition` 或 `animation` 配置 +2. **渐变**:`fillStyle` 支持 `background: linear-gradient(...)` +3. **垂直模式**:增加 `vertical` prop,切换为纵向进度条 diff --git a/docs/components/MarketCard.md b/docs/components/MarketCard.md new file mode 100644 index 0000000..f942b68 --- /dev/null +++ b/docs/components/MarketCard.md @@ -0,0 +1,59 @@ +# MarketCard.vue + +**路径**:`src/components/MarketCard.vue` + +## 功能用途 + +首页事件卡片组件,展示市场标题、概率、Yes/No 或 Up/Down 按钮、多选项轮播。支持单一(single)与多选项(multi)两种展示类型,点击可跳转交易详情或直接发起交易。 + +## Props + +| 属性 | 类型 | 说明 | +|------|------|------| +| id | string | 事件 ID | +| marketTitle | string | 市场标题 | +| chanceValue | number | 概率值(0–100) | +| marketInfo | string | 如 "$1.2k Vol." | +| imageUrl | string | 图片 URL | +| category | string | 分类 | +| expiresAt | string | 到期日 | +| displayType | 'single' \| 'multi' | 展示类型 | +| outcomes | EventCardOutcome[] | 多选项时每项数据 | +| yesLabel / noLabel | string | 按钮文案 | +| isNew | boolean | 是否显示 NEW 角标 | +| marketId | string | 市场 ID | +| clobTokenIds | string[] | 下单用 token ID | + +## 事件 + +- `navigate`:点击卡片跳转 +- `trade`:点击 Yes/No 发起交易,携带 market 信息 + +## 使用方式 + +```vue + +``` + +## 扩展方式 + +1. **新展示类型**:扩展 `displayType`,如 `compact`、`featured` +2. **收藏/分享**:增加图标按钮与对应事件 +3. **骨架屏**:增加 loading 态 props diff --git a/docs/components/OrderBook.md b/docs/components/OrderBook.md new file mode 100644 index 0000000..bb7e124 --- /dev/null +++ b/docs/components/OrderBook.md @@ -0,0 +1,27 @@ +# OrderBook.vue + +**路径**:`src/components/OrderBook.vue` + +## 功能用途 + +订单簿组件,展示 Asks(卖单)与 Bids(买单)列表,含价格、份额、累计总量,以及横向进度条表示深度。当前使用 mock 数据。 + +## 核心能力 + +- Trade Up / Trade Down Tab +- Asks、Bids 列表,带 `HorizontalProgressBar` 深度条 +- Last price、Spread 展示 + +## 使用方式 + +```vue + +``` + +当前为展示组件,无 props。后续可扩展为接收 `marketId` 等,从接口或 WebSocket 获取真实数据。 + +## 扩展方式 + +1. **真实数据**:接收 `asks`、`bids` props,或内部根据路由/context 拉取 +2. **WebSocket**:订阅订单簿推送,实时更新 +3. **点击下单**:点击某行价格时,将价格传入 TradeComponent diff --git a/docs/components/TradeComponent.md b/docs/components/TradeComponent.md new file mode 100644 index 0000000..6d3dbe8 --- /dev/null +++ b/docs/components/TradeComponent.md @@ -0,0 +1,39 @@ +# TradeComponent.vue + +**路径**:`src/components/TradeComponent.vue` + +## 功能用途 + +交易核心组件,支持 Buy/Sell、Market/Limit、Merge/Split。根据 `market` 与 `initialOption` 展示 Yes/No 或 Up/Down 价格,计算 Total、To win、You'll receive 等,并调用 `pmOrderPlace`、`pmMarketSplit`、`pmMarketMerge`。 + +## Props + +| 属性 | 类型 | 说明 | +|------|------|------| +| market | object | 市场信息,含 marketId、clobTokenIds、outcomes、outcomePrices 等 | +| initialOption | 'yes' \| 'no' | 初始选中的选项 | +| embeddedInSheet | boolean | 是否嵌入底部弹窗(移动端) | + +## 核心能力 + +- Buy/Sell Tab 切换 +- Market/Limit 类型、Merge/Split 菜单 +- 余额不足时 Buy 显示 Deposit 按钮 +- 25%/50%/Max 快捷份额 +- 调用 market API 下单、Split、Merge + +## 使用方式 + +```vue + +``` + +## 扩展方式 + +1. **Limit 单**:完善 Limit 模式下的价格输入与下单逻辑 +2. **订单确认**:增加确认弹窗 +3. **滑点设置**:增加滑点配置 diff --git a/docs/components/WithdrawDialog.md b/docs/components/WithdrawDialog.md new file mode 100644 index 0000000..75e8943 --- /dev/null +++ b/docs/components/WithdrawDialog.md @@ -0,0 +1,30 @@ +# WithdrawDialog.vue + +**路径**:`src/components/WithdrawDialog.vue` + +## 功能用途 + +提现弹窗,支持输入金额、选择网络、选择提现目标(Connected wallet / Custom address)。 + +## Props + +| 属性 | 类型 | 说明 | +|------|------|------| +| modelValue | boolean | v-model 控制显隐 | +| balance | string | 当前余额展示 | + +## 事件 + +- `update:modelValue`:关闭时更新 + +## 使用方式 + +```vue + +``` + +## 扩展方式 + +1. **真实提现**:对接提现接口,校验余额与地址 +2. **手续费**:展示网络手续费与到账金额 +3. **限额**:增加单笔/每日限额校验 diff --git a/docs/composables/useSearchHistory.md b/docs/composables/useSearchHistory.md new file mode 100644 index 0000000..357135f --- /dev/null +++ b/docs/composables/useSearchHistory.md @@ -0,0 +1,37 @@ +# useSearchHistory.ts + +**路径**:`src/composables/useSearchHistory.ts` + +## 功能用途 + +搜索历史组合式函数,将关键词持久化到 localStorage(键 `polyclient_search_history`),最多保留 10 条,去重且新词置顶。 + +## 核心能力 + +- `list`:只读的搜索历史数组 +- `add(keyword)`:添加关键词,去重并限制数量 +- `remove(index)`:删除指定索引 +- `clearAll`:清空全部 + +## 使用方式 + +```typescript +import { useSearchHistory } from '@/composables/useSearchHistory' + +const searchHistory = useSearchHistory() + +// 提交搜索时 +searchHistory.add(searchKeyword) + +// 展示历史 +const searchHistoryList = searchHistory.list.value + +// 清空 +searchHistory.clearAll() +``` + +## 扩展方式 + +1. **分类历史**:扩展为 `useSearchHistory(category)`,按分类存储 +2. **同步服务端**:在 `add` 时调用接口同步到后端 +3. **最大条数**:修改 `MAX_HISTORY` 常量 diff --git a/docs/config/package.md b/docs/config/package.md new file mode 100644 index 0000000..4d12817 --- /dev/null +++ b/docs/config/package.md @@ -0,0 +1,31 @@ +# package.json + +**路径**:`package.json` + +## 功能用途 + +项目依赖与脚本定义。 + +## 主要脚本 + +| 命令 | 说明 | +|------|------| +| npm run dev | 启动开发服务器 | +| npm run build | 类型检查 + 构建 | +| npm run deploy | 打包并通过 SSH 部署 | +| npm run preview | 预览构建产物 | +| npm run test:unit | Vitest 单测 | +| npm run test:e2e | Playwright E2E | +| npm run format | Prettier 格式化 | + +## 核心依赖 + +- Vue 3、Vue Router 5、Pinia、Vuetify 4 +- ethers、siwe(钱包登录) +- echarts(图表) +- @mdi/font(图标) + +## 扩展方式 + +- 新增脚本:在 `scripts` 中增加 +- 新增依赖:`npm install xxx` 或手动编辑后 `npm install` diff --git a/docs/config/vite.md b/docs/config/vite.md new file mode 100644 index 0000000..37af6d0 --- /dev/null +++ b/docs/config/vite.md @@ -0,0 +1,19 @@ +# vite.config.ts + +**路径**:`vite.config.ts` + +## 功能用途 + +Vite 7 构建配置,包含路径别名、Vue 插件、Node polyfills(用于 ethers、SIWE 等)、开发服务器 host。 + +## 关键配置 + +- `resolve.alias`:`@` → `./src` +- `vite-plugin-node-polyfills`:解决 SIWE 等库的 Node 兼容 +- `server.host: true`:监听 0.0.0.0,支持局域网访问 + +## 扩展方式 + +1. **环境变量**:在 `define` 中注入 `import.meta.env.XXX` +2. **代理**:`server.proxy` 解决跨域 +3. **构建优化**:`build.rollupOptions` 分包、压缩 diff --git a/docs/core/App.md b/docs/core/App.md new file mode 100644 index 0000000..f779ff9 --- /dev/null +++ b/docs/core/App.md @@ -0,0 +1,20 @@ +# App.vue + +**路径**:`src/App.vue` + +## 功能用途 + +根组件,包含全局 AppBar、主内容区(router-view)。AppBar 含返回按钮、标题、登录/余额/头像菜单,主内容区使用 keep-alive 缓存 Home。 + +## 核心能力 + +- 顶部导航栏:返回、PolyMarket 标题、Login 或余额+头像菜单 +- 登录态:`userStore.isLoggedIn` 控制展示 +- 挂载时:若已登录,拉取用户信息与余额 +- keep-alive:`include="['Home']"` 缓存首页 + +## 扩展方式 + +1. **多级导航**:根据路由深度调整返回逻辑 +2. **主题切换**:增加亮/暗模式切换 +3. **多语言**:接入 i18n 插件 diff --git a/docs/core/main.md b/docs/core/main.md new file mode 100644 index 0000000..b0d4856 --- /dev/null +++ b/docs/core/main.md @@ -0,0 +1,17 @@ +# main.ts + +**路径**:`src/main.ts` + +## 功能用途 + +应用入口,创建 Vue 实例并挂载 Pinia、Router、Vuetify 插件。 + +## 使用方式 + +由 `index.html` 中的脚本加载,无需手动调用。 + +## 扩展方式 + +1. **全局错误处理**:`app.config.errorHandler` +2. **全局属性**:`app.config.globalProperties` +3. **新插件**:`app.use(plugin)` 注册 diff --git a/docs/core/router.md b/docs/core/router.md new file mode 100644 index 0000000..ec4cc1f --- /dev/null +++ b/docs/core/router.md @@ -0,0 +1,30 @@ +# router/index.ts + +**路径**:`src/router/index.ts` + +## 功能用途 + +Vue Router 配置,定义路由表与滚动行为。 + +## 路由表 + +| path | name | component | +|------|------|-----------| +| / | home | Home | +| /trade | trade | Trade | +| /login | login | Login | +| /trade-detail/:id | trade-detail | TradeDetail | +| /event/:id/markets | event-markets | EventMarkets | +| /wallet | wallet | Wallet | + +## 滚动行为 + +- 有 `savedPosition` 且来自已命名路由:恢复位置 +- 有 `to.hash`:滚动到锚点 +- 否则:滚动到顶部 + +## 扩展方式 + +1. **路由守卫**:`beforeEach` 做鉴权、重定向 +2. **懒加载**:`component: () => import('./views/Home.vue')` +3. **meta**:为路由增加 `meta.requiresAuth` 等 diff --git a/docs/core/vuetify.md b/docs/core/vuetify.md new file mode 100644 index 0000000..9edd9a0 --- /dev/null +++ b/docs/core/vuetify.md @@ -0,0 +1,18 @@ +# plugins/vuetify.ts + +**路径**:`src/plugins/vuetify.ts` + +## 功能用途 + +Vuetify 4 插件配置,注册组件、指令、主题。引入 VPullToRefresh(下拉刷新)与 MDI 图标。 + +## 主题 + +- `light`:默认主题,含 primary、secondary、accent 等 +- `dark`:暗色主题 + +## 扩展方式 + +1. **自定义主题**:在 `themes` 中增加新主题,或修改现有颜色 +2. **新组件**:从 `vuetify/labs` 引入并注册 +3. **RTL**:配置 `rtl: true` 支持从右到左布局 diff --git a/docs/stores/counter.md b/docs/stores/counter.md new file mode 100644 index 0000000..54bc49a --- /dev/null +++ b/docs/stores/counter.md @@ -0,0 +1,21 @@ +# counter.ts (Store) + +**路径**:`src/stores/counter.ts` + +## 功能用途 + +示例 Pinia Store,用于演示 setup 写法:`count`、`doubleCount`、`increment`。项目中可能仅用于测试或示例,业务可忽略。 + +## 使用方式 + +```typescript +import { useCounterStore } from '@/stores/counter' + +const counter = useCounterStore() +counter.increment() +console.log(counter.doubleCount) +``` + +## 扩展方式 + +可删除或改为业务相关 demo(如示例数据 store)。 diff --git a/docs/stores/user.md b/docs/stores/user.md new file mode 100644 index 0000000..97b2d34 --- /dev/null +++ b/docs/stores/user.md @@ -0,0 +1,43 @@ +# user.ts (Store) + +**路径**:`src/stores/user.ts` + +## 功能用途 + +用户登录态与基础信息的 Pinia Store,管理 token、user、余额,并提供鉴权请求头。登录数据持久化到 localStorage(键 `poly-user`)。 + +## 核心能力 + +- `token`、`user`:登录凭证与用户信息 +- `isLoggedIn`、`avatarUrl`:派生状态 +- `balance`:USDC 余额显示(如 "0.00") +- `setUser`:设置登录数据并持久化 +- `logout`:清空并清除持久化 +- `getAuthHeaders`:返回 `{ 'x-token', 'x-user-id' }`,未登录时返回 `undefined` +- `fetchUserInfo`、`fetchUsdcBalance`:拉取并更新用户信息与余额 + +## 使用方式 + +```typescript +import { useUserStore } from '@/stores/user' + +const userStore = useUserStore() + +// 登录后设置 +userStore.setUser({ token: 'xxx', user: { id: 1, nickName: 'User' } }) + +// 鉴权请求 +const headers = userStore.getAuthHeaders() +if (headers) { + await someApiCall(undefined, { headers }) +} + +// 刷新余额 +await userStore.fetchUsdcBalance() +``` + +## 扩展方式 + +1. **多端登录**:扩展 `setUser` 支持多设备 token 管理 +2. **Token 刷新**:在 `getAuthHeaders` 或请求拦截器中加入 refresh 逻辑 +3. **登出回调**:在 `logout` 中增加清理逻辑(如取消订阅、重置其他 store) diff --git a/docs/views/EventMarkets.md b/docs/views/EventMarkets.md new file mode 100644 index 0000000..2951375 --- /dev/null +++ b/docs/views/EventMarkets.md @@ -0,0 +1,18 @@ +# EventMarkets.vue + +**路径**:`src/views/EventMarkets.vue` +**路由**:`/event/:id/markets`,name: `event-markets` + +## 功能用途 + +事件下的市场列表页,展示某个 Event 的多个 Market(如 NFL 多支队伍),支持选择并跳转交易详情。 + +## 使用方式 + +- 从首页或详情进入,路由 `/event/123/markets` +- 路由参数 `id` 为 Event ID + +## 扩展方式 + +- 增加市场筛选、排序 +- 与 TradeDetail 联动,支持从市场列表直接进入指定 market 的交易 diff --git a/docs/views/Home.md b/docs/views/Home.md new file mode 100644 index 0000000..7022da5 --- /dev/null +++ b/docs/views/Home.md @@ -0,0 +1,27 @@ +# Home.vue + +**路径**:`src/views/Home.vue` +**路由**:`/`,name: `home` + +## 功能用途 + +首页,展示分类 Tab、搜索、事件卡片列表。支持三层分类、下拉刷新、无限滚动、搜索历史,卡片支持单一/多选项展示。 + +## 核心能力 + +- 分类:第一层 Tab、第二层图标、第三层 Tab,从 `getPmTagMain` 获取 +- 搜索:展开浮层、历史记录、`useSearchHistory` +- 列表:`getPmEventPublic` 分页、`mapEventItemToCard` 映射、`MarketCard` 渲染 +- 缓存:`eventListCache` 切换页面时复用,下拉刷新时清空 +- Keep-alive:`Home` 被 include,切换回来时保留状态 + +## 使用方式 + +- 访问 `/` 即可进入 +- 分类切换、搜索、下拉刷新、滚动加载均自动工作 + +## 扩展方式 + +1. **新增筛选**:在搜索浮层旁增加筛选按钮,修改 `getPmEventPublic` 的 params +2. **骨架屏**:在 loading 时展示 `v-skeleton-loader` +3. **空状态**:列表为空时展示空状态插画与文案 diff --git a/docs/views/Login.md b/docs/views/Login.md new file mode 100644 index 0000000..5069ea8 --- /dev/null +++ b/docs/views/Login.md @@ -0,0 +1,25 @@ +# Login.vue + +**路径**:`src/views/Login.vue` +**路由**:`/login`,name: `login` + +## 功能用途 + +登录页,支持邮箱+密码登录与钱包连接(SIWE)。登录成功后调用 `userStore.setUser` 并跳转首页。 + +## 核心能力 + +- 邮箱密码:表单校验,调用登录接口 +- 钱包连接:ethers + SIWE,签名后换取 token +- 错误提示:`errorMessage` 展示 + +## 使用方式 + +- 未登录时点击 AppBar 的 Login 进入 +- 登录成功后自动跳转 `/` + +## 扩展方式 + +1. **注册**:增加注册表单或跳转注册页(路由 `/register` 需在 router 中配置) +2. **忘记密码**:增加找回密码流程 +3. **社交登录**:接入 OAuth 等 diff --git a/docs/views/Trade.md b/docs/views/Trade.md new file mode 100644 index 0000000..ac188a0 --- /dev/null +++ b/docs/views/Trade.md @@ -0,0 +1,17 @@ +# Trade.vue + +**路径**:`src/views/Trade.vue` +**路由**:`/trade`,name: `trade` + +## 功能用途 + +交易入口页,展示可交易市场列表或快捷入口,通常作为交易功能的聚合入口。 + +## 使用方式 + +访问 `/trade` 进入。 + +## 扩展方式 + +- 可增加市场筛选、推荐市场、最近交易等模块 +- 可与 TradeDetail 联动,支持从列表直接跳转详情并预选市场 diff --git a/docs/views/TradeDetail.md b/docs/views/TradeDetail.md new file mode 100644 index 0000000..4391235 --- /dev/null +++ b/docs/views/TradeDetail.md @@ -0,0 +1,28 @@ +# TradeDetail.vue + +**路径**:`src/views/TradeDetail.vue` +**路由**:`/trade-detail/:id`,name: `trade-detail` + +## 功能用途 + +交易详情页,展示单个市场的分时图、订单簿、Comments/Top Holders/Activity 标签页,以及右侧交易组件(Buy/Sell、Merge/Split)。支持桌面端与移动端布局,移动端使用底部 Yes/No 栏 + 弹窗。 + +## 核心能力 + +- 分时图:ECharts 渲染,支持 Past、时间粒度切换 +- 订单簿:`OrderBook` 组件 +- 交易:`TradeComponent`,传入 `market`、`initialOption` +- 移动端:底部栏 + `v-bottom-sheet` 嵌入 `TradeComponent` +- Merge/Split:通过 `TradeComponent` 或底部菜单触发 + +## 使用方式 + +- 从首页卡片点击进入,或直接访问 `/trade-detail/123` +- 路由参数 `id` 为 Event ID,用于 `findPmEvent` + +## 扩展方式 + +1. **实时数据**:订单簿、分时图接入 WebSocket +2. **Comments**:对接评论接口,替换 placeholder +3. **Top Holders**:对接持仓接口 +4. **Activity**:对接交易活动接口,替换 mock 数据 diff --git a/docs/views/Wallet.md b/docs/views/Wallet.md new file mode 100644 index 0000000..fb32835 --- /dev/null +++ b/docs/views/Wallet.md @@ -0,0 +1,26 @@ +# Wallet.vue + +**路径**:`src/views/Wallet.vue` +**路由**:`/wallet`,name: `wallet` + +## 功能用途 + +钱包页,展示 Portfolio、Profit/Loss、Positions、Open orders、History。支持 Deposit/Withdraw 弹窗、搜索、筛选(如 Close Losses)。 + +## 核心能力 + +- Portfolio 卡片:余额、Deposit/Withdraw 按钮 +- Profit/Loss 卡片:时间范围切换、ECharts 图表 +- Tab:Positions、Open orders、History +- DepositDialog、WithdrawDialog 组件 + +## 使用方式 + +- 登录后点击 AppBar 余额或头像菜单进入 +- 路由 `/wallet` + +## 扩展方式 + +1. **真实数据**:Positions、Orders、History 对接接口 +2. **导出**:History 支持导出 CSV +3. **筛选**:按市场、时间、盈亏等筛选