diff --git a/.gitignore b/.gitignore index d5e0305..d44ce9a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,7 @@ web/package-lock.json .planning/ # Superpowers files +.claude/ docs/superpowers/ +docs/scripts-documentation.md .pids/ \ No newline at end of file diff --git a/.gitlab/merge_request_templates/default.md b/.gitlab/merge_request_templates/default.md new file mode 100644 index 0000000..9caba46 --- /dev/null +++ b/.gitlab/merge_request_templates/default.md @@ -0,0 +1,20 @@ +## 变更描述 + + +## 关联需求 + + +## 变更类型 +- [ ] Feature +- [ ] Bugfix +- [ ] Hotfix +- [ ] Refactor +- [ ] Docs + +## 自检清单 +- [ ] 代码已通过 Pre-commit 检查(后端 ruff / 前端 lint-staged) +- [ ] 已添加必要的测试 +- [ ] 文档已更新(如需) + +## Reviewer 备注 + diff --git a/CLAUDE.md b/CLAUDE.md index 978c5f1..b441c6b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -103,3 +103,10 @@ Backend settings are split: - The `miscprocurement` app handles询价 (RFQ) and cost template building - Supplier quotations are managed in `pissupplier` app - Default demo credentials: `superadmin` / `admin123456` + +## Git 注意事项 + +**不要提交本地文档和 superpowers 相关文件**: +- `.claude/` 目录下的 superpowers 相关文件(`.planning/`、skills 等) +- `docs/` 目录下的本地文档 +- 这些文件每个人开发任务不同,不应提交到仓库 diff --git a/docs/scripts-documentation.md b/docs/scripts-documentation.md deleted file mode 100644 index 05088be..0000000 --- a/docs/scripts-documentation.md +++ /dev/null @@ -1,295 +0,0 @@ -# 脚本文档 - -PIS 项目跨平台服务管理脚本。 - -## 概述 - -| 脚本 | Windows (PowerShell) | Unix/Linux/macOS (Bash) | -|------|---------------------|------------------------| -| 启动后端 | `start-backend.ps1` | `start-backend.sh` | -| 启动前端 | `start-frontend.ps1` | `start-frontend.sh` | -| 启动 Celery | `start-celery.ps1` | `start-celery.sh` | -| 停止所有 | `stop-all.ps1` | `stop-all.sh` | -| 停止 Celery | `stop-celery.ps1` | `stop-celery.sh` | -| 查看日志 | `view-logs.ps1` | `view-logs.sh` | -| 检查状态 | `check-status.ps1` | `check-status.sh` | - -## 快速开始 - -### Windows (PowerShell) - -```powershell -# 启动所有服务 -.\make.ps1 dev - -# 停止所有服务 -.\make.ps1 stop - -# 查看日志 -.\make.ps1 logs - -# 检查状态 -.\make.ps1 status -``` - -### Unix/Linux/macOS (Bash) - -```bash -# 启动所有服务 -make dev - -# 停止所有服务 -make stop - -# 查看日志 -make logs - -# 检查状态 -make status -``` - -## 使用方法 - -### make.ps1 命令 (Windows PowerShell) - -| 命令 | 说明 | -|------|------| -| `.\make.ps1 help` | 显示所有可用命令 | -| `.\make.ps1 dev` | 启动开发环境(前端 + 后端 + Celery) | -| `.\make.ps1 dev-backend` | 仅启动后端 | -| `.\make.ps1 dev-frontend` | 仅启动前端 | -| `.\make.ps1 dev-celery` | 仅启动 Celery | -| `.\make.ps1 stop` | 停止所有服务 | -| `.\make.ps1 restart` | 重启所有服务 | -| `.\make.ps1 restart-celery` | 仅重启 Celery | -| `.\make.ps1 logs` | 查看所有日志 | -| `.\make.ps1 logs-backend` | 查看后端日志 | -| `.\make.ps1 logs-frontend` | 查看前端日志 | -| `.\make.ps1 logs-celery` | 查看 Celery 日志 | -| `.\make.ps1 status` | 检查服务状态 | -| `.\make.ps1 clean-logs` | 清理日志文件 | -| `.\make.ps1 clean-pids` | 清理 PID 文件 | - -### make 命令 (Unix/Linux/macOS Bash) - -| 命令 | 说明 | -|------|------| -| `make help` | 显示所有可用命令 | -| `make dev` | 启动开发环境(前端 + 后端 + Celery) | -| `make dev-backend` | 仅启动后端 | -| `make dev-frontend` | 仅启动前端 | -| `make dev-celery` | 仅启动 Celery | -| `make stop` | 停止所有服务 | -| `make restart` | 重启所有服务 | -| `make restart-celery` | 仅重启 Celery | -| `make logs` | 查看所有日志 | -| `make logs-backend` | 查看后端日志 | -| `make logs-frontend` | 查看前端日志 | -| `make logs-celery` | 查看 Celery 日志 | -| `make status` | 检查服务状态 | -| `make clean-logs` | 清理日志文件 | -| `make clean-pids` | 清理 PID 文件 | - -## 直接调用脚本 - -### Windows PowerShell - -```powershell -# 启动后端 -.\scripts\start-backend.ps1 [dev|prod] - -# 启动前端 -.\scripts\start-frontend.ps1 [dev|prod] - -# 启动 Celery -.\scripts\start-celery.ps1 [dev|prod] - -# 停止所有服务 -.\scripts\stop-all.ps1 - -# 仅停止 Celery -.\scripts\stop-celery.ps1 - -# 查看日志 -.\scripts\view-logs.ps1 [backend|frontend|celery|all] - -# 检查状态 -.\scripts\check-status.ps1 -``` - -### Unix/Linux/macOS Bash - -```bash -# 启动后端 -./scripts/start-backend.sh [dev|prod] - -# 启动前端 -./scripts/start-frontend.sh [dev|prod] - -# 启动 Celery -./scripts/start-celery.sh [dev|prod] - -# 停止所有服务 -./scripts/stop-all.sh - -# 仅停止 Celery -./scripts/stop-celery.sh - -# 查看日志 -./scripts/view-logs.sh [backend|frontend|celery|all] - -# 检查状态 -./scripts/check-status.sh -``` - -## 环境参数 - -- `dev`(默认):开发模式,带热重载 -- `prod`:生产模式,使用优化构建 - -### Windows PowerShell -```powershell -.\make.ps1 dev -ENV prod -``` - -### Unix/Linux/macOS -```bash -ENV=prod make dev -``` - -## 端口 - -| 服务 | 端口 | -|------|------| -| 后端 (Django) | 8000 | -| 前端 (Vue) | 8080 | - -## 日志文件 - -日志存储在 `backend/logs/`: - -- `backend.log` - 后端应用日志 -- `frontend.log` - 前端应用日志 -- `celery_worker.log` - Celery Worker 日志 -- `celery_beat.log` - Celery Beat 调度器日志 - -## PID 文件 - -PID 文件存储在 `.pids/`: - -- `backend.pid` -- `frontend.pid` -- `celery_worker.pid` -- `celery_beat.pid` - -## 跨平台兼容性 - -### Windows PowerShell -- 支持 Windows PowerShell 5.1 及 PowerShell 7+ -- 使用 `System.Net.Sockets.TcpClient` 检查端口 -- 使用 WMI 查询检测进程(兼容 PS 5.1 和 PS 7+) -- 所有输出使用英文(避免编码问题) - -### Unix/Linux/macOS -- 需要 Bash 4.0+ -- 使用 `nc`(netcat)检查端口(如果可用) -- 使用 `pgrep` 和 `pkill` 管理进程 -- 输出使用中文 - -### Windows PowerShell Celery 已知问题 - -**Celery 在 Windows PowerShell 上有已知的兼容性问题。** - -问题原因:PowerShell 的 `Start-Process` 与 Celery 的多进程池(billiard)不兼容,导致以下错误: -- `PermissionError: [WinError 5] 拒绝访问` -- `OSError: [WinError 6] 句柄无效` - -**推荐解决方案:使用 Git Bash** - -在 Windows 上,推荐使用 Git Bash 运行 Celery 脚本: - -```bash -# 启动 Celery (推荐) -bash scripts/start-celery.sh - -# 停止 Celery -bash scripts/stop-celery.sh -``` - -Git Bash 使用 `nohup` 和 `&` 后台运行,与 Celery 的多进程机制完全兼容。 - -**如需使用 PowerShell:** - -可以尝试使用 `--pool solo` 参数(单进程模式): - -```powershell -.\scripts\start-celery.ps1 -``` - -但这可能会影响 Celery 的性能和稳定性。 - -## 依赖要求 - -### 后端 -- Python 3.10+ -- Django 4.2.14 -- uvicorn(开发)或 gunicorn(生产) -- Celery + Redis broker - -### 前端 -- Node.js 18+ -- Yarn 或 npm - -### Celery -- Redis 服务运行中 -- django-celery-beat - -## 故障排除 - -### 后端无法启动 -1. 检查端口 8000 是否被占用 -2. 检查 Python 依赖是否安装 -3. 检查 Django 配置:确保 `backend/conf/env.py` 已配置 - -### 前端无法启动 -1. 检查 Node.js 是否安装 -2. 安装依赖:`cd web && yarn install` -3. 检查端口 8080 是否被占用 - -### Celery 无法启动 -1. 检查 Redis 是否运行 -2. 执行数据库迁移:`python manage.py migrate` -3. 查看 Celery 日志 -4. **Windows 用户**:如果使用 PowerShell 启动失败,请改用 Git Bash: - ```bash - bash scripts/start-celery.sh - ``` - 这是 Windows 上的已知问题,PowerShell 的进程管理机制与 Celery 不兼容。 - -### 编码问题 -如果 PowerShell 显示乱码,确保使用 UTF-8 with BOM 编码保存的脚本文件。 - -## 脚本架构 - -``` -scripts/ -├── start-backend.ps1/.sh # 启动 Django 后端服务 -├── start-frontend.ps1/.sh # 启动 Vue 前端开发服务器 -├── start-celery.ps1/.sh # 启动 Celery worker 和 beat -├── stop-all.ps1/.sh # 停止所有服务 -├── stop-celery.ps1/.sh # 仅停止 Celery 服务 -├── view-logs.ps1/.sh # 查看和跟踪日志文件 -├── check-status.ps1/.sh # 检查服务运行状态 -├── Makefile # Unix/Linux/macOS 编排 -└── make.ps1 # Windows PowerShell 编排 -``` - -## 注意事项 - -- 所有脚本都是幂等的 - 多次运行是安全的 -- 脚本会检测服务是否已运行,已运行则跳过启动 -- 使用 PID 文件实现优雅关闭 -- 停止时会清理残留进程 -- PowerShell 脚本输出使用英文,避免编码问题 -- Bash 脚本输出使用中文 -- **Windows 用户**:建议使用 Git Bash 运行 Celery 脚本,以避免进程兼容性问题 diff --git a/docs/superpowers/plans/2026-04-03-git-collaboration-plan.md b/docs/superpowers/plans/2026-04-03-git-collaboration-plan.md deleted file mode 100644 index 28c0ee8..0000000 --- a/docs/superpowers/plans/2026-04-03-git-collaboration-plan.md +++ /dev/null @@ -1,281 +0,0 @@ -# Git 协作规范实施计划 - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**目标:** 建立标准 Git 协作规范,包含 Git Flow 分支模型、PR 模板、Code Review 流程、Git Hooks(后端 pre-commit + 前端 husky) - -**架构概述:** -- 后端 Python 项目使用 `pre-commit` + `ruff` 管理 Git Hooks -- 前端 Node.js 项目使用 `husky` + `lint-staged` 管理 Git Hooks -- PR 模板放在 `.github/` 目录(GitHub 自动识别) -- Jenkins CI 配置在各自的 Jenkinsfile 中(后端已存在) - -**技术栈:** pre-commit, ruff, husky, lint-staged - ---- - -## 文件结构 - -``` -backend/ - ├── .pre-commit-config.yaml # 新建:pre-commit hooks 配置 - └── requirements.txt # 修改:添加 pre-commit, ruff - -web/ - ├── .husky/ # 新建:husky git hooks 目录 - │ └── pre-commit # 新建:pre-commit hook script - ├── .lintstagedrc.json # 新建:lint-staged 配置 - └── package.json # 修改:添加 husky, lint-staged - -.github/ - └── PULL_REQUEST_TEMPLATE.md # 新建:PR 模板 -``` - ---- - -## 任务清单 - -### 任务 1:后端 pre-commit 配置(ruff) - -**文件:** -- 创建:`backend/.pre-commit-config.yaml` -- 修改:`backend/requirements.txt` - -- [ ] **Step 1: 创建 backend/.pre-commit-config.yaml** - -```yaml -# 后端 pre-commit hooks 配置 -# 安装方式:pip install pre-commit && pre-commit install -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-added-large-files - args: ['--maxkb=5000'] - - id: check-merge-conflict - - id: debug-statements - - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.0 - hooks: - - id: ruff - args: [--fix] - - id: ruff-format -``` - -- [ ] **Step 2: 验证文件创建** - -命令:`cat backend/.pre-commit-config.yaml` -预期:显示上述 yaml 内容 - -- [ ] **Step 3: 添加依赖到 requirements.txt** - -在 `backend/requirements.txt` 末尾添加: - -``` -# Git hooks -pre-commit>=3.0.0 -ruff>=0.9.0 -``` - -- [ ] **Step 4: 验证 requirements.txt 更新** - -命令:`grep -E "pre-commit|ruff" backend/requirements.txt` -预期:显示 pre-commit 和 ruff 两行 - -- [ ] **Step 5: 提交** - -```bash -git add backend/.pre-commit-config.yaml backend/requirements.txt -git commit -m "feat(git): add pre-commit with ruff for backend - -- Add .pre-commit-config.yaml with ruff (lint + format) -- Add pre-commit and ruff to requirements.txt -- Ruff replaces flake8 + black + isort (10-100x faster)" -``` - ---- - -### 任务 2:前端 husky + lint-staged 配置 - -**文件:** -- 创建:`web/.husky/pre-commit` -- 创建:`web/.lintstagedrc.json` -- 修改:`web/package.json` - -- [ ] **Step 1: 安装 husky 和 lint-staged** - -```bash -cd web -npm install husky lint-staged -D -``` - -- [ ] **Step 2: 初始化 husky** - -```bash -cd web -npx husky install -``` - -- [ ] **Step 3: 创建 .lintstagedrc.json** - -```json -{ - "*.{js,vue,ts,jsx,tsx}": [ - "eslint --fix", - "prettier --write" - ], - "*.{css,scss,vue}": [ - "prettier --write" - ] -} -``` - -- [ ] **Step 4: 添加 husky pre-commit hook** - -```bash -cd web -npx husky add .husky/pre-commit "npx lint-staged" -``` - -- [ ] **Step 5: 验证 .husky/pre-commit 内容** - -命令:`cat web/.husky/pre-commit` -预期:包含 `npx lint-staged` - -- [ ] **Step 6: 更新 package.json 添加 prepare script** - -在 `web/package.json` 的 `scripts` 中添加: - -```json -"prepare": "cd .. && husky install" -``` - -原有 scripts 示例: -```json -"scripts": { - "dev": "vite --force", - "prepare": "cd .. && husky install", - ... -} -``` - -- [ ] **Step 7: 验证 lint-staged 配置** - -命令:`cat web/.lintstagedrc.json` -预期:显示上述 json 内容 - -- [ ] **Step 8: 提交** - -```bash -git add web/package.json web/.lintstagedrc.json web/.husky/ -git commit -m "feat(git): add husky + lint-staged for frontend - -- Add .husky/pre-commit hook running lint-staged -- Add .lintstagedrc.json for staged file linting -- Add prepare script for husky setup on npm install" -``` - ---- - -### 任务 3:PR 模板 - -**文件:** -- 创建:`.github/PULL_REQUEST_TEMPLATE.md` - -- [ ] **Step 1: 创建 .github 目录** - -```bash -mkdir -p .github -``` - -- [ ] **Step 2: 创建 .github/PULL_REQUEST_TEMPLATE.md** - -```markdown -## 变更描述 - - -## 关联需求 - - -## 变更类型 -- [ ] Feature -- [ ] Bugfix -- [ ] Hotfix -- [ ] Refactor - -## 自检清单 -- [ ] 代码已通过 Pre-commit 检查(后端 ruff / 前端 lint-staged) -- [ ] 已添加必要的测试 -- [ ] 文档已更新(如需) - -## Reviewer 备注 - -``` - -- [ ] **Step 3: 验证模板创建** - -命令:`cat .github/PULL_REQUEST_TEMPLATE.md` -预期:显示上述 markdown 内容 - -- [ ] **Step 4: 提交** - -```bash -git add .github/PULL_REQUEST_TEMPLATE.md -git commit -m "docs: add PR template for standardized pull requests - -- Add change description, related issues -- Add change type checklist (Feature/Bugfix/Hotfix/Refactor) -- Add self-check checklist for pre-commit compliance -- Add reviewer notes section" -``` - ---- - -## 实施后验证 - -所有任务完成后,验证步骤: - -### 后端验证 - -```bash -cd backend -pip install pre-commit ruff -pre-commit install -# 测试运行 -pre-commit run --all-files -``` - -预期:ruff 检查通过(无 error) - -### 前端验证 - -```bash -cd web -# 首次 clone 后安装依赖 -npm install -# 测试 pre-commit hook -git add . -git commit -m "test: verify husky hook" -``` - -预期:lint-staged 运行,eslint + prettier 检查通过 - ---- - -## Spec 覆盖检查 - -- ✅ 分支模型:规范文档(已在 spec 中定义,无需代码实现) -- ✅ PR/MR 模板:任务 3 创建 `.github/PULL_REQUEST_TEMPLATE.md` -- ✅ Code Review 规范:规范文档(已在 spec 中定义,无需代码实现) -- ✅ Git Hooks 后端(pre-commit + ruff):任务 1 -- ✅ Git Hooks 前端(husky + lint-staged):任务 2 -- ✅ CI/CD 联动:Jenkinsfile 已存在(后端 `backend/Jenkinsfile`),无需修改 -- ✅ 分支保护规则:GitHub/GitLab 界面配置,不在代码库中 - -## 占位符扫描 - -无占位符,所有步骤均包含完整配置和命令。 diff --git a/docs/superpowers/specs/2026-04-02-ai-agent-design.md b/docs/superpowers/specs/2026-04-02-ai-agent-design.md deleted file mode 100644 index 6a294d4..0000000 --- a/docs/superpowers/specs/2026-04-02-ai-agent-design.md +++ /dev/null @@ -1,322 +0,0 @@ -# AVC 内部 Agent 开发设计方案 - -**日期**: 2026-04-02 -**状态**: 设计中 - ---- - -## 一、需求概述 - -### 1.1 背景 - -为 AVC 内部设计开发 AI Agent 平台,用于: -- 智能助手/问答(查询政策、制度、流程文档) -- 业务流程自动化(审批、数据录入、报表生成) -- 数据分析/决策支持 -- 客户服务/工单处理 - -### 1.2 约束条件 - -- 大型企业(500-2000人) -- 完全私有化部署,数据不出公司 -- **国产 LLM**(通义千问/Qwen、智谱/ChatGLM 等)在本地 GPU 运行 -- 多端访问:网页 + 嵌入现有后台 + 企业IM + API -- 全数据源接入:文档、数据库(SQL Server)、业务系统API、文件 -- 单租户架构(多租户后期考虑) - ---- - -## 二、整体架构 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 多端访问层 │ -│ (Web客户端 │ 嵌入现有后台 │ 企业IM(钉钉/飞书) │ REST API) │ -└─────────────────────────┬───────────────────────────────────────┘ - │ -┌─────────────────────────▼───────────────────────────────────────┐ -│ API 网关层 │ -│ (认证 · 鉴权 · 限流 · 日志) │ -└─────────────────────────┬───────────────────────────────────────┘ - │ -┌─────────────────────────▼───────────────────────────────────────┐ -│ LangChain Agent 编排层 │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ 问答 Agent │ │ 自动化 Agent │ │ 分析 Agent │ │ -│ │ (RAG+Vector) │ │ (RPA+Tools) │ │ (DB+API) │ │ -│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ -│ │ │ │ │ -│ ┌──────▼─────────────────▼─────────────────▼───────┐ │ -│ │ LangChain Core / LangGraph │ │ -│ │ (Agent Executor · Tool Router) │ │ -│ └─────────────────────────┬─────────────────────────┘ │ -└─────────────────────────────┼─────────────────────────────────────┘ - │ -┌─────────────────────────────▼─────────────────────────────────────┐ -│ 工具层 (Tools) │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ SQL Svr │ │ HTTP API│ │File Parse│ │ RAG搜索 │ ... │ -│ │ Query │ │ Call │ │(Excel/ │ │ (向量检索)│ │ -│ │ │ │ │ │Word/PDF) │ │ │ │ -│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ -│ ┌──────────┐ ┌──────────┐ │ -│ │ Python │ │ Msg │ │ -│ │ Script │ │ Send │ │ -│ └──────────┘ └──────────┘ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 三、核心组件 - -| 组件 | 技术选型 | 职责 | -|------|---------|------| -| **Agent 框架** | LangChain / LangGraph | Agent 编排、推理循环、Tool 调度 | -| **RAG 引擎** | LangChain VectorStore + Embedding | 企业知识库检索 | -| **向量数据库** | Milvus | 文本向量存储与检索 | -| **Embedding 模型** | 本地 BGE / XInference | 文本向量化 | -| **LLM 推理** | vLLM + 国产模型(Qwen/ChatGLM) | 大语言模型推理(国产化) | -| **工具层** | LangChain Tools | DB查询、API调用、文件处理等 | -| **API 服务** | FastAPI | 对外接口、多端接入 | -| **任务队列** | Celery + Redis | 异步任务处理 | -| **主数据库** | SQL Server | Agent 记忆、对话历史、配置存储 | - ---- - -## 四、Router 设计 - -### 4.1 混合路由策略 - -采用 **规则 + 小模型 LLM 混合路由**,优先级: - -1. **规则优先匹配**:高频、明确意图(如"发邮件"、"查考勤") -2. **小模型意图分类**:中频、可描述的意图 -3. **大模型路由兜底**:复杂、模糊意图 - -### 4.2 意图分类 - -| 意图类型 | 标识 | 示例 | -|---------|------|------| -| 问答类 | `qa` | "年假有多少天?"、"如何申请设备维修?" | -| 自动化类 | `automation` | "帮我给张三发邮件说会议改到下午3点" | -| 分析类 | `analysis` | "统计一下各部门本月报销金额" | - -### 4.3 路由实现伪代码 - -```python -def classify_intent(query: str) -> str: - """ - 规则优先,匹配则直接返回 - 未命中则调用小模型分类 - """ - # 规则匹配 - for rule in intent_rules: - if rule.matches(query): - return rule.intent - - # 小模型分类 - return llm_small.invoke( - f"判断意图类型:qa/automation/analysis\n问题:{query}" - ).content.strip() -``` - -### 4.4 插件化扩展 - -```python -class BaseAgent(ABC): - name: str - description: str - tools: list[BaseTool] - - @abstractmethod - def run(self, query: str) -> str: - pass - -class AgentRegistry: - _agents: dict[str, BaseAgent] = {} - - @classmethod - def register(cls, agent: BaseAgent): - cls._agents[agent.name] = agent -``` - -新增 Agent 只需: -```python -@AgentRegistry.register -class NewAgent(BaseAgent): - name = "new_agent" - description = "处理XXX类型问题" - tools = [tool1, tool2] -``` - ---- - -## 五、工具层设计 - -### 5.1 工具列表 - -| 工具 | 输入 | 输出 | 说明 | -|------|------|------|------| -| **MySQLQueryTool** | SQL 查询语句 | JSON 数组 | 只读查询,支持超时保护 | -| **HttpApiTool** | URL + Method + Body | JSON 响应 | 封装常见 HTTP 方法,自动重试 | -| **FileParserTool** | 文件路径 | 文本内容 | 支持 xlsx/docx/pdf/txt,自动提取结构化数据 | -| **RAGSearchTool** | 自然语言查询 | Top-K 相关文本块 | 配合向量库,返回知识库检索结果 | -| **PythonScriptTool** | 脚本内容 + 参数 | JSON 结果 | 沙箱执行,用于复杂数据处理 | -| **MessageSendTool** | 接收人 + 内容 + 渠道 | 发送状态 | 支持邮件/钉钉/飞书/企业微信 | - -### 5.2 工具架构 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Tools 层 │ -├─────────────┬─────────────┬─────────────┬─────────────────┤ -│ SQL Server │ HTTP API │ File Parse │ RAG Search │ -│ Query │ Call │ (Excel/ │ (Milvus) │ -│ │ │ Word/PDF) │ │ -├─────────────┼─────────────┼─────────────┼─────────────────┤ -│ Script Run │ Msg Send │ ...更多工具可扩展 │ -│ (Python) │ (邮件/IM) │ │ │ -└─────────────┴─────────────┴─────────────┴─────────────────┘ -``` - ---- - -## 六、数据流设计 - -### 6.1 用户查询完整流程 - -``` -用户输入 - │ - ▼ -┌─────────────┐ -│ FastAPI │ ← 限流、日志记录 -└──────┬──────┘ - │ - ▼ -┌─────────────┐ -│ Router │ ← 规则匹配 → 小模型分类 -└──────┬──────┘ - │ - ▼ -┌─────────────────────────────────────────┐ -│ LangGraph Agent │ -│ │ -│ ┌─────────────────────────────────┐ │ -│ │ LLM (国产模型: Qwen/ChatGLM) │ │ -│ │ reasoning + tool calling │ │ -│ └───────────────┬─────────────────┘ │ -│ │ │ -│ ┌────────▼────────┐ │ -│ │ Tool Router │ │ -│ │ (选择合适的tool)│ │ -│ └────────┬────────┘ │ -│ │ │ -│ ┌────────▼────────┐ │ -│ │ Tool Executor │ │ -│ │ (并行执行tools) │ │ -│ └────────┬────────┘ │ -│ │ │ -│ ┌────────▼────────┐ │ -│ │ Response │ │ -│ │ Synthesizer │ │ -│ │ (整合tool结果) │ │ -│ └─────────────────┘ │ -└──────────────────┬──────────────────────┘ - │ - ▼ - ┌─────────────┐ - │ 返回用户 │ - └─────────────┘ -``` - ---- - -## 七、错误处理策略 - -| 错误类型 | 处理策略 | -|---------|---------| -| **LLM 超时/宕机** | 自动切换备用模型;返回"服务暂时不可用,请稍后重试" | -| **Tool 执行失败** | 重试 3 次 → 失败则返回错误信息 + 部分结果 | -| **数据库连接失败** | 返回"数据库暂时不可用";记录错误日志 | -| **文件解析失败** | 返回"文件格式不支持或文件损坏" | -| **RAG 检索为空** | 返回"未找到相关内容,建议换个问法" | -| **恶意注入攻击** | SQL/指令注入检测;敏感操作需二次确认 | - ---- - -## 八、存储层设计 - -| 用途 | 技术选型 | 说明 | -|------|---------|------| -| **向量数据库** | Milvus | 企业文档向量存储,RAG 检索用 | -| **知识库原始文档** | MinIO / 本地文件系统 | 存储原始文档(PDF/Word/Excel) | -| **主业务数据库** | SQL Server | Agent 记忆、对话历史、配置存储 | -| **任务状态** | Redis + Celery | 异步任务队列、任务状态 | -| **日志存储** | Elasticsearch + Loki | 请求日志、Agent 执行日志 | - ---- - -## 九、部署架构 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 内网环境 │ -│ │ -│ ┌─────────────┐ │ -│ │ 用户端 │ ← Web / 嵌入后台 / 钉钉 / API │ -│ └──────┬──────┘ │ -│ │ │ -│ ┌──────▼──────┐ │ -│ │ FastAPI │ │ -│ └──────┬──────┘ │ -│ │ │ -│ ┌──────▼──────┐ │ -│ │ Router │ ← 规则 + 小模型混合路由 │ -│ └──────┬──────┘ │ -│ │ │ -│ ┌──────▼──────────────────────────────┐ │ -│ │ LangChain Agent 集群 │ │ -│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ -│ │ │ QA Agent │ │Auto Agent│ │Analysis │ │ │ -│ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ -│ └───────┼────────────┼────────────┼───────┘ │ -│ │ │ │ │ -│ ┌───────▼────────────▼────────────▼───────┐ │ -│ │ Tools 层 │ │ -│ │ (SQL Server │ API │ 文件解析 │ RAG) │ │ -│ └──────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ vLLM │ │ Milvus │ │ SQL Server │ │ -│ │ (国产模型) │ │ (向量库) │ │ (主库) │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - ---- - -## 十、技术选型总结 - -| 模块 | 技术选型 | -|------|---------| -| Agent 框架 | LangChain / LangGraph | -| Router | 规则 + 小模型混合意图分类 | -| Agent 类型 | QA Agent、Automation Agent、Analysis Agent | -| 工具层 | SQL Server 查询、HTTP API 调用、文件解析、RAG 检索、脚本执行、消息发送 | -| 向量库 | Milvus | -| LLM 推理 | vLLM + 国产模型(Qwen 通义千问 / 智谱 ChatGLM) | -| 主数据库 | SQL Server | -| 任务队列 | Redis + Celery | -| 访问端 | Web + 嵌入后台 + 钉钉/飞书 + API | - ---- - -## 十一、后续步骤 - -1. 编写详细实现方案(implementation plan) -2. 确定开发优先级和里程碑 -3. 开始原型开发 diff --git a/docs/superpowers/specs/2026-04-02-quote-deadline-email-notification-design.md b/docs/superpowers/specs/2026-04-02-quote-deadline-email-notification-design.md deleted file mode 100644 index 8991936..0000000 --- a/docs/superpowers/specs/2026-04-02-quote-deadline-email-notification-design.md +++ /dev/null @@ -1,93 +0,0 @@ -# 报价截止时间到期邮件通知采购 — 设计文档 - -## 1. 需求概述 - -每 5 分钟轮询 `pissupplier.QuotationMaster`,找出已到期(`quote_deadline < now`)但仍未报价(`status ∈ {1 待报价, 2 报价中}`)的报价单,按**询价单维度**合并发送一封邮件给采购负责人,每天最多一次。 - -## 2. 触发条件 - -- **字段**:`pissupplier.QuotationMaster.quote_deadline` 和 `status` -- **逻辑**:`quote_deadline < now` 且 `status in (1, 2)` -- **轮询间隔**:Celery Beat 每 5 分钟 - -## 3. 通知逻辑 - -### 3.1 合并规则 -- 按 `inquiry_no` 分组,同一询价单下所有到期未报价的供应商合并到一封邮件 -- 避免邮件轰炸 - -### 3.2 去重规则 -- 复用现有 `should_send_quote_timeout_reminder(inquiry_no, cooldown_hours=24)` 按 `inquiry_no` 做 24 小时冷却期 -- 已发送过(EmailNotice.biz_type="inquiry_quote_timeout" + status="success")的询价单跳过 - -### 3.3 收件人 -- 仅「采购负责人」(buyer),对应 Inquiry.buyer 字段 -- 复用现有 `resolve_inquiry_purchaser_emails` 函数 - -### 3.4 邮件内容 -- 字段:询价单名称、编号、报价截止时间、到期供应商列表、比价页面链接 -- 模板:参考 `backend/templates/emails/quote_timeout_body.html` - -## 4. 数据流 - -``` -Celery Beat (每5分钟) - └── check_quote_deadline_expired() [Celery Task] - ├── 查询所有 status∈{1,2} 且 quote_deadline < now 的 QuotationMaster - ├── 按 inquiry_no 分组 - ├── 对每个 inquiry_no: - │ ├── 检查24h冷却期(should_send_quote_timeout_reminder) - │ ├── 查找 Inquiry,获取采购负责人邮箱 - │ ├── 渲染邮件内容(过期供应商列表) - │ └── 发送邮件(send_email_notice) - └── 写 EmailNotice 记录(biz_type="inquiry_quote_timeout") -``` - -## 5. 新增文件 - -| 文件路径 | 说明 | -|---|---| -| `backend/apps/pisadmin/miscprocurement/tasks.py` | Celery 定时任务:轮询报价截止时间、发送邮件 | - -## 6. 修改文件 - -| 文件路径 | 修改内容 | -|---|---| -| `backend/application/celery.py` | 注册 Celery Beat Schedule(新增 `check_quote_deadline_expired` 任务) | - -## 7. 核心任务函数签名 - -```python -@app.task -def check_quote_deadline_expired() -> dict: - """ - Celery Beat 定时任务:轮询报价截止时间已到期的报价单, - 按询价单合并发送邮件通知采购负责人,每天最多一次。 - - Returns: {"checked": N, "sent": M, "skipped": K} - """ -``` - -## 8. Celery Beat Schedule 配置 - -```python -CELERY_BEAT_SCHEDULE = { - "check-quote-deadline-expired": { - "task": "apps.pisadmin.miscprocurement.tasks.check_quote_deadline_expired", - "schedule": crontab(minute="*/5"), # 每5分钟 - }, -} -``` - -## 9. 已有可复用代码 - -- `apps.pisadmin.basicinfo.views.email_utils.send_quote_timeout_notice_to_purchaser` — 单封邮件发送 -- `apps.pisadmin.basicinfo.views.email_utils.should_send_quote_timeout_reminder` — 24h冷却期判断 -- `apps.pisadmin.basicinfo.views.email_utils.resolve_inquiry_purchaser_emails` — 采购负责人邮箱解析 -- `apps.pisadmin.basicinfo.views.email_utils.send_email_notice` — 邮件发送底层 -- `backend/templates/emails/quote_timeout_body.html` — 邮件模板 - -## 10. 异常处理 - -- 邮件发送失败不影响其他询价单处理,记录异常日志 -- Celery 任务失败自动重试(最多3次,间隔3分钟) diff --git a/docs/superpowers/specs/2026-04-03-git-collaboration-design.md b/docs/superpowers/specs/2026-04-03-git-collaboration-design.md deleted file mode 100644 index 3e3683c..0000000 --- a/docs/superpowers/specs/2026-04-03-git-collaboration-design.md +++ /dev/null @@ -1,270 +0,0 @@ -# Git 协作规范设计 - -> 创建日期:2026-04-03 -> 状态:已批准 -> 关联:Git 协作标准化 - ---- - -## 1. 分支模型 - -采用标准 Git Flow。 - -``` -main ──────────────────────────── 生产环境(受保护,禁止直接 push) - ↑ - │ ← hotfix/xxx(从 main 分出,修复完成需合并回 main + develop) - │ -develop ───────────────────────── 开发集成主线(受保护,禁止直接 push) - ↑ - │ ← feature/xxx(从 develop 分出,功能完成后合并回 develop) - │ ← bugfix/xxx(从 develop 分出,develop 上的 bug 修复) -``` - -### 分支命名规范 - -| 分支类型 | 命名格式 | 示例 | -|---------|---------|------| -| Feature | `feature/功能描述` 或 `feature/ISSUE号-功能描述` | `feature/PIS-123-user-auth` | -| Bugfix | `bugfix/问题描述` 或 `bugfix/ISSUE号-修复描述` | `bugfix/PIS-456-login-timeout` | -| Hotfix | `hotfix/紧急修复描述` | `hotfix/critical-payment-fix` | - -### 分支生命周期 - -- **创建**:`git checkout develop && git pull && git checkout -b feature/xxx` -- **同步上游**:`git merge develop` 或 `git rebase develop` -- **完成合并后**:分支自动删除(GitHub/GitLab 设置 `delete branch after merge`) - ---- - -## 2. PR/MR 流程 - -### 标准流程 - -``` -1. 从 develop 创建分支 -2. 开发并 commit(保持原子性) -3. Push 到远程 -4. 创建 PR,填写模板 -5. 指定 Reviewer -6. 等待 Review 通过 -7. Jenkins CI 构建通过 -8. 合并到 develop -9. 分支自动删除 -``` - -### PR 模板 - -```markdown -## 变更描述 - - -## 关联需求 - - -## 变更类型 -- [ ] Feature -- [ ] Bugfix -- [ ] Hotfix -- [ ] Refactor - -## 自检清单 -- [ ] 代码已通过 Pre-commit 检查 -- [ ] 已添加必要的测试 -- [ ] 文档已更新(如需) - -## Reviewer 备注 - -``` - -### 合并标准 - -- 至少 **1 人** Approve -- **Jenkins CI** 构建通过 -- 无未解决的 Conversation -- 分支已最新(解决与目标分支的冲突) - ---- - -## 3. Code Review 规范 - -### 作者职责 - -- 代码逻辑复杂处添加必要注释 -- 准备好回复 Review 意见 -- **不要在 Review 前自行合并** -- 不要在 PR 中混入不相关的改动 - -### Reviewer 职责 - -- **24 小时内**完成 Review -- 聚焦:逻辑正确性、代码风格、安全隐患 -- 评价客观,避免个人偏好带入 -- 确认 Jenkins CI 状态 - -### 合并门槛 - -``` -最低 1 人 Approve + CI 通过 → 可合并 -``` - ---- - -## 4. Git Hooks - -后端和前端分开管理,各自使用最合适的工具。 - -### 后端(Python)— pre-commit - -**安装方式:** -```bash -cd backend -pip install pre-commit commitlint -pre-commit install -``` - -**检查内容:** -- Python:`flake8`、`black` -- 通用:禁止 debug 代码、敏感信息检查 - -**.pre-commit-config.yaml 示例:** -```yaml -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-added-large-files - - - repo: https://github.com/pycqa/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - args: [--max-line-length=120] -``` - -### 前端(Node.js)— husky - -**安装方式:** -```bash -cd web -npm install husky lint-staged -D -npx husky install -npx husky add .husky/pre-commit "npx lint-staged" -``` - -**package.json lint-staged 配置:** -```json -{ - "lint-staged": { - "*.{js,vue,ts}": ["eslint --fix", "prettier --write"] - } -} -``` - ---- - -## 5. Git Etiquette - -### 鼓励的行为 - -``` -✅ Commit Often — 小步提交,每次有清晰改动 -✅ 保持 commit 原子性 — 一个 commit 只做一件事 -✅ 提交前本地跑测试 — 不要把坏代码推向远程 -✅ Review 通过后再合并 — 不要绕过 Review -✅ 功能完成后及时开 PR — 不要等代码变坏 -✅ 同步上游分支 — 经常 pull/rebase develop 减少冲突 -``` - -### 禁止的行为 - -``` -❌ 不要 push WIP(未完成的工作)到远程主分支 -❌ 不要强制 push(git push --force)到 main/develop -❌ 不要在 PR 里混入不相关的改动 -❌ 不要跳过 Pre-commit 直接 commit -``` - ---- - -## 6. CI/CD 联动(Jenkins) - -### Pre-commit(本地) - -- 在开发者本地运行 -- 不阻塞远程,但作为质量门槛 -- 失败则无法 commit(可 --no-verify 绕过,但不推荐) - -### Jenkins Pipeline - -``` -Push → 自动触发 Jenkins Build - ├── Backend - │ ├── 单元测试 (pytest) - │ ├── 代码检查 (flake8) - │ └── 构建 - │ - ├── Frontend - │ ├── 依赖安装 - │ ├── ESLint 检查 - │ ├── 构建 - │ └── 预览部署 - │ - └── 结果通知(可选:邮件/Slack) -``` - -### 部署规则 - -| 合并目标 | 触发动作 | -|---------|---------| -| `main` | 自动部署到生产环境(可选,视团队节奏) | -| `develop` | 自动部署到测试环境 | - ---- - -## 7. 分支保护规则 - -### main(生产环境) - -- ❌ 禁止直接 push -- ❌ 禁止 force push -- ✅ 必须通过 PR 合并 -- ✅ 必须有 CI 通过 -- ✅ 必须有 1 人 Approve - -### develop(开发主线) - -- ❌ 禁止直接 push -- ❌ 禁止 force push -- ✅ 必须通过 PR 合并 -- ✅ 必须有 CI 通过 - -### feature/bugfix/hotfix - -- 可直接 push -- 鼓励通过 PR 协作 - ---- - -## 8. 工具链汇总 - -| 环节 | 工具 | 适用范围 | -|-----|------|---------| -| Git Hooks(后端) | pre-commit | backend/ | -| Git Hooks(前端) | husky + lint-staged | web/ | -| CI/CD | Jenkins | 全项目 | -| 代码风格(后端) | flake8, black | backend/ | -| 代码风格(前端) | eslint, prettier | web/ | - ---- - -## 设计决策 - -1. **分支模型**:标准 Git Flow,平衡了规范性和灵活性 -2. **Review 门槛**:1 人 Approve,门槛适中不过度拖延 -3. **Hook 管理**:后端 pre-commit、前端 husky,各自用最合适的工具 -4. **分支合并后自动删除**:保持仓库整洁 -5. **CI 联动**:Jenkins 覆盖构建和测试,不重复造轮子 diff --git a/web/package-lock.json b/web/package-lock.json index 2286d0e..6f3f865 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -80,6 +80,8 @@ "baseline-browser-mapping": "^2.9.19", "eslint": "^8.57.1", "eslint-plugin-vue": "^9.27.0", + "husky": "^9.1.7", + "lint-staged": "^16.4.0", "prettier": "^2.8.1", "sass": "^1.56.2", "typescript": "^4.9.4", @@ -1482,7 +1484,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1499,7 +1500,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1516,7 +1516,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1533,7 +1532,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1550,7 +1548,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1567,7 +1564,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1584,7 +1580,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1601,7 +1596,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1618,7 +1612,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1635,7 +1628,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1652,7 +1644,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1669,7 +1660,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1686,7 +1676,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1703,7 +1692,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1720,7 +1708,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1737,7 +1724,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1754,7 +1740,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1771,7 +1756,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1788,7 +1772,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1805,7 +1788,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1822,7 +1804,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1839,7 +1820,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1856,7 +1836,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2440,7 +2419,6 @@ "version": "2.5.6", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2480,7 +2458,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2501,7 +2478,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2522,7 +2498,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2543,7 +2518,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2564,7 +2538,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2585,7 +2558,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2606,7 +2578,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2627,7 +2598,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2648,7 +2618,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2669,7 +2638,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2690,7 +2658,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2711,7 +2678,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2732,7 +2698,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2779,7 +2744,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2793,7 +2757,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2807,7 +2770,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2821,7 +2783,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2835,7 +2796,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2849,7 +2809,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2863,7 +2822,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2877,7 +2835,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2891,7 +2848,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2905,7 +2861,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2919,7 +2874,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2933,7 +2887,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2947,7 +2900,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2961,7 +2913,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2975,7 +2926,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2989,7 +2939,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3003,7 +2952,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3017,7 +2965,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3031,7 +2978,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3045,7 +2991,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3059,7 +3004,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3073,7 +3017,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3087,7 +3030,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3101,7 +3043,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3115,7 +3056,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3879,7 +3819,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, "node_modules/@types/event-emitter": { @@ -4746,6 +4685,22 @@ "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==", "license": "MIT" }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", @@ -5261,7 +5216,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -5278,6 +5233,56 @@ "resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-8.2.0.tgz", + "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/clipboard": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", @@ -5331,6 +5336,13 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5968,7 +5980,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, "license": "Apache-2.0", "optional": true, "engines": { @@ -6319,6 +6330,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -6421,7 +6445,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -7120,6 +7143,19 @@ "node": ">=6.9.0" } }, + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -7425,6 +7461,22 @@ "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmmirror.com/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/i18next": { "version": "20.6.1", "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", @@ -7521,7 +7573,7 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/import-cwd": { @@ -8106,6 +8158,137 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/lint-staged": { + "version": "16.4.0", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-16.4.0.tgz", + "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.3", + "listr2": "^9.0.5", + "picomatch": "^4.0.3", + "string-argv": "^0.3.2", + "tinyexec": "^1.0.4", + "yaml": "^2.8.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/loader-utils": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", @@ -8216,6 +8399,115 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "license": "MIT" }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -8382,6 +8674,19 @@ "node": ">= 0.6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -8660,7 +8965,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, "license": "MIT", "optional": true }, @@ -8798,6 +9102,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -10060,7 +10380,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 14.18.0" @@ -10126,6 +10446,23 @@ "node": ">=4" } }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -10181,6 +10518,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "2.80.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-2.80.0.tgz", + "integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==", + "license": "MIT", + "peer": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/rollup-plugin-postcss": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", @@ -10310,7 +10663,7 @@ "version": "1.97.3", "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -10609,6 +10962,52 @@ "slate": ">=0.65.3" } }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/snabbdom": { "version": "3.6.3", "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.3.tgz", @@ -10778,6 +11177,16 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", @@ -11163,6 +11572,23 @@ "node": ">=8.10.0" } }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/terser": { "version": "5.46.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", @@ -11233,6 +11659,16 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -11353,7 +11789,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11515,7 +11951,6 @@ "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -11599,7 +12034,6 @@ "version": "4.59.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 9b82115..25d3e5f 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -139,7 +139,7 @@ importers: version: 3.2.0(vue@3.5.31(typescript@4.9.5)) tailwindcss: specifier: ^3.2.7 - version: 3.4.19 + version: 3.4.19(yaml@2.8.3) ts-md5: specifier: ^1.3.1 version: 1.3.1 @@ -216,6 +216,12 @@ importers: eslint-plugin-vue: specifier: ^9.27.0 version: 9.33.0(eslint@8.57.1) + husky: + specifier: ^9.1.7 + version: 9.1.7 + lint-staged: + specifier: ^16.4.0 + version: 16.4.0 prettier: specifier: ^2.8.1 version: 2.8.8 @@ -1668,6 +1674,10 @@ packages: resolution: {integrity: sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==} engines: {node: '>=8'} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1830,6 +1840,14 @@ packages: claygl@1.3.0: resolution: {integrity: sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} + engines: {node: '>=20'} + clipboard@2.0.11: resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} @@ -1851,10 +1869,17 @@ packages: colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -2150,6 +2175,9 @@ packages: peerDependencies: vue: ^2.6.11 || ^3.2.0 + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2170,6 +2198,10 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -2284,6 +2316,9 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + ext@1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} @@ -2407,6 +2442,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -2491,6 +2530,11 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + i18next@20.6.1: resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} @@ -2579,6 +2623,10 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2735,6 +2783,15 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lint-staged@16.4.0: + resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==} + engines: {node: '>=20.17'} + hasBin: true + + listr2@9.0.5: + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} + engines: {node: '>=20.0.0'} + loader-utils@3.3.1: resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} engines: {node: '>= 12.13.0'} @@ -2790,6 +2847,10 @@ packages: lodash@4.18.0: resolution: {integrity: sha512-l1mfj2atMqndAHI3ls7XqPxEjV2J9ZkcNyHpoZA3r2T1LLwDB69jgkMWh71YKwhBbK0G2f4WSn05ahmQXVxupA==} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2862,6 +2923,10 @@ packages: engines: {node: '>=4.0.0'} hasBin: true + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -2992,6 +3057,10 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3492,6 +3561,10 @@ packages: engines: {node: '>= 0.4'} hasBin: true + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -3631,6 +3704,14 @@ packages: slate@0.72.8: resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==} + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + snabbdom@3.6.3: resolution: {integrity: sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==} engines: {node: '>=12.17.0'} @@ -3692,6 +3773,10 @@ packages: resolution: {integrity: sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==} engines: {node: '>=4.0.0'} + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + string-hash@1.1.3: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} @@ -3706,6 +3791,14 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + engines: {node: '>=20'} + string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -3786,6 +3879,10 @@ packages: tiny-warning@1.0.3: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -4042,6 +4139,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -4106,6 +4207,11 @@ packages: resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} engines: {node: '>= 6'} + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + yarn@1.22.22: resolution: {integrity: sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==} engines: {node: '>=4.0.0'} @@ -6088,6 +6194,10 @@ snapshots: - proxy-agent - supports-color + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -6268,6 +6378,15 @@ snapshots: claygl@1.3.0: {} + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@5.2.0: + dependencies: + slice-ansi: 8.0.0 + string-width: 8.2.0 + clipboard@2.0.11: dependencies: good-listener: 1.2.2 @@ -6286,10 +6405,14 @@ snapshots: colord@2.9.3: {} + colorette@2.0.20: {} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 + commander@14.0.3: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -6626,6 +6749,8 @@ snapshots: dependencies: vue: 3.5.31(typescript@4.9.5) + emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -6640,6 +6765,8 @@ snapshots: entities@7.0.1: {} + environment@1.1.0: {} + errno@0.1.8: dependencies: prr: 1.0.1 @@ -6819,6 +6946,8 @@ snapshots: eventemitter3@4.0.7: {} + eventemitter3@5.0.4: {} + ext@1.7.0: dependencies: type: 2.7.3 @@ -6933,6 +7062,8 @@ snapshots: gensync@1.0.0-beta.2: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -7040,6 +7171,8 @@ snapshots: dependencies: ms: 2.1.3 + husky@9.1.7: {} + i18next@20.6.1: dependencies: '@babel/runtime': 7.29.2 @@ -7113,6 +7246,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.5.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -7252,6 +7389,24 @@ snapshots: lines-and-columns@1.2.4: {} + lint-staged@16.4.0: + dependencies: + commander: 14.0.3 + listr2: 9.0.5 + picomatch: 4.0.4 + string-argv: 0.3.2 + tinyexec: 1.0.4 + yaml: 2.8.3 + + listr2@9.0.5: + dependencies: + cli-truncate: 5.2.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + loader-utils@3.3.1: {} locate-path@6.0.0: @@ -7290,6 +7445,14 @@ snapshots: lodash@4.18.0: {} + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -7350,6 +7513,8 @@ snapshots: mime@2.6.0: {} + mimic-function@5.0.1: {} + mimic-response@3.1.0: {} minimatch@3.1.5: @@ -7483,6 +7648,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -7643,12 +7812,13 @@ snapshots: optionalDependencies: postcss: 8.5.8 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.8): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.8)(yaml@2.8.3): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 postcss: 8.5.8 + yaml: 2.8.3 postcss-merge-longhand@5.1.7(postcss@8.5.8): dependencies: @@ -7930,6 +8100,11 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + reusify@1.1.0: {} rfdc@1.4.1: {} @@ -8117,6 +8292,16 @@ snapshots: is-plain-object: 5.0.0 tiny-warning: 1.0.3 + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + snabbdom@3.6.3: {} sortablejs@1.14.0: {} @@ -8166,6 +8351,8 @@ snapshots: stream-wormhole@1.1.0: {} + string-argv@0.3.2: {} + string-hash@1.1.3: {} string-split-by@1.0.0: @@ -8184,6 +8371,17 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.2.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + + string-width@8.2.0: + dependencies: + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -8240,7 +8438,7 @@ snapshots: sax: 1.6.0 stable: 0.1.8 - tailwindcss@3.4.19: + tailwindcss@3.4.19(yaml@2.8.3): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8259,7 +8457,7 @@ snapshots: postcss: 8.5.8 postcss-import: 15.1.0(postcss@8.5.8) postcss-js: 4.1.0(postcss@8.5.8) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.8) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.8)(yaml@2.8.3) postcss-nested: 6.2.0(postcss@8.5.8) postcss-selector-parser: 6.1.2 resolve: 1.22.11 @@ -8291,6 +8489,8 @@ snapshots: tiny-warning@1.0.3: {} + tinyexec@1.0.4: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.4) @@ -8531,6 +8731,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.2.0 + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrappy@1.0.2: {} ws@7.5.10: {} @@ -8568,6 +8774,8 @@ snapshots: yaml@1.10.3: {} + yaml@2.8.3: {} + yarn@1.22.22: {} yocto-queue@0.1.0: {} diff --git a/web/src/stores/modules/dashboard.ts b/web/src/stores/modules/dashboard.ts index d430923..d84613f 100644 --- a/web/src/stores/modules/dashboard.ts +++ b/web/src/stores/modules/dashboard.ts @@ -2,71 +2,73 @@ import { defineStore } from 'pinia'; import { getDashboard } from '/@/api/pisadmin/dashboard'; interface BuyerDashboard { - kpi: { - total_inquiries: number; - pending_inquiries: number; - completed_quotes: number; - total_suppliers: number; - } | null; - tasks: Array<{ - id: number; - title: string; - inquiry_no: string; - status: string; - created_at: string; - }>; - messages: Array<{ - id: number; - title: string; - content: string; - is_read: boolean; - created_at: string; - }>; - trend: Array<{ month: string; count: number }>; + kpi: { + total_inquiries: number; + pending_inquiries: number; + completed_quotes: number; + total_suppliers: number; + quote_timely_rate: number; + } | null; + tasks: Array<{ + id: number; + title: string; + inquiry_no: string; + status: string; + created_at: string; + }>; + messages: Array<{ + id: number; + title: string; + content: string; + is_read: boolean; + created_at: string; + }>; + trend: Array<{ month: string; count: number }>; } interface SupplierDashboard { - kpi: { - total_quotes: number; - pending_quotes: number; - won_quotes: number; - conversion_rate: number; - } | null; - pending_quotes: Array<{ - id: number; - inquiry_no: string; - item_name: string; - quantity: number; - unit: string; - deadline: string; - }>; - messages: Array<{ - id: number; - title: string; - content: string; - is_read: boolean; - created_at: string; - }>; - trend: Array<{ month: string; quotes: number; won: number }>; + kpi: { + total_quotes: number; + pending_quotes: number; + won_quotes: number; + conversion_rate: number; + } | null; + pending_quotes: Array<{ + id: number; + inquiry_no: string; + item_name: string; + quantity: number; + unit: string; + deadline: string; + status: number; + }>; + messages: Array<{ + id: number; + title: string; + content: string; + is_read: boolean; + created_at: string; + }>; + trend: Array<{ month: string; quotes: number; won: number }>; } export const useDashboardStore = defineStore('dashboard', { - state: () => ({ - buyer: null as BuyerDashboard | null, - supplier: null as SupplierDashboard | null, - loading: false, - }), - actions: { - async fetchDashboard() { - this.loading = true; - try { - const res: any = await getDashboard(); - // 后端直接返回 {buyer, supplier} 结构 - this.buyer = res?.buyer || null; - this.supplier = res?.supplier || null; - } finally { - this.loading = false; - } - }, - }, + state: () => ({ + buyer: null as BuyerDashboard | null, + supplier: null as SupplierDashboard | null, + loading: false, + }), + actions: { + async fetchDashboard() { + this.loading = true; + try { + const res: any = await getDashboard(); + // 后端直接返回 {buyer, supplier} 结构 + this.buyer = res?.buyer || null; + this.supplier = res?.supplier || null; + } finally { + this.loading = false; + } + }, + }, });