Files
rxthinkcmf-wiki/RXThinkCMF_ThinkPhp8_EleVue/.vitepress/dist/assets/zh_architecture_overview.md.DetfYU6G.js
T
2026-10-25 18:52:36 +08:00

189 lines
49 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as a,o as i,c as n,a2 as p}from"./chunks/framework.B-QBKwc1.js";const o=JSON.parse('{"title":"整体架构概览","description":"本章从全局视角阐述系统的整体技术架构,涵盖前端、后端、数据库及基础设施等核心组成部分,旨在帮助开发者快速建立对系统全貌的清晰认知。","frontmatter":{},"headers":[],"relativePath":"zh/architecture/overview.md","filePath":"zh/architecture/overview.md"}'),t={name:"zh/architecture/overview.md"};function l(e,s,h,k,d,r){return i(),n("div",null,[...s[0]||(s[0]=[p(`<h1 id="_4-1-整体架构概览" tabindex="-1">4.1 整体架构概览 <a class="header-anchor" href="#_4-1-整体架构概览" aria-label="Permalink to &quot;4.1 整体架构概览&quot;">​</a></h1><div class="tip custom-block"><p class="custom-block-title">概述</p><p>本章从全局视角阐述系统的整体技术架构,涵盖前端、后端、数据库及基础设施等核心组成部分,旨在帮助开发者快速建立对系统全貌的清晰认知。</p></div><h2 id="架构总览" tabindex="-1">架构总览 <a class="header-anchor" href="#架构总览" aria-label="Permalink to &quot;架构总览&quot;">​</a></h2><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 浏览器(Vue3 + ElementPlus) │</span></span>
<span class="line"><span>│ Axios HTTP 请求 / Vite 开发代理 │</span></span>
<span class="line"><span>└──────────────────────────────┬──────────────────────────────────┘</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ Nginx(反向代理) │</span></span>
<span class="line"><span>│ 静态资源托管 / SSL 终止 / 负载均衡 / gzip 压缩 │</span></span>
<span class="line"><span>└──────────────────────────────┬──────────────────────────────────┘</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ ThinkPHP 8 Application │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ ┌───────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 中间件链(按顺序执行) │ │</span></span>
<span class="line"><span>│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────┐ ┌───────┐ │ │</span></span>
<span class="line"><span>│ │ │ CORS │→│ Auth │→│ Tenant │→│ Demo │→│ Log │ │ │</span></span>
<span class="line"><span>│ │ │ 跨域处理 │ │JWT+权限 │ │ 租户上下文│ │演示拦截│ │操作日志│ │ │</span></span>
<span class="line"><span>│ │ └─────────┘ └─────────┘ └─────────┘ └──────┘ └───────┘ │ │</span></span>
<span class="line"><span>│ └───────────────────────────────┬───────────────────────────┘ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ ┌───────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 控制器层(Controller) │ │</span></span>
<span class="line"><span>│ │ BaseController → 统一响应 · 参数获取 · 通用 CRUD │ │</span></span>
<span class="line"><span>│ │ #[Permission] 权限注解 · #[Log] 日志注解 │ │</span></span>
<span class="line"><span>│ └───────────────────────────────┬───────────────────────────┘ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ ┌───────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 逻辑层(Logic) │ │</span></span>
<span class="line"><span>│ │ BaseLogic / BaseTenantLogic │ │</span></span>
<span class="line"><span>│ │ 属性配置 · 生命周期钩子 · 文件处理 · 枚举翻译 │ │</span></span>
<span class="line"><span>│ │ 唯一性校验 · 数据权限 · 租户隔离 · 事务管理 │ │</span></span>
<span class="line"><span>│ └───────────────────────────────┬───────────────────────────┘ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ ┌───────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 模型层(Model) │ │</span></span>
<span class="line"><span>│ │ BaseModel │ │</span></span>
<span class="line"><span>│ │ 软删除(is_delete)· 审计字段自动写入 │ │</span></span>
<span class="line"><span>│ └───────────────────────────────┬───────────────────────────┘ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │</span></span>
<span class="line"><span>│ │ MySQL │ │ Redis │ │ 文件系统 │ │</span></span>
<span class="line"><span>│ │ 数据库 │ │ 缓存 │ │ uploads/ │ │</span></span>
<span class="line"><span>│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │</span></span>
<span class="line"><span>└─────────────────────────────────────────────────────────────────┘</span></span></code></pre></div><h2 id="架构特征" tabindex="-1">架构特征 <a class="header-anchor" href="#架构特征" aria-label="Permalink to &quot;架构特征&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">核心设计原则</p><p>遵循以下架构设计原则,确保系统在长期演进中保持高质量和可维护性:</p></div><h3 id="_1-前后端分离" tabindex="-1">1. 前后端分离 <a class="header-anchor" href="#_1-前后端分离" aria-label="Permalink to &quot;1. 前后端分离&quot;">​</a></h3><p>前端 Vue3 应用通过 HTTP API 调用后端 ThinkPHP 服务,两者独立开发、独立部署。前端开发阶段通过 Vite 的 <code>proxy</code> 配置将 <code>/api</code> 请求代理到后端 <code>http://localhost:8000</code>,生产环境由 Nginx 统一反向代理。</p><h3 id="_2-分层架构" tabindex="-1">2. 分层架构 <a class="header-anchor" href="#_2-分层架构" aria-label="Permalink to &quot;2. 分层架构&quot;">​</a></h3><p>后端严格分为三层,每层职责单一、依赖单向:</p><table tabindex="0"><thead><tr><th>层次</th><th>目录</th><th>职责</th></tr></thead><tbody><tr><td>控制器层</td><td><code>app/controller/</code></td><td>路由入口、权限注解、参数获取、响应返回</td></tr><tr><td>逻辑层</td><td><code>app/logic/</code></td><td>业务逻辑、属性配置、生命周期钩子、横切处理</td></tr><tr><td>模型层</td><td><code>app/model/</code></td><td>数据库表映射、软删除、审计字段</td></tr></tbody></table><h3 id="_3-模板方法模式-声明式-CRUD-" tabindex="-1">3. 模板方法模式(声明式 CRUD) <a class="header-anchor" href="#_3-模板方法模式-声明式-CRUD-" aria-label="Permalink to &quot;3. 模板方法模式(声明式 CRUD)&quot;">​</a></h3><p>通过 <code>BaseLogic</code> 基类,将通用 CRUD 流程固化为模板方法。子类只需声明差异点(过滤字段、排序规则、唯一性校验等),即可获得完整的增删改查能力,极大减少重复代码。</p><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 子类只需声明差异点,即可获得完整 CRUD 能力</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">class</span><span style="--shiki-dark:#97E1F1;--shiki-light:#2E8F82;"> ExampleLogic</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> extends</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#59873A;--shiki-light-font-style:inherit;"> BaseLogic</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 关联的模型类</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">modelClass</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> Example</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">class</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * LIKE 模糊匹配字段</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">pageLikeFields</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">name</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 精确匹配字段</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">pageEqFields</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">status</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 默认排序规则</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">pageOrderBy</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">field</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">=&gt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sort</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">type</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">=&gt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">asc</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 唯一性校验字段</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">uniqueFields</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">name</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 枚举显示名映射</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">serializeMaps</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">status</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">=&gt;</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">example_status</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><h3 id="_4-中间件链式处理" tabindex="-1">4. 中间件链式处理 <a class="header-anchor" href="#_4-中间件链式处理" aria-label="Permalink to &quot;4. 中间件链式处理&quot;">​</a></h3><p>请求处理采用中间件链,按注册顺序依次执行:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>请求进入 → CORS → Auth → Tenant → Demo → Log → 控制器</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span>响应返回 ← CORS ← Auth ← Tenant ← Demo ← Log ←───┘</span></span></code></pre></div><table tabindex="0"><thead><tr><th>中间件</th><th>职责</th><th>配置方式</th></tr></thead><tbody><tr><td>CorsMiddleware</td><td>跨域处理</td><td>全局,config/cors.php</td></tr><tr><td>AuthMiddleware</td><td>JWT 认证 + RBAC 鉴权</td><td>路由级,config/middleware.php</td></tr><tr><td>TenantMiddleware</td><td>租户上下文注入</td><td>路由级</td></tr><tr><td>DemoMiddleware</td><td>演示环境拦截</td><td>路由级,.env [APP] DEMO</td></tr><tr><td>LogMiddleware</td><td>操作日志记录</td><td>路由级,config/middleware.php</td></tr></tbody></table><h3 id="_5-全局异常处理" tabindex="-1">5. 全局异常处理 <a class="header-anchor" href="#_5-全局异常处理" aria-label="Permalink to &quot;5. 全局异常处理&quot;">​</a></h3><p><code>ExceptionHandle</code> 统一捕获所有异常并返回标准 JSON 响应:</p><table tabindex="0"><thead><tr><th>来源</th><th>异常类型</th><th>触发场景</th><th>响应</th></tr></thead><tbody><tr><td>ExceptionHandle</td><td>ValidateException</td><td>参数验证失败</td><td><code>{code:1, msg:&quot;参数验证失败&quot;, data:{错误明细}}</code></td></tr><tr><td>ExceptionHandle</td><td>ModelNotFoundException</td><td>数据不存在</td><td><code>{code:1, msg:&quot;数据不存在&quot;}</code></td></tr><tr><td>ExceptionHandle</td><td>HttpException</td><td>HTTP 错误</td><td><code>{code:1, msg:&quot;请求错误&quot;}</code></td></tr><tr><td>ExceptionHandle</td><td>Exception</td><td>未捕获异常</td><td><code>{code:1, msg:&quot;操作失败&quot;}</code></td></tr><tr><td>AuthMiddleware</td><td>—</td><td>JWT 缺失/过期/无效、token 类型错误</td><td><code>{code:401, msg:&quot;未提供认证令牌&quot;}</code> 等</td></tr><tr><td>PermissionMiddleware</td><td>—</td><td>无接口权限</td><td><code>{code:403, msg:&quot;没有权限&quot;}</code></td></tr></tbody></table><h3 id="_6-统一响应格式" tabindex="-1">6. 统一响应格式 <a class="header-anchor" href="#_6-统一响应格式" aria-label="Permalink to &quot;6. 统一响应格式&quot;">​</a></h3><p>所有 API 端点返回统一的 JSON 结构:</p><div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;"> &quot;</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">code</span><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 0</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;"> &quot;</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">ok</span><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> true</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;"> &quot;</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">msg</span><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">操作成功</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;"> &quot;</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">data</span><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {}</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><p>成功响应 <code>code=0</code>,失败响应 <code>code=1</code>(ExceptionHandle 统一处理)。<code>code=401</code>(AuthMiddleware 直接返回)和 <code>code=403</code>(PermissionMiddleware 直接返回)由中间件在请求到达控制器之前拦截,不经过 ExceptionHandle。前端无需针对不同接口做差异化解析。</p><h3 id="_7-软删除策略" tabindex="-1">7. 软删除策略 <a class="header-anchor" href="#_7-软删除策略" aria-label="Permalink to &quot;7. 软删除策略&quot;">​</a></h3><div class="warning custom-block"><p class="custom-block-title">禁止物理删除</p><p>所有业务数据必须使用软删除(<code>is_delete</code> 字段),禁止物理删除。物理删除仅用于日志清理等特殊场景。</p></div><p>所有业务表通过 <code>is_delete</code> 字段实现软删除(0=正常,1=已删除)。<code>BaseModel</code> 的全局查询范围自动追加 <code>is_delete=0</code> 过滤,业务代码无需关心已删除数据。</p><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 自动过滤已删除数据</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">users</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> User</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">select</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // WHERE is_delete = 0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 查询已删除数据</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">deleted</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> User</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">withoutGlobalScope</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">([</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">soft_delete</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">])</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">select</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 软删除</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">user</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">softDelete</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // UPDATE SET is_delete = 1</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 批量软删除</span></span>
<span class="line"><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;">User</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">::</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">batchSoftDelete</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">([</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;">1</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 2</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#2F798A;"> 3</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]);</span></span></code></pre></div><h3 id="_8-审计字段自动写入" tabindex="-1">8. 审计字段自动写入 <a class="header-anchor" href="#_8-审计字段自动写入" aria-label="Permalink to &quot;8. 审计字段自动写入&quot;">​</a></h3><p>通过 BaseModel 的模型事件自动填充审计字段:</p><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 创建前自动填充</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">public</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> static</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> onBeforeInsert</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> void</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">create_user</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> request</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">userInfo</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">username</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ??</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">create_time</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 更新前自动填充</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">public</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> static</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> onBeforeUpdate</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> void</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">update_user</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> request</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">userInfo</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">username</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ??</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">model</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">-&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">update_time</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> date</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">Y-m-d H:i:s</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><h3 id="_9-多数据库支持" tabindex="-1">9. 多数据库支持 <a class="header-anchor" href="#_9-多数据库支持" aria-label="Permalink to &quot;9. 多数据库支持&quot;">​</a></h3><p>通过 <code>DATABASE.TYPE</code> 环境变量切换数据库驱动(MySQL / PostgreSQL / SQL Server / Oracle / SQLite),ThinkPHP ORM 的方言层屏蔽了底层差异,业务代码无需修改。</p><h3 id="_10-两级缓存架构" tabindex="-1">10. 两级缓存架构 <a class="header-anchor" href="#_10-两级缓存架构" aria-label="Permalink to &quot;10. 两级缓存架构&quot;">​</a></h3><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>请求级缓存(static 变量) ← 同一请求内不重复查库</span></span>
<span class="line"><span> │ 未命中</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>持久缓存(file / Redis) ← 跨请求复用,1小时过期</span></span>
<span class="line"><span> │ 未命中</span></span>
<span class="line"><span> ▼</span></span>
<span class="line"><span>数据库查询 ← 查询后写入两级缓存</span></span></code></pre></div><p>DictService 和 ParamService 均采用此架构,大幅减少数据库查询。</p><h2 id="技术分层图" tabindex="-1">技术分层图 <a class="header-anchor" href="#技术分层图" aria-label="Permalink to &quot;技术分层图&quot;">​</a></h2><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌──────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 前端(Vue3 + ElementPlus) │</span></span>
<span class="line"><span>│ Pinia · Vue Router · Axios · TinyMce · ECharts │</span></span>
<span class="line"><span>└──────────────────────────┬───────────────────────────────────┘</span></span>
<span class="line"><span> │ HTTP / JSON</span></span>
<span class="line"><span>┌──────────────────────────┴───────────────────────────────────┐</span></span>
<span class="line"><span>│ ThinkPHP 8 Application │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐ │</span></span>
<span class="line"><span>│ │ 中间件 │ │ 路由 │ │ 异常处理器 │ │</span></span>
<span class="line"><span>│ │ ───────── │ │ ───────── │ │ ───────────────── │ │</span></span>
<span class="line"><span>│ │ CORS │ │ route/ │ │ ValidateException │ │</span></span>
<span class="line"><span>│ │ Auth │ │ app.php │ │ ModelNotFound │ │</span></span>
<span class="line"><span>│ │ Tenant │ │ │ │ RuntimeException │ │</span></span>
<span class="line"><span>│ │ Demo │ │ │ │ HttpException │ │</span></span>
<span class="line"><span>│ │ Log │ │ │ │ Exception │ │</span></span>
<span class="line"><span>│ └─────────────┘ └─────────────┘ └──────────────────────┘ │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ ┌────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 控制器层(app/controller/) │ │</span></span>
<span class="line"><span>│ │ BaseController · #[Permission] · #[Log] │ │</span></span>
<span class="line"><span>│ └────────────────────────────────────────────────────────┘ │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ┌────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 逻辑层(app/logic/) │ │</span></span>
<span class="line"><span>│ │ BaseLogic / BaseTenantLogic │ │</span></span>
<span class="line"><span>│ │ 属性配置 · 钩子 · 文件处理 · 枚举翻译 · 数据权限 │ │</span></span>
<span class="line"><span>│ └────────────────────────────────────────────────────────┘ │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ┌────────────────────────────────────────────────────────┐ │</span></span>
<span class="line"><span>│ │ 模型层(app/model/) │ │</span></span>
<span class="line"><span>│ │ BaseModel · 软删除 · 审计字段 │ │</span></span>
<span class="line"><span>│ └────────────────────────────────────────────────────────┘ │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ ┌──────────────────┐ ┌─────────────┐ ┌──────────────────────┐ │</span></span>
<span class="line"><span>│ │ 服务层 │ │ 验证器 │ │ 注解 │ │</span></span>
<span class="line"><span>│ │ ────────────── │ │ ───────── │ │ ───────────────── │ │</span></span>
<span class="line"><span>│ │ JwtService │ │ Validate │ │ #[Log] │ │</span></span>
<span class="line"><span>│ │ PasswordService │ │ │ │ #[Permission] │ │</span></span>
<span class="line"><span>│ │ DictService │ │ │ │ #[DemoAllow] │ │</span></span>
<span class="line"><span>│ │ ParamService │ │ │ │ │ │</span></span>
<span class="line"><span>│ │ ExcelService │ │ │ │ │ │</span></span>
<span class="line"><span>│ │ CaptchaService │ │ │ │ │ │</span></span>
<span class="line"><span>│ │ GeneratorService│ │ │ │ │ │</span></span>
<span class="line"><span>│ │ AttributeService│ │ │ │ │ │</span></span>
<span class="line"><span>│ │ DbMigrateService│ │ │ │ │ │</span></span>
<span class="line"><span>│ │ DbSchemaBuilder │ │ │ │ │ │</span></span>
<span class="line"><span>│ │ RequestInfoServ │ │ │ │ │ │</span></span>
<span class="line"><span>│ └──────────────────┘ └─────────────┘ └──────────────────────┘ │</span></span>
<span class="line"><span>└──────────────────────────┬───────────────────────────────────┘</span></span>
<span class="line"><span> │</span></span>
<span class="line"><span> ┌────────────┴────────────┐</span></span>
<span class="line"><span> ▼ ▼</span></span>
<span class="line"><span> ┌─────────────┐ ┌─────────────┐</span></span>
<span class="line"><span> │ MySQL │ │ Redis │</span></span>
<span class="line"><span> │ PostgreSQL │ │ 缓存 │</span></span>
<span class="line"><span> │ SQL Server │ └─────────────┘</span></span>
<span class="line"><span> │ Oracle │</span></span>
<span class="line"><span> │ SQLite │</span></span>
<span class="line"><span> └─────────────┘</span></span></code></pre></div><h2 id="模块化设计" tabindex="-1">模块化设计 <a class="header-anchor" href="#模块化设计" aria-label="Permalink to &quot;模块化设计&quot;">​</a></h2><p>每个业务模块遵循统一的文件结构:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>app/controller/UserController.php # HTTP 入口</span></span>
<span class="line"><span>app/logic/UserLogic.php # 业务逻辑</span></span>
<span class="line"><span>app/model/User.php # 数据模型</span></span>
<span class="line"><span>app/validate/UserValidate.php # 参数验证</span></span></code></pre></div><table tabindex="0"><thead><tr><th>文件</th><th>职责</th><th>基类</th></tr></thead><tbody><tr><td>Controller</td><td>接收请求、调用 Logic、返回响应</td><td>BaseController</td></tr><tr><td>Logic</td><td>业务逻辑、属性配置、钩子处理</td><td>BaseLogic / BaseTenantLogic</td></tr><tr><td>Model</td><td>数据库表映射</td><td>BaseModel</td></tr><tr><td>Validate</td><td>参数校验规则</td><td>ThinkPHP Validate</td></tr></tbody></table><h2 id="关键设计决策" tabindex="-1">关键设计决策 <a class="header-anchor" href="#关键设计决策" aria-label="Permalink to &quot;关键设计决策&quot;">​</a></h2><table tabindex="0"><thead><tr><th>决策</th><th>选择</th><th>原因</th></tr></thead><tbody><tr><td>认证方案</td><td>JWT 双令牌</td><td>无状态,适合分布式部署</td></tr><tr><td>删除策略</td><td>软删除(is_delete)</td><td>数据可恢复,避免误删</td></tr><tr><td>字段命名</td><td>数据库 snake_case / 前端 camelCase</td><td>各端遵循各自惯例</td></tr><tr><td>缓存策略</td><td>两级缓存(请求级 + 持久缓存)</td><td>减少数据库查询</td></tr><tr><td>数据库</td><td>多数据库支持</td><td>适配不同客户需求</td></tr><tr><td>权限模型</td><td>RBAC(用户→角色→菜单)</td><td>灵活的权限配置</td></tr></tbody></table>`,45)])])}const F=a(t,[["render",l]]);export{o as __pageData,F as default};