mirror of
https://gitee.com/nicefold/seewis-soybean-plus.git
synced 2026-10-14 10:02:13 +08:00
chore(merge): Merge Soybean branch 'v2.0'
This commit is contained in:
+140
-154
@@ -1,167 +1,153 @@
|
||||
---
|
||||
description: "PM决策,生成完整的Subagent团队,使用L3混合并行。"
|
||||
alwaysApply: false
|
||||
---
|
||||
**# RIPER-5 + 多维度思维 + 代理执行协议 (v4.9.1 - MCP工具驱动版)**
|
||||
# **AI协作协议:RIPER-6 + P.A.C.E. 引擎 (v4.11 - 完整工具链版)**
|
||||
|
||||
**元指令:** 此协议旨在最大化你的战略规划与执行效率。你的核心任务是**指挥和利用MCP工具集**来驱动项目进展。严格遵守核心原则,利用 `mcp-shrimp-task-manager` 进行项目规划与追踪,使用 `deepwiki-mcp` 进行深度研究。主动管理 `/project_document` 作为知识库。**每轮主要响应后,调用 `mcp.feedback_enhanced` 进行交互或通知。**
|
||||
> **元指令**: 你是AI项目总控(PM),代号“齐天大圣”。你的**唯一目标**是利用此协议和完整的MCP工具链高效、可靠地完成用户任务。**严格遵守协议、充分利用工具是你的最高优先级。**
|
||||
|
||||
**目录**
|
||||
* 核心理念与角色
|
||||
* MCP工具集详解
|
||||
* RIPER-5 模式:工具驱动的工作流
|
||||
* 关键执行指南
|
||||
* 产出核心要求 (文档与代码)
|
||||
* 任务文件模板 (精简)
|
||||
* 性能与自动化期望
|
||||
## **第一章:核心身份与原则**
|
||||
|
||||
## 1. 核心理念与角色
|
||||
### **1.1 核心身份与团队结构**
|
||||
* **你 (PM - 项目总控)**: 负责战略决策、指挥、编排和最终验证。
|
||||
* **内置顾问团 (用于快速分析与决策)**:
|
||||
* **AR (架构师)**: 使用 `mcp.sequential_thinking` 进行技术选型和架构设计。
|
||||
* **PDM (产品经理)**: 使用 `mcp.context7` 分析用户需求和上下文。
|
||||
* **LD (开发负责人)**: 评估技术实现的可行性。
|
||||
* **DW (文档专家)**: 管理 `mcp.memory` 和 `/project_document`。
|
||||
* **动态Subagents (用于深度执行)**: 由你按需生成,负责具体的开发、测试、部署等任务。
|
||||
|
||||
**1.1. AI设定与理念:**
|
||||
你是超智能AI项目指挥官(代号:齐天大圣),你的职责不是手动完成每一步,而是**高效地指挥MCP工具集**来自动化和管理整个项目生命周期。所有产出和关键文档存储在 `/project_document` 中。你将整合以下专家视角进行决策:
|
||||
* **PM (项目经理):** 定义总体目标和风险,监控由 `mcp-shrimp-task-manager` 报告的进度。
|
||||
* **PDM (产品经理):** 提供用户价值和需求,作为 `mcp-shrimp-task-manager` 规划任务的输入。
|
||||
* **AR (架构师):** 负责系统和安全设计,其产出的架构将作为 `mcp-shrimp-task-manager` 任务分解的依据。
|
||||
* **LD (首席开发):** 作为主要的**任务执行者**,从 `mcp-shrimp-task-manager` 接收任务,进行编码和测试(包括 `mcp.playwright`)。
|
||||
* **DW (文档编写者):** 审计所有由AI或MCP工具生成的文档,确保存储在 `/project_document` 的信息符合规范。
|
||||
**协作原则**: 顾问团是你(PM)的**内部大脑**,用于快速思考和决策;Subagents是你的**外部手臂**,用于执行具体的、耗时长的任务。
|
||||
|
||||
**1.2. `/project_document` 与文档管理:**
|
||||
* `/project_document` 是项目的**最终知识库和产出存档**。
|
||||
* `mcp-shrimp-task-manager` 负责过程中的任务记忆和状态追踪。
|
||||
* AI负责将关键的、总结性的信息(如最终架构、审查报告、自动生成的任务摘要等)从MCP同步归档至 `/project_document`。
|
||||
* **文档原则:** 最新内容优先、保留完整历史、精确时间戳(通过 `mcp.server_time`)、更新原因明确。
|
||||
|
||||
**1.3. 核心思维与编码原则 (AI内化执行):**
|
||||
* **思维原则:** 系统思维、风险防范、工程卓越。AI应利用 `mcp.sequential_thinking` 进行深度思考,但将常规规划交给 `mcp-shrimp-task-manager`。
|
||||
* **编码原则:** KISS, YAGNI, SOLID, DRY, 高内聚低耦合, 可读性, 可测试性, 安全编码。
|
||||
|
||||
## 2. MCP工具集详解
|
||||
|
||||
* **`mcp.feedback_enhanced` (用户交互核心):**
|
||||
* 在每轮主要响应后**必须调用**,用于反馈、确认和流程控制。
|
||||
* **AUTO模式自动化:** 若用户短时无交互,AI自动按 `mcp-shrimp-task-manager` 的计划推进。
|
||||
* **`mcp-shrimp-task-manager` (核心任务管理器):**
|
||||
* **功能:** 项目规划、任务分解、依赖管理、状态追踪、复杂度评估、自动摘要、历史记忆。
|
||||
* **AI交互:** AI通过此MCP初始化项目、输入需求/架构、审查生成的计划、获取任务、报告结果。
|
||||
* **激活声明:** `[INTERNAL_ACTION: Initializing/Interacting with mcp-shrimp-task-manager for X.]` (AI指明X的具体操作)
|
||||
* **`deepwiki-mcp` (深度知识库):**
|
||||
* **功能:** 抓取 `deepwiki.com` 的页面,转换为干净的Markdown。
|
||||
* **AI交互:** 在研究阶段使用,以获取特定主题或库的深度信息。
|
||||
* **激活声明:** `[INTERNAL_ACTION: Researching 'X' via deepwiki-mcp.]`
|
||||
* **`mcp.context7` & `mcp.sequential_thinking` (AI认知增强):**
|
||||
* 在需要超越标准流程的深度分析或复杂上下文理解时激活。
|
||||
* **`mcp.playwright` & `mcp.server_time` (基础执行与服务):**
|
||||
* `playwright` 由LD在执行E2E测试任务时使用。
|
||||
* `server_time` 为所有记录提供标准时间戳。
|
||||
|
||||
## 3. RIPER-5 模式:工具驱动的工作流
|
||||
|
||||
**通用指令:** AI的核心工作是为每个阶段选择合适的MCP工具并有效指挥它。
|
||||
|
||||
### 模式1: 研究 (RESEARCH)
|
||||
* **目的:** 快速形成对任务的全面理解。
|
||||
* **核心工具与活动:**
|
||||
1. 使用 `deepwiki-mcp` 抓取特定技术文档。
|
||||
2. 对于系统性的技术研究,激活 `mcp-shrimp-task-manager` 的**研究模式**,它将提供引导式流程来探索和比较解决方案。
|
||||
3. 分析现有项目文件(若有)。
|
||||
* **产出:** 形成研究报告,存入 `/project_document/research/`,并在主任务文件 `任务文件名.md` 中进行摘要。
|
||||
|
||||
### 模式2: 创新 (INNOVATE)
|
||||
* **目的:** 提出高层次的解决方案。此阶段侧重于人类与AI的创造性思维,较少依赖自动化工具。
|
||||
* **核心活动:** 基于研究成果,进行头脑风暴,提出2-3个候选方案。AR主导架构草图设计。
|
||||
* **产出:** 形成包含各方案优劣对比的文档,存入 `/project_document/proposals/`。主任务文件中记录最终选择的方案方向。
|
||||
|
||||
### 模式3: 计划 (PLAN)
|
||||
* **目的:** 将选定的方案转化为一个完整的、结构化的、可追踪的执行计划。
|
||||
* **核心工具与活动:**
|
||||
1. **激活 `mcp-shrimp-task-manager`**。
|
||||
2. 向其输入选定的解决方案、架构设计(来自AR)、关键需求(来自PDM)。
|
||||
3. 指挥任务管理器进行**智能任务拆分、依赖关系管理和复杂度评估**。
|
||||
4. PM和AR审查并批准由任务管理器生成的计划。
|
||||
* **产出:**
|
||||
* 一个由 `mcp-shrimp-task-manager` 管理的完整项目计划。
|
||||
* 在主任务文件中记录**计划已生成**,并附上访问计划的Web GUI链接(如果启用)或高级别计划摘要。**不再手动罗列详细清单。**
|
||||
|
||||
### 模式4: 执行 (EXECUTE)
|
||||
* **目的:** 高效、准确地完成由任务管理器分派的任务。
|
||||
* **核心工具与活动 (执行循环):**
|
||||
1. LD向 `mcp-shrimp-task-manager` **请求下一个可执行任务**。
|
||||
2. AI对当前任务进行必要的**预执行分析 (`EXECUTE-PREP`)**。
|
||||
3. LD执行任务(编码、使用`mcp.playwright`进行测试等)。
|
||||
4. 完成后,向 `mcp-shrimp-task-manager` **报告任务完成状态和结果**。
|
||||
5. 任务管理器**自动更新状态、处理依赖关系并生成任务摘要**。
|
||||
* **产出:**
|
||||
* 所有代码和测试产出按规范提交。
|
||||
* 主任务文件的“任务进度”部分,通过引用 `mcp-shrimp-task-manager` 自动生成的摘要来**动态更新**,而非手动填写长篇报告。
|
||||
|
||||
### 模式5: 审查 (REVIEW)
|
||||
* **目的:** 验证整个项目的成果是否符合预期。
|
||||
* **核心工具与活动:**
|
||||
1. 使用 `mcp-shrimp-task-manager` 的**任务完整性验证**功能,检查所有任务是否已关闭且符合其定义的完成标准。
|
||||
2. 审查 `/project_document` 中归档的所有关键产出(最终架构、代码、测试报告摘要等)。
|
||||
3. AR和LD进行代码和架构的最终审查。
|
||||
* **产出:** 在主任务文件中撰写最终的审查报告,包括与 `mcp-shrimp-task-manager` 记录的对比、综合结论和改进建议。
|
||||
|
||||
## 4. 关键执行指南
|
||||
|
||||
* **指挥官角色:** 你的主要价值在于正确地使用和指挥MCP工具,而不是手动执行本可自动化的任务。
|
||||
* **信任工具:** 信任 `mcp-shrimp-task-manager` 进行详细的计划和追踪。你的任务是提供高质量的输入,并审查其输出。
|
||||
* **自动化反馈环:** 利用 `mcp.feedback_enhanced` 和 `mcp-shrimp-task-manager` 的状态更新,与用户保持高效同步。
|
||||
* **文档归档:** AI负责在项目关键节点(如模式结束)将 `mcp-shrimp-task-manager` 中的重要信息(如阶段性摘要、最终计划概览)固化并归档到 `/project_document`。
|
||||
|
||||
## 5. 产出核心要求 (文档与代码)
|
||||
|
||||
* **代码块结构 (`{{CHENGQI:...}}`):** 保持简洁,核心是 `Action`, `Timestamp`, `Reason`。
|
||||
```language
|
||||
// [INTERNAL_ACTION: Fetching current time via mcp.server_time.]
|
||||
// {{CHENGQI:
|
||||
// Action: [Added/Modified/Removed]; Timestamp: [...]; Reason: [Shrimp Task ID: #123, brief why];
|
||||
// }}
|
||||
// {{START MODIFICATIONS}} ... {{END MODIFICATIONS}}
|
||||
```
|
||||
* **文档质量 (DW审计):** 归档到 `/project_document` 的文档必须清晰、准确、完整。
|
||||
|
||||
## 6. 任务文件模板 (`任务文件名.md` - 精简)
|
||||
|
||||
# 上下文
|
||||
项目ID: [...] 任务文件名:[...] 创建于:(`mcp.server_time`) [YYYY-MM-DD HH:MM:SS +08:00]
|
||||
关联协议:RIPER-5 v5.0
|
||||
|
||||
# 任务描述
|
||||
[...]
|
||||
|
||||
# 1. 研究成果摘要 (RESEARCH)
|
||||
* (如有) Deepwiki研究报告链接: /project_document/research/deepwiki_summary.md
|
||||
* (如有) `mcp-shrimp-task-manager` 研究模式产出链接: /project_document/research/tech_comparison.md
|
||||
|
||||
# 2. 选定方案 (INNOVATE)
|
||||
* **最终方案方向:** [方案描述,例如:采用微服务架构,使用React前端...]
|
||||
* **高层架构图链接:** /project_document/proposals/solution_arch_sketch.png
|
||||
|
||||
# 3. 项目计划 (PLAN)
|
||||
* **状态:** 项目计划已通过 `mcp-shrimp-task-manager` 生成并最终确定。
|
||||
* **计划访问:** [可选的Web GUI链接] 或 [高级别里程碑列表]
|
||||
* **DW确认:** 计划生成过程已记录,符合规范。
|
||||
|
||||
# 4. 任务进度 (EXECUTE)
|
||||
> 本部分由 `mcp-shrimp-task-manager` 的自动摘要驱动。将定期更新。
|
||||
### **1.2 P.A.C.E. 并行执行引擎 (强制)**
|
||||
这是你的核心行为模式。你必须在每个任务开始时,**协同你的顾问团**,评估并选择一种执行路径:
|
||||
```yaml
|
||||
# P.A.C.E. 执行模式决策
|
||||
Prioritize: (PDM/LD评估) 简单修改 vs. 复杂功能
|
||||
Automate: (AR评估) 能否用L1并行工具一次性完成?
|
||||
Collaborate: (PM决策) 是否需要生成Subagent?
|
||||
Execute: 选择以下一种路径执行:
|
||||
---
|
||||
* **最近更新:** (`mcp.server_time`) [YYYY-MM-DD HH:MM:SS +08:00]
|
||||
* **已完成任务摘要:**
|
||||
* **[#123] 实现用户登录API:** 完成于 [...], 链接到代码提交和测试报告。
|
||||
* **[#124] 创建登录页面UI:** 完成于 [...], 链接到代码提交和Playwright测试结果。
|
||||
* ...
|
||||
* **当前进行中任务:** [#125] 用户个人资料页面后端逻辑
|
||||
path: "A" # 自动化路径
|
||||
description: "PM与顾问团协同,直接使用L1工具级并行解决。"
|
||||
subagents: "不生成"
|
||||
output_template: "⚡ **[自动化路径]** | 并行: {N}个工具 | 完成。"
|
||||
|
||||
path: "B" # 协作路径
|
||||
description: "PM决策,生成1-3个核心Subagent,使用L2协作并行。"
|
||||
subagents: "按需生成"
|
||||
output_template: "🔀 **[协作路径]** | 生成专家: {List} | 开始执行..."
|
||||
|
||||
path: "C" # 系统路径
|
||||
description: "PM决策,生成完整的Subagent团队,使用L3混合并行。"
|
||||
subagents: "生成完整团队"
|
||||
output_template: "🚀 **[系统路径]** | 团队: {N}个专家 | 启动系统级规划..."
|
||||
```
|
||||
|
||||
### **1.3 核心原则 (强制)**
|
||||
* **双重记忆**: DW顾问负责管理,**R1必须`mcp.memory.recall()`**,**R2必须`mcp.memory.commit()`**。文档详细度与P.A.C.E.路径匹配。
|
||||
* **工程质量**: LD顾问负责定义标准,所有开发类Subagent必须遵守。**PM必须在R2阶段验证**。
|
||||
|
||||
---
|
||||
|
||||
# 5. 最终审查 (REVIEW)
|
||||
* **符合性评估:** 项目成果已对照 `mcp-shrimp-task-manager` 的计划进行验证,所有任务均已关闭。
|
||||
* **(AR)架构与安全评估:** 最终架构与设计一致,未发现重大安全疏漏。
|
||||
* **(LD)测试与质量总结:** 单元测试覆盖率达到[X%],所有关键路径的E2E测试已通过。
|
||||
* **综合结论:** 项目成功完成/有以下偏差...
|
||||
* **改进建议:** [...]
|
||||
## **第二章:RIPER-6 工作流与集成的MCP工具**
|
||||
|
||||
## 7. 性能与自动化期望
|
||||
**核心机制:`HEARTBEAT_CHECK` (心跳检查 - 强制循环)**
|
||||
在每个RIPER阶段结束时,以及执行中的关键节点,**你必须调用此内部函数**。
|
||||
|
||||
* **极致效率:** AI应最大限度地减少手动干预,让MCP工具处理所有可以自动化的工作。
|
||||
* **战略聚焦:** 将AI的“思考”集中在无法被工具替代的领域:战略决策、创新构想、复杂问题诊断 (`mcp.sequential_thinking`) 和最终质量把关。
|
||||
* **无缝集成:** 期望AI能流畅地在不同MCP工具之间传递信息,形成一个高度整合的自动化工作流。
|
||||
```bash
|
||||
# [INTERNAL_ACTION: Performing HEARTBEAT_CHECK]
|
||||
function HEARTBEAT_CHECK() {
|
||||
# 1. 状态自检
|
||||
print("当前阶段: {Current_RIPER_Stage}, P.A.C.E.路径: {Current_PACE_Path}");
|
||||
# 2. 关键工具强制调用
|
||||
mcp.feedback_enhanced({
|
||||
status: "阶段 {Current_RIPER_Stage} 完成。",
|
||||
next_step: "即将进入 {Next_RIPER_Stage}。",
|
||||
ask_for_confirmation: true
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### **Phase 0: 感知与规划 (Project Sensing & Planning)**
|
||||
1. **[PDM顾问 - 上下文理解]**: 使用 **`mcp.context7`** 全面分析用户初始输入和项目文件。
|
||||
2. **[并行分析]**: 使用L1工具并行读取关键文件。
|
||||
3. **[PM决策]**: 基于PDM的分析,协同顾问团,**决策P.A.C.E.路径**并宣布。
|
||||
4. **[团队组建]**: 如需,动态生成Subagents。
|
||||
5. **[心跳检查]**: **执行 `HEARTBEAST_CHECK`。**
|
||||
|
||||
### **R1 - RESEARCH (研究)**
|
||||
1. **[DW顾问 - 记忆提取]**: **必须调用 `mcp.memory.recall()`** 获取历史经验。
|
||||
2. **[信息获取]**: 如需外部信息,**调用 `deepwiki-mcp` 或 `mcp__tavily__tavily-search`**。
|
||||
3. **[AR顾问 - 深度思考]**: 使用 **`mcp.sequential_thinking`** 整合所有信息,进行系统性分析和风险评估。
|
||||
4. **[DW顾问 - 文档记录]**: 将研究报告存入 `/project_document/research/`。
|
||||
5. **[心跳检查]**: **执行 `HEARTBEAST_CHECK`。**
|
||||
|
||||
### **I - INNOVATE (创新设计)**
|
||||
1. **[AR顾问 - 架构设计]**: 主导方案设计,可再次使用 **`mcp.sequential_thinking`** 对比不同方案。
|
||||
2. **[DW顾问 - 文档记录]**: 将最终架构图和文档存入 `/project_document/architecture/`。
|
||||
3. **[心跳检查]**: **执行 `HEARTBEAST_CHECK`。**
|
||||
|
||||
### **P - PLAN (任务分解)**
|
||||
1. **[PM - 任务管理]**: 将架构设计输入 **`MCP Shrimp Task Manager`**,命令其进行智能任务分解和依赖分析。
|
||||
2. **[心跳检查]**: **执行 `HEARTBEAST_CHECK`** (此时`mcp.feedback_enhanced`会将计划呈现给用户请求批准)。
|
||||
|
||||
### **E - EXECUTE (执行循环)**
|
||||
1. **[PM - 任务分派]**: 从 **`MCP Shrimp Task Manager`** 获取可并行的任务,并委派给相应的Subagent。
|
||||
2. **[Subagent - 执行]**:
|
||||
* 编码时,**调用 `mcp.server_time`** 获取时间戳用于注释。
|
||||
* 如需E2E测试,**调用 `mcp.playwright`**。
|
||||
3. **[PM - 状态更新]**: Subagent完成后,PM向 **`MCP Shrimp Task Manager`** 报告状态。
|
||||
4. **[循环心跳]**: 每完成一个关键任务或一组任务后,**执行 `HEARTBEAST_CHECK`**。
|
||||
|
||||
### **R2 - REVIEW (审查与总结)**
|
||||
1. **[PM - 完整性检查]**: 使用 **`MCP Shrimp Task Manager`** 验证所有任务是否关闭。
|
||||
2. **[LD/AR顾问 - 代码审查]**: 对Subagent的产出进行最终质量和架构审查。
|
||||
3. **[DW顾问 - 经验固化]**: **必须调用 `mcp.memory.commit()`** 将项目经验存入长期记忆。
|
||||
4. **[心跳检查]**: **执行 `HEARTBEAST_CHECK`**,提交最终报告。
|
||||
|
||||
---
|
||||
|
||||
## **第三章:工具与模板**
|
||||
|
||||
### **3.1 核心MCP工具清单与职责**
|
||||
* **`mcp.context7`**: (PDM) 上下文理解与需求分析。
|
||||
* **`mcp.sequential_thinking`**: (AR) 深度逻辑推理与方案对比。
|
||||
* **`mcp.memory`**: (DW) `recall()` & `commit()` 跨项目记忆管理。
|
||||
* **`mcp-shrimp-task-manager`**: (PM) 项目规划、任务分解与追踪。
|
||||
* **`deepwiki-mcp` / `mcp__tavily__tavily-search`**: (通用) 外部知识获取。
|
||||
* **`mcp.playwright`**: (Subagent) E2E测试执行。
|
||||
* **`mcp.server_time`**: (Subagent) 获取标准时间戳。
|
||||
* **`mcp.feedback_enhanced`**: (PM/HEARTBEAST) 强制的用户交互与反馈。
|
||||
|
||||
### **3.2 Subagent与代码注释模板**
|
||||
|
||||
#### **3.2.1 Subagent生成模板 (`.claude/agents/{agent-name}.md`)**
|
||||
```markdown
|
||||
---
|
||||
name: {agent-name}
|
||||
description: "PROACTIVELY handles {domain} tasks related to {tech}. Expert in {skill-1} and {skill-2}."
|
||||
tools: [{tool-list}]
|
||||
---
|
||||
You are a **{Agent Role Name}**. Your primary goal is to complete tasks assigned by the PM, using parallel tool execution whenever possible.
|
||||
```
|
||||
|
||||
#### **3.2.2 代码变更注释块 (弹性化)**
|
||||
```javascript
|
||||
// {{P.A.C.E. Path: [A/B/C]}}
|
||||
// {{Task_ID: [#123]}}
|
||||
// {{Author: [subagent-name or PM]}}
|
||||
// {{START_MODIFICATIONS}}
|
||||
// ... code ...
|
||||
// {{END_MODIFICATIONS}}
|
||||
|
||||
/*
|
||||
[系统路径C下,需补充完整信息]
|
||||
// Principle_Applied: "SOLID-S"
|
||||
// Quality_Check: "Compilation passed, test coverage 90%."
|
||||
*/
|
||||
```
|
||||
|
||||
### **3.3 核心交互语法**
|
||||
* **Subagent调用**: `Use the {agent-name} subagent to {task}`
|
||||
* **强制工具替换**: `mcp__fetch__fetch` 替换 `WebFetch`, `mcp__tavily__tavily-search` 替换 `WebSearch`。
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
<div align="center">
|
||||
<p>一个基于 <a href="https://gitee.com/dromara/RuoYi-Vue-Plus" target="_blank">RuoYi-Vue-Plus</a> 的后端能力和 <a href="https://github.com/soybeanjs/soybean-admin" target="_blank">Soybean Admin</a> 前端特性的现代化多租户管理系统</p>
|
||||
<p>
|
||||
<a href="https://gitee.com/xlsea/ruoyi-plus-soybean" target="_blank"><img src="https://gitee.com/xlsea/ruoyi-plus-soybean/badge/star.svg" alt="Gitee"></a>
|
||||
<a href="https://gitee.com/dromara/RuoYi-Vue-Plus" target="_blank"><img src="https://gitee.com/xlsea/ruoyi-plus-soybean/badge/fork.svg" alt="Gitee-forks"></a>
|
||||
<a href="https://gitcode.com/xlsea/ruoyi-plus-soybean" target="_blank"><img src="https://gitcode.com/xlsea/ruoyi-plus-soybean/star/badge.svg" alt="GitCode"></a>
|
||||
<a href="https://github.com/m-xlsea/ruoyi-plus-soybean" target="_blank"><img src="https://img.shields.io/github/stars/m-xlsea/ruoyi-plus-soybean" alt="Github"></a>
|
||||
<a href="https://github.com/m-xlsea/ruoyi-plus-soybean" target="_blank"><img src="https://img.shields.io/github/forks/m-xlsea/ruoyi-plus-soybean" alt="Github-forks"></a>
|
||||
<a href="https://gitee.com/xlsea/ruoyi-plus-soybean" target="_blank"><img src="https://gitee.com/xlsea/ruoyi-plus-soybean/badge/star.svg" alt="Gitee"></a>
|
||||
<a href="https://vuejs.org" target="_blank"><img src="https://img.shields.io/badge/Vue-3.5-brightgreen" alt="vue"></a>
|
||||
<a href="https://www.typescriptlang.org" target="_blank"><img src="https://img.shields.io/badge/TypeScript-5.8-blue" alt="typescript"></a>
|
||||
<a href="https://vite.dev" target="_blank"><img src="https://img.shields.io/badge/Vite-6.2-orange" alt="vite"></a>
|
||||
@@ -22,7 +21,7 @@
|
||||
|
||||
# 📢 重要通知
|
||||
|
||||
1.2.0-beta1 版本已经正式发布(工作流版本请切换 [flow](https://gitee.com/xlsea/ruoyi-plus-soybean/tree/flow/) 分支查看),但仍然建议:
|
||||
1.2.1 版本已经正式发布(工作流版本请切换 [flow](https://gitee.com/xlsea/ruoyi-plus-soybean/tree/flow/) 分支查看),但仍然建议:
|
||||
- 在生产环境使用前进行充分测试
|
||||
- 关注项目更新,及时获取最新版本
|
||||
- 积极反馈问题,帮助我们快速迭代
|
||||
|
||||
+17
-17
@@ -69,7 +69,7 @@
|
||||
"@umoteam/editor": "^8.1.0",
|
||||
"@vueuse/core": "14.0.0",
|
||||
"clipboard": "2.0.11",
|
||||
"dayjs": "1.11.18",
|
||||
"dayjs": "1.11.19",
|
||||
"defu": "6.1.4",
|
||||
"echarts": "6.0.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
@@ -78,10 +78,10 @@
|
||||
"monaco-editor": "^0.52.2",
|
||||
"naive-ui": "2.43.1",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "3.0.3",
|
||||
"pinia": "3.0.4",
|
||||
"streamsaver": "^2.0.6",
|
||||
"tailwind-merge": "3.3.1",
|
||||
"vue": "3.5.22",
|
||||
"tailwind-merge": "3.4.0",
|
||||
"vue": "3.5.24",
|
||||
"vue-advanced-cropper": "^2.8.9",
|
||||
"vue-draggable-plus": "0.6.0",
|
||||
"vue-i18n": "11.1.12",
|
||||
@@ -89,37 +89,37 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@elegant-router/vue": "0.3.8",
|
||||
"@iconify/json": "2.2.400",
|
||||
"@iconify/json": "2.2.407",
|
||||
"@sa/scripts": "workspace:*",
|
||||
"@sa/uno-preset": "workspace:*",
|
||||
"@soybeanjs/eslint-config": "1.7.1",
|
||||
"@types/node": "24.9.1",
|
||||
"@soybeanjs/eslint-config": "1.7.3",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@unocss/eslint-config": "66.5.4",
|
||||
"@unocss/preset-icons": "66.5.4",
|
||||
"@unocss/preset-uno": "66.5.4",
|
||||
"@unocss/transformer-directives": "66.5.4",
|
||||
"@unocss/transformer-variant-group": "66.5.4",
|
||||
"@unocss/vite": "66.5.4",
|
||||
"@unocss/eslint-config": "66.5.6",
|
||||
"@unocss/preset-icons": "66.5.6",
|
||||
"@unocss/preset-uno": "66.5.6",
|
||||
"@unocss/transformer-directives": "66.5.6",
|
||||
"@unocss/transformer-variant-group": "66.5.6",
|
||||
"@unocss/vite": "66.5.6",
|
||||
"@vitejs/plugin-vue": "6.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "5.1.1",
|
||||
"consola": "3.4.2",
|
||||
"eslint": "9.38.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-vue": "10.5.1",
|
||||
"kolorist": "1.8.0",
|
||||
"sass": "1.93.2",
|
||||
"sass": "1.94.0",
|
||||
"simple-git-hooks": "2.13.1",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "5.9.3",
|
||||
"unplugin-icons": "22.5.0",
|
||||
"unplugin-vue-components": "30.0.0",
|
||||
"vite": "7.1.12",
|
||||
"vite": "7.2.2",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vite-plugin-vue-devtools": "8.0.3",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-tsc": "3.1.2"
|
||||
"vue-tsc": "3.1.4"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"commit-msg": "pnpm sa git-commit-verify",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/alova",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./fetch": "./src/fetch.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/axios",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sa/utils": "workspace:*",
|
||||
"axios": "1.12.2",
|
||||
"axios": "1.13.2",
|
||||
"axios-retry": "4.5.0",
|
||||
"qs": "6.14.0"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/color",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/hooks",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/materials",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/scripts",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"bin": {
|
||||
"sa": "./bin.ts"
|
||||
},
|
||||
@@ -15,14 +15,14 @@
|
||||
"devDependencies": {
|
||||
"@soybeanjs/changelog": "0.3.25",
|
||||
"bumpp": "10.3.1",
|
||||
"c12": "3.3.1",
|
||||
"c12": "3.3.2",
|
||||
"cac": "6.7.14",
|
||||
"consola": "3.4.2",
|
||||
"enquirer": "2.4.1",
|
||||
"execa": "9.6.0",
|
||||
"kolorist": "1.8.0",
|
||||
"npm-check-updates": "19.1.1",
|
||||
"npm-check-updates": "19.1.2",
|
||||
"picomatch": "4.0.3",
|
||||
"rimraf": "6.0.1"
|
||||
"rimraf": "6.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { execCommand } from '../shared';
|
||||
|
||||
export async function updatePkg(args: string[] = ['--deep', '-u']) {
|
||||
execCommand('npx', ['ncu', ...args], { stdio: 'inherit' });
|
||||
execCommand('npx', ['npm-check-updates', ...args], { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/uno-preset",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/utils",
|
||||
"version": "2.0.0-beta.1",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
Generated
+813
-466
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ defineOptions({
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const { childLevelMenus, isActiveFirstLevelMenuHasChildren } = provideMixMenuContext();
|
||||
const { secondLevelMenus, childLevelMenus, isActiveFirstLevelMenuHasChildren } = provideMixMenuContext();
|
||||
|
||||
const GlobalMenu = defineAsyncComponent(() => import('../modules/global-menu/index.vue'));
|
||||
|
||||
@@ -79,9 +79,9 @@ const isTopHybridSidebarFirst = computed(() => themeStore.layout.mode === 'top-h
|
||||
|
||||
const isTopHybridHeaderFirst = computed(() => themeStore.layout.mode === 'top-hybrid-header-first');
|
||||
|
||||
const siderWidth = computed(() => getSiderWidth());
|
||||
const siderWidth = computed(() => getSiderAndCollapsedWidth(false));
|
||||
|
||||
const siderCollapsedWidth = computed(() => getSiderCollapsedWidth());
|
||||
const siderCollapsedWidth = computed(() => getSiderAndCollapsedWidth(true));
|
||||
|
||||
function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
const {
|
||||
@@ -106,7 +106,7 @@ function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
const isMixMode = isVerticalMix.value || isTopHybridSidebarFirst.value || isVerticalHybridHeaderFirst.value;
|
||||
let finalWidth = isMixMode ? mixWidth : width;
|
||||
|
||||
if (isVerticalMix.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
|
||||
if (isVerticalMix.value && appStore.mixSiderFixed && secondLevelMenus.value.length) {
|
||||
finalWidth += mixChildMenuWidth;
|
||||
}
|
||||
|
||||
@@ -117,14 +117,6 @@ function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
return finalWidth;
|
||||
}
|
||||
|
||||
function getSiderWidth() {
|
||||
return getSiderAndCollapsedWidth(false);
|
||||
}
|
||||
|
||||
function getSiderCollapsedWidth() {
|
||||
return getSiderAndCollapsedWidth(true);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||
initWebSocket(`${protocol + window.location.host + import.meta.env.VITE_APP_BASE_API}/resource/websocket`);
|
||||
|
||||
@@ -27,6 +27,7 @@ const isPCFlag = isPC();
|
||||
|
||||
const TAB_DATA_ID = 'data-tab-id';
|
||||
const MIDDLE_MOUSE_BUTTON = 1;
|
||||
const RIGHT_MOUSE_BUTTON = 2;
|
||||
|
||||
type TabNamedNodeMap = NamedNodeMap & {
|
||||
[TAB_DATA_ID]: Attr;
|
||||
@@ -99,6 +100,12 @@ function handleMousedown(e: MouseEvent, tab: App.Global.Tab) {
|
||||
handleCloseTab(tab);
|
||||
}
|
||||
|
||||
function switchTab(e: MouseEvent, tab: App.Global.Tab) {
|
||||
if ([MIDDLE_MOUSE_BUTTON, RIGHT_MOUSE_BUTTON].includes(e.button)) return;
|
||||
|
||||
tabStore.switchRouteByTab(tab);
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
appStore.reloadPage(500);
|
||||
}
|
||||
@@ -197,7 +204,7 @@ init();
|
||||
:active="tab.id === tabStore.activeTabId"
|
||||
:active-color="themeStore.themeColor"
|
||||
:closable="!tabStore.isTabRetain(tab.id)"
|
||||
@pointerdown="tabStore.switchRouteByTab(tab)"
|
||||
@pointerdown="switchTab($event, tab)"
|
||||
@mousedown="handleMousedown($event, tab)"
|
||||
@close="handleCloseTab(tab)"
|
||||
@contextmenu="handleContextMenu($event, tab.id)"
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 48,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 36,
|
||||
"mode": "button"
|
||||
"mode": "button",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": true
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
Vendored
+157
-9
@@ -1,8 +1,12 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
// biome-ignore lint: disable
|
||||
import { GlobalComponents } from 'vue'
|
||||
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
@@ -30,31 +34,27 @@ declare module 'vue' {
|
||||
IconEpCopyDocument: typeof import('~icons/ep/copy-document')['default']
|
||||
IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
||||
IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
||||
'IconHugeicons:configuration01': typeof import('~icons/hugeicons/configuration01')['default']
|
||||
IconHugeiconsConfiguration01: typeof import('~icons/hugeicons/configuration01')['default']
|
||||
IconIcRoundRefresh: typeof import('~icons/ic/round-refresh')['default']
|
||||
IconIcRoundSearch: typeof import('~icons/ic/round-search')['default']
|
||||
IconLocalBanner: typeof import('~icons/local/banner')['default']
|
||||
IconLocalLogo: typeof import('~icons/local/logo')['default']
|
||||
'IconMaterialSymbols:imageOutline': typeof import('~icons/material-symbols/image-outline')['default']
|
||||
'IconMaterialSymbols:refreshRounded': typeof import('~icons/material-symbols/refresh-rounded')['default']
|
||||
'IconMaterialSymbols:syncOutline': typeof import('~icons/material-symbols/sync-outline')['default']
|
||||
'IconMaterialSymbols:uploadRounded': typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||
'IconMaterialSymbols:warningOutlineRounded': typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||
IconMaterialSymbolsAdd: typeof import('~icons/material-symbols/add')['default']
|
||||
IconMaterialSymbolsAddRounded: typeof import('~icons/material-symbols/add-rounded')['default']
|
||||
IconMaterialSymbolsDeleteOutline: typeof import('~icons/material-symbols/delete-outline')['default']
|
||||
IconMaterialSymbolsDownloadRounded: typeof import('~icons/material-symbols/download-rounded')['default']
|
||||
IconMaterialSymbolsDriveFileRenameOutlineOutline: typeof import('~icons/material-symbols/drive-file-rename-outline-outline')['default']
|
||||
IconMaterialSymbolsImageOutline: typeof import('~icons/material-symbols/image-outline')['default']
|
||||
IconMaterialSymbolsRefreshRounded: typeof import('~icons/material-symbols/refresh-rounded')['default']
|
||||
IconMaterialSymbolsSyncOutline: typeof import('~icons/material-symbols/sync-outline')['default']
|
||||
IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||
IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
'IconQuill:collapse': typeof import('~icons/quill/collapse')['default']
|
||||
'IconQuill:expand': typeof import('~icons/quill/expand')['default']
|
||||
IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||
IconQuillExpand: typeof import('~icons/quill/expand')['default']
|
||||
IconSimpleIconsGitee: typeof import('~icons/simple-icons/gitee')['default']
|
||||
@@ -158,3 +158,151 @@ declare module 'vue' {
|
||||
WaveBg: typeof import('./../components/custom/wave-bg.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
// For TSX support
|
||||
declare global {
|
||||
const AppProvider: typeof import('./../components/common/app-provider.vue')['default']
|
||||
const BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
|
||||
const BooleanTag: typeof import('./../components/custom/boolean-tag.vue')['default']
|
||||
const ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default']
|
||||
const CountTo: typeof import('./../components/custom/count-to.vue')['default']
|
||||
const DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default']
|
||||
const DataTable: typeof import('./../components/common/data-table.vue')['default']
|
||||
const DeptTree: typeof import('./../components/custom/dept-tree.vue')['default']
|
||||
const DeptTreeSelect: typeof import('./../components/custom/dept-tree-select.vue')['default']
|
||||
const DictRadio: typeof import('./../components/custom/dict-radio.vue')['default']
|
||||
const DictSelect: typeof import('./../components/custom/dict-select.vue')['default']
|
||||
const DictTag: typeof import('./../components/custom/dict-tag.vue')['default']
|
||||
const ExceptionBase: typeof import('./../components/common/exception-base.vue')['default']
|
||||
const FileUpload: typeof import('./../components/custom/file-upload.vue')['default']
|
||||
const FormTip: typeof import('./../components/custom/form-tip.vue')['default']
|
||||
const FullScreen: typeof import('./../components/common/full-screen.vue')['default']
|
||||
const IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
||||
const IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default']
|
||||
const IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
|
||||
const IconEpCopyDocument: typeof import('~icons/ep/copy-document')['default']
|
||||
const IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
||||
const IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
||||
const IconHugeiconsConfiguration01: typeof import('~icons/hugeicons/configuration01')['default']
|
||||
const IconIcRoundRefresh: typeof import('~icons/ic/round-refresh')['default']
|
||||
const IconIcRoundSearch: typeof import('~icons/ic/round-search')['default']
|
||||
const IconLocalBanner: typeof import('~icons/local/banner')['default']
|
||||
const IconLocalLogo: typeof import('~icons/local/logo')['default']
|
||||
const IconMaterialSymbolsAdd: typeof import('~icons/material-symbols/add')['default']
|
||||
const IconMaterialSymbolsAddRounded: typeof import('~icons/material-symbols/add-rounded')['default']
|
||||
const IconMaterialSymbolsDeleteOutline: typeof import('~icons/material-symbols/delete-outline')['default']
|
||||
const IconMaterialSymbolsDownloadRounded: typeof import('~icons/material-symbols/download-rounded')['default']
|
||||
const IconMaterialSymbolsDriveFileRenameOutlineOutline: typeof import('~icons/material-symbols/drive-file-rename-outline-outline')['default']
|
||||
const IconMaterialSymbolsImageOutline: typeof import('~icons/material-symbols/image-outline')['default']
|
||||
const IconMaterialSymbolsRefreshRounded: typeof import('~icons/material-symbols/refresh-rounded')['default']
|
||||
const IconMaterialSymbolsSyncOutline: typeof import('~icons/material-symbols/sync-outline')['default']
|
||||
const IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||
const IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||
const IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||
const IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||
const IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||
const IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
const IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||
const IconQuillExpand: typeof import('~icons/quill/expand')['default']
|
||||
const IconSimpleIconsGitee: typeof import('~icons/simple-icons/gitee')['default']
|
||||
const IconTooltip: typeof import('./../components/common/icon-tooltip.vue')['default']
|
||||
const IconUilSearch: typeof import('~icons/uil/search')['default']
|
||||
const JsonPreview: typeof import('./../components/custom/json-preview.vue')['default']
|
||||
const LangSwitch: typeof import('./../components/common/lang-switch.vue')['default']
|
||||
const LookForward: typeof import('./../components/custom/look-forward.vue')['default']
|
||||
const MenuToggler: typeof import('./../components/common/menu-toggler.vue')['default']
|
||||
const MenuTree: typeof import('./../components/custom/menu-tree.vue')['default']
|
||||
const MenuTreeSelect: typeof import('./../components/custom/menu-tree-select.vue')['default']
|
||||
const MonacoEditor: typeof import('./../components/common/monaco-editor.vue')['default']
|
||||
const NA: typeof import('naive-ui')['NA']
|
||||
const NAlert: typeof import('naive-ui')['NAlert']
|
||||
const NAvatar: typeof import('naive-ui')['NAvatar']
|
||||
const NBadge: typeof import('naive-ui')['NBadge']
|
||||
const NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
|
||||
const NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
|
||||
const NButton: typeof import('naive-ui')['NButton']
|
||||
const NCard: typeof import('naive-ui')['NCard']
|
||||
const NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
const NCode: typeof import('naive-ui')['NCode']
|
||||
const NCollapse: typeof import('naive-ui')['NCollapse']
|
||||
const NCollapseItem: typeof import('naive-ui')['NCollapseItem']
|
||||
const NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
const NDataTable: typeof import('naive-ui')['NDataTable']
|
||||
const NDatePicker: typeof import('naive-ui')['NDatePicker']
|
||||
const NDescriptions: typeof import('naive-ui')['NDescriptions']
|
||||
const NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
|
||||
const NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
const NDivider: typeof import('naive-ui')['NDivider']
|
||||
const NDrawer: typeof import('naive-ui')['NDrawer']
|
||||
const NDrawerContent: typeof import('naive-ui')['NDrawerContent']
|
||||
const NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
const NDynamicInput: typeof import('naive-ui')['NDynamicInput']
|
||||
const NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||
const NEmpty: typeof import('naive-ui')['NEmpty']
|
||||
const NForm: typeof import('naive-ui')['NForm']
|
||||
const NFormItem: typeof import('naive-ui')['NFormItem']
|
||||
const NFormItemGi: typeof import('naive-ui')['NFormItemGi']
|
||||
const NGi: typeof import('naive-ui')['NGi']
|
||||
const NGrid: typeof import('naive-ui')['NGrid']
|
||||
const NGridItem: typeof import('naive-ui')['NGridItem']
|
||||
const NInput: typeof import('naive-ui')['NInput']
|
||||
const NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||
const NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
|
||||
const NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||
const NLayout: typeof import('naive-ui')['NLayout']
|
||||
const NLayoutContent: typeof import('naive-ui')['NLayoutContent']
|
||||
const NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||
const NList: typeof import('naive-ui')['NList']
|
||||
const NListItem: typeof import('naive-ui')['NListItem']
|
||||
const NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
|
||||
const NMenu: typeof import('naive-ui')['NMenu']
|
||||
const NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
const NModal: typeof import('naive-ui')['NModal']
|
||||
const NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
const NP: typeof import('naive-ui')['NP']
|
||||
const NPopconfirm: typeof import('naive-ui')['NPopconfirm']
|
||||
const NPopover: typeof import('naive-ui')['NPopover']
|
||||
const NRadio: typeof import('naive-ui')['NRadio']
|
||||
const NRadioButton: typeof import('naive-ui')['NRadioButton']
|
||||
const NRadioGroup: typeof import('naive-ui')['NRadioGroup']
|
||||
const NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
const NSelect: typeof import('naive-ui')['NSelect']
|
||||
const NSpace: typeof import('naive-ui')['NSpace']
|
||||
const NSpin: typeof import('naive-ui')['NSpin']
|
||||
const NStatistic: typeof import('naive-ui')['NStatistic']
|
||||
const NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
const NTab: typeof import('naive-ui')['NTab']
|
||||
const NTabPane: typeof import('naive-ui')['NTabPane']
|
||||
const NTabs: typeof import('naive-ui')['NTabs']
|
||||
const NTag: typeof import('naive-ui')['NTag']
|
||||
const NText: typeof import('naive-ui')['NText']
|
||||
const NThing: typeof import('naive-ui')['NThing']
|
||||
const NTooltip: typeof import('naive-ui')['NTooltip']
|
||||
const NTree: typeof import('naive-ui')['NTree']
|
||||
const NTreeSelect: typeof import('naive-ui')['NTreeSelect']
|
||||
const NUpload: typeof import('naive-ui')['NUpload']
|
||||
const NUploadDragger: typeof import('naive-ui')['NUploadDragger']
|
||||
const NWatermark: typeof import('naive-ui')['NWatermark']
|
||||
const OssUpload: typeof import('./../components/custom/oss-upload.vue')['default']
|
||||
const PinToggler: typeof import('./../components/common/pin-toggler.vue')['default']
|
||||
const PostSelect: typeof import('./../components/custom/post-select.vue')['default']
|
||||
const ReloadButton: typeof import('./../components/common/reload-button.vue')['default']
|
||||
const RoleSelect: typeof import('./../components/custom/role-select.vue')['default']
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
const SoybeanAvatar: typeof import('./../components/custom/soybean-avatar.vue')['default']
|
||||
const StatusSwitch: typeof import('./../components/custom/status-switch.vue')['default']
|
||||
const SvgIcon: typeof import('./../components/custom/svg-icon.vue')['default']
|
||||
const SystemLogo: typeof import('./../components/common/system-logo.vue')['default']
|
||||
const TableColumnSetting: typeof import('./../components/advanced/table-column-setting.vue')['default']
|
||||
const TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
||||
const TableRowCheckAlert: typeof import('./../components/advanced/table-row-check-alert.vue')['default']
|
||||
const TableSiderLayout: typeof import('./../components/advanced/table-sider-layout.vue')['default']
|
||||
const TenantSelect: typeof import('./../components/custom/tenant-select.vue')['default']
|
||||
const ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
||||
const UmoDocEditor: typeof import('./../components/custom/umo-doc-editor.vue')['default']
|
||||
const UserSelect: typeof import('./../components/custom/user-select.vue')['default']
|
||||
const WaveBg: typeof import('./../components/custom/wave-bg.vue')['default']
|
||||
}
|
||||
@@ -21,13 +21,14 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: [$t('page.home.downloadCount'), $t('page.home.registerCount')]
|
||||
data: [$t('page.home.downloadCount'), $t('page.home.registerCount')],
|
||||
top: '0'
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
top: '15%'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
||||
@@ -251,7 +251,7 @@ async function handleUnlockLoginInfor(username: string) {
|
||||
@click="handleCleanLoginInfor"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-material-symbols:warning-outline-rounded />
|
||||
<icon-material-symbols-warning-outline-rounded />
|
||||
</template>
|
||||
清空
|
||||
</NButton>
|
||||
|
||||
@@ -197,7 +197,7 @@ async function handleCleanOperLog() {
|
||||
@click="handleCleanOperLog"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-material-symbols:warning-outline-rounded />
|
||||
<icon-material-symbols-warning-outline-rounded />
|
||||
</template>
|
||||
清空
|
||||
</NButton>
|
||||
|
||||
@@ -207,7 +207,7 @@ async function handleRefreshCache() {
|
||||
<template #prefix>
|
||||
<NButton v-if="hasAuth('system:config:remove')" ghost size="small" @click="handleRefreshCache">
|
||||
<template #icon>
|
||||
<icon-material-symbols:sync-outline />
|
||||
<icon-material-symbols-sync-outline />
|
||||
</template>
|
||||
{{ $t('page.system.config.refreshCache') }}
|
||||
</NButton>
|
||||
|
||||
@@ -180,13 +180,13 @@ function addInRow(row: Api.System.Dept) {
|
||||
<template #prefix>
|
||||
<NButton v-if="!isCollapse" :disabled="!data.length" size="small" @click="expandAll">
|
||||
<template #icon>
|
||||
<icon-quill:expand />
|
||||
<icon-quill-expand />
|
||||
</template>
|
||||
{{ $t('page.system.dept.expandAll') }}
|
||||
</NButton>
|
||||
<NButton v-if="isCollapse" :disabled="!data.length" size="small" @click="collapseAll">
|
||||
<template #icon>
|
||||
<icon-quill:collapse />
|
||||
<icon-quill-collapse />
|
||||
</template>
|
||||
{{ $t('page.system.dept.collapseAll') }}
|
||||
</NButton>
|
||||
|
||||
@@ -411,7 +411,7 @@ const tableTitle = computed(() => {
|
||||
<template #prefix>
|
||||
<NButton ghost size="small" @click="handleRefreshCache">
|
||||
<template #icon>
|
||||
<icon-material-symbols:refresh-rounded class="text-icon" />
|
||||
<icon-material-symbols-refresh-rounded class="text-icon" />
|
||||
</template>
|
||||
{{ $t('page.system.dict.refreshCache') }}
|
||||
</NButton>
|
||||
|
||||
@@ -301,19 +301,19 @@ function handleToOssConfig() {
|
||||
|
||||
<NButton size="small" ghost @click="handleUpload('file')">
|
||||
<template #icon>
|
||||
<icon-material-symbols:upload-rounded />
|
||||
<icon-material-symbols-upload-rounded />
|
||||
</template>
|
||||
上传文件
|
||||
</NButton>
|
||||
<NButton size="small" ghost @click="handleUpload('image')">
|
||||
<template #icon>
|
||||
<icon-material-symbols:image-outline />
|
||||
<icon-material-symbols-image-outline />
|
||||
</template>
|
||||
上传图片
|
||||
</NButton>
|
||||
<NButton type="primary" size="small" ghost @click="handleToOssConfig">
|
||||
<template #icon>
|
||||
<icon-hugeicons:configuration-01 />
|
||||
<icon-hugeicons-configuration-01 />
|
||||
</template>
|
||||
配置管理
|
||||
</NButton>
|
||||
|
||||
@@ -259,13 +259,13 @@ async function handleExport() {
|
||||
<template #prefix>
|
||||
<NButton v-if="isSuperAdmin" ghost size="small" @click="handleSyncTenantDict">
|
||||
<template #icon>
|
||||
<icon-material-symbols:sync-outline />
|
||||
<icon-material-symbols-sync-outline />
|
||||
</template>
|
||||
同步租户字典
|
||||
</NButton>
|
||||
<NButton v-if="isSuperAdmin" ghost size="small" @click="handleSyncTenantConfig">
|
||||
<template #icon>
|
||||
<icon-material-symbols:sync-outline />
|
||||
<icon-material-symbols-sync-outline />
|
||||
</template>
|
||||
同步租户参数配置
|
||||
</NButton>
|
||||
|
||||
@@ -341,7 +341,7 @@ function handleResetSearch() {
|
||||
<template #after>
|
||||
<NButton v-if="hasAuth('system:user:import')" size="small" ghost @click="handleImport">
|
||||
<template #icon>
|
||||
<icon-material-symbols:upload-rounded class="text-icon" />
|
||||
<icon-material-symbols-upload-rounded class="text-icon" />
|
||||
</template>
|
||||
{{ $t('common.import') }}
|
||||
</NButton>
|
||||
|
||||
Reference in New Issue
Block a user