commit 498849dc1e57b657bde3967b48beea348fbdd187 Author: steve <1050403040@qq.com> Date: Fri Aug 22 17:30:53 2025 +0800 Initial public release diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..671e312 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,25 @@ +module.exports = { + root: true, + env: { + node: true, + browser: true, + es2022: true + }, + extends: [ + 'eslint:recommended', + 'plugin:vue/vue3-recommended' + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module' + }, + rules: { + 'no-console': 'warn', + 'no-debugger': 'warn', + 'vue/multi-word-component-names': 'off', + 'no-unused-vars': 'warn' + }, + globals: { + globalThis: 'readonly' + } +}; \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb26859 --- /dev/null +++ b/.gitignore @@ -0,0 +1,64 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Production builds +dist/ +build/ + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# nyc test coverage +.nyc_output + +# Dependency directories +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# Local cache +.cache/ + +# Temporary folders +tmp/ +temp/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bc54775 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,70 @@ +# 更新日志 + +## [2.0.0] - 2024-01-20 + +### 🎉 重大更新 - Token管理系统重构 + +#### ✨ 新增功能 +- **Base64 Token导入**: 支持多种格式的Base64编码Token解析 +- **可视化Token管理**: 名称-Token列表形式管理多个游戏角色 +- **WebSocket连接管理**: 自动建立和监控WebSocket连接状态 +- **批量操作功能**: 导入/导出、清理过期Token等批量功能 +- **响应式Token界面**: 完美适配桌面和移动设备的Token管理界面 + +#### 🗑️ 移除功能 +- **登录注册系统**: 完全移除传统的用户认证流程 +- **用户管理**: 不再需要用户账户系统 +- **API依赖**: 移除所有后端接口依赖 + +#### 🔄 重大变更 +- **入口页面**: 从登录页面改为Token导入页面 (`/tokens`) +- **路由结构**: 重构路由,旧路由自动重定向到Token管理 +- **数据结构**: 全新的Token数据结构,支持自定义名称和完整信息 +- **访问控制**: 基于Token存在性而非用户认证状态 + +#### 🛠️ 技术改进 +- **本地存储**: 所有数据完全本地化存储 +- **智能解析**: 自动识别和解析各种Base64格式 +- **连接监控**: 实时WebSocket连接状态显示 +- **容错处理**: 完善的错误处理和用户提示 + +#### 📱 用户体验 +- **简化流程**: 无需注册登录,直接导入Token使用 +- **直观管理**: 卡片式Token列表,状态一目了然 +- **快速操作**: 一键选择、连接、管理Token +- **数据安全**: 本地存储,Token信息脱敏显示 + +--- + +## [1.x.x] - 历史版本 + +### 特性 +- 基于用户认证的传统系统 +- API接口依赖的数据管理 +- 游戏角色CRUD操作 +- 日常任务管理功能 + +--- + +## 升级指南 + +### 从1.x版本升级到2.0 +1. **数据迁移**: + - 导出现有游戏角色数据 + - 获取每个角色对应的Token + - 将Token转换为Base64格式后导入新系统 + +2. **使用变更**: + - 不再需要注册登录 + - 直接访问 `/tokens` 页面导入Token + - 通过Token名称管理多个游戏角色 + +3. **功能对照**: + - 游戏角色管理 → Token管理 + - 用户认证 → Token导入 + - 角色选择 → Token选择 + +### 兼容性说明 +- 旧版本路由会自动重定向到新系统 +- 本地存储数据需要手动迁移 +- WebSocket连接方式保持兼容 \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..3619628 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,218 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a Vue 3 Token Manager application for XYZW game automation. The application manages game tokens via Base64 decoding, establishes WebSocket connections, and provides a visual interface for token management and game automation. + +## Development Commands + +### Core Commands +```bash +# Development server (port 3000) +npm run dev + +# Production build +npm run build + +# Preview production build +npm run preview + +# Lint Vue, JS, TS files with auto-fix +npm run lint + +# Format code (Prettier) +npm run format +``` + +### Installation +```bash +npm install +``` + +## Architecture Overview + +### Core System Design +The application is built around a **token-centric architecture** that replaces traditional user authentication: + +1. **Token Management System**: Base64-encoded tokens are imported, decoded, and stored locally +2. **WebSocket Connection Layer**: Automatic WebSocket connections using BON protocol for game communication +3. **Local-First Storage**: All data stored in browser localStorage, no backend dependencies +4. **Protocol Layer**: Custom BON (Binary Object Notation) protocol for game message encoding/decoding + +### Key Architectural Components + +#### 1. Token Store (`src/stores/tokenStore.js`) +Central state management for token operations: +- **Token Lifecycle**: Import → Parse → Store → Select → Connect +- **Base64 Parsing**: Supports multiple formats (JSON, plain text, prefixed) +- **WebSocket Management**: Automatic connection establishment and status tracking +- **Data Persistence**: localStorage with cross-session state recovery + +#### 2. BON Protocol Implementation (`src/utils/bonProtocol.js`) +Custom binary protocol for game communication: +- **Message Encoding/Decoding**: Binary serialization with type safety +- **Game Message Templates**: Predefined message structures for common operations +- **Encryption Layer**: Multi-channel encryption with XOR-based security +- **WebSocket Message Handling**: Structured message parsing and creation + +#### 3. WebSocket Client (`src/utils/xyzwWebSocket.js`) +Enhanced WebSocket client based on reference implementation: +- **Command Registry**: Pre-registered game commands with default parameters +- **Queue Management**: Automatic message queuing and batch processing +- **Connection Management**: Auto-reconnection, heartbeat, and status monitoring +- **Promise Support**: Both fire-and-forget and request-response patterns + +#### 4. Router Architecture (`src/router/index.js`) +Token-aware navigation system: +- **Access Control**: Route guards based on token availability +- **Smart Redirects**: Automatic routing based on token state +- **Legacy Compatibility**: Redirects from old authentication routes + +### Data Flow Architecture + +``` +Token Import → Base64 Decode → Local Storage → Token Selection → WebSocket Connection → Game Communication + ↑ ↓ ↓ ↓ ↓ ↓ + User Input JSON/String Token Store Router Guards BON Protocol Game Messages +``` + +### State Management Pattern + +**Pinia Store Structure**: +- `tokenStore`: Primary token management and WebSocket connections +- `auth`: Simplified authentication state (legacy compatibility) +- `gameRoles`: Role-specific game data management +- `localTokenManager`: Low-level token persistence utilities + +## Key Framework Features + +### Token Data Structure +```javascript +{ + id: "token_xxx", // Unique identifier + name: "主号战士", // User-defined name + token: "base64_token", // Actual token string + wsUrl: "wss://...", // WebSocket endpoint + server: "风云服", // Game server + level: 85, // Character level + profession: "战士", // Character class + createdAt: "2024-...", // Creation timestamp + lastUsed: "2024-...", // Last usage timestamp + isActive: true // Activation status +} +``` + +### WebSocket Connection Flow +1. **Token Selection**: User selects token from management interface +2. **Base64 Parsing**: Extract actual game token from Base64 string +3. **URL Construction**: Build WebSocket URL with token parameter +4. **Client Creation**: Create `XyzwWebSocketClient` instance with game utilities +5. **Connection Establishment**: Automatic connection with heartbeat and queue setup +6. **Message Handling**: Bi-directional communication using command registry + +### BON Protocol Message Format +```javascript +{ + cmd: "command_name", // Command identifier + body: encodedData, // BON-encoded message body + ack: 0, // Acknowledgment number + seq: 12345, // Sequence number + time: 1234567890 // Timestamp +} +``` + +## Project Structure + +``` +src/ +├── components/ +│ ├── TokenManager.vue # Primary token management interface +│ ├── DailyTaskCard.vue # Game task visualization +│ ├── MessageTester.vue # Protocol debugging tool +│ └── WebSocketTester.vue # Connection testing utility +├── stores/ +│ ├── tokenStore.js # Core token management state +│ ├── auth.js # Legacy authentication compatibility +│ ├── gameRoles.js # Role-specific game data +│ └── localTokenManager.js # Token persistence utilities +├── utils/ +│ ├── bonProtocol.js # BON protocol implementation +│ ├── gameCommands.js # Game-specific command helpers +│ └── wsAgent.js # WebSocket connection management +├── views/ +│ ├── TokenImport.vue # Token import/management page +│ ├── Dashboard.vue # Main game control interface +│ ├── DailyTasks.vue # Task management interface +│ └── Profile.vue # User preferences and settings +└── router/index.js # Token-aware routing configuration +``` + +## Development Guidelines + +### Working with Tokens +- Always use the `tokenStore` for token operations +- Test Base64 parsing with various input formats +- Verify WebSocket connections after token operations +- Handle token validation errors gracefully + +### WebSocket Development +- Use the new `XyzwWebSocketClient` class for WebSocket connections +- Send messages with `client.send(cmd, params)` or `client.sendWithPromise(cmd, params)` +- Monitor connection status via `tokenStore.getWebSocketStatus(tokenId)` +- WebSocket client includes automatic reconnection, queued sending, and heartbeat management +- Built-in command registry supports game-specific message formats + +### State Management +- Access token data through computed properties (`selectedToken`, `hasTokens`) +- Use reactive WebSocket status via `getWebSocketStatus(tokenId)` +- Persist critical state changes to localStorage automatically +- Handle cross-session state recovery on application startup + +### Protocol Implementation +- Follow BON encoding/decoding patterns for message handling +- Use predefined `GameMessages` templates for common operations +- Implement proper type checking for message validation +- Handle protocol errors with fallback to JSON parsing + +## Configuration Notes + +### Vite Configuration +- Path aliases configured for clean imports (`@/`, `@components/`, etc.) +- Development server runs on port 3000 +- Proxy configured for `/api` routes to `http://xyzw.my` +- SCSS preprocessing with global variables + +### Browser Compatibility +- Requires modern browser with WebSocket support +- localStorage required for token persistence +- Base64 decoding and TextEncoder/TextDecoder APIs used + +### Security Considerations +- All tokens stored locally in browser storage +- WebSocket connections use WSS encryption +- BON protocol includes basic XOR encryption +- Token display masked (shows only first/last 4 characters) + +## Testing and Debugging + +### Built-in Testing Tools +- **MessageTester.vue**: Test BON protocol message encoding/decoding +- **WebSocketTester.vue**: Debug WebSocket connections and message flow +- Browser DevTools WebSocket monitoring for connection debugging + +### Common Development Tasks +- Test token import with various Base64 formats +- Verify WebSocket connection establishment with new client architecture +- Debug game command sending using command registry +- Test Promise-based message responses +- Validate route guards and navigation flow +- Test localStorage persistence across sessions + +### Key API Changes +- `tokenStore.sendMessage(tokenId, cmd, params)` - Send game commands +- `tokenStore.sendMessageWithPromise(tokenId, cmd, params)` - Send with response +- `tokenStore.getWebSocketClient(tokenId)` - Get client instance +- WebSocket client provides `send()`, `sendWithPromise()`, and game-specific methods +- Built-in commands: `getRoleInfo()`, `signIn()`, `claimDailyReward()`, etc. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5fe8aaa --- /dev/null +++ b/LICENSE @@ -0,0 +1,42 @@ +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License + +Copyright (c) 2024 XYZW Team + +This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. + +You are free to: +- Share — copy and redistribute the material in any medium or format +- Adapt — remix, transform, and build upon the material + +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: +- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. +- NonCommercial — You may not use the material for commercial purposes. +- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. +- No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. + +Notices: +You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. + +No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. + +For the full legal text of this license, please visit: +https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode + +--- + +ADDITIONAL TERMS FOR THIS SOFTWARE: + +This software is specifically designed for educational and personal use only. +Commercial use, including but not limited to: +- Selling this software or derivative works +- Using this software in commercial gaming operations +- Integrating this software into commercial products or services +- Using this software to generate revenue in any form + +is strictly prohibited without explicit written permission from the copyright holders. + +The software is provided "AS IS", without warranty of any kind, express or implied, +including but not limited to the warranties of merchantability, fitness for a +particular purpose and noninfringement. \ No newline at end of file diff --git a/LOCAL_TOKEN_CHANGES.md b/LOCAL_TOKEN_CHANGES.md new file mode 100644 index 0000000..d3e9a9d --- /dev/null +++ b/LOCAL_TOKEN_CHANGES.md @@ -0,0 +1,143 @@ +# 本地Token存储重构说明 + +本次重构完全移除了所有API接口请求,改为使用本地存储管理用户认证和游戏角色token。 + +## 主要变更 + +### 1. 新增文件 + +#### `/src/stores/localTokenManager.js` +- 完整的本地token管理系统 +- 支持用户认证token和游戏角色token管理 +- 内置WebSocket连接管理 +- 支持token导入/导出、过期清理等功能 + +#### `/src/components/TokenManager.vue` +- Token管理界面组件 +- 可视化显示所有token状态 +- 支持WebSocket连接控制 +- 提供批量操作功能 + +### 2. 修改的文件 + +#### `/src/stores/auth.js` +- **移除**: 所有`api.auth.*`调用 +- **新增**: 本地认证逻辑,模拟用户登录 +- **集成**: localTokenStore进行token管理 + +#### `/src/stores/gameRoles.js` +- **移除**: 所有`api.gameRoles.*`调用 +- **新增**: 本地角色管理,自动生成游戏token +- **集成**: 角色选择时自动建立WebSocket连接 + +#### `/src/views/DailyTasks.vue` +- **移除**: `api.dailyTasks.*`调用 +- **新增**: 本地模拟任务数据生成 +- **集成**: 通过WebSocket执行任务(模拟) + +#### `/src/views/Profile.vue` +- **新增**: TokenManager组件,提供token管理界面 + +## 核心功能 + +### 用户认证 +```javascript +// 本地认证,无需API调用 +const result = await authStore.login({ username, password }) +``` + +### 游戏角色管理 +```javascript +// 添加角色时自动生成游戏token +const result = await gameRolesStore.addGameRole(roleData) +// 自动生成: roleId, gameToken, wsUrl +``` + +### WebSocket连接 +```javascript +// 选择角色时自动建立WebSocket连接 +gameRolesStore.selectRole(role) +// 使用本地存储的token建立连接 + +// 手动控制连接 +localTokenStore.createWebSocketConnection(roleId, token, wsUrl) +localTokenStore.closeWebSocketConnection(roleId) +``` + +### Token管理 +```javascript +// 添加游戏token +localTokenStore.addGameToken(roleId, tokenData) + +// 获取token +const tokenData = localTokenStore.getGameToken(roleId) + +// 导出所有token +const backup = localTokenStore.exportTokens() + +// 导入token +localTokenStore.importTokens(backupData) +``` + +## 数据结构 + +### 游戏Token数据结构 +```javascript +{ + token: "game_token_xxx", // 游戏token + roleId: "role_xxx", // 角色ID + roleName: "角色名称", // 角色名称 + server: "服务器名", // 服务器 + wsUrl: "wss://game.xxx/ws", // WebSocket URL + createdAt: "2024-01-01T00:00:00Z", + lastUsed: "2024-01-01T00:00:00Z", + isActive: true +} +``` + +### WebSocket连接状态 +```javascript +{ + connection: WebSocket, // WebSocket连接对象 + status: "connected", // 连接状态 + roleId: "role_xxx", // 关联角色ID + connectedAt: "2024-01-01T00:00:00Z" +} +``` + +## 使用说明 + +### 1. 登录 +- 用户名/密码任意输入即可本地认证 +- 自动生成用户token并保存 + +### 2. 添加游戏角色 +- 填写角色信息后自动生成: + - 角色ID + - 游戏token + - WebSocket连接URL + +### 3. 管理Token +- 访问"个人设置"页面查看Token管理器 +- 可以查看、编辑、删除、导出/导入token +- 可以手动控制WebSocket连接 + +### 4. 执行任务 +- 选择角色后自动建立WebSocket连接 +- 执行任务通过WebSocket发送指令(模拟) +- 所有操作记录保存在本地 + +## 优势 + +1. **完全离线**: 无需任何服务器接口 +2. **数据安全**: 所有数据存储在本地 +3. **功能完整**: 保留原有所有功能 +4. **易于扩展**: 模块化设计,便于添加新功能 +5. **WebSocket支持**: 内置完整的WebSocket连接管理 + +## 注意事项 + +1. 所有数据存储在浏览器localStorage中 +2. 清除浏览器数据会丢失所有token +3. 建议定期使用导出功能备份token数据 +4. WebSocket连接使用模拟URL,需要根据实际情况修改 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..458f6e2 --- /dev/null +++ b/README.md @@ -0,0 +1,477 @@ +# XYZW Web Helper + +
+ +![XYZW Logo](public/xiaoyugan.png) + +**🎮 咸鱼自动化web平台** + +[![Vue 3](https://img.shields.io/badge/Vue-3.4+-4FC08D?style=flat&logo=vue.js&logoColor=white)](https://vuejs.org/) +[![Vite](https://img.shields.io/badge/Vite-5.0+-646CFF?style=flat&logo=vite&logoColor=white)](https://vitejs.dev/) +[![Naive UI](https://img.shields.io/badge/Naive%20UI-2.38+-18A058?style=flat&logo=vue.js&logoColor=white)](https://www.naiveui.com/) +[![WebSocket](https://img.shields.io/badge/WebSocket-BON%20Protocol-FF6B6B?style=flat&logo=websocket&logoColor=white)](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) +[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg?style=flat)](https://creativecommons.org/licenses/by-nc-sa/4.0/) + +基于Vue 3 + Vite的现代化XYZW游戏辅助工具,支持Token管理、WebSocket通信、游戏自动化等功能。 + +
+ +--- + +## ✨ 核心特性 + +### 🔐 Token管理系统 +- **Base64解码支持**:自动识别和解析多种Base64格式的游戏Token +- **多角色管理**:同时管理多个游戏账号,支持角色信息展示 +- **本地存储**:安全的本地数据存储,无需后端服务器 +- **Token验证**:自动验证Token有效性和格式完整性 + +### 🌐 WebSocket通信 +- **BON协议支持**:内置Binary Object Notation协议编解码 +- **多重加密**:支持LX、X、XTM等多种加密方式 +- **自动重连**:智能断线重连机制,确保连接稳定 +- **消息队列**:内置消息队列系统,支持批量发送和响应处理 + +### 🎮 游戏功能 +- **日常任务管理**:自动化日常任务执行和奖励领取 +- **角色状态监控**:实时显示角色等级、职业、服务器等信息 +- **团队管理**:队伍状态查看和管理功能 +- **爬塔进度**:爬塔状态追踪和数据分析 + +### 🛠️ 开发工具 +- **消息测试器**:BON协议消息编码/解码测试工具 +- **WebSocket调试**:实时WebSocket连接和消息调试 +- **协议验证**:游戏协议消息格式验证工具 + +--- + +## 🏗️ 技术架构 + +### 前端技术栈 +``` +Vue 3.4+ # 渐进式JavaScript框架 +├── Composition API # Vue 3组合式API +├── + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7787006 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3586 @@ +{ + "name": "xyzw-token-manager", + "version": "2.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "xyzw-token-manager", + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "@vicons/ionicons5": "^0.12.0", + "@vicons/material": "^0.12.0", + "axios": "^1.6.0", + "lz4js": "^0.2.0", + "naive-ui": "^2.38.0", + "pinia": "^2.1.0", + "vue": "^3.4.0", + "vue-router": "^4.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@vitejs/plugin-vue": "^5.0.0", + "eslint": "^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "prettier": "^3.0.0", + "sass": "^1.69.0", + "typescript": "^5.0.0", + "vite": "^5.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@css-render/plugin-bem": { + "version": "0.15.14", + "resolved": "https://repo.huaweicloud.com/repository/npm/@css-render/plugin-bem/-/plugin-bem-0.15.14.tgz", + "integrity": "sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==", + "license": "MIT", + "peerDependencies": { + "css-render": "~0.15.14" + } + }, + "node_modules/@css-render/vue3-ssr": { + "version": "0.15.14", + "resolved": "https://repo.huaweicloud.com/repository/npm/@css-render/vue3-ssr/-/vue3-ssr-0.15.14.tgz", + "integrity": "sha512-//8027GSbxE9n3QlD73xFY6z4ZbHbvrOVB7AO6hsmrEzGbg+h2A09HboUyDgu+xsmj7JnvJD39Irt+2D0+iV8g==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.11" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "license": "Apache-2.0" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.3.tgz", + "integrity": "sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.3.tgz", + "integrity": "sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.3.tgz", + "integrity": "sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.3.tgz", + "integrity": "sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.3.tgz", + "integrity": "sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.3.tgz", + "integrity": "sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.3.tgz", + "integrity": "sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.3.tgz", + "integrity": "sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.3.tgz", + "integrity": "sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.3.tgz", + "integrity": "sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.3.tgz", + "integrity": "sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.3.tgz", + "integrity": "sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.3.tgz", + "integrity": "sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.3.tgz", + "integrity": "sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.3.tgz", + "integrity": "sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.3.tgz", + "integrity": "sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.3.tgz", + "integrity": "sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.3.tgz", + "integrity": "sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.3.tgz", + "integrity": "sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.3.tgz", + "integrity": "sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://repo.huaweicloud.com/repository/npm/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/@types/node/-/node-20.19.11.tgz", + "integrity": "sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vicons/ionicons5": { + "version": "0.12.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vicons/ionicons5/-/ionicons5-0.12.0.tgz", + "integrity": "sha512-Iy1EUVRpX0WWxeu1VIReR1zsZLMc4fqpt223czR+Rpnrwu7pt46nbnC2ycO7ItI/uqDLJxnbcMC7FujKs9IfFA==", + "license": "MIT" + }, + "node_modules/@vicons/material": { + "version": "0.12.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vicons/material/-/material-0.12.0.tgz", + "integrity": "sha512-chv1CYAl8P32P3Ycwgd5+vw/OFNc2mtkKdb1Rw4T5IJmKy6GVDsoUKV3N2l208HATn7CCQphZtuPDdsm7K2kmA==", + "license": "Apache 2.0" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/compiler-core/-/compiler-core-3.5.18.tgz", + "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@vue/shared": "3.5.18", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", + "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", + "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@vue/compiler-core": "3.5.18", + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.17", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", + "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/reactivity/-/reactivity-3.5.18.tgz", + "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/runtime-core/-/runtime-core-3.5.18.tgz", + "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz", + "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.18", + "@vue/runtime-core": "3.5.18", + "@vue/shared": "3.5.18", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/server-renderer/-/server-renderer-3.5.18.tgz", + "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18" + }, + "peerDependencies": { + "vue": "3.5.18" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/@vue/shared/-/shared-3.5.18.tgz", + "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/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/callsites": { + "version": "3.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/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/concat-map": { + "version": "0.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-render": { + "version": "0.15.14", + "resolved": "https://repo.huaweicloud.com/repository/npm/css-render/-/css-render-0.15.14.tgz", + "integrity": "sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "~0.8.0", + "csstype": "~3.0.5" + } + }, + "node_modules/css-render/node_modules/csstype": { + "version": "3.0.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", + "license": "MIT" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-tz": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/date-fns-tz/-/date-fns-tz-3.2.0.tgz", + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", + "license": "MIT", + "peerDependencies": { + "date-fns": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/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/entities": { + "version": "4.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "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://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/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.21.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", + "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/evtd": { + "version": "0.2.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/evtd/-/evtd-0.2.4.tgz", + "integrity": "sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "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.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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/glob": { + "version": "7.2.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/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/graphemer": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lz4js": { + "version": "0.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lz4js/-/lz4js-0.2.0.tgz", + "integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==", + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://repo.huaweicloud.com/repository/npm/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/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://repo.huaweicloud.com/repository/npm/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/minimatch": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/naive-ui": { + "version": "2.42.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/naive-ui/-/naive-ui-2.42.0.tgz", + "integrity": "sha512-c7cXR2YgOjgtBadXHwiWL4Y0tpGLAI5W5QzzHksOi22iuHXoSGMAzdkVTGVPE/PM0MSGQ/JtUIzCx2Y0hU0vTQ==", + "license": "MIT", + "dependencies": { + "@css-render/plugin-bem": "^0.15.14", + "@css-render/vue3-ssr": "^0.15.14", + "@types/katex": "^0.16.2", + "@types/lodash": "^4.14.198", + "@types/lodash-es": "^4.17.9", + "async-validator": "^4.2.5", + "css-render": "^0.15.14", + "csstype": "^3.1.3", + "date-fns": "^3.6.0", + "date-fns-tz": "^3.1.3", + "evtd": "^0.2.4", + "highlight.js": "^11.8.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "seemly": "^0.3.8", + "treemate": "^0.3.11", + "vdirs": "^0.1.8", + "vooks": "^0.2.12", + "vueuc": "^0.4.63" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "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.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.46.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/rollup/-/rollup-4.46.3.tgz", + "integrity": "sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.3", + "@rollup/rollup-android-arm64": "4.46.3", + "@rollup/rollup-darwin-arm64": "4.46.3", + "@rollup/rollup-darwin-x64": "4.46.3", + "@rollup/rollup-freebsd-arm64": "4.46.3", + "@rollup/rollup-freebsd-x64": "4.46.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.3", + "@rollup/rollup-linux-arm-musleabihf": "4.46.3", + "@rollup/rollup-linux-arm64-gnu": "4.46.3", + "@rollup/rollup-linux-arm64-musl": "4.46.3", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.3", + "@rollup/rollup-linux-ppc64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-gnu": "4.46.3", + "@rollup/rollup-linux-riscv64-musl": "4.46.3", + "@rollup/rollup-linux-s390x-gnu": "4.46.3", + "@rollup/rollup-linux-x64-gnu": "4.46.3", + "@rollup/rollup-linux-x64-musl": "4.46.3", + "@rollup/rollup-win32-arm64-msvc": "4.46.3", + "@rollup/rollup-win32-ia32-msvc": "4.46.3", + "@rollup/rollup-win32-x64-msvc": "4.46.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sass": { + "version": "1.90.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/sass/-/sass-1.90.0.tgz", + "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/seemly": { + "version": "0.3.10", + "resolved": "https://repo.huaweicloud.com/repository/npm/seemly/-/seemly-0.3.10.tgz", + "integrity": "sha512-2+SMxtG1PcsL0uyhkumlOU6Qo9TAQ/WyH7tthnPIOQB05/12jz9naq6GZ6iZ6ApVsO3rr2gsnTf3++OV63kE1Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/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/strip-ansi": { + "version": "6.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/treemate": { + "version": "0.3.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/treemate/-/treemate-0.3.11.tgz", + "integrity": "sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==", + "license": "MIT" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vdirs": { + "version": "0.1.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/vdirs/-/vdirs-0.1.8.tgz", + "integrity": "sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==", + "license": "MIT", + "dependencies": { + "evtd": "^0.2.2" + }, + "peerDependencies": { + "vue": "^3.0.11" + } + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://repo.huaweicloud.com/repository/npm/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vooks": { + "version": "0.2.12", + "resolved": "https://repo.huaweicloud.com/repository/npm/vooks/-/vooks-0.2.12.tgz", + "integrity": "sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==", + "license": "MIT", + "dependencies": { + "evtd": "^0.2.2" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue": { + "version": "3.5.18", + "resolved": "https://repo.huaweicloud.com/repository/npm/vue/-/vue-3.5.18.tgz", + "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-sfc": "3.5.18", + "@vue/runtime-dom": "3.5.18", + "@vue/server-renderer": "3.5.18", + "@vue/shared": "3.5.18" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://repo.huaweicloud.com/repository/npm/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vueuc": { + "version": "0.4.64", + "resolved": "https://repo.huaweicloud.com/repository/npm/vueuc/-/vueuc-0.4.64.tgz", + "integrity": "sha512-wlJQj7fIwKK2pOEoOq4Aro8JdPOGpX8aWQhV8YkTW9OgWD2uj2O8ANzvSsIGjx7LTOc7QbS7sXdxHi6XvRnHPA==", + "license": "MIT", + "dependencies": { + "@css-render/vue3-ssr": "^0.15.10", + "@juggle/resize-observer": "^3.3.1", + "css-render": "^0.15.10", + "evtd": "^0.2.4", + "seemly": "^0.3.6", + "vdirs": "^0.1.4", + "vooks": "^0.2.4" + }, + "peerDependencies": { + "vue": "^3.0.11" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e1db723 --- /dev/null +++ b/package.json @@ -0,0 +1,44 @@ +{ + "name": "xyzw-token-manager", + "version": "2.0.0", + "description": "XYZW游戏Token管理器 - 支持Base64导入和WebSocket连接管理", + "main": "src/main.js", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint src --ext .vue,.js,.ts --fix", + "format": "prettier --write \"src/**/*.{js,vue,ts,css,scss}\"" + }, + "dependencies": { + "@vicons/ionicons5": "^0.12.0", + "@vicons/material": "^0.12.0", + "axios": "^1.6.0", + "lz4js": "^0.2.0", + "naive-ui": "^2.38.0", + "pinia": "^2.1.0", + "vue": "^3.4.0", + "vue-router": "^4.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@vitejs/plugin-vue": "^5.0.0", + "eslint": "^8.0.0", + "eslint-plugin-vue": "^9.0.0", + "prettier": "^3.0.0", + "sass": "^1.69.0", + "typescript": "^5.0.0", + "vite": "^5.0.0" + }, + "keywords": [ + "vue", + "token-management", + "websocket", + "base64", + "game-automation", + "xyzw", + "frontend" + ], + "author": "XYZW Team", + "license": "CC-BY-NC-SA-4.0" +} diff --git a/public/1733492491706148.png b/public/1733492491706148.png new file mode 100644 index 0000000..9469552 Binary files /dev/null and b/public/1733492491706148.png differ diff --git a/public/1733492491706152.png b/public/1733492491706152.png new file mode 100644 index 0000000..f37f0a4 Binary files /dev/null and b/public/1733492491706152.png differ diff --git a/public/1736425783912140.png b/public/1736425783912140.png new file mode 100644 index 0000000..6159ec6 Binary files /dev/null and b/public/1736425783912140.png differ diff --git a/public/173746572831736.png b/public/173746572831736.png new file mode 100644 index 0000000..de62431 Binary files /dev/null and b/public/173746572831736.png differ diff --git a/public/174023274867420.png b/public/174023274867420.png new file mode 100644 index 0000000..fd453ff Binary files /dev/null and b/public/174023274867420.png differ diff --git a/public/174061875626614.png b/public/174061875626614.png new file mode 100644 index 0000000..3ef5905 Binary files /dev/null and b/public/174061875626614.png differ diff --git a/public/IMG_8007.JPG b/public/IMG_8007.JPG new file mode 100644 index 0000000..6920d0e Binary files /dev/null and b/public/IMG_8007.JPG differ diff --git a/public/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png b/public/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png new file mode 100644 index 0000000..62ec56f Binary files /dev/null and b/public/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png differ diff --git a/public/icons/1733492491706148.png b/public/icons/1733492491706148.png new file mode 100644 index 0000000..9469552 Binary files /dev/null and b/public/icons/1733492491706148.png differ diff --git a/public/icons/1733492491706152.png b/public/icons/1733492491706152.png new file mode 100644 index 0000000..f37f0a4 Binary files /dev/null and b/public/icons/1733492491706152.png differ diff --git a/public/icons/1736425783912140.png b/public/icons/1736425783912140.png new file mode 100644 index 0000000..6159ec6 Binary files /dev/null and b/public/icons/1736425783912140.png differ diff --git a/public/icons/173746572831736.png b/public/icons/173746572831736.png new file mode 100644 index 0000000..de62431 Binary files /dev/null and b/public/icons/173746572831736.png differ diff --git a/public/icons/174023274867420.png b/public/icons/174023274867420.png new file mode 100644 index 0000000..fd453ff Binary files /dev/null and b/public/icons/174023274867420.png differ diff --git a/public/icons/174061875626614.png b/public/icons/174061875626614.png new file mode 100644 index 0000000..3ef5905 Binary files /dev/null and b/public/icons/174061875626614.png differ diff --git a/public/icons/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png b/public/icons/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png new file mode 100644 index 0000000..62ec56f Binary files /dev/null and b/public/icons/Ob7pyorzmHiJcbab2c25af264d0758b527bc1b61cc3b.png differ diff --git a/public/icons/ta.png b/public/icons/ta.png new file mode 100644 index 0000000..e5ad5dd Binary files /dev/null and b/public/icons/ta.png differ diff --git a/public/icons/xiaoyugan.png b/public/icons/xiaoyugan.png new file mode 100644 index 0000000..695e0c0 Binary files /dev/null and b/public/icons/xiaoyugan.png differ diff --git a/public/ta.png b/public/ta.png new file mode 100644 index 0000000..e5ad5dd Binary files /dev/null and b/public/ta.png differ diff --git a/public/xiaoyugan.png b/public/xiaoyugan.png new file mode 100644 index 0000000..695e0c0 Binary files /dev/null and b/public/xiaoyugan.png differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..843a1a4 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,78 @@ + + + + + \ No newline at end of file diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..d190561 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,134 @@ +import axios from 'axios' +import { useAuthStore } from '@/stores/auth' + +// 创建axios实例 +const request = axios.create({ + baseURL: '/api/v1', + timeout: 10000, + headers: { + 'Content-Type': 'application/json' + } +}) + +// 请求拦截器 +request.interceptors.request.use( + (config) => { + const authStore = useAuthStore() + if (authStore.token) { + config.headers.Authorization = `Bearer ${authStore.token}` + } + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +request.interceptors.response.use( + (response) => { + const data = response.data + + // 统一处理响应格式 + if (data.success !== undefined) { + return data + } + + // 兼容不同的响应格式 + return { + success: true, + data: data, + message: 'success' + } + }, + (error) => { + const authStore = useAuthStore() + + // 处理HTTP错误 + if (error.response) { + const { status, data } = error.response + + switch (status) { + case 401: + // 未授权,清除登录状态 + authStore.logout() + window.location.href = '/login' + return Promise.reject({ + success: false, + message: '登录已过期,请重新登录' + }) + case 403: + return Promise.reject({ + success: false, + message: '没有权限访问' + }) + case 404: + return Promise.reject({ + success: false, + message: '请求的资源不存在' + }) + case 500: + return Promise.reject({ + success: false, + message: '服务器内部错误' + }) + default: + return Promise.reject({ + success: false, + message: data?.message || '请求失败' + }) + } + } else if (error.request) { + // 网络错误 + return Promise.reject({ + success: false, + message: '网络连接失败,请检查网络' + }) + } else { + // 其他错误 + return Promise.reject({ + success: false, + message: error.message || '未知错误' + }) + } + } +) + +// API接口定义 +const api = { + // 认证相关 + auth: { + login: (credentials) => request.post('/auth/login', credentials), + register: (userInfo) => request.post('/auth/register', userInfo), + logout: () => request.post('/auth/logout'), + getUserInfo: () => request.get('/auth/user'), + refreshToken: () => request.post('/auth/refresh') + }, + + // 游戏角色相关 + gameRoles: { + getList: () => request.get('/gamerole_list'), + add: (roleData) => request.post('/gameroles', roleData), + update: (roleId, roleData) => request.put(`/gameroles/${roleId}`, roleData), + delete: (roleId) => request.delete(`/gameroles/${roleId}`), + getDetail: (roleId) => request.get(`/gameroles/${roleId}`) + }, + + // 日常任务相关 + dailyTasks: { + getList: (roleId) => request.get(`/daily-tasks?roleId=${roleId}`), + getStatus: (roleId) => request.get(`/daily-tasks/status?roleId=${roleId}`), + complete: (taskId, roleId) => request.post(`/daily-tasks/${taskId}/complete`, { roleId }), + getHistory: (roleId, page = 1, limit = 20) => request.get(`/daily-tasks/history?roleId=${roleId}&page=${page}&limit=${limit}`) + }, + + // 用户相关 + user: { + getProfile: () => request.get('/user/profile'), + updateProfile: (profileData) => request.put('/user/profile', profileData), + changePassword: (passwordData) => request.put('/user/password', passwordData), + getStats: () => request.get('/user/stats') + } +} + +export default api \ No newline at end of file diff --git a/src/assets/styles/global.scss b/src/assets/styles/global.scss new file mode 100644 index 0000000..82cfc27 --- /dev/null +++ b/src/assets/styles/global.scss @@ -0,0 +1,314 @@ +// 全局样式重置 +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + height: 100%; + scroll-behavior: smooth; +} + +body { + height: 100%; + font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: var(--font-size-md); + line-height: var(--line-height-normal); + color: var(--text-primary); + background: var(--bg-primary); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +#app { + min-height: 100vh; +} + +// 链接样式 +a { + color: var(--primary-color); + text-decoration: none; + transition: color var(--transition-fast); + + &:hover { + color: var(--primary-color-hover); + } +} + +// 按钮重置 +button { + border: none; + background: none; + cursor: pointer; + font-family: inherit; +} + +// 输入框重置 +input, textarea, select { + font-family: inherit; + font-size: inherit; + border: none; + outline: none; +} + +// 列表重置 +ul, ol { + list-style: none; +} + +// 图片 +img { + max-width: 100%; + height: auto; +} + +// 滚动条样式 +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.3); + border-radius: 3px; + + &:hover { + background: rgba(0, 0, 0, 0.5); + } +} + +// 工具类 +.text-center { + text-align: center; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.flex { + display: flex; +} + +.flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +.flex-between { + display: flex; + align-items: center; + justify-content: space-between; +} + +.flex-column { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.flex-1 { + flex: 1; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +// 间距工具类 +.m-0 { margin: 0; } +.m-1 { margin: var(--spacing-xs); } +.m-2 { margin: var(--spacing-sm); } +.m-3 { margin: var(--spacing-md); } +.m-4 { margin: var(--spacing-lg); } +.m-5 { margin: var(--spacing-xl); } + +.mt-0 { margin-top: 0; } +.mt-1 { margin-top: var(--spacing-xs); } +.mt-2 { margin-top: var(--spacing-sm); } +.mt-3 { margin-top: var(--spacing-md); } +.mt-4 { margin-top: var(--spacing-lg); } +.mt-5 { margin-top: var(--spacing-xl); } + +.mb-0 { margin-bottom: 0; } +.mb-1 { margin-bottom: var(--spacing-xs); } +.mb-2 { margin-bottom: var(--spacing-sm); } +.mb-3 { margin-bottom: var(--spacing-md); } +.mb-4 { margin-bottom: var(--spacing-lg); } +.mb-5 { margin-bottom: var(--spacing-xl); } + +.ml-0 { margin-left: 0; } +.ml-1 { margin-left: var(--spacing-xs); } +.ml-2 { margin-left: var(--spacing-sm); } +.ml-3 { margin-left: var(--spacing-md); } +.ml-4 { margin-left: var(--spacing-lg); } +.ml-5 { margin-left: var(--spacing-xl); } + +.mr-0 { margin-right: 0; } +.mr-1 { margin-right: var(--spacing-xs); } +.mr-2 { margin-right: var(--spacing-sm); } +.mr-3 { margin-right: var(--spacing-md); } +.mr-4 { margin-right: var(--spacing-lg); } +.mr-5 { margin-right: var(--spacing-xl); } + +.p-0 { padding: 0; } +.p-1 { padding: var(--spacing-xs); } +.p-2 { padding: var(--spacing-sm); } +.p-3 { padding: var(--spacing-md); } +.p-4 { padding: var(--spacing-lg); } +.p-5 { padding: var(--spacing-xl); } + +.pt-0 { padding-top: 0; } +.pt-1 { padding-top: var(--spacing-xs); } +.pt-2 { padding-top: var(--spacing-sm); } +.pt-3 { padding-top: var(--spacing-md); } +.pt-4 { padding-top: var(--spacing-lg); } +.pt-5 { padding-top: var(--spacing-xl); } + +.pb-0 { padding-bottom: 0; } +.pb-1 { padding-bottom: var(--spacing-xs); } +.pb-2 { padding-bottom: var(--spacing-sm); } +.pb-3 { padding-bottom: var(--spacing-md); } +.pb-4 { padding-bottom: var(--spacing-lg); } +.pb-5 { padding-bottom: var(--spacing-xl); } + +.pl-0 { padding-left: 0; } +.pl-1 { padding-left: var(--spacing-xs); } +.pl-2 { padding-left: var(--spacing-sm); } +.pl-3 { padding-left: var(--spacing-md); } +.pl-4 { padding-left: var(--spacing-lg); } +.pl-5 { padding-left: var(--spacing-xl); } + +.pr-0 { padding-right: 0; } +.pr-1 { padding-right: var(--spacing-xs); } +.pr-2 { padding-right: var(--spacing-sm); } +.pr-3 { padding-right: var(--spacing-md); } +.pr-4 { padding-right: var(--spacing-lg); } +.pr-5 { padding-right: var(--spacing-xl); } + +// 文字大小 +.text-xs { font-size: var(--font-size-xs); } +.text-sm { font-size: var(--font-size-sm); } +.text-md { font-size: var(--font-size-md); } +.text-lg { font-size: var(--font-size-lg); } +.text-xl { font-size: var(--font-size-xl); } +.text-2xl { font-size: var(--font-size-2xl); } +.text-3xl { font-size: var(--font-size-3xl); } + +// 文字颜色 +.text-primary { color: var(--text-primary); } +.text-secondary { color: var(--text-secondary); } +.text-tertiary { color: var(--text-tertiary); } +.text-success { color: var(--success-color); } +.text-warning { color: var(--warning-color); } +.text-error { color: var(--error-color); } +.text-info { color: var(--info-color); } + +// 字重 +.font-light { font-weight: var(--font-weight-light); } +.font-normal { font-weight: var(--font-weight-normal); } +.font-medium { font-weight: var(--font-weight-medium); } +.font-semibold { font-weight: var(--font-weight-semibold); } +.font-bold { font-weight: var(--font-weight-bold); } + +// 圆角 +.rounded-sm { border-radius: var(--border-radius-small); } +.rounded { border-radius: var(--border-radius-medium); } +.rounded-lg { border-radius: var(--border-radius-large); } +.rounded-xl { border-radius: var(--border-radius-xl); } +.rounded-full { border-radius: 50%; } + +// 阴影 +.shadow-sm { box-shadow: var(--shadow-light); } +.shadow { box-shadow: var(--shadow-medium); } +.shadow-lg { box-shadow: var(--shadow-heavy); } + +// 动画 +.transition { + transition: all var(--transition-normal); +} + +.transition-fast { + transition: all var(--transition-fast); +} + +.transition-slow { + transition: all var(--transition-slow); +} + +// 布局 +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 var(--spacing-md); +} + +.container-sm { + max-width: 768px; + margin: 0 auto; + padding: 0 var(--spacing-md); +} + +.container-lg { + max-width: 1400px; + margin: 0 auto; + padding: 0 var(--spacing-md); +} + +// 玻璃效果 +.glass { + backdrop-filter: blur(10px); + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +// 悬停效果 +.hover-scale { + transition: transform var(--transition-fast); + + &:hover { + transform: scale(1.05); + } +} + +// 响应式 +@media (max-width: 768px) { + .container, + .container-sm, + .container-lg { + padding: 0 var(--spacing-sm); + } + + .text-3xl { + font-size: var(--font-size-2xl); + } + + .text-2xl { + font-size: var(--font-size-xl); + } +} \ No newline at end of file diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss new file mode 100644 index 0000000..f839e5f --- /dev/null +++ b/src/assets/styles/variables.scss @@ -0,0 +1,102 @@ +// 颜色变量 +:root { + // 主题色 + --primary-color: #667eea; + --primary-color-hover: #5a67d8; + --primary-color-light: #e6f7ff; + + // 辅助色 + --secondary-color: #764ba2; + --success-color: #18a058; + --warning-color: #f5a623; + --error-color: #d03050; + --info-color: #2080f0; + + // 中性色 + --text-primary: #333333; + --text-secondary: #666666; + --text-tertiary: #999999; + --text-disabled: #cccccc; + + // 背景色 + --bg-primary: #ffffff; + --bg-secondary: #f5f7fa; + --bg-tertiary: #f0f2f5; + --bg-overlay: rgba(0, 0, 0, 0.5); + + // 边框色 + --border-light: #e5e7eb; + --border-medium: #d1d5db; + --border-dark: #9ca3af; + + // 阴影 + --shadow-light: 0 1px 3px rgba(0, 0, 0, 0.1); + --shadow-medium: 0 4px 6px rgba(0, 0, 0, 0.1); + --shadow-heavy: 0 10px 15px rgba(0, 0, 0, 0.1); + + // 圆角 + --border-radius-small: 4px; + --border-radius-medium: 8px; + --border-radius-large: 12px; + --border-radius-xl: 16px; + + // 间距 + --spacing-xs: 4px; + --spacing-sm: 8px; + --spacing-md: 16px; + --spacing-lg: 24px; + --spacing-xl: 32px; + --spacing-2xl: 48px; + + // 字体 + --font-size-xs: 12px; + --font-size-sm: 14px; + --font-size-md: 16px; + --font-size-lg: 18px; + --font-size-xl: 20px; + --font-size-2xl: 24px; + --font-size-3xl: 32px; + + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + // 行高 + --line-height-tight: 1.2; + --line-height-normal: 1.5; + --line-height-relaxed: 1.75; + + // 动画 + --transition-fast: 0.15s ease; + --transition-normal: 0.3s ease; + --transition-slow: 0.5s ease; + + // Z-index + --z-dropdown: 1000; + --z-sticky: 1020; + --z-fixed: 1030; + --z-modal-backdrop: 1040; + --z-modal: 1050; + --z-popover: 1060; + --z-tooltip: 1070; + --z-toast: 1080; +} + +// 暗色主题 +[data-theme="dark"] { + --text-primary: #ffffff; + --text-secondary: #d1d5db; + --text-tertiary: #9ca3af; + --text-disabled: #6b7280; + + --bg-primary: #1f2937; + --bg-secondary: #374151; + --bg-tertiary: #4b5563; + --bg-overlay: rgba(0, 0, 0, 0.7); + + --border-light: #4b5563; + --border-medium: #6b7280; + --border-dark: #9ca3af; +} \ No newline at end of file diff --git a/src/components/DailyTaskCard.vue b/src/components/DailyTaskCard.vue new file mode 100644 index 0000000..cb9f351 --- /dev/null +++ b/src/components/DailyTaskCard.vue @@ -0,0 +1,582 @@ + + + + + \ No newline at end of file diff --git a/src/components/DailyTaskStatus.vue b/src/components/DailyTaskStatus.vue new file mode 100644 index 0000000..4f521a7 --- /dev/null +++ b/src/components/DailyTaskStatus.vue @@ -0,0 +1,751 @@ + + + + + \ No newline at end of file diff --git a/src/components/GameStatus.vue b/src/components/GameStatus.vue new file mode 100644 index 0000000..0d50a25 --- /dev/null +++ b/src/components/GameStatus.vue @@ -0,0 +1,673 @@ + + + + + \ No newline at end of file diff --git a/src/components/MessageTester.vue b/src/components/MessageTester.vue new file mode 100644 index 0000000..6470500 --- /dev/null +++ b/src/components/MessageTester.vue @@ -0,0 +1,319 @@ + + + + + \ No newline at end of file diff --git a/src/components/TeamStatus.vue b/src/components/TeamStatus.vue new file mode 100644 index 0000000..30807e8 --- /dev/null +++ b/src/components/TeamStatus.vue @@ -0,0 +1,454 @@ + + + + + \ No newline at end of file diff --git a/src/components/TokenManager.vue b/src/components/TokenManager.vue new file mode 100644 index 0000000..0c9dc8c --- /dev/null +++ b/src/components/TokenManager.vue @@ -0,0 +1,507 @@ + + + + + \ No newline at end of file diff --git a/src/components/TowerStatus.vue b/src/components/TowerStatus.vue new file mode 100644 index 0000000..8201e8c --- /dev/null +++ b/src/components/TowerStatus.vue @@ -0,0 +1,404 @@ + + + + + diff --git a/src/components/WebSocketTester.vue b/src/components/WebSocketTester.vue new file mode 100644 index 0000000..169d242 --- /dev/null +++ b/src/components/WebSocketTester.vue @@ -0,0 +1,496 @@ + + + + + \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..259889b --- /dev/null +++ b/src/main.js @@ -0,0 +1,17 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import naive from 'naive-ui' +import router from './router' +import App from './App.vue' +import './assets/styles/global.scss' + +// 创建应用实例 +const app = createApp(App) + +// 使用插件 +app.use(createPinia()) +app.use(router) +app.use(naive) + +// 挂载应用 +app.mount('#app') \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..99a5529 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,137 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { useTokenStore } from '@/stores/tokenStore' + +const routes = [ + { + path: '/', + name: 'Home', + component: () => import('@/views/Home.vue'), + meta: { + title: '首页', + requiresToken: false + } + }, + { + path: '/tokens', + name: 'TokenImport', + component: () => import('@/views/TokenImport.vue'), + meta: { + title: 'Token管理', + requiresToken: false + } + }, + { + path: '/dashboard', + name: 'Dashboard', + component: () => import('@/views/Dashboard.vue'), + meta: { + title: '控制台', + requiresToken: true + } + }, + { + path: '/profile', + name: 'Profile', + component: () => import('@/views/Profile.vue'), + meta: { + title: '个人设置', + requiresToken: true + } + }, + { + path: '/daily-tasks', + name: 'DailyTasks', + component: () => import('@/views/DailyTasks.vue'), + meta: { + title: '日常任务', + requiresToken: true + } + }, + { + path: '/game-features', + name: 'GameFeatures', + component: () => import('@/views/GameFeatures.vue'), + meta: { + title: '游戏功能', + requiresToken: true + } + }, + { + path: '/message-test', + name: 'MessageTest', + component: () => import('@/components/MessageTester.vue'), + meta: { + title: '消息测试', + requiresToken: true + } + }, + { + path: '/websocket-test', + name: 'WebSocketTest', + component: () => import('@/components/WebSocketTester.vue'), + meta: { + title: 'WebSocket测试', + requiresToken: true + } + }, + // 兼容旧路由,重定向到新的token管理页面 + { + path: '/login', + redirect: '/tokens' + }, + { + path: '/register', + redirect: '/tokens' + }, + { + path: '/game-roles', + redirect: '/tokens' + }, + { + path: '/:pathMatch(.*)*', + name: 'NotFound', + component: () => import('@/views/NotFound.vue'), + meta: { + title: '页面不存在' + } + } +] + +const router = createRouter({ + history: createWebHistory(), + routes, + scrollBehavior(to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { top: 0 } + } + } +}) + +// 导航守卫 +router.beforeEach((to, from, next) => { + const tokenStore = useTokenStore() + + // 设置页面标题 + document.title = to.meta.title ? `${to.meta.title} - XYZW 游戏管理系统` : 'XYZW 游戏管理系统' + + // 检查是否需要Token + if (to.meta.requiresToken && !tokenStore.hasTokens) { + next('/tokens') + } else if (to.name === 'TokenImport' && tokenStore.hasTokens && tokenStore.selectedToken) { + // 如果已有token且已选择,重定向到控制台 + next('/dashboard') + } else if (to.path === '/' && tokenStore.hasTokens) { + // 首页重定向逻辑 + if (tokenStore.selectedToken) { + next('/dashboard') + } else { + next('/tokens') + } + } else { + next() + } +}) + +export default router \ No newline at end of file diff --git a/src/stores/auth.js b/src/stores/auth.js new file mode 100644 index 0000000..2cda174 --- /dev/null +++ b/src/stores/auth.js @@ -0,0 +1,158 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { useLocalTokenStore } from './localTokenManager' + +export const useAuthStore = defineStore('auth', () => { + // 状态 + const user = ref(null) + const token = ref(localStorage.getItem('token') || null) + const isLoading = ref(false) + + const localTokenStore = useLocalTokenStore() + + // 计算属性 + const isAuthenticated = computed(() => !!token.value && !!user.value) + const userInfo = computed(() => user.value) + + // 登录 - 移除API调用,使用本地认证 + const login = async (credentials) => { + try { + isLoading.value = true + + // 模拟本地认证逻辑 + const mockUser = { + id: 'local_user_' + Date.now(), + username: credentials.username, + email: credentials.email || `${credentials.username}@local.game`, + avatar: '/icons/xiaoyugan.png', + createdAt: new Date().toISOString() + } + + const mockToken = 'local_token_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) + + token.value = mockToken + user.value = mockUser + + // 保存到本地存储 + localStorage.setItem('token', token.value) + localStorage.setItem('user', JSON.stringify(user.value)) + + // 同时保存到token管理器 + localTokenStore.setUserToken(mockToken) + + return { success: true } + } catch (error) { + console.error('登录错误:', error) + return { success: false, message: '本地认证失败' } + } finally { + isLoading.value = false + } + } + + // 注册 - 移除API调用,使用本地注册 + const register = async (userInfo) => { + try { + isLoading.value = true + + // 检查用户名是否已存在(简单的本地检查) + const existingUsers = JSON.parse(localStorage.getItem('registeredUsers') || '[]') + const userExists = existingUsers.some(u => u.username === userInfo.username) + + if (userExists) { + return { success: false, message: '用户名已存在' } + } + + // 保存新用户信息到本地 + const newUser = { + ...userInfo, + id: 'user_' + Date.now(), + createdAt: new Date().toISOString() + } + + existingUsers.push(newUser) + localStorage.setItem('registeredUsers', JSON.stringify(existingUsers)) + + return { success: true, message: '注册成功,请登录' } + } catch (error) { + console.error('注册错误:', error) + return { success: false, message: '本地注册失败' } + } finally { + isLoading.value = false + } + } + + // 登出 + const logout = () => { + user.value = null + token.value = null + + // 清除本地存储 + localStorage.removeItem('token') + localStorage.removeItem('user') + localStorage.removeItem('gameRoles') + + // 清除token管理器中的数据 + localTokenStore.clearUserToken() + localTokenStore.clearAllGameTokens() + } + + // 获取用户信息 - 移除API调用,使用本地数据 + const fetchUserInfo = async () => { + try { + if (!token.value) return false + + // 从本地存储获取用户信息 + const savedUser = localStorage.getItem('user') + if (savedUser) { + try { + user.value = JSON.parse(savedUser) + return true + } catch (error) { + console.error('解析用户信息失败:', error) + logout() + return false + } + } else { + logout() + return false + } + } catch (error) { + console.error('获取用户信息失败:', error) + logout() + return false + } + } + + // 初始化认证状态 - 移除API验证,使用本地验证 + const initAuth = async () => { + const savedUser = localStorage.getItem('user') + if (token.value && savedUser) { + try { + user.value = JSON.parse(savedUser) + // 初始化token管理器 + localTokenStore.initTokenManager() + } catch (error) { + console.error('初始化认证失败:', error) + logout() + } + } + } + + return { + // 状态 + user, + token, + isLoading, + + // 计算属性 + isAuthenticated, + userInfo, + + // 方法 + login, + register, + logout, + fetchUserInfo, + initAuth + } +}) \ No newline at end of file diff --git a/src/stores/gameRoles.js b/src/stores/gameRoles.js new file mode 100644 index 0000000..e3d8ae3 --- /dev/null +++ b/src/stores/gameRoles.js @@ -0,0 +1,204 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { useLocalTokenStore } from './localTokenManager' + +export const useGameRolesStore = defineStore('gameRoles', () => { + // 状态 + const gameRoles = ref([]) + const isLoading = ref(false) + const selectedRole = ref(null) + + const localTokenStore = useLocalTokenStore() + + // 获取游戏角色列表 - 移除API调用,使用本地数据 + const fetchGameRoles = async () => { + try { + isLoading.value = true + + // 从本地存储获取角色数据 + const savedRoles = localStorage.getItem('gameRoles') + if (savedRoles) { + try { + gameRoles.value = JSON.parse(savedRoles) + } catch (error) { + console.error('解析游戏角色数据失败:', error) + gameRoles.value = [] + } + } else { + gameRoles.value = [] + } + + return { success: true } + } catch (error) { + console.error('获取游戏角色失败:', error) + return { success: false, message: '本地数据读取失败' } + } finally { + isLoading.value = false + } + } + + // 添加游戏角色 - 移除API调用,本地生成角色和token + const addGameRole = async (roleData) => { + try { + isLoading.value = true + + // 生成角色ID和游戏token + const roleId = 'role_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) + const gameToken = 'game_token_' + Date.now() + '_' + Math.random().toString(36).substr(2, 16) + + const newRole = { + ...roleData, + id: roleId, + createdAt: new Date().toISOString(), + isActive: false, + exp: 0, + gold: 1000, // 默认金币 + vip: false, + avatar: roleData.avatar || '/icons/xiaoyugan.png' + } + + // 添加到角色列表 + gameRoles.value.push(newRole) + localStorage.setItem('gameRoles', JSON.stringify(gameRoles.value)) + + // 生成并保存游戏token + const tokenData = { + token: gameToken, + roleId: roleId, + roleName: newRole.name, + server: newRole.server, + wsUrl: null, // 使用默认的游戏WebSocket地址 + createdAt: new Date().toISOString(), + isActive: true + } + + localTokenStore.addGameToken(roleId, tokenData) + + return { success: true, message: '添加角色成功,已生成游戏token' } + } catch (error) { + console.error('添加游戏角色失败:', error) + return { success: false, message: '添加角色失败' } + } finally { + isLoading.value = false + } + } + + // 更新游戏角色 - 移除API调用,使用本地更新 + const updateGameRole = async (roleId, roleData) => { + try { + isLoading.value = true + + const index = gameRoles.value.findIndex(role => role.id === roleId) + if (index !== -1) { + gameRoles.value[index] = { + ...gameRoles.value[index], + ...roleData, + updatedAt: new Date().toISOString() + } + localStorage.setItem('gameRoles', JSON.stringify(gameRoles.value)) + + // 更新对应的token信息 + const existingToken = localTokenStore.getGameToken(roleId) + if (existingToken) { + localTokenStore.updateGameToken(roleId, { + roleName: roleData.name || existingToken.roleName, + server: roleData.server || existingToken.server + }) + } + + return { success: true, message: '更新角色成功' } + } else { + return { success: false, message: '角色不存在' } + } + } catch (error) { + console.error('更新游戏角色失败:', error) + return { success: false, message: '更新角色失败' } + } finally { + isLoading.value = false + } + } + + // 删除游戏角色 - 移除API调用,同时删除对应token + const deleteGameRole = async (roleId) => { + try { + isLoading.value = true + + gameRoles.value = gameRoles.value.filter(role => role.id !== roleId) + localStorage.setItem('gameRoles', JSON.stringify(gameRoles.value)) + + // 删除对应的token和WebSocket连接 + localTokenStore.removeGameToken(roleId) + + // 如果删除的是当前选中角色,清除选中状态 + if (selectedRole.value && selectedRole.value.id === roleId) { + selectedRole.value = null + localStorage.removeItem('selectedRole') + } + + return { success: true, message: '删除角色成功,已清理相关token' } + } catch (error) { + console.error('删除游戏角色失败:', error) + return { success: false, message: '删除角色失败' } + } finally { + isLoading.value = false + } + } + + // 选择角色 - 添加WebSocket连接功能 + const selectRole = (role) => { + selectedRole.value = role + localStorage.setItem('selectedRole', JSON.stringify(role)) + + // 自动建立WebSocket连接 + const tokenData = localTokenStore.getGameToken(role.id) + if (tokenData && tokenData.token) { + try { + localTokenStore.createWebSocketConnection( + role.id, + tokenData.token, + tokenData.wsUrl + ) + console.log(`已为角色 ${role.name} 建立WebSocket连接`) + } catch (error) { + console.error(`建立WebSocket连接失败 [${role.name}]:`, error) + } + } + } + + // 初始化数据 + const initGameRoles = () => { + const cachedRoles = localStorage.getItem('gameRoles') + const cachedSelectedRole = localStorage.getItem('selectedRole') + + if (cachedRoles) { + try { + gameRoles.value = JSON.parse(cachedRoles) + } catch (error) { + console.error('解析缓存的游戏角色数据失败:', error) + } + } + + if (cachedSelectedRole) { + try { + selectedRole.value = JSON.parse(cachedSelectedRole) + } catch (error) { + console.error('解析缓存的选中角色数据失败:', error) + } + } + } + + return { + // 状态 + gameRoles, + isLoading, + selectedRole, + + // 方法 + fetchGameRoles, + addGameRole, + updateGameRole, + deleteGameRole, + selectRole, + initGameRoles + } +}) \ No newline at end of file diff --git a/src/stores/localTokenManager.js b/src/stores/localTokenManager.js new file mode 100644 index 0000000..c71357d --- /dev/null +++ b/src/stores/localTokenManager.js @@ -0,0 +1,454 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' + +/** + * 本地Token管理器 + * 用于管理用户认证token和游戏角色token的本地存储 + */ +export const useLocalTokenStore = defineStore('localToken', () => { + // 状态 + const userToken = ref(localStorage.getItem('userToken') || null) + const gameTokens = ref(JSON.parse(localStorage.getItem('gameTokens') || '{}')) + const wsConnections = ref({}) // WebSocket连接状态 + + // 计算属性 + const isUserAuthenticated = computed(() => !!userToken.value) + const hasGameTokens = computed(() => Object.keys(gameTokens.value).length > 0) + + // 用户认证token管理 + const setUserToken = (token) => { + userToken.value = token + localStorage.setItem('userToken', token) + } + + const clearUserToken = () => { + userToken.value = null + localStorage.removeItem('userToken') + } + + // 游戏token管理 + const addGameToken = (roleId, tokenData) => { + const newTokenData = { + ...tokenData, + roleId, + createdAt: new Date().toISOString(), + lastUsed: new Date().toISOString() + } + + gameTokens.value[roleId] = newTokenData + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + + return newTokenData + } + + const getGameToken = (roleId) => { + const token = gameTokens.value[roleId] + if (token) { + // 更新最后使用时间 + token.lastUsed = new Date().toISOString() + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + } + return token + } + + const updateGameToken = (roleId, updates) => { + if (gameTokens.value[roleId]) { + gameTokens.value[roleId] = { + ...gameTokens.value[roleId], + ...updates, + updatedAt: new Date().toISOString() + } + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + } + } + + const removeGameToken = (roleId) => { + delete gameTokens.value[roleId] + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + + // 同时断开对应的WebSocket连接 + if (wsConnections.value[roleId]) { + closeWebSocketConnection(roleId) + } + } + + const clearAllGameTokens = () => { + // 关闭所有WebSocket连接 + Object.keys(wsConnections.value).forEach(roleId => { + closeWebSocketConnection(roleId) + }) + + gameTokens.value = {} + localStorage.removeItem('gameTokens') + } + + // WebSocket连接管理 - 使用新的WsAgent + const createWebSocketConnection = async (roleId, base64Token, customWsUrl = null) => { + if (wsConnections.value[roleId]) { + closeWebSocketConnection(roleId) + } + + try { + // 动态导入WebSocket客户端 + const { WsAgent } = await import('../utils/wsAgent.js') + const { gameCommands } = await import('../utils/gameCommands.js') + + // 解析Base64获取实际Token + let actualToken = base64Token + + // 尝试解析Base64获取实际token + try { + const cleanBase64 = base64Token.replace(/^data:.*base64,/, '').trim() + const decoded = atob(cleanBase64) + + // 尝试解析为JSON获取token字段 + try { + const tokenData = JSON.parse(decoded) + actualToken = tokenData.token || tokenData.gameToken || decoded + } catch { + // 如果不是JSON,直接使用解码后的字符串 + actualToken = decoded + } + } catch (error) { + console.warn('Base64解析失败,使用原始token:', error.message) + actualToken = base64Token + } + + // 创建WebSocket客户端实例 + const wsAgent = new WsAgent({ + heartbeatInterval: 2000, + queueInterval: 50, + channel: 'x', // 使用x通道 + autoReconnect: true, + maxReconnectAttempts: 5 + }) + + // 设置事件监听器 + wsAgent.onOpen = () => { + console.log(`✅ WebSocket连接已建立: ${roleId}`) + + // 更新连接状态 + wsConnections.value[roleId].status = 'connected' + wsConnections.value[roleId].connectedAt = new Date().toISOString() + + // 发送初始化命令 + setTimeout(() => { + // 获取角色信息 + wsAgent.send(gameCommands.role_getroleinfo(0, 0, { roleId })) + + // 获取数据包版本 + wsAgent.send(gameCommands.system_getdatabundlever()) + }, 1000) + } + + wsAgent.onMessage = (message) => { + console.log(`📨 收到消息 [${roleId}]:`, message) + + // 处理不同类型的消息 + if (message.cmd) { + handleGameMessage(roleId, message) + } + } + + wsAgent.onError = (error) => { + console.error(`❌ WebSocket错误 [${roleId}]:`, error) + if (wsConnections.value[roleId]) { + wsConnections.value[roleId].status = 'error' + wsConnections.value[roleId].lastError = error.message + } + } + + wsAgent.onClose = (event) => { + console.log(`🔌 WebSocket连接已关闭 [${roleId}]:`, event.code, event.reason) + if (wsConnections.value[roleId]) { + wsConnections.value[roleId].status = 'disconnected' + } + } + + wsAgent.onReconnect = (attempt) => { + console.log(`🔄 WebSocket重连中 [${roleId}] 第${attempt}次`) + if (wsConnections.value[roleId]) { + wsConnections.value[roleId].status = 'reconnecting' + wsConnections.value[roleId].reconnectAttempt = attempt + } + } + + // 构建WebSocket URL + const baseWsUrl = 'wss://xxz-xyzw.hortorgames.com/agent' + const wsUrl = customWsUrl || WsAgent.buildUrl(baseWsUrl, { + p: actualToken, + e: 'x', + lang: 'chinese' + }) + + // 保存连接信息 + wsConnections.value[roleId] = { + agent: wsAgent, + gameCommands, + status: 'connecting', + roleId, + wsUrl, + actualToken, + createdAt: new Date().toISOString(), + lastError: null, + reconnectAttempt: 0 + } + + // 建立连接 + await wsAgent.connect(wsUrl) + + return wsAgent + } catch (error) { + console.error(`创建WebSocket连接失败 [${roleId}]:`, error) + if (wsConnections.value[roleId]) { + wsConnections.value[roleId].status = 'error' + wsConnections.value[roleId].lastError = error.message + } + return null + } + } + + // 处理游戏消息 + const handleGameMessage = (roleId, message) => { + const { cmd, body } = message + + switch (cmd) { + case 'role_getroleinfo': + console.log(`角色信息 [${roleId}]:`, body) + break + + case 'system_getdatabundlever': + console.log(`数据包版本 [${roleId}]:`, body) + break + + case 'task_claimdailyreward': + console.log(`每日任务奖励 [${roleId}]:`, body) + break + + case 'system_signinreward': + console.log(`签到奖励 [${roleId}]:`, body) + break + + default: + console.log(`未处理的消息 [${roleId}] ${cmd}:`, body) + } + } + + const closeWebSocketConnection = (roleId) => { + const connection = wsConnections.value[roleId] + if (connection) { + // 如果是新的WsAgent实例 + if (connection.agent && typeof connection.agent.close === 'function') { + connection.agent.close() + } + // 如果是旧的WebSocket实例 + else if (connection.connection && typeof connection.connection.close === 'function') { + connection.connection.close() + } + + delete wsConnections.value[roleId] + } + } + + const getWebSocketStatus = (roleId) => { + return wsConnections.value[roleId]?.status || 'disconnected' + } + + // 发送游戏命令 + const sendGameCommand = (roleId, commandName, params = {}) => { + const connection = wsConnections.value[roleId] + if (!connection || !connection.agent) { + console.warn(`角色 ${roleId} 的WebSocket连接不存在`) + return false + } + + if (connection.status !== 'connected') { + console.warn(`角色 ${roleId} 的WebSocket未连接`) + return false + } + + try { + const { gameCommands } = connection + + if (typeof gameCommands[commandName] === 'function') { + const command = gameCommands[commandName](0, 0, params) + connection.agent.send(command) + console.log(`发送游戏命令 [${roleId}] ${commandName}:`, params) + return true + } else { + console.error(`未知的游戏命令: ${commandName}`) + return false + } + } catch (error) { + console.error(`发送游戏命令失败 [${roleId}] ${commandName}:`, error) + return false + } + } + + // 发送游戏命令并等待响应 + const sendGameCommandWithPromise = async (roleId, commandName, params = {}, timeout = 8000) => { + const connection = wsConnections.value[roleId] + if (!connection || !connection.agent) { + throw new Error(`角色 ${roleId} 的WebSocket连接不存在`) + } + + if (connection.status !== 'connected') { + throw new Error(`角色 ${roleId} 的WebSocket未连接`) + } + + try { + const { gameCommands } = connection + + if (typeof gameCommands[commandName] === 'function') { + const response = await connection.agent.sendWithPromise({ + cmd: commandName, + body: params, + timeout + }) + console.log(`游戏命令响应 [${roleId}] ${commandName}:`, response) + return response + } else { + throw new Error(`未知的游戏命令: ${commandName}`) + } + } catch (error) { + console.error(`发送游戏命令失败 [${roleId}] ${commandName}:`, error) + throw error + } + } + + // 获取连接详细状态 + const getWebSocketDetails = (roleId) => { + const connection = wsConnections.value[roleId] + if (!connection) { + return { + status: 'disconnected', + roleId, + error: '连接不存在' + } + } + + return { + status: connection.status, + roleId: connection.roleId, + wsUrl: connection.wsUrl, + connectedAt: connection.connectedAt, + createdAt: connection.createdAt, + lastError: connection.lastError, + reconnectAttempt: connection.reconnectAttempt, + agentStatus: connection.agent ? connection.agent.getStatus() : null + } + } + + // 批量导入/导出功能 + const exportTokens = () => { + return { + userToken: userToken.value, + gameTokens: gameTokens.value, + exportedAt: new Date().toISOString() + } + } + + const importTokens = (tokenData) => { + try { + if (tokenData.userToken) { + setUserToken(tokenData.userToken) + } + + if (tokenData.gameTokens) { + gameTokens.value = tokenData.gameTokens + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + } + + return { success: true, message: 'Token导入成功' } + } catch (error) { + console.error('Token导入失败:', error) + return { success: false, message: '导入失败:数据格式错误' } + } + } + + // 清理过期token + const cleanExpiredTokens = () => { + const now = new Date() + const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000) + + const cleanedTokens = {} + let cleanedCount = 0 + + Object.entries(gameTokens.value).forEach(([roleId, tokenData]) => { + const lastUsed = new Date(tokenData.lastUsed || tokenData.createdAt) + if (lastUsed > oneDayAgo) { + cleanedTokens[roleId] = tokenData + } else { + cleanedCount++ + // 关闭对应的WebSocket连接 + if (wsConnections.value[roleId]) { + closeWebSocketConnection(roleId) + } + } + }) + + gameTokens.value = cleanedTokens + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + + return cleanedCount + } + + // 初始化 + const initTokenManager = () => { + // 从localStorage恢复数据 + const savedUserToken = localStorage.getItem('userToken') + const savedGameTokens = localStorage.getItem('gameTokens') + + if (savedUserToken) { + userToken.value = savedUserToken + } + + if (savedGameTokens) { + try { + gameTokens.value = JSON.parse(savedGameTokens) + } catch (error) { + console.error('解析游戏token数据失败:', error) + gameTokens.value = {} + } + } + + // 清理过期token + cleanExpiredTokens() + } + + return { + // 状态 + userToken, + gameTokens, + wsConnections, + + // 计算属性 + isUserAuthenticated, + hasGameTokens, + + // 用户token方法 + setUserToken, + clearUserToken, + + // 游戏token方法 + addGameToken, + getGameToken, + updateGameToken, + removeGameToken, + clearAllGameTokens, + + // WebSocket方法 + createWebSocketConnection, + closeWebSocketConnection, + getWebSocketStatus, + getWebSocketDetails, + sendGameCommand, + sendGameCommandWithPromise, + + // 工具方法 + exportTokens, + importTokens, + cleanExpiredTokens, + initTokenManager + } +}) \ No newline at end of file diff --git a/src/stores/tokenStore.js b/src/stores/tokenStore.js new file mode 100644 index 0000000..1a64a09 --- /dev/null +++ b/src/stores/tokenStore.js @@ -0,0 +1,792 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { bonProtocol, GameMessages, g_utils } from '../utils/bonProtocol.js' +import { XyzwWebSocketClient } from '../utils/xyzwWebSocket.js' + +/** + * 重构后的Token管理存储 + * 以名称-token列表形式管理多个游戏角色 + */ +export const useTokenStore = defineStore('tokens', () => { + // 状态 + const gameTokens = ref(JSON.parse(localStorage.getItem('gameTokens') || '[]')) + const selectedTokenId = ref(localStorage.getItem('selectedTokenId') || null) + const wsConnections = ref({}) // WebSocket连接状态 + + // 游戏数据存储 + const gameData = ref({ + roleInfo: null, + legionInfo: null, + presetTeam: null, + lastUpdated: null + }) + + // 计算属性 + const hasTokens = computed(() => gameTokens.value.length > 0) + const selectedToken = computed(() => + gameTokens.value.find(token => token.id === selectedTokenId.value) + ) + + // Token管理 + const addToken = (tokenData) => { + const newToken = { + id: 'token_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9), + name: tokenData.name, + token: tokenData.token, // 保存原始Base64 token + wsUrl: tokenData.wsUrl || null, // 可选的自定义WebSocket URL + server: tokenData.server || '', + level: tokenData.level || 1, + profession: tokenData.profession || '', + createdAt: new Date().toISOString(), + lastUsed: new Date().toISOString(), + isActive: true + } + + gameTokens.value.push(newToken) + saveTokensToStorage() + + return newToken + } + + const updateToken = (tokenId, updates) => { + const index = gameTokens.value.findIndex(token => token.id === tokenId) + if (index !== -1) { + gameTokens.value[index] = { + ...gameTokens.value[index], + ...updates, + updatedAt: new Date().toISOString() + } + saveTokensToStorage() + return true + } + return false + } + + const removeToken = (tokenId) => { + gameTokens.value = gameTokens.value.filter(token => token.id !== tokenId) + saveTokensToStorage() + + // 关闭对应的WebSocket连接 + if (wsConnections.value[tokenId]) { + closeWebSocketConnection(tokenId) + } + + // 如果删除的是当前选中token,清除选中状态 + if (selectedTokenId.value === tokenId) { + selectedTokenId.value = null + localStorage.removeItem('selectedTokenId') + } + + return true + } + + const selectToken = (tokenId) => { + const token = gameTokens.value.find(t => t.id === tokenId) + if (token) { + selectedTokenId.value = tokenId + localStorage.setItem('selectedTokenId', tokenId) + + // 更新最后使用时间 + updateToken(tokenId, { lastUsed: new Date().toISOString() }) + + // 自动建立WebSocket连接 + createWebSocketConnection(tokenId, token.token, token.wsUrl) + + return token + } + return null + } + + // 辅助函数:分析数据结构 + const analyzeDataStructure = (obj, depth = 0, maxDepth = 3) => { + if (depth > maxDepth || !obj || typeof obj !== 'object') { + return typeof obj + } + + const structure = {} + for (const [key, value] of Object.entries(obj)) { + if (Array.isArray(value)) { + structure[key] = `Array[${value.length}]${value.length > 0 ? `: ${analyzeDataStructure(value[0], depth + 1, maxDepth)}` : ''}` + } else if (typeof value === 'object' && value !== null) { + structure[key] = analyzeDataStructure(value, depth + 1, maxDepth) + } else { + structure[key] = typeof value + } + } + return structure + } + + // 辅助函数:尝试解析队伍数据 + const tryParseTeamData = (data, cmd) => { + console.log(`👥 尝试解析队伍数据 [${cmd}]:`, data) + + // 查找队伍相关字段 + const teamFields = [] + const scanForTeamData = (obj, path = '') => { + if (!obj || typeof obj !== 'object') return + + for (const [key, value] of Object.entries(obj)) { + const currentPath = path ? `${path}.${key}` : key + + if (key.toLowerCase().includes('team') || + key.toLowerCase().includes('preset') || + key.toLowerCase().includes('formation') || + key.toLowerCase().includes('lineup')) { + teamFields.push({ + path: currentPath, + key: key, + value: value, + type: typeof value, + isArray: Array.isArray(value) + }) + } + + if (typeof value === 'object' && value !== null && !Array.isArray(value)) { + scanForTeamData(value, currentPath) + } + } + } + + scanForTeamData(data) + + if (teamFields.length > 0) { + console.log(`👥 找到 ${teamFields.length} 个队伍相关字段:`, teamFields) + + // 尝试更新游戏数据 + teamFields.forEach(field => { + if (field.key === 'presetTeamInfo' || field.path.includes('presetTeamInfo')) { + console.log(`👥 发现预设队伍信息,准备更新:`, field.value) + if (!gameData.value.presetTeam) { + gameData.value.presetTeam = {} + } + gameData.value.presetTeam.presetTeamInfo = field.value + gameData.value.lastUpdated = new Date().toISOString() + } + }) + } else { + console.log(`👥 未找到明显的队伍字段,完整数据结构:`, analyzeDataStructure(data)) + } + } + + // 游戏消息处理 + const handleGameMessage = (tokenId, message) => { + try { + if (!message || message.error) { + console.warn(`⚠️ 消息处理跳过 [${tokenId}]:`, message?.error || '无效消息') + return + } + + const cmd = message.cmd?.toLowerCase() + // 优先使用rawData(ProtoMsg自动解码),然后decodedBody(手动解码),最后body(原始数据) + const body = message.rawData !== undefined ? message.rawData : + message.decodedBody !== undefined ? message.decodedBody : + message.body + + console.log(`📋 处理消息 [${tokenId}] ${cmd}:`, { + hasRawData: message.rawData !== undefined, + hasDecodedBody: message.decodedBody !== undefined, + hasBody: message.body !== undefined, + bodyType: body ? typeof body : 'undefined', + bodyContent: body, + originalCmd: message.cmd, + fullMessage: message + }) + + // 记录所有消息的原始命令名 + console.log(`📨 收到消息 [${tokenId}] 原始cmd: "${message.cmd}", 处理cmd: "${cmd}"`) + + // 特别记录所有包含tower的消息 + if (cmd && cmd.includes('tower')) { + console.log(`🗼 发现塔相关消息 [${tokenId}] ${cmd}:`, message) + } + + // 处理角色信息 - 支持多种可能的响应命令 + if (cmd === 'role_getroleinfo' || cmd === 'role_getroleinforesp' || cmd.includes('role') && cmd.includes('info')) { + console.log(`📊 匹配到角色信息命令: ${cmd}`) + + if (body) { + gameData.value.roleInfo = body + gameData.value.lastUpdated = new Date().toISOString() + console.log('📊 角色信息已更新:', body) + console.log('📊 角色信息类型:', typeof body) + console.log('📊 角色信息内容概览:', Object.keys(body || {})) + + // 特别检查塔信息 + if (body.role?.tower) { + console.log('🗼 在角色信息中找到塔信息:', body.role.tower) + } else if (body.tower) { + console.log('🗼 在响应根级别找到塔信息:', body.tower) + } else { + console.log('🗼 未找到塔信息在角色数据中') + console.log('📊 角色数据结构:', body.role ? Object.keys(body.role) : '没有role对象') + } + } else { + console.log('📊 角色信息响应body为空') + } + } + + // 处理军团信息 + else if (cmd === 'legion_getinfo') { + if (body) { + gameData.value.legionInfo = body + console.log('🏛️ 军团信息已更新:', body) + } + } + + // 处理队伍信息 - 支持多种队伍相关响应 + else if (cmd === 'presetteam_getteam' || cmd === 'presetteam_getteamresp' || + cmd === 'presetteam_setteam' || cmd === 'presetteam_setteamresp' || + cmd === 'presetteam_saveteam' || cmd === 'presetteam_saveteamresp' || + cmd === 'role_gettargetteam' || cmd === 'role_gettargetteamresp' || + (cmd && cmd.includes('presetteam')) || (cmd && cmd.includes('team'))) { + console.log(`👥 匹配到队伍信息命令: ${cmd}`) + + if (body) { + // 更新队伍数据 + if (!gameData.value.presetTeam) { + gameData.value.presetTeam = {} + } + + // 根据不同的响应类型处理数据 + if (cmd.includes('getteam')) { + // 获取队伍信息响应 + gameData.value.presetTeam = { ...gameData.value.presetTeam, ...body } + } else if (cmd.includes('setteam') || cmd.includes('saveteam')) { + // 设置/保存队伍响应 - 可能只返回确认信息 + if (body.presetTeamInfo) { + gameData.value.presetTeam.presetTeamInfo = body.presetTeamInfo + } + // 合并其他队伍相关数据 + Object.keys(body).forEach(key => { + if (key.includes('team') || key.includes('Team')) { + gameData.value.presetTeam[key] = body[key] + } + }) + } else { + // 其他队伍相关响应 + gameData.value.presetTeam = { ...gameData.value.presetTeam, ...body } + } + + gameData.value.lastUpdated = new Date().toISOString() + console.log('👥 队伍信息已更新:', { + cmd: cmd, + updatedData: gameData.value.presetTeam, + bodyKeys: Object.keys(body), + bodyContent: body + }) + + // 详细日志队伍数据结构 + if (gameData.value.presetTeam.presetTeamInfo) { + console.log('👥 队伍详细结构:', { + teamCount: Object.keys(gameData.value.presetTeam.presetTeamInfo).length, + teamIds: Object.keys(gameData.value.presetTeam.presetTeamInfo), + useTeamId: gameData.value.presetTeam.presetTeamInfo.useTeamId, + sampleTeam: gameData.value.presetTeam.presetTeamInfo[1] || gameData.value.presetTeam.presetTeamInfo[Object.keys(gameData.value.presetTeam.presetTeamInfo)[0]] + }) + } + } else { + console.log('👥 队伍信息响应body为空') + } + } + + // 处理爬塔响应 + else if (cmd === 'fight_starttower' || cmd === 'fight_starttowerresp') { + if (body) { + console.log('🗼 爬塔响应:', body) + // 爬塔后立即更新角色信息和塔信息 + setTimeout(() => { + console.log('🗼 爬塔后自动更新数据') + try { + const connection = wsConnections.value[tokenId] + if (connection && connection.status === 'connected' && connection.client) { + // 获取最新角色信息 + console.log('🗼 正在请求角色信息...') + connection.client.send('role_getroleinfo', {}) + } else { + console.warn('🗼 WebSocket未连接,无法更新数据') + } + } catch (error) { + console.warn('爬塔后更新数据失败:', error) + } + }, 1000) + } + } + + // 处理心跳响应 + else if (cmd === '_sys/ack') { + console.log(`💗 心跳响应 [${tokenId}]`) + } + + // 处理其他消息 + else { + console.log(`📋 收到游戏消息 [${tokenId}] ${cmd}:`, body) + + // 特别关注队伍相关的未处理消息 + if (cmd && (cmd.includes('team') || cmd.includes('preset') || cmd.includes('formation'))) { + console.log(`👥 未处理的队伍相关消息 [${tokenId}] ${cmd}:`, { + originalMessage: message, + parsedBody: body, + messageKeys: Object.keys(message || {}), + bodyStructure: body ? analyzeDataStructure(body) : null + }) + + // 尝试自动解析队伍数据 + if (body && typeof body === 'object') { + tryParseTeamData(body, cmd) + } + } + + // 特别关注塔相关的未处理消息 + if (cmd && cmd.includes('tower')) { + console.log(`🗼 未处理的塔相关消息 [${tokenId}] ${cmd}:`, { + originalMessage: message, + parsedBody: body, + messageKeys: Object.keys(message || {}) + }) + } + } + + } catch (error) { + console.error('处理游戏消息失败:', error) + } + } + + // Base64解析功能 + const parseBase64Token = (base64String) => { + try { + // 移除可能的前缀和空格 + const cleanBase64 = base64String.replace(/^data:.*base64,/, '').trim() + + // 解码base64 + const decoded = atob(cleanBase64) + + // 尝试解析为JSON + let tokenData + try { + tokenData = JSON.parse(decoded) + } catch { + // 如果不是JSON,当作纯token字符串处理 + tokenData = { token: decoded } + } + + return { + success: true, + data: tokenData + } + } catch (error) { + return { + success: false, + error: '解析失败:' + error.message + } + } + } + + const importBase64Token = (name, base64String, additionalInfo = {}) => { + const parseResult = parseBase64Token(base64String) + + if (!parseResult.success) { + return parseResult + } + + const tokenData = { + name, + token: parseResult.data.token || parseResult.data.gameToken || base64String, + ...additionalInfo, + ...parseResult.data // 解析出的数据覆盖手动输入 + } + + const newToken = addToken(tokenData) + + return { + success: true, + data: newToken, + message: `Token "${name}" 导入成功` + } + } + + // WebSocket连接管理 + const createWebSocketConnection = (tokenId, base64Token, customWsUrl = null) => { + if (wsConnections.value[tokenId]) { + closeWebSocketConnection(tokenId) + } + + try { + // 解析Base64获取实际Token + let actualToken = base64Token + + // 尝试解析Base64获取实际token + try { + const cleanBase64 = base64Token.replace(/^data:.*base64,/, '').trim() + const decoded = atob(cleanBase64) + + // 尝试解析为JSON获取token字段 + try { + const tokenData = JSON.parse(decoded) + actualToken = tokenData.token || tokenData.gameToken || decoded + } catch { + // 如果不是JSON,直接使用解码后的字符串 + actualToken = decoded + } + } catch (error) { + console.warn('Base64解析失败,使用原始token:', error.message) + actualToken = base64Token + } + + // 使用固定的WebSocket基础地址,将token带入占位符 + const baseWsUrl = 'wss://xxz-xyzw.hortorgames.com/agent?p=%s&e=x&lang=chinese' + const wsUrl = customWsUrl || baseWsUrl.replace('%s', encodeURIComponent(actualToken)) + + console.log(`🔗 创建WebSocket连接:`, wsUrl) + console.log(`🎯 Token ID: ${tokenId}`) + console.log(`🔑 使用Token: ${actualToken.substring(0, 20)}...`) + + // 检查g_utils结构 + console.log('🔍 g_utils结构检查:', { + hasGetEnc: !!g_utils.getEnc, + hasEncode: !!g_utils.encode, + hasParse: !!g_utils.parse, + hasBon: !!g_utils.bon, + bonHasDecode: !!(g_utils.bon && g_utils.bon.decode) + }) + + // 创建新的WebSocket客户端 + const wsClient = new XyzwWebSocketClient({ + url: wsUrl, + utils: g_utils, + heartbeatMs: 5000 // 5秒心跳间隔 + }) + + // 设置连接状态 + wsConnections.value[tokenId] = { + client: wsClient, + status: 'connecting', + tokenId, + wsUrl, + actualToken, + connectedAt: null, + lastMessage: null, + lastError: null + } + + // 设置事件监听 + wsClient.onConnect = () => { + console.log(`✅ WebSocket连接已建立: ${tokenId}`) + if (wsConnections.value[tokenId]) { + wsConnections.value[tokenId].status = 'connected' + wsConnections.value[tokenId].connectedAt = new Date().toISOString() + } + } + + wsClient.onDisconnect = (event) => { + console.log(`🔌 WebSocket连接已断开: ${tokenId}`, event) + if (wsConnections.value[tokenId]) { + wsConnections.value[tokenId].status = 'disconnected' + } + } + + wsClient.onError = (error) => { + console.error(`❌ WebSocket错误 [${tokenId}]:`, error) + if (wsConnections.value[tokenId]) { + wsConnections.value[tokenId].status = 'error' + wsConnections.value[tokenId].lastError = { + timestamp: new Date().toISOString(), + error: error.toString(), + url: wsUrl + } + } + } + + // 设置消息监听 + wsClient.setMessageListener((message) => { + console.log(`📨 收到消息 [${tokenId}]:`, message) + + // 更新连接状态中的最后接收消息 + if (wsConnections.value[tokenId]) { + wsConnections.value[tokenId].lastMessage = { + timestamp: new Date().toISOString(), + data: message + } + } + + // 处理游戏消息 + handleGameMessage(tokenId, message) + }) + + // 开启调试模式 + wsClient.setShowMsg(true) + + // 初始化连接 + wsClient.init() + + return wsClient + } catch (error) { + console.error(`创建WebSocket连接失败 [${tokenId}]:`, error) + return null + } + } + + const closeWebSocketConnection = (tokenId) => { + const connection = wsConnections.value[tokenId] + if (connection && connection.client) { + connection.client.disconnect() + delete wsConnections.value[tokenId] + } + } + + const getWebSocketStatus = (tokenId) => { + return wsConnections.value[tokenId]?.status || 'disconnected' + } + + // 获取WebSocket客户端 + const getWebSocketClient = (tokenId) => { + return wsConnections.value[tokenId]?.client || null + } + + + // 发送消息到WebSocket + const sendMessage = (tokenId, cmd, params = {}, options = {}) => { + const connection = wsConnections.value[tokenId] + if (!connection || connection.status !== 'connected') { + console.error(`❌ WebSocket未连接,无法发送消息 [${tokenId}]`) + return false + } + + try { + const client = connection.client + if (!client) { + console.error(`❌ WebSocket客户端不存在 [${tokenId}]`) + return false + } + + client.send(cmd, params, options) + console.log(`📤 发送消息 [${tokenId}]: ${cmd}`, params) + + return true + } catch (error) { + console.error(`❌ 发送消息失败 [${tokenId}]:`, error) + return false + } + } + + // Promise版发送消息 + const sendMessageWithPromise = async (tokenId, cmd, params = {}, timeout = 5000) => { + const connection = wsConnections.value[tokenId] + if (!connection || connection.status !== 'connected') { + throw new Error(`WebSocket未连接 [${tokenId}]`) + } + + const client = connection.client + if (!client) { + throw new Error(`WebSocket客户端不存在 [${tokenId}]`) + } + + return await client.sendWithPromise(cmd, params, timeout) + } + + // 发送心跳消息 + const sendHeartbeat = (tokenId) => { + return sendMessage(tokenId, 'heart_beat') + } + + // 发送获取角色信息请求 + const sendGetRoleInfo = (tokenId, params = {}) => { + return sendMessageWithPromise(tokenId, 'role_getroleinfo', params) + } + + // 发送获取数据版本请求 + const sendGetDataBundleVersion = (tokenId, params = {}) => { + return sendMessageWithPromise(tokenId, 'system_getdatabundlever', params) + } + + // 发送签到请求 + const sendSignIn = (tokenId) => { + return sendMessageWithPromise(tokenId, 'system_signinreward') + } + + // 发送领取日常任务奖励 + const sendClaimDailyReward = (tokenId, rewardId = 0) => { + return sendMessageWithPromise(tokenId, 'task_claimdailyreward', { rewardId }) + } + + // 发送获取队伍信息 + const sendGetTeamInfo = (tokenId, params = {}) => { + return sendMessageWithPromise(tokenId, 'presetteam_getteam', params) + } + + // 发送自定义游戏消息 + const sendGameMessage = (tokenId, cmd, params = {}, options = {}) => { + if (options.usePromise) { + return sendMessageWithPromise(tokenId, cmd, params, options.timeout) + } else { + return sendMessage(tokenId, cmd, params, options) + } + } + + // 获取当前塔层数 + const getCurrentTowerLevel = () => { + try { + // 从游戏数据中获取塔信息 + const roleInfo = gameData.value.roleInfo + if (!roleInfo || !roleInfo.role) { + console.warn('⚠️ 角色信息不存在') + return null + } + + const tower = roleInfo.role.tower + if (!tower) { + console.warn('⚠️ 塔信息不存在') + return null + } + + // 可能的塔层数字段(根据实际数据结构调整) + const level = tower.level || tower.currentLevel || tower.floor || tower.stage + + console.log('🗼 当前塔层数:', level, '塔信息:', tower) + return level + } catch (error) { + console.error('❌ 获取塔层数失败:', error) + return null + } + } + + // 获取详细塔信息 + const getTowerInfo = () => { + try { + const roleInfo = gameData.value.roleInfo + if (!roleInfo || !roleInfo.role) { + return null + } + + return roleInfo.role.tower || null + } catch (error) { + console.error('❌ 获取塔信息失败:', error) + return null + } + } + + // 工具方法 + const exportTokens = () => { + return { + tokens: gameTokens.value, + exportedAt: new Date().toISOString(), + version: '2.0' + } + } + + const importTokens = (data) => { + try { + if (data.tokens && Array.isArray(data.tokens)) { + gameTokens.value = data.tokens + saveTokensToStorage() + return { success: true, message: `成功导入 ${data.tokens.length} 个Token` } + } else { + return { success: false, message: '导入数据格式错误' } + } + } catch (error) { + return { success: false, message: '导入失败:' + error.message } + } + } + + const clearAllTokens = () => { + // 关闭所有WebSocket连接 + Object.keys(wsConnections.value).forEach(tokenId => { + closeWebSocketConnection(tokenId) + }) + + gameTokens.value = [] + selectedTokenId.value = null + localStorage.removeItem('gameTokens') + localStorage.removeItem('selectedTokenId') + } + + const cleanExpiredTokens = () => { + const now = new Date() + const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000) + + const cleanedTokens = gameTokens.value.filter(token => { + const lastUsed = new Date(token.lastUsed || token.createdAt) + return lastUsed > oneDayAgo + }) + + const cleanedCount = gameTokens.value.length - cleanedTokens.length + gameTokens.value = cleanedTokens + saveTokensToStorage() + + return cleanedCount + } + + const saveTokensToStorage = () => { + localStorage.setItem('gameTokens', JSON.stringify(gameTokens.value)) + } + + // 初始化 + const initTokenStore = () => { + // 恢复数据 + const savedTokens = localStorage.getItem('gameTokens') + const savedSelectedId = localStorage.getItem('selectedTokenId') + + if (savedTokens) { + try { + gameTokens.value = JSON.parse(savedTokens) + } catch (error) { + console.error('解析Token数据失败:', error) + gameTokens.value = [] + } + } + + if (savedSelectedId) { + selectedTokenId.value = savedSelectedId + } + + // 清理过期token + cleanExpiredTokens() + } + + return { + // 状态 + gameTokens, + selectedTokenId, + wsConnections, + gameData, + + // 计算属性 + hasTokens, + selectedToken, + + // Token管理方法 + addToken, + updateToken, + removeToken, + selectToken, + + // Base64解析方法 + parseBase64Token, + importBase64Token, + + // WebSocket方法 + createWebSocketConnection, + closeWebSocketConnection, + getWebSocketStatus, + getWebSocketClient, + sendMessage, + sendMessageWithPromise, + sendHeartbeat, + sendGetRoleInfo, + sendGetDataBundleVersion, + sendSignIn, + sendClaimDailyReward, + sendGetTeamInfo, + sendGameMessage, + + // 工具方法 + exportTokens, + importTokens, + clearAllTokens, + cleanExpiredTokens, + initTokenStore, + + // 塔信息方法 + getCurrentTowerLevel, + getTowerInfo + } +}) diff --git a/src/utils/bonProtocol.js b/src/utils/bonProtocol.js new file mode 100644 index 0000000..882d7a2 --- /dev/null +++ b/src/utils/bonProtocol.js @@ -0,0 +1,779 @@ +/** + * BON (Binary Object Notation) 协议实现 + * 基于提供的真实 BON 源码重新实现 + */ +import lz4 from 'lz4js'; + +// ----------------------------- +// BON 编解码器核心实现 +// ----------------------------- + +export class Int64 { + constructor(high, low) { + this.high = high; + this.low = low; + } +} + +export class DataReader { + constructor(bytes) { + this._data = bytes || new Uint8Array(0); + this._view = null; + this.position = 0; + } + + get data() { return this._data; } + get dataView() { + return this._view || (this._view = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength)); + } + + reset(bytes) { + this._data = bytes; + this.position = 0; + this._view = null; + } + + validate(n) { + if (this.position + n > this._data.length) { + console.error('read eof'); + return false; + } + return true; + } + + readUInt8() { + if (!this.validate(1)) return; + return this._data[this.position++]; + } + + readInt16() { + if (!this.validate(2)) return; + const v = this._data[this.position++] | (this._data[this.position++] << 8); + return (v << 16) >> 16; + } + + readInt32() { + if (!this.validate(4)) return; + const v = this._data[this.position++] | (this._data[this.position++] << 8) | (this._data[this.position++] << 16) | (this._data[this.position++] << 24); + return v | 0; + } + + readInt64() { + const lo = this.readInt32(); + if (lo === undefined) return; + let _lo = lo; + if (_lo < 0) _lo += 0x100000000; + const hi = this.readInt32(); + if (hi === undefined) return; + return _lo + 0x100000000 * hi; + } + + readFloat32() { + if (!this.validate(4)) return; + const v = this.dataView.getFloat32(this.position, true); + this.position += 4; + return v; + } + + readFloat64() { + if (!this.validate(8)) return; + const v = this.dataView.getFloat64(this.position, true); + this.position += 8; + return v; + } + + read7BitInt() { + let value = 0; + let shift = 0; + let b = 0; + let count = 0; + do { + if (count++ === 35) throw new Error('Format_Bad7BitInt32'); + b = this.readUInt8(); + value |= (b & 0x7F) << shift; + shift += 7; + } while ((b & 0x80) !== 0); + return value >>> 0; + } + + readUTF() { + const len = this.read7BitInt(); + return this.readUTFBytes(len); + } + + readUint8Array(length, copy = false) { + const start = this.position; + const end = start + length; + const out = copy ? this._data.slice(start, end) : this._data.subarray(start, end); + this.position = end; + return out; + } + + readUTFBytes(length) { + if (length === 0) return ''; + if (!this.validate(length)) return; + const str = new TextDecoder('utf8').decode(this._data.subarray(this.position, this.position + length)); + this.position += length; + return str; + } +} + +let _shared = new Uint8Array(524288); // 512 KB initial buffer + +export class DataWriter { + constructor() { + this.position = 0; + this._view = null; + this.data = _shared; + } + + get dataView() { + return this._view || (this._view = new DataView(this.data.buffer, 0, this.data.byteLength)); + } + + reset() { + this.data = _shared; + this._view = null; + this.position = 0; + } + + ensureBuffer(size) { + if (this.position + size <= _shared.byteLength) return; + const prev = _shared; + const need = this.position + size; + const nextLen = Math.max(Math.floor((_shared.byteLength * 12) / 10), need); + _shared = new Uint8Array(nextLen); + _shared.set(prev, 0); + this.data = _shared; + this._view = null; + } + + writeInt8(v) { + this.ensureBuffer(1); + this.data[this.position++] = v | 0; + } + + writeInt16(v) { + this.ensureBuffer(2); + this.data[this.position++] = v | 0; + this.data[this.position++] = (v >> 8) & 0xFF; + } + + writeInt32(v) { + this.ensureBuffer(4); + this.data[this.position++] = v | 0; + this.data[this.position++] = (v >> 8) & 0xFF; + this.data[this.position++] = (v >> 16) & 0xFF; + this.data[this.position++] = (v >> 24) & 0xFF; + } + + writeInt64(v) { + this.writeInt32(v); + if (v < 0) { + this.writeInt32(~Math.floor((-v) / 0x100000000)); + } else { + this.writeInt32(Math.floor(v / 0x100000000) | 0); + } + } + + writeFloat32(v) { + this.ensureBuffer(4); + this.dataView.setFloat32(this.position, v, true); + this.position += 4; + } + + writeFloat64(v) { + this.ensureBuffer(8); + this.dataView.setFloat64(this.position, v, true); + this.position += 8; + } + + _write7BitInt(v) { + let n = v >>> 0; + while (n >= 0x80) { + this.data[this.position++] = (n & 0xFF) | 0x80; + n >>>= 7; + } + this.data[this.position++] = n & 0x7F; + } + + write7BitInt(v) { + this.ensureBuffer(5); + this._write7BitInt(v); + } + + _7BitIntLen(v) { + return v < 0 ? 5 + : v < 0x80 ? 1 + : v < 0x4000 ? 2 + : v < 0x200000 ? 3 + : v < 0x10000000 ? 4 + : 5; + } + + writeUTF(str) { + const t = str.length; + if (t === 0) { + this.write7BitInt(0); + return; + } + const max = 6 * t; + this.ensureBuffer(5 + max); + const start = this.position; + this.position += this._7BitIntLen(max); + const from = this.position; + const reserved = from - start; + + const encoder = new TextEncoder(); + const { written } = encoder.encodeInto(str, this.data.subarray(this.position)); + this.position += written; + const after = this.position; + const size = after - from; + + this.position = start; + this._write7BitInt(size); + const used = this.position - start; + if (used !== reserved) { + this.data.copyWithin(from + (used - reserved), from, after); + } + this.position = from + size + (used - reserved); + } + + writeUint8Array(src, offset = 0, length) { + const start = offset | 0; + const end = Math.min(src.byteLength, start + (length ?? src.byteLength)); + const n = end - start; + if (n <= 0) return; + this.ensureBuffer(n); + this.data.set(src.subarray(start, end), this.position); + this.position += n; + } + + writeUTFBytes(str) { + this.ensureBuffer(6 * str.length); + const encoder = new TextEncoder(); + const { written } = encoder.encodeInto(str, this.data.subarray(this.position)); + this.position += written; + } + + getBytes(clone = false) { + return clone ? this.data.slice(0, this.position) : this.data.subarray(0, this.position); + } +} + +export class BonEncoder { + constructor() { + this.dw = new DataWriter(); + this.strMap = new Map(); + } + + reset() { + this.dw.reset(); + this.strMap.clear(); + } + + encodeInt(v) { + this.dw.writeInt8(1); + this.dw.writeInt32(v | 0); + } + + encodeLong(v) { + this.dw.writeInt8(2); + if (typeof v === 'number') { + this.dw.writeInt64(v); + } else { + this.dw.writeInt32(v.low | 0); + this.dw.writeInt32(v.high | 0); + } + } + + encodeFloat(v) { + this.dw.writeInt8(3); + this.dw.writeFloat32(v); + } + + encodeDouble(v) { + this.dw.writeInt8(4); + this.dw.writeFloat64(v); + } + + encodeNumber(v) { + if ((v | 0) === v) this.encodeInt(v); + else if (Math.floor(v) === v) this.encodeLong(v); + else this.encodeDouble(v); + } + + encodeString(s) { + const hit = this.strMap.get(s); + if (hit !== undefined) { + this.dw.writeInt8(99); // StringRef + this.dw.write7BitInt(hit); + return; + } + this.dw.writeInt8(5); // String + this.dw.writeUTF(s); + this.strMap.set(s, this.strMap.size); + } + + encodeBoolean(b) { + this.dw.writeInt8(6); + this.dw.writeInt8(b ? 1 : 0); + } + + encodeNull() { + this.dw.writeInt8(0); + } + + encodeDateTime(d) { + this.dw.writeInt8(10); + this.dw.writeInt64(d.getTime()); + } + + encodeBinary(u8) { + this.dw.writeInt8(7); + this.dw.write7BitInt(u8.byteLength); + this.dw.writeUint8Array(u8); + } + + encodeArray(arr) { + this.dw.writeInt8(9); + this.dw.write7BitInt(arr.length); + for (let i = 0; i < arr.length; i++) this.encode(arr[i]); + } + + encodeMap(mp) { + this.dw.writeInt8(8); + this.dw.write7BitInt(mp.size); + mp.forEach((v, k) => { + this.encode(k); + this.encode(v); + }); + } + + encodeObject(obj) { + this.dw.writeInt8(8); + const keys = []; + for (const k in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, k)) continue; + if (k.startsWith('_')) continue; + const type = typeof obj[k]; + if (type === 'function' || type === 'undefined') continue; + keys.push(k); + } + this.dw.write7BitInt(keys.length); + for (const k of keys) { + this.encode(k); + this.encode(obj[k]); + } + } + + encode(v) { + if (v == null) { + this.encodeNull(); + return; + } + switch (v.constructor) { + case Number: + this.encodeNumber(v); + return; + case Boolean: + this.encodeBoolean(v); + return; + case String: + this.encodeString(v); + return; + case Int64: + this.encodeLong(v); + return; + case Array: + this.encodeArray(v); + return; + case Map: + this.encodeMap(v); + return; + case Date: + this.encodeDateTime(v); + return; + case Uint8Array: + this.encodeBinary(v); + return; + default: + if (typeof v !== 'object') { + this.encodeNull(); + return; + } + this.encodeObject(v); + return; + } + } + + getBytes(clone = false) { + return this.dw.getBytes(clone); + } +} + +export class BonDecoder { + constructor() { + this.dr = new DataReader(new Uint8Array(0)); + this.strArr = []; + } + + reset(bytes) { + this.dr.reset(bytes); + this.strArr.length = 0; + } + + decode() { + const tag = this.dr.readUInt8(); + switch (tag) { + default: + return null; + case 1: + return this.dr.readInt32(); + case 2: + return this.dr.readInt64(); + case 3: + return this.dr.readFloat32(); + case 4: + return this.dr.readFloat64(); + case 5: { + const s = this.dr.readUTF(); + this.strArr.push(s); + return s; + } + case 6: + return this.dr.readUInt8() === 1; + case 7: { + const len = this.dr.read7BitInt(); + return this.dr.readUint8Array(len, false); + } + case 8: { + const count = this.dr.read7BitInt(); + const obj = {}; + for (let i = 0; i < count; i++) { + const k = this.decode(); + const v = this.decode(); + obj[k] = v; + } + return obj; + } + case 9: { + const len = this.dr.read7BitInt(); + const arr = new Array(len); + for (let i = 0; i < len; i++) arr[i] = this.decode(); + return arr; + } + case 10: + return new Date(this.dr.readInt64()); + case 99: + return this.strArr[this.dr.read7BitInt()]; + } + } +} + +// 单例实例 +const _enc = new BonEncoder(); +const _dec = new BonDecoder(); + +// BON 编解码函数 +export const bon = { + encode: (value, clone = true) => { + _enc.reset(); + _enc.encode(value); + return _enc.getBytes(clone); + }, + decode: (bytes) => { + _dec.reset(bytes); + return _dec.decode(); + } +}; + +/** —— 协议消息包装,与原 ProtoMsg 类等价 —— */ +export class ProtoMsg { + constructor(raw) { + if (raw?.cmd) { + raw.cmd = raw.cmd.toLowerCase(); + } + this._raw = raw; + this._rawData = undefined; + this._data = undefined; + this._t = undefined; + this._sendMsg = undefined; + this.rtt = 0; + } + + get sendMsg() { return this._sendMsg; } + get seq() { return this._raw.seq; } + get resp() { return this._raw.resp; } + get ack() { return this._raw.ack; } + get cmd() { return this._raw?.cmd && this._raw?.cmd.toLowerCase(); } + get code() { return ~~this._raw.code; } + get error() { return this._raw.error; } + get time() { return this._raw.time; } + get body() { return this._raw.body; } + + /** 惰性 decode body → rawData(bon.decode) */ + get rawData() { + if (this._rawData !== undefined || this.body === undefined) return this._rawData; + this._rawData = bon.decode(this.body); + return this._rawData; + } + + /** 指定数据类型 */ + setDataType(t) { + if (t) this._t = { name: t.name ?? 'Anonymous', ctor: t }; + return this; + } + + /** 配置"请求"对象,让 respType 自动对齐 */ + setSendMsg(msg) { + this._sendMsg = msg; + return this.setDataType(msg.respType); + } + + /** 将 rawData 反序列化为业务对象 */ + getData(clazz) { + if (this._data !== undefined || this.rawData === undefined) return this._data; + + let t = this._t; + if (clazz && t && clazz !== t.ctor) { + console.warn(`getData type not match, ${clazz.name} != ${t.name}`); + t = { name: clazz.name, ctor: clazz }; + } + + this._data = this.rawData; + return this._data; + } + + toLogString() { + const e = { ...this._raw }; + delete e.body; + e.data = this.rawData; + e.rtt = this.rtt; + return JSON.stringify(e); + } +} + +/** —— 加解密器注册表 —— */ +const registry = new Map(); + +/** lz4 + 头部掩码的 "lx" 方案 */ +const lx = { + encrypt: (buf) => { + let e = lz4.compress(buf); + const t = 2 + ~~(Math.random() * 248); + for (let n = Math.min(e.length, 100); --n >= 0; ) e[n] ^= t; + + // 写入标识与混淆位 + e[0] = 112; e[1] = 108; + e[2] = (e[2] & 0b10101010) | ((t >> 7 & 1) << 6) | ((t >> 6 & 1) << 4) | ((t >> 5 & 1) << 2) | (t >> 4 & 1); + e[3] = (e[3] & 0b10101010) | ((t >> 3 & 1) << 6) | ((t >> 2 & 1) << 4) | ((t >> 1 & 1) << 2) | (t & 1); + return e; + }, + decrypt: (e) => { + const t = + ((e[2] >> 6 & 1) << 7) | ((e[2] >> 4 & 1) << 6) | ((e[2] >> 2 & 1) << 5) | ((e[2] & 1) << 4) | + ((e[3] >> 6 & 1) << 3) | ((e[3] >> 4 & 1) << 2) | ((e[3] >> 2 & 1) << 1) | (e[3] & 1); + for (let n = Math.min(100, e.length); --n >= 2; ) e[n] ^= t; + e[0] = 4; e[1] = 34; e[2] = 77; e[3] = 24; // 还原头以便 lz4 解 + return lz4.decompress(e); + } +}; + +/** 随机首 4 字节 + XOR 的 "x" 方案 */ +const x = { + encrypt: (e) => { + const rnd = ~~(Math.random() * 0xFFFFFFFF) >>> 0; + const n = new Uint8Array(e.length + 4); + n[0] = rnd & 0xFF; n[1] = (rnd >>> 8) & 0xFF; n[2] = (rnd >>> 16) & 0xFF; n[3] = (rnd >>> 24) & 0xFF; + n.set(e, 4); + const r = 2 + ~~(Math.random() * 248); + for (let i = n.length; --i >= 0; ) n[i] ^= r; + n[0] = 112; n[1] = 120; + n[2] = (n[2] & 0b10101010) | ((r >> 7 & 1) << 6) | ((r >> 6 & 1) << 4) | ((r >> 5 & 1) << 2) | (r >> 4 & 1); + n[3] = (n[3] & 0b10101010) | ((r >> 3 & 1) << 6) | ((r >> 2 & 1) << 4) | ((r >> 1 & 1) << 2) | (r & 1); + return n; + }, + decrypt: (e) => { + const t = + ((e[2] >> 6 & 1) << 7) | ((e[2] >> 4 & 1) << 6) | ((e[2] >> 2 & 1) << 5) | ((e[2] & 1) << 4) | + ((e[3] >> 6 & 1) << 3) | ((e[3] >> 4 & 1) << 2) | ((e[3] >> 2 & 1) << 1) | (e[3] & 1); + for (let n = e.length; --n >= 4; ) e[n] ^= t; + return e.subarray(4); + } +}; + +/** 依赖 globalThis.XXTEA 的 "xtm" 方案 */ +const xtm = { + encrypt: (e) => globalThis.XXTEA ? globalThis.XXTEA.encryptMod({ data: e.buffer, length: e.length }) : e, + decrypt: (e) => globalThis.XXTEA ? globalThis.XXTEA.decryptMod({ data: e.buffer, length: e.length }) : e, +}; + +/** 注册器 */ +function register(name, impl) { + registry.set(name, impl); +} + +register('lx', lx); +register('x', x); +register('xtm', xtm); + +/** 默认使用 x 加密(自动检测解密) */ +const passthrough = { + encrypt: (e) => getEnc('x').encrypt(e), + decrypt: (e) => { + if (e.length > 4 && e[0] === 112 && e[1] === 108) e = getEnc('lx').decrypt(e); + else if (e.length > 4 && e[0] === 112 && e[1] === 120) e = getEnc('x').decrypt(e); + else if (e.length > 3 && e[0] === 112 && e[1] === 116) e = getEnc('xtm').decrypt(e); + return e; + } +}; + +/** 对外:按名称取加解密器;找不到则用默认 */ +export function getEnc(name) { + return registry.get(name) ?? passthrough; +} + +/** 对外:encode(bon.encode → 加密) */ +export function encode(obj, enc) { + let bytes = bon.encode(obj, false); + const out = enc.encrypt(bytes); + return out.buffer.byteLength === out.length ? out.buffer : out.buffer.slice(0, out.length); +} + +/** 对外:parse(解密 → bon.decode → ProtoMsg) */ +export function parse(buf, enc) { + const u8 = new Uint8Array(buf); + const plain = enc.decrypt(u8); + const raw = bon.decode(plain); + return new ProtoMsg(raw); +} + +// 游戏消息模板 +export const GameMessages = { + // 心跳消息 + heartBeat: (ack = 0, seq = 0) => ({ + ack, + body: undefined, + c: undefined, + cmd: "_sys/ack", + hint: undefined, + seq, + time: Date.now() + }), + + // 获取角色信息 + getRoleInfo: (ack = 0, seq = 0, params = {}) => ({ + cmd: "role_getroleinfo", + body: encode({ + clientVersion: "1.65.3-wx", + inviteUid: 0, + platform: "hortor", + platformExt: "mix", + scene: "", + ...params + }, getEnc('x')), + ack: ack || 0, + seq: seq || 0, + time: Date.now() + }), + + // 获取数据包版本 + getDataBundleVer: (ack = 0, seq = 0, params = {}) => ({ + cmd: "system_getdatabundlever", + body: encode({ + isAudit: false, + ...params + }, getEnc('x')), + ack: ack || 0, + seq: seq || 0, + time: Date.now() + }), + + // 购买金币 + buyGold: (ack = 0, seq = 0, params = {}) => ({ + ack, + body: encode({ + buyNum: 1, + ...params + }, getEnc('x')), + cmd: "system_buygold", + seq, + time: Date.now() + }), + + // 签到奖励 + signInReward: (ack = 0, seq = 0, params = {}) => ({ + ack, + body: encode({ + ...params + }, getEnc('x')), + cmd: "system_signinreward", + seq, + time: Date.now() + }), + + // 领取每日任务奖励 + claimDailyReward: (ack = 0, seq = 0, params = {}) => ({ + ack, + body: encode({ + rewardId: 0, + ...params + }, getEnc('x')), + cmd: "task_claimdailyreward", + seq, + time: Date.now() + }) +}; + +// 创建全局实例 +export const g_utils = { + getEnc, + encode: (obj, encName = 'x') => encode(obj, getEnc(encName)), + parse: (data, encName = 'auto') => parse(data, getEnc(encName)), + bon // 添加BON编解码器 +}; + +// 兼容性导出(保持旧的接口) +export const bonProtocol = { + encode: bon.encode, + decode: bon.decode, + createMessage: (cmd, body = {}, ack = 0, seq = 0, options = {}) => ({ + cmd, + body: bon.encode(body), + ack: ack || 0, + seq: seq || 0, + time: Date.now(), + ...options + }), + parseMessage: (messageData) => { + try { + let message; + if (typeof messageData === 'string') { + message = JSON.parse(messageData); + } else { + message = messageData; + } + if (message.body && (message.body instanceof ArrayBuffer || message.body instanceof Uint8Array)) { + message.body = bon.decode(message.body); + } + return message; + } catch (error) { + console.error('消息解析失败:', error); + return { + error: true, + message: '消息解析失败', + originalData: messageData + }; + } + }, + generateSeq: () => Math.floor(Math.random() * 1000000), + generateMessageId: () => 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) +}; + +// 导出单独的加密器类以兼容测试文件 +export const LXCrypto = lx; +export const XCrypto = x; +export const XTMCrypto = xtm; + +export default { ProtoMsg, getEnc, encode, parse, GameMessages, g_utils, bon, bonProtocol }; \ No newline at end of file diff --git a/src/utils/gameCommands.js b/src/utils/gameCommands.js new file mode 100644 index 0000000..04851a3 --- /dev/null +++ b/src/utils/gameCommands.js @@ -0,0 +1,692 @@ +/** + * 游戏命令构造器 + * 基于mirror代码中的游戏指令实现完整的游戏功能 + */ + +import { g_utils } from './bonProtocol.js' + +// 生成随机数工具函数 +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min +} + +/** + * 游戏命令构造器类 + * 每个命令方法返回标准的WebSocket消息格式 + */ +export class GameCommands { + constructor(g_utils_instance = g_utils) { + this.g_utils = g_utils_instance + } + + /** + * 心跳消息 + */ + heart_beat(ack = 0, seq = 0, params = {}) { + return { + ack, + body: undefined, + c: undefined, + cmd: "_sys/ack", + hint: undefined, + seq, + time: Date.now() + } + } + + /** + * 获取角色信息 + */ + role_getroleinfo(ack = 0, seq = 0, params = {}) { + return { + cmd: "role_getroleinfo", + body: this.g_utils.bon.encode({ + clientVersion: "1.65.3-wx", + inviteUid: 0, + platform: "hortor", + platformExt: "mix", + scene: "", + ...params + }), + ack: ack || 0, + seq: seq || 0, + rtt: randomInt(0, 500), + code: 0, + time: Date.now() + } + } + + /** + * 获取数据包版本 + */ + system_getdatabundlever(ack = 0, seq = 0, params = {}) { + return { + cmd: "system_getdatabundlever", + body: this.g_utils.bon.encode({ + isAudit: false, + ...params + }), + ack: ack || 0, + seq: seq || 0, + rtt: randomInt(0, 500), + code: 0, + time: Date.now() + } + } + + /** + * 购买金币 + */ + system_buygold(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + buyNum: 1, + ...params + }), + cmd: "system_buygold", + seq, + time: Date.now() + } + } + + /** + * 分享回调 + */ + system_mysharecallback(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + type: 3, + isSkipShareCard: true, + ...params + }), + cmd: "system_mysharecallback", + seq, + time: Date.now() + } + } + + /** + * 好友批处理 + */ + friend_batch(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + friendId: 0, + ...params + }), + cmd: "friend_batch", + seq, + time: Date.now() + } + } + + /** + * 英雄招募 + */ + hero_recruit(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + byClub: false, + recruitNumber: 1, + recruitType: 3, + ...params + }), + cmd: "hero_recruit", + seq, + time: Date.now() + } + } + + /** + * 领取挂机奖励 + */ + system_claimhangupreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "system_claimhangupreward", + seq, + time: Date.now() + } + } + + /** + * 开宝箱 + */ + item_openbox(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + itemId: 2001, + number: 10, + ...params + }), + cmd: "item_openbox", + seq, + time: Date.now() + } + } + + /** + * 开始竞技场 + */ + arena_startarea(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "arena_startarea", + seq, + time: Date.now() + } + } + + /** + * 获取竞技场目标 + */ + arena_getareatarget(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + refresh: false, + ...params + }), + cmd: "arena_getareatarget", + seq, + time: Date.now() + } + } + + /** + * 开始竞技场战斗 + */ + fight_startareaarena(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + targetId: 530479307, + ...params + }), + cmd: "fight_startareaarena", + seq, + time: Date.now() + } + } + + /** + * 获取竞技场排名 + */ + arena_getarearank(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + rankType: 0, + ...params + }), + cmd: "arena_getarearank", + seq, + time: Date.now() + } + } + + /** + * 获取商店商品列表 + */ + store_goodslist(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + storeId: 1, + ...params + }), + cmd: "store_goodslist", + seq, + time: Date.now() + } + } + + /** + * 商店购买 + */ + store_buy(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + goodsId: 1, + ...params + }), + cmd: "store_buy", + seq, + time: Date.now() + } + } + + /** + * 商店刷新 + */ + store_refresh(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + storeId: 1, + ...params + }), + cmd: "store_refresh", + seq, + time: Date.now() + } + } + + /** + * 领取机器人助手奖励 + */ + bottlehelper_claim(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "bottlehelper_claim", + seq, + time: Date.now() + } + } + + /** + * 启动机器人助手 + */ + bottlehelper_start(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + bottleType: -1, + ...params + }), + cmd: "bottlehelper_start", + seq, + time: Date.now() + } + } + + /** + * 停止机器人助手 + */ + bottlehelper_stop(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + bottleType: -1, + ...params + }), + cmd: "bottlehelper_stop", + seq, + time: Date.now() + } + } + + /** + * 神器抽奖 + */ + artifact_lottery(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + lotteryNumber: 1, + newFree: true, + type: 1, + ...params + }), + cmd: "artifact_lottery", + seq, + time: Date.now() + } + } + + /** + * 领取每日积分 + */ + task_claimdailypoint(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + taskId: 1, + ...params + }), + cmd: "task_claimdailypoint", + seq, + time: Date.now() + } + } + + /** + * 领取周奖励 + */ + task_claimweekreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + rewardId: 0, + ...params + }), + cmd: "task_claimweekreward", + seq, + time: Date.now() + } + } + + /** + * 开始BOSS战 + */ + fight_startboss(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "fight_startboss", + seq, + time: Date.now() + } + } + + /** + * 精灵扫荡 + */ + genie_sweep(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "genie_sweep", + seq, + time: Date.now() + } + } + + /** + * 购买精灵扫荡 + */ + genie_buysweep(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "genie_buysweep", + seq, + time: Date.now() + } + } + + /** + * 签到奖励 + */ + system_signinreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "system_signinreward", + seq, + time: Date.now() + } + } + + /** + * 领取折扣奖励 + */ + discount_claimreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + discountId: 1, + ...params + }), + cmd: "discount_claimreward", + seq, + time: Date.now() + } + } + + /** + * 领取卡片奖励 + */ + card_claimreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + cardId: 1, + ...params + }), + cmd: "card_claimreward", + seq, + time: Date.now() + } + } + + /** + * 军团签到 + */ + legion_signin(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "legion_signin", + seq, + time: Date.now() + } + } + + /** + * 开始军团BOSS战 + */ + fight_startlegionboss(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "fight_startlegionboss", + seq, + time: Date.now() + } + } + + /** + * 领取每日任务奖励 + */ + task_claimdailyreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + rewardId: 0, + ...params + }), + cmd: "task_claimdailyreward", + seq, + time: Date.now() + } + } + + /** + * 获取军团信息 + */ + legion_getinfo(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({}), + cmd: "legion_getinfo", + seq, + time: Date.now() + } + } + + /** + * 军团匹配角色报名 + */ + legionmatch_rolesignup(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({}), + cmd: "legionmatch_rolesignup", + seq, + time: Date.now() + } + } + + /** + * 开始爬塔 + */ + fight_starttower(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({}), + cmd: "fight_starttower", + seq, + time: Date.now() + } + } + + /** + * 领取爬塔奖励 + */ + tower_claimreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "tower_claimreward", + seq, + time: Date.now() + } + } + + /** + * 获取爬塔信息 + */ + tower_getinfo(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "tower_getinfo", + seq, + time: Date.now() + } + } + + /** + * 开始答题游戏 + */ + study_startgame(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({}), + cmd: "study_startgame", + seq, + time: Date.now() + } + } + + /** + * 答题 + */ + study_answer(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + ...params + }), + cmd: "study_answer", + seq, + time: Date.now() + } + } + + /** + * 领取答题奖励 + */ + study_claimreward(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + rewardId: 1, + ...params + }), + cmd: "study_claimreward", + seq, + time: Date.now() + } + } + + /** + * 获取邮件列表 + */ + mail_getlist(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + category: [0, 4, 5], + lastId: 0, + size: 60, + ...params + }), + cmd: "mail_getlist", + seq, + time: Date.now() + } + } + + /** + * 领取所有邮件附件 + */ + mail_claimallattachment(ack = 0, seq = 0, params = {}) { + return { + ack, + body: this.g_utils.bon.encode({ + category: 0, + ...params + }), + cmd: "mail_claimallattachment", + seq, + time: Date.now() + } + } +} + +// 三国答题题库(基于mirror代码中的题目) +export const studyQuestions = [ + {name: "", value: 2}, + {name: "《三国演义》中,「大意失街亭」的是马谩?", value: 1}, + {name: "《三国演义》中,「挥泪斩马谩」的是孙权?", value: 2}, + {name: "《三国演义》中,「火烧博望坡」的是庞统?", value: 2}, + {name: "《三国演义》中,「火烧藤甲兵」的是徐庶?", value: 2}, + {name: "《三国演义》中,「千里走单骑」的是赵云?", value: 2}, + {name: "《三国演义》中,「温酒斩华雄」的是张飞?", value: 2}, + {name: "《三国演义》中,关羽在长坂坡「七进七出」?", value: 2}, + {name: "《三国演义》中,刘备三顾茅庐请诸葛亮出山?", value: 1}, + {name: "《三国演义》中,孙权与曹操「煮酒论英雄」?", value: 2}, + {name: "《三国演义》中,提出「隆中对」的是诸葛亮?", value: 1}, + {name: "《三国演义》中,夏侯杰在当阳桥被张飞吓死?", value: 1}, + {name: "《三国演义》中,张飞在当阳桥厉吼吓退曹军?", value: 1}, + {name: "《三国演义》中,赵云参与了「三英战吕布」?", value: 2}, + {name: "《三国演义》中,赵云参与了「桃园三结义」?", value: 2} + // 更多题目可以从原始数据中添加... +] + +// 创建命令实例 +export const gameCommands = new GameCommands() +export default GameCommands \ No newline at end of file diff --git a/src/utils/readable-xyzw-ws.js b/src/utils/readable-xyzw-ws.js new file mode 100644 index 0000000..88542be --- /dev/null +++ b/src/utils/readable-xyzw-ws.js @@ -0,0 +1,547 @@ +// 解析后的XYZW WebSocket通信库 +// 原文件: CTx_gHj7.js (混淆版本) + +// 导入依赖模块 +import { a$ as createRef, G as createApp, $ as defineComponent, n as ref, b0 as computed } from "./DpD38Hq9.js"; +import { c as useI18n, g as getConfig, u as useState } from "./BUzHT0Ek.js"; + +// 字符串相似度计算函数 (Levenshtein Distance 算法) +const calculateStringSimilarity = (() => { + let cache, isInitialized; + + return createRef(isInitialized ? cache : (isInitialized = 1, cache = function () { + // 计算两个字符串之间的编辑距离 + function calculateDistance(a, b, c, d, e) { + return a < b || c < b ? a > c ? c + 1 : a + 1 : d === e ? b : b + 1; + } + + return function (str1, str2) { + if (str1 === str2) return 0; + + // 确保str1是较短的字符串 + if (str1.length > str2.length) { + [str1, str2] = [str2, str1]; + } + + let len1 = str1.length; + let len2 = str2.length; + + // 去除相同的前缀和后缀 + while (len1 > 0 && str1.charCodeAt(len1 - 1) === str2.charCodeAt(len2 - 1)) { + len1--; + len2--; + } + + let start = 0; + while (start < len1 && str1.charCodeAt(start) === str2.charCodeAt(start)) { + start++; + } + + len2 -= start; + len1 -= start; + + if (len1 === 0 || len2 < 3) return len2; + + // 动态规划计算编辑距离 + let row = []; + for (let i = 0; i < len1; i++) { + row.push(i + 1, str1.charCodeAt(start + i)); + } + + let currentRow = 0; + let rowLength = row.length - 1; + + while (currentRow < len2 - 3) { + let char1 = str2.charCodeAt(start + currentRow); + let char2 = str2.charCodeAt(start + currentRow + 1); + let char3 = str2.charCodeAt(start + currentRow + 2); + let char4 = str2.charCodeAt(start + currentRow + 3); + + let newValue = currentRow += 4; + + for (let j = 0; j < rowLength; j += 2) { + let oldValue = row[j]; + let charCode = row[j + 1]; + + char1 = calculateDistance(oldValue, char1, char2, char1, charCode); + char2 = calculateDistance(char1, char2, char3, char2, charCode); + char3 = calculateDistance(char2, char3, char4, char3, charCode); + newValue = calculateDistance(char3, char4, newValue, char4, charCode); + + row[j] = newValue; + char4 = char3; + char3 = char2; + char2 = char1; + char1 = oldValue; + } + } + + // 处理剩余字符 + while (currentRow < len2) { + let char = str2.charCodeAt(start + currentRow); + let newValue = ++currentRow; + + for (let j = 0; j < rowLength; j += 2) { + let oldValue = row[j]; + row[j] = newValue = calculateDistance(oldValue, char, newValue, char, row[j + 1]); + char = oldValue; + } + } + + return newValue; + }; + }())); +})(); + +// 生成随机数 +function generateRandomNumber(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +// 时间格式化函数 +function formatTime(seconds) { + const totalSeconds = Math.floor(seconds); + const hours = Math.floor(totalSeconds / 3600).toString().padStart(2, "0"); + const remainingSeconds = totalSeconds % 3600; + const minutes = Math.floor(remainingSeconds / 60); + const secs = Math.floor(remainingSeconds % 60); + + const formattedHours = hours.toString().padStart(2, "0"); + const formattedMinutes = minutes.toString().padStart(2, "0"); + const formattedSeconds = (secs < 10 ? "0" : "") + secs.toString(); + + let formatTime = "00:00:00"; + if (seconds > 0) { + formatTime = `${formattedHours}:${formattedMinutes}:${formattedSeconds}`; + } + + return { + hours: formattedHours, + minutes: formattedMinutes, + seconds: formattedSeconds, + formatTime: formatTime + }; +} + +// 字符串相似度检查 +function checkStringSimilarity(str1, str2, threshold) { + if (!str1 || !str2) return false; + return 1 - calculateStringSimilarity(str1, str2) / Math.max(str1.length, str2.length) >= threshold; +} + +// 数值格式化函数 (支持万、亿单位) +function formatNumber(num, decimals = 2) { + if (num === undefined || isNaN(num) || num <= 0) return "0"; + + const billion = 100000000; // 1亿 + const tenThousand = 10000; // 1万 + + const formatDecimal = (value) => { + const str = value.toString(); + const [integer, decimal = ""] = str.split("."); + return decimal.length >= decimals + ? `${integer}.${decimal.slice(0, decimals)}` + : `${integer}.${"0".repeat(decimals - decimal.length)}${decimal}`; + }; + + if (num >= billion) { + return `${formatDecimal(num / billion)}亿`; + } else if (num >= tenThousand) { + return `${formatDecimal(num / tenThousand)}万`; + } else if (num < 1) { + return `0.${"0".repeat(decimals)}${num.toFixed(decimals + 1).slice(-decimals)}`; + } else { + return num.toString(); + } +} + +// 延迟函数 +function delay(milliseconds) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)); +} + +// 游戏消息模板定义 +const gameMessageTemplates = { + // 心跳包 + heart_beat: (client, ack, seq, params) => ({ + ack: ack, + body: undefined, + c: undefined, + cmd: "_sys/ack", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 获取角色信息 + role_getroleinfo: (client, ack, seq, params) => ({ + cmd: "role_getroleinfo", + body: client.bon.encode({ + clientVersion: "1.65.3-wx", + inviteUid: 0, + platform: "hortor", + platformExt: "mix", + scene: "", + ...params + }), + ack: ack || 0, + seq: seq || 0, + rtt: generateRandomNumber(0, 500), + code: 0, + time: Date.now() + }), + + // 获取数据包版本 + system_getdatabundlever: (client, ack, seq, params) => ({ + cmd: "system_getdatabundlever", + body: client.bon.encode({ + isAudit: false, + ...params + }), + ack: ack || 0, + seq: seq || 0, + rtt: generateRandomNumber(0, 500), + code: 0, + time: Date.now() + }), + + // 购买金币 + system_buygold: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + buyNum: 1, + ...params + }), + c: undefined, + cmd: "system_buygold", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 分享回调 + system_mysharecallback: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + type: 3, + isSkipShareCard: true, + ...params + }), + c: undefined, + cmd: "system_mysharecallback", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 好友批处理 + friend_batch: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + friendId: 0, + ...params + }), + c: undefined, + cmd: "friend_batch", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 英雄招募 + hero_recruit: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + byClub: false, + recruitNumber: 1, + recruitType: 3, + ...params + }), + c: undefined, + cmd: "hero_recruit", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 领取挂机奖励 + system_claimhangupreward: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + ...params + }), + c: undefined, + cmd: "system_claimhangupreward", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 开启宝箱 + item_openbox: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + itemId: 2001, + number: 10, + ...params + }), + c: undefined, + cmd: "item_openbox", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 竞技场相关命令 + arena_startarea: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({...params}), + c: undefined, + cmd: "arena_startarea", + hint: undefined, + seq: seq, + time: Date.now() + }), + + arena_getareatarget: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + refresh: false, + ...params + }), + c: undefined, + cmd: "arena_getareatarget", + hint: undefined, + seq: seq, + time: Date.now() + }), + + fight_startareaarena: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + targetId: 530479307, + ...params + }), + c: undefined, + cmd: "fight_startareaarena", + hint: undefined, + seq: seq, + time: Date.now() + }), + + arena_getarearank: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + rankType: 0, + ...params + }), + c: undefined, + cmd: "arena_getarearank", + hint: undefined, + seq: seq, + time: Date.now() + }), + + // 商店相关 + store_goodslist: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + storeId: 1, + ...params + }), + c: undefined, + cmd: "store_goodslist", + hint: undefined, + seq: seq, + time: Date.now() + }), + + store_buy: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({ + goodsId: 1, + ...params + }), + c: undefined, + cmd: "store_buy", + hint: undefined, + seq: seq, + time: Date.now() + }), + + store_refresh: (client, ack, seq, params) => ({ + ack: ack, + body: client.bon.encode({...params}), + c: undefined, + cmd: "store_refresh", + hint: undefined, + seq: seq, + time: Date.now() + }) +}; + +// 游戏逻辑处理函数 (从原始混淆代码中提取的核心逻辑) +function processGameLogic(client) { + const app = createApp(); + const state = useState(); + const { message } = useI18n(["message", "dialog"]); + + // 处理问答逻辑 + const handleQuestionsLogic = (responseData) => { + const questionList = responseData.body.questionList; + let hasMatch = false; + const config = useState(); + + // 遍历问题列表寻找匹配 + for (let i = 0; i < questionList.length; i++) { + const question = questionList[i]; + //todo + // 这里应该有问题匹配逻辑,但在原代码中被混淆了 + // 原始逻辑涉及某个答案数组 v,可能需要根据实际需求补充 + } + + return hasMatch; + }; + + return { + handleQuestionsLogic, + // 其他游戏逻辑函数可以在这里添加 + }; +} + +// Base64 编解码工具 (从原始代码第1部分提取) +const base64Utils = { + // 字节长度计算 + byteLength: function (str) { + const parsed = this.parseBase64(str); + const validLength = parsed[0]; + const paddingLength = parsed[1]; + return validLength; + }, + + // 转换为字节数组 + toByteArray: function (str) { + const parsed = this.parseBase64(str); + const validLength = parsed[0]; + const paddingLength = parsed[1]; + const result = new Uint8Array(this.calculateLength(validLength, paddingLength, str.length)); + + // 解码逻辑 + // ... 这里应该包含完整的Base64解码实现 + + return result; + }, + + // 从字节数组转换 + fromByteArray: function (uint8Array) { + const length = uint8Array.length; + const remainder = length % 3; + const chunks = []; + const maxChunkLength = 16383; + + // 处理主要部分 + for (let i = 0; i < length - remainder; i += maxChunkLength) { + const end = i + maxChunkLength > length - remainder ? length - remainder : i + maxChunkLength; + chunks.push(this.encodeChunk(uint8Array, i, end)); + } + + // 处理剩余字节 + if (remainder === 1) { + const byte = uint8Array[length - 1]; + chunks.push(this.chars[byte >> 2] + this.chars[byte << 4 & 63] + '=='); + } else if (remainder === 2) { + const byte1 = uint8Array[length - 2]; + const byte2 = uint8Array[length - 1]; + chunks.push( + this.chars[byte1 >> 2] + + this.chars[byte1 << 4 & 63 | byte2 >> 4] + + this.chars[byte2 << 2 & 63] + + '=' + ); + } + + return chunks.join(''); + }, + + // Base64字符表 + chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + + // 辅助函数 + parseBase64: function (str) { + const length = str.length; + let paddingIndex = str.indexOf('='); + if (paddingIndex === -1) paddingIndex = length; + + const validLength = paddingIndex; + const paddingLength = paddingIndex === length ? 0 : 4 - (paddingIndex % 4); + + return [validLength, paddingLength]; + }, + + calculateLength: function (validLength, paddingLength, totalLength) { + return Math.floor((validLength + paddingLength) * 3 / 4); + }, + + encodeChunk: function (uint8Array, start, end) { + const chars = this.chars; + const result = []; + + for (let i = start; i < end; i += 3) { + const byte1 = uint8Array[i]; + const byte2 = i + 1 < end ? uint8Array[i + 1] : 0; + const byte3 = i + 2 < end ? uint8Array[i + 2] : 0; + + const triplet = (byte1 << 16) + (byte2 << 8) + byte3; + + result.push( + chars[triplet >> 18 & 63] + + chars[triplet >> 12 & 63] + + chars[triplet >> 6 & 63] + + chars[triplet & 63] + ); + } + + return result.join(''); + } +}; + +// 数据存储管理 (从文件末尾部分提取) +const createDataStore = () => { + return { + // 响应数据存储 + resp: {}, + + // 更新军团信息 + updateLegioninfo: function(newData) { + const currentLegionData = this.resp.legion_getinforesp; + + if (currentLegionData && currentLegionData.data) { + this.resp.legion_getinforesp = { + loading: false, + data: Object.assign({}, currentLegionData.data, newData), + cmd: "legion_getinfor" + }; + } else { + this.resp.legion_getinforesp = { + loading: false, + data: newData, + cmd: "legion_getinfor" + }; + } + } + }; +}; + +// 导出的主要功能模块 +export { + useState as createGameState, // b -> a + formatNumber as formatGameNumber, // h -> b + gameMessageTemplates as gameCommands, // m -> c + processGameLogic as gameLogicHandler, // y -> d + createDataStore as dataStoreFactory, // C -> e + formatTime, // f + base64Utils as encodingUtils, // E -> g + createDataStore as storeManager, // S -> h + delay as sleep, // g -> s + createApp as appFactory // A -> u +}; diff --git a/src/utils/wsAgent.js b/src/utils/wsAgent.js new file mode 100644 index 0000000..41bb5ff --- /dev/null +++ b/src/utils/wsAgent.js @@ -0,0 +1,438 @@ +/** + * WebSocket客户端 - 基于mirror代码的完整实现 + * 支持BON协议编解码、加密通道、心跳保活、消息队列等 + */ + +import { g_utils } from './bonProtocol.js' + +export class WsAgent { + /** + * @param {Object} options 配置选项 + */ + constructor(options = {}) { + const { + heartbeatInterval = 2000, // 心跳间隔(ms) + queueInterval = 50, // 发送队列轮询间隔(ms) + heartbeatCmd = 'heart_beat', // 心跳命令 + channel = 'x', // 加密通道 + autoReconnect = true, // 自动重连 + maxReconnectAttempts = 5, // 最大重连次数 + reconnectDelay = 3000 // 重连延迟(ms) + } = options + + // 配置参数 + this.heartbeatInterval = heartbeatInterval + this.queueInterval = queueInterval + this.heartbeatCmd = heartbeatCmd + this.channel = channel + this.autoReconnect = autoReconnect + this.maxReconnectAttempts = maxReconnectAttempts + this.reconnectDelay = reconnectDelay + + // 连接状态 + this.ws = null + this.connected = false + this.connecting = false + this.reconnectAttempts = 0 + + // 协议状态 + this.ack = 0 + this.seq = 1 + + // 定时器 + this._heartbeatTimer = null + this._queueTimer = null + this._reconnectTimer = null + + // 发送队列 + this.sendQueue = [] + + // Promise等待队列 respKey -> {resolve, reject, timeoutId} + this.waitingPromises = new Map() + + // 事件监听器 + this.onOpen = () => {} + this.onClose = () => {} + this.onError = () => {} + this.onMessage = () => {} + this.onReconnect = () => {} + } + + /** + * 连接WebSocket + * @param {string} url WebSocket URL + * @param {Object} connectionParams 连接参数 + */ + connect(url, connectionParams = {}) { + if (this.connecting || (this.ws && this.ws.readyState === WebSocket.OPEN)) { + console.warn('WebSocket已连接或正在连接中') + return Promise.resolve() + } + + return new Promise((resolve, reject) => { + try { + this.connecting = true + console.log(`🔗 连接WebSocket: ${url}`) + + this.ws = new WebSocket(url) + this.ws.binaryType = 'arraybuffer' + + // 连接打开 + this.ws.onopen = () => { + this.connecting = false + this.connected = true + this.reconnectAttempts = 0 + + console.log('✅ WebSocket连接已建立') + + // 重置协议状态 + this.seq = 1 + + // 启动心跳和队列处理 + this._startHeartbeat() + this._startQueueProcessor() + + this.onOpen() + resolve() + } + + // 消息接收 + this.ws.onmessage = (event) => { + this._handleMessage(event.data) + } + + // 连接关闭 + this.ws.onclose = (event) => { + this.connecting = false + this.connected = false + this._cleanup() + + console.log(`🔌 WebSocket连接已关闭: ${event.code} ${event.reason}`) + + this.onClose(event) + + // 自动重连 + if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) { + this._scheduleReconnect(url, connectionParams) + } + } + + // 连接错误 + this.ws.onerror = (error) => { + console.error('❌ WebSocket错误:', error) + this.onError(error) + + if (this.connecting) { + this.connecting = false + reject(error) + } + } + + } catch (error) { + this.connecting = false + reject(error) + } + }) + } + + /** + * 关闭连接 + * @param {number} code 关闭码 + * @param {string} reason 关闭原因 + */ + close(code = 1000, reason = 'normal') { + this.autoReconnect = false + if (this.ws) { + this.ws.close(code, reason) + } + this._cleanup() + } + + /** + * 发送消息 + * @param {Object|Array} payload 消息载荷 + */ + send(payload) { + if (Array.isArray(payload)) { + this.sendQueue.push(...payload) + } else { + this.sendQueue.push(payload) + } + } + + /** + * 发送消息并等待响应 + * @param {Object} options 请求选项 + * @returns {Promise} 响应Promise + */ + sendWithPromise(options) { + const { cmd, body = {}, respKey, timeout = 8000 } = options + const responseKey = respKey || `${cmd}resp` + + return new Promise((resolve, reject) => { + // 设置超时 + const timeoutId = setTimeout(() => { + this.waitingPromises.delete(responseKey) + reject(new Error(`请求超时: ${cmd}`)) + }, timeout) + + // 注册Promise + this.waitingPromises.set(responseKey, { + resolve, + reject, + timeoutId + }) + + // 发送消息 + this.send({ cmd, body, respKey: responseKey }) + }) + } + + /** + * 处理接收到的消息 + * @private + */ + _handleMessage(data) { + try { + // 使用g_utils解密和解码消息 + const message = g_utils.parse(data, this.channel) + + if (!message) { + console.warn('消息解析失败') + return + } + + console.log('📨 收到消息:', message) + + // 更新ack + if (message.seq) { + this.ack = message.seq + } + + // 检查是否有等待的Promise + const cmd = message.cmd || message.c + const respKey = message.respKey || cmd + + if (respKey && this.waitingPromises.has(respKey)) { + const { resolve, timeoutId } = this.waitingPromises.get(respKey) + clearTimeout(timeoutId) + this.waitingPromises.delete(respKey) + resolve(message) + return + } + + // 派发给普通消息处理器 + this.onMessage(message) + + } catch (error) { + console.error('消息处理失败:', error) + this.onError(error) + } + } + + /** + * 启动心跳 + * @private + */ + _startHeartbeat() { + this._stopHeartbeat() + + if (!this.heartbeatInterval) return + + this._heartbeatTimer = setInterval(() => { + if (this.connected && this.ws?.readyState === WebSocket.OPEN) { + this._sendHeartbeat() + } + }, this.heartbeatInterval) + } + + /** + * 停止心跳 + * @private + */ + _stopHeartbeat() { + if (this._heartbeatTimer) { + clearInterval(this._heartbeatTimer) + this._heartbeatTimer = null + } + } + + /** + * 发送心跳消息 + * @private + */ + _sendHeartbeat() { + const heartbeatMsg = { + ack: this.ack, + body: undefined, + c: undefined, + cmd: '_sys/ack', + hint: undefined, + seq: 0, // 心跳消息seq为0 + time: Date.now() + } + + this._rawSend(heartbeatMsg) + } + + /** + * 启动队列处理器 + * @private + */ + _startQueueProcessor() { + this._stopQueueProcessor() + this._queueTimer = setInterval(() => { + this._processQueue() + }, this.queueInterval) + } + + /** + * 停止队列处理器 + * @private + */ + _stopQueueProcessor() { + if (this._queueTimer) { + clearInterval(this._queueTimer) + this._queueTimer = null + } + } + + /** + * 处理发送队列 + * @private + */ + _processQueue() { + if (!this.connected || !this.ws || this.ws.readyState !== WebSocket.OPEN) { + return + } + + if (this.sendQueue.length === 0) { + return + } + + const item = this.sendQueue.shift() + const packet = this._buildPacket(item) + this._rawSend(packet) + } + + /** + * 构建数据包 + * @private + */ + _buildPacket(payload) { + const { cmd, body = {}, respKey } = payload + + // 生成随机RTT (0-500ms) + const rtt = Math.floor(Math.random() * 500) + + const packet = { + ack: this.ack, + seq: cmd === this.heartbeatCmd ? 0 : this.seq++, + time: Date.now(), + cmd, + body, + respKey, + rtt, + code: 0 + } + + return packet + } + + /** + * 原始发送数据 + * @private + */ + _rawSend(packet) { + try { + // 使用g_utils编码和加密 + const data = g_utils.encode(packet, this.channel) + this.ws.send(data) + } catch (error) { + console.error('发送消息失败:', error) + this.onError(error) + } + } + + /** + * 计划重连 + * @private + */ + _scheduleReconnect(url, connectionParams) { + if (this._reconnectTimer) { + clearTimeout(this._reconnectTimer) + } + + this.reconnectAttempts++ + console.log(`🔄 计划重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts}) 延迟: ${this.reconnectDelay}ms`) + + this._reconnectTimer = setTimeout(() => { + console.log(`🔄 开始第${this.reconnectAttempts}次重连...`) + this.onReconnect(this.reconnectAttempts) + this.connect(url, connectionParams).catch(error => { + console.error('重连失败:', error) + }) + }, this.reconnectDelay) + } + + /** + * 清理资源 + * @private + */ + _cleanup() { + this._stopHeartbeat() + this._stopQueueProcessor() + + if (this._reconnectTimer) { + clearTimeout(this._reconnectTimer) + this._reconnectTimer = null + } + + // 清理等待的Promise + for (const [key, { reject, timeoutId }] of this.waitingPromises) { + clearTimeout(timeoutId) + reject(new Error('连接已关闭')) + } + this.waitingPromises.clear() + } + + /** + * 获取连接状态 + */ + getStatus() { + return { + connected: this.connected, + connecting: this.connecting, + readyState: this.ws?.readyState, + ack: this.ack, + seq: this.seq, + queueLength: this.sendQueue.length, + waitingPromises: this.waitingPromises.size, + reconnectAttempts: this.reconnectAttempts + } + } + + /** + * 构建WebSocket URL + * @static + */ + static buildUrl(baseUrl, params = {}) { + const url = new URL(baseUrl) + + // 添加连接参数到p参数 + if (params.p && typeof params.p === 'object') { + url.searchParams.set('p', JSON.stringify(params.p)) + } + + // 添加其他参数 + Object.keys(params).forEach(key => { + if (key !== 'p' && params[key] !== undefined) { + url.searchParams.set(key, params[key]) + } + }) + + return url.toString() + } +} + +export default WsAgent \ No newline at end of file diff --git a/src/utils/xyzwWebSocket.js b/src/utils/xyzwWebSocket.js new file mode 100644 index 0000000..8e03b87 --- /dev/null +++ b/src/utils/xyzwWebSocket.js @@ -0,0 +1,537 @@ +/** + * XYZW WebSocket 客户端 + * 基于 readable-xyzw-ws.js 重构,适配本项目架构 + */ + +import { bonProtocol, g_utils } from './bonProtocol.js' + +/** 生成 [min,max] 的随机整数 */ +const randInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min + +/** Promise 版 sleep */ +const sleep = (ms) => new Promise((res) => setTimeout(res, ms)) + +/** + * 命令注册器:保存每个 cmd 的默认体,发送时与 params 合并 + */ +export class CommandRegistry { + constructor(encoder, enc) { + this.encoder = encoder + this.enc = enc + this.commands = new Map() + } + + /** 注册命令 */ + register(cmd, defaultBody = {}) { + this.commands.set(cmd, (ack = 0, seq = 0, params = {}) => ({ + cmd, + ack, + seq, + code: 0, + rtt: randInt(0, 500), + time: Date.now(), + body: this.encoder?.bon?.encode + ? this.encoder.bon.encode({ ...defaultBody, ...params }) + : undefined, + c: undefined, + hint: undefined, + })) + return this + } + + /** 特例:系统心跳的 ack 用的是 "_sys/ack" */ + registerHeartbeat() { + this.commands.set("heart_beat", (ack, seq) => ({ + cmd: "_sys/ack", + ack, + seq, + time: Date.now(), + body: undefined, + c: undefined, + hint: undefined, + })) + return this + } + + /** 生成最终可发送的二进制 */ + encodePacket(raw) { + if (this.encoder?.encode && this.enc) { + // 使用加密编码 + return this.encoder.encode(raw, this.enc) + } else { + // 降级到JSON字符串 + return JSON.stringify(raw) + } + } + + /** 构造报文 */ + build(cmd, ack, seq, params) { + const fn = this.commands.get(cmd) + if (!fn) throw new Error(`Unknown cmd: ${cmd}`) + return fn(ack, seq, params) + } +} + +/** 预注册游戏命令 */ +export function registerDefaultCommands(reg) { + return reg.registerHeartbeat() + // 角色/系统 + .register("role_getroleinfo", { + clientVersion: "1.65.3-wx", + inviteUid: 0, + platform: "hortor", + platformExt: "mix", + scene: "", + }) + .register("system_getdatabundlever", { isAudit: false }) + .register("system_buygold", { buyNum: 1 }) + .register("system_claimhangupreward") + .register("system_signinreward") + + // 任务相关 + .register("task_claimdailypoint", { taskId: 1 }) + .register("task_claimdailyreward", { rewardId: 0 }) + .register("task_claimweekreward", { rewardId: 0 }) + + // 好友/招募 + .register("friend_batch", { friendId: 0 }) + .register("hero_recruit", { byClub: false, recruitNumber: 1, recruitType: 3 }) + .register("item_openbox", { itemId: 2001, number: 10 }) + + // 竞技场 + .register("arena_startarea") + .register("arena_getareatarget", { refresh: false }) + .register("fight_startareaarena", { targetId: 530479307 }) + .register("arena_getarearank", { rankType: 0 }) + + // 商店 + .register("store_goodslist", { storeId: 1 }) + .register("store_buy", { goodsId: 1 }) + .register("store_refresh", { storeId: 1 }) + + // 军团 + .register("legion_getinfo") + .register("legion_signin") + .register("legion_getwarrank") + + // 邮件 + .register("mail_getlist", { category: [0, 4, 5], lastId: 0, size: 60 }) + .register("mail_claimallattachment", { category: 0 }) + + // 学习问答 + .register("study_startgame") + .register("study_answer") + .register("study_claimreward", { rewardId: 1 }) + + // 战斗相关 + .register("fight_starttower") + .register("fight_startboss") + .register("fight_startlegionboss") + .register("fight_startdungeon") + .register("fight_startpvp") + + // 瓶子机器人 + .register("bottlehelper_claim") + .register("bottlehelper_start", { bottleType: -1 }) + .register("bottlehelper_stop", { bottleType: -1 }) + + // 军团匹配和签到 + .register("legionmatch_rolesignup") + .register("legion_signin") + + // 神器抽奖 + .register("artifact_lottery", { lotteryNumber: 1, newFree: true, type: 1 }) + + // 爬塔相关 + .register("tower_getinfo") + .register("tower_claimreward") + + // 队伍相关 + .register("presetteam_getteam") + .register("presetteam_setteam") + .register("presetteam_saveteam") + .register("role_gettargetteam") + + // 排名相关 + .register("rank_getroleinfo") + + // 梦魇相关 + .register("nightmare_getroleinfo") +} + +/** + * XYZW WebSocket 客户端 + */ +export class XyzwWebSocketClient { + constructor({ url, utils, heartbeatMs = 5000 }) { + this.url = url + this.utils = utils || g_utils + this.enc = this.utils?.getEnc ? this.utils.getEnc("auto") : undefined + + this.socket = null + this.ack = 1 + this.seq = 0 + this.sendQueue = [] + this.sendQueueTimer = null + this.heartbeatTimer = null + this.heartbeatInterval = heartbeatMs + + this.dialogStatus = false + this.messageListener = null + this.showMsg = false + this.connected = false + + this.promises = Object.create(null) + this.registry = registerDefaultCommands(new CommandRegistry(this.utils, this.enc)) + + console.log('🔧 WebSocket客户端初始化:', { + url: this.url, + hasUtils: !!this.utils, + hasEnc: !!this.enc, + hasEncoder: !!this.utils?.encode + }) + + // 状态回调 + this.onConnect = null + this.onDisconnect = null + this.onError = null + } + + /** 初始化连接 */ + init() { + console.log(`🔗 连接 WebSocket: ${this.url}`) + + this.socket = new WebSocket(this.url) + + this.socket.onopen = () => { + console.log(`✅ WebSocket 连接成功`) + this.connected = true + console.log(`🔄 启动心跳机制,间隔: ${this.heartbeatInterval}ms`) + this._setupHeartbeat() + console.log(`🔄 启动消息队列处理`) + this._processQueueLoop() + if (this.onConnect) this.onConnect() + } + + this.socket.onmessage = (evt) => { + try { + let packet + if (typeof evt.data === "string") { + packet = JSON.parse(evt.data) + } else if (evt.data instanceof ArrayBuffer) { + // 二进制数据需要自动检测并解码 + packet = this.utils?.parse ? this.utils.parse(evt.data, "auto") : evt.data + } else if (evt.data instanceof Blob) { + // 处理Blob数据 + console.log('📦 收到Blob数据, 大小:', evt.data.size) + evt.data.arrayBuffer().then(buffer => { + try { + packet = this.utils?.parse ? this.utils.parse(buffer, "auto") : buffer + console.log('📦 Blob解析结果:', packet) + + // 处理消息体解码(ProtoMsg会自动解码) + if (packet instanceof Object && packet.rawData !== undefined) { + console.log('✅ ProtoMsg消息,使用rawData:', packet.rawData) + } else if (packet.body && packet.body instanceof Uint8Array) { + try { + if (this.utils && this.utils.bon && this.utils.bon.decode) { + const decodedBody = this.utils.bon.decode(packet.body) + console.log('✅ 手动解码消息体成功:', decodedBody) + // 不修改packet.body,而是创建一个新的属性存储解码后的数据 + packet.decodedBody = decodedBody + } else { + console.warn('⚠️ BON解码器不可用:', this.utils) + } + } catch (error) { + console.warn('❌ 消息体解码失败:', error) + } + } + + if (this.showMsg) { + console.log(`📨 收到消息(Blob解析后):`, packet) + } + + // 回调处理 + if (this.messageListener) { + this.messageListener(packet) + } + + // Promise 响应处理 + this._handlePromiseResponse(packet) + + } catch (error) { + console.error('❌ Blob解析失败:', error) + } + }) + return // 异步处理,直接返回 + } else { + console.warn('⚠️ 未知数据类型:', typeof evt.data, evt.data) + packet = evt.data + } + + if (this.showMsg) { + console.log(`📨 收到消息:`, packet) + } + + // 处理消息体解码(ProtoMsg会自动解码) + if (packet instanceof Object && packet.rawData !== undefined) { + console.log('✅ ProtoMsg消息,使用rawData:', packet.rawData) + } else if (packet.body && packet.body instanceof Uint8Array) { + try { + if (this.utils && this.utils.bon && this.utils.bon.decode) { + const decodedBody = this.utils.bon.decode(packet.body) + console.log('✅ 手动解码消息体成功:', decodedBody) + // 不修改packet.body,而是创建一个新的属性存储解码后的数据 + packet.decodedBody = decodedBody + } else { + console.warn('⚠️ BON解码器不可用:', this.utils) + } + } catch (error) { + console.warn('❌ 消息体解码失败:', error) + } + } + + // 回调处理 + if (this.messageListener) { + this.messageListener(packet) + } + + // Promise 响应处理 + this._handlePromiseResponse(packet) + + } catch (error) { + console.error(`❌ 消息处理失败:`, error) + } + } + + this.socket.onclose = (evt) => { + console.log(`🔌 WebSocket 连接关闭:`, evt.code, evt.reason) + console.log(`🔍 关闭详情:`, { + code: evt.code, + reason: evt.reason || '未提供原因', + wasClean: evt.wasClean, + timestamp: new Date().toISOString() + }) + this.connected = false + this._clearTimers() + if (this.onDisconnect) this.onDisconnect(evt) + } + + this.socket.onerror = (error) => { + console.error(`❌ WebSocket 错误:`, error) + this.connected = false + this._clearTimers() + if (this.onError) this.onError(error) + } + } + + /** 注册消息回调 */ + setMessageListener(fn) { + this.messageListener = fn + } + + /** 控制台消息开关 */ + setShowMsg(val) { + this.showMsg = !!val + } + + /** 重连 */ + reconnect() { + this.disconnect() + setTimeout(() => this.init(), 1000) + } + + /** 断开连接 */ + disconnect() { + if (this.socket) { + this.socket.close() + this.socket = null + } + this.connected = false + this._clearTimers() + } + + /** 发送消息 */ + send(cmd, params = {}, options = {}) { + if (!this.connected) { + console.warn(`⚠️ WebSocket 未连接,消息已入队: ${cmd}`) + if (!this.dialogStatus) { + this.dialogStatus = true + this.reconnect() + setTimeout(() => { this.dialogStatus = false }, 2000) + } + } + + const task = { + cmd, + params, + respKey: options.respKey || cmd, + sleep: options.sleep || 0, + onSent: options.onSent + } + + this.sendQueue.push(task) + return task + } + + /** Promise 版发送 */ + sendWithPromise(cmd, params = {}, timeoutMs = 5000) { + const respKey = `${cmd}_${this.seq + 1}` + + return new Promise((resolve, reject) => { + if (!this.connected && !this.socket) { + return reject(new Error("WebSocket 连接已关闭")) + } + + // 设置 Promise 状态 + this.promises[respKey] = { resolve, reject } + + // 超时处理 + const timer = setTimeout(() => { + delete this.promises[respKey] + reject(new Error(`请求超时: ${cmd} (${timeoutMs}ms)`)) + }, timeoutMs) + + // 发送消息 + this.send(cmd, params, { + respKey, + onSent: () => { + clearTimeout(timer) + } + }) + }) + } + + /** 发送心跳 */ + sendHeartbeat() { + console.log('💓 发送心跳消息') + this.send("heart_beat", {}, { respKey: "_sys/ack" }) + } + + /** 获取角色信息 */ + getRoleInfo(params = {}) { + return this.sendWithPromise("role_getroleinfo", params) + } + + /** 获取数据版本 */ + getDataBundleVersion(params = {}) { + return this.sendWithPromise("system_getdatabundlever", params) + } + + /** 签到 */ + signIn() { + return this.sendWithPromise("system_signinreward") + } + + /** 领取日常任务奖励 */ + claimDailyReward(rewardId = 0) { + return this.sendWithPromise("task_claimdailyreward", { rewardId }) + } + + /** =============== 内部方法 =============== */ + + /** 设置心跳 */ + _setupHeartbeat() { + // 延迟3秒后开始发送第一个心跳,避免连接刚建立就发送 + setTimeout(() => { + if (this.connected && this.socket?.readyState === WebSocket.OPEN) { + console.log('💓 开始发送首次心跳') + this.sendHeartbeat() + } + }, 3000) + + // 设置定期心跳 + this.heartbeatTimer = setInterval(() => { + if (this.connected && this.socket?.readyState === WebSocket.OPEN) { + this.sendHeartbeat() + } else { + console.log('⚠️ 心跳检查失败: 连接状态异常') + } + }, this.heartbeatInterval) + } + + /** 队列处理循环 */ + _processQueueLoop() { + if (this.sendQueueTimer) clearInterval(this.sendQueueTimer) + + this.sendQueueTimer = setInterval(async () => { + if (!this.sendQueue.length) return + if (!this.connected || this.socket?.readyState !== WebSocket.OPEN) return + + const task = this.sendQueue.shift() + if (!task) return + + try { + // 构建报文 + const raw = this.registry.build(task.cmd, this.ack, this.seq, task.params) + if (task.cmd !== "heart_beat") this.seq++ + + // 编码并发送 + const bin = this.registry.encodePacket(raw) + this.socket?.send(bin) + + if (this.showMsg || task.cmd === "heart_beat") { + console.log(`📤 发送消息: ${task.cmd}`, task.params) + if (this.showMsg) { + console.log(`🔐 原始数据:`, raw) + console.log(`🚀 编码后数据:`, bin) + console.log(`🔧 编码类型:`, typeof bin, bin instanceof Uint8Array ? '✅ Uint8Array (加密)' : '❌ String (明文)') + if (bin instanceof Uint8Array && bin.length > 0) { + console.log(`🎯 加密验证: 前8字节 [${Array.from(bin.slice(0, 8)).join(', ')}]`) + } + } + } + + // 触发发送回调 + if (task.onSent) { + try { + task.onSent(task.respKey, task.cmd) + } catch (error) { + console.warn('发送回调执行失败:', error) + } + } + + // 可选延时 + if (task.sleep) await sleep(task.sleep) + + } catch (error) { + console.error(`❌ 发送消息失败: ${task.cmd}`, error) + } + }, 50) + } + + /** 处理 Promise 响应 */ + _handlePromiseResponse(packet) { + const cmd = packet.cmd + if (!cmd) return + + // 查找对应的 Promise + for (const [key, promise] of Object.entries(this.promises)) { + if (key.startsWith(cmd) || cmd === key) { + delete this.promises[key] + + if (packet.code === 0 || packet.code === undefined) { + promise.resolve(packet.body || packet) + } else { + promise.reject(new Error(`服务器错误: ${packet.code} - ${packet.hint || '未知错误'}`)) + } + break + } + } + } + + /** 清理定时器 */ + _clearTimers() { + if (this.heartbeatTimer) { + clearInterval(this.heartbeatTimer) + this.heartbeatTimer = null + } + if (this.sendQueueTimer) { + clearInterval(this.sendQueueTimer) + this.sendQueueTimer = null + } + } +} + +/** 默认导出 */ +export default XyzwWebSocketClient diff --git a/src/views/DailyTasks.vue b/src/views/DailyTasks.vue new file mode 100644 index 0000000..b2aad5f --- /dev/null +++ b/src/views/DailyTasks.vue @@ -0,0 +1,759 @@ + + + + + \ No newline at end of file diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue new file mode 100644 index 0000000..7056c71 --- /dev/null +++ b/src/views/Dashboard.vue @@ -0,0 +1,840 @@ + + + + + \ No newline at end of file diff --git a/src/views/GameFeatures.vue b/src/views/GameFeatures.vue new file mode 100644 index 0000000..e639135 --- /dev/null +++ b/src/views/GameFeatures.vue @@ -0,0 +1,570 @@ + + + + + diff --git a/src/views/GameRoles.vue b/src/views/GameRoles.vue new file mode 100644 index 0000000..19d7204 --- /dev/null +++ b/src/views/GameRoles.vue @@ -0,0 +1,575 @@ + + + + + \ No newline at end of file diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 0000000..038328a --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,605 @@ + + + + + \ No newline at end of file diff --git a/src/views/Login.vue b/src/views/Login.vue new file mode 100644 index 0000000..5fe0ec7 --- /dev/null +++ b/src/views/Login.vue @@ -0,0 +1,554 @@ + + + + + \ No newline at end of file diff --git a/src/views/NotFound.vue b/src/views/NotFound.vue new file mode 100644 index 0000000..721748e --- /dev/null +++ b/src/views/NotFound.vue @@ -0,0 +1,116 @@ + + + + + \ No newline at end of file diff --git a/src/views/Profile.vue b/src/views/Profile.vue new file mode 100644 index 0000000..93535d3 --- /dev/null +++ b/src/views/Profile.vue @@ -0,0 +1,558 @@ + + + + + \ No newline at end of file diff --git a/src/views/Register.vue b/src/views/Register.vue new file mode 100644 index 0000000..ba603be --- /dev/null +++ b/src/views/Register.vue @@ -0,0 +1,333 @@ + + + + + \ No newline at end of file diff --git a/src/views/TokenImport.vue b/src/views/TokenImport.vue new file mode 100644 index 0000000..794b4d9 --- /dev/null +++ b/src/views/TokenImport.vue @@ -0,0 +1,1044 @@ + + + + + \ No newline at end of file diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..4dd97be --- /dev/null +++ b/vite.config.js @@ -0,0 +1,36 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, 'src'), + '@components': path.resolve(__dirname, 'src/components'), + '@views': path.resolve(__dirname, 'src/views'), + '@assets': path.resolve(__dirname, 'src/assets'), + '@utils': path.resolve(__dirname, 'src/utils'), + '@api': path.resolve(__dirname, 'src/api'), + '@stores': path.resolve(__dirname, 'src/stores') + } + }, + server: { + port: 3000, + open: true, + proxy: { + '/api': { + target: 'http://xyzw.my', + changeOrigin: true, + rewrite: (path) => path + } + } + }, + css: { + preprocessorOptions: { + scss: { + additionalData: '@use "@/assets/styles/variables.scss" as vars;' + } + } + } +}) \ No newline at end of file