Walltech-Family

新版 - 沃行平台


前端 - 后台设计方案

<h1>后台管理系统架构设计文档</h1> <h2>1. 项目背景</h2> <p>本项目旨在构建一个支持两套登录体系的后台管理系统,需要同时满足客户端后台和运营端后台的需求。两套系统在页面展示上有较大的相似性,存在大量可复用的组件和页面,但在登录体系、账号系统和API接口上需要完全分离。</p> <h3>核心需求</h3> <ul> <li>支持客户端后台和运营端后台两套登录体系</li> <li>大量页面可在两套系统间共享</li> <li>两套系统需要分开部署</li> <li>使用与h5-portal相同的技术架构(Vue 3 + TypeScript + Vite)</li> </ul> <h2>2. 架构设计原则</h2> <ul> <li><strong>代码复用最大化</strong>:通过合理的模块化设计,最大限度地复用代码</li> <li><strong>系统隔离</strong>:确保两套系统的用户状态和API调用相互隔离</li> <li><strong>灵活部署</strong>:支持独立构建和部署两套系统</li> <li><strong>扩展性</strong>:设计应允许后续轻松添加新功能或调整现有功能</li> </ul> <h2>3. 技术栈选择</h2> <ul> <li><strong>前端框架</strong>:Vue 3</li> <li><strong>开发语言</strong>:TypeScript</li> <li><strong>构建工具</strong>:Vite</li> <li><strong>UI组件库</strong>:Ant Design Vue</li> <li><strong>状态管理</strong>:Pinia</li> <li><strong>路由管理</strong>:Vue Router</li> <li><strong>HTTP请求</strong>:Axios</li> <li><strong>CSS预处理器</strong>:SCSS/Less</li> </ul> <h2>4. 整体架构</h2> <p>采用&quot;单仓库多应用&quot;的架构方案,将共享代码抽象为核心模块,客户端后台和运营端后台作为独立应用,共享核心逻辑和组件。</p> <h3>系统架构图</h3> <pre><code>                    +-------------------+                     |   共享核心模块    |                     | (组件/工具/接口)  |                     +-------------------+                            /  \                           /    \                          /      \             +-----------+        +------------+             | 客户端后台 |        | 运营端后台 |             +-----------+        +------------+                 |                      |                 v                      v         +---------------+      +---------------+         | 客户端特有模块 |      | 运营端特有模块 |         +---------------+      +---------------+                 |                      |                 v                      v         +---------------+      +---------------+         | 客户端部署产物 |      | 运营端部署产物 |         +---------------+      +---------------+</code></pre> <h2>5. 目录结构设计</h2> <pre><code>admin-panel/ ├── src/ │   ├── shared/                 # 共享模块 │   │   ├── components/         # 共享UI组件 │   │   ├── views/              # 共享页面 │   │   ├── composables/        # 共享组合式函数 │   │   ├── utils/              # 共享工具函数 │   │   ├── hooks/              # 共享钩子函数 │   │   ├── types/              # 共享类型定义 │   │   └── styles/             # 共享样式 │   │ │   ├── client/                 # 客户端后台 │   │   ├── main.ts             # 客户端入口 │   │   ├── App.vue             # 客户端根组件 │   │   ├── api/                # 客户端API调用 │   │   ├── stores/             # 客户端状态管理 │   │   ├── router/             # 客户端路由 │   │   ├── views/              # 客户端特有页面 │   │   ├── components/         # 客户端特有组件 │   │   └── config/             # 客户端配置 │   │ │   ├── admin/                  # 运营端后台 │   │   ├── main.ts             # 运营端入口 │   │   ├── App.vue             # 运营端根组件 │   │   ├── api/                # 运营端API调用 │   │   ├── stores/             # 运营端状态管理 │   │   ├── router/             # 运营端路由 │   │   ├── views/              # 运营端特有页面 │   │   ├── components/         # 运营端特有组件 │   │   └── config/             # 运营端配置 │   │ │   └── core/                   # 核心功能模块 │       ├── request/            # HTTP请求封装 │       ├── auth/               # 认证相关逻辑 │       └── permission/         # 权限控制逻辑 │ ├── public/                     # 静态资源 │   ├── client/                 # 客户端静态资源 │   └── admin/                  # 运营端静态资源 │ ├── vite.client.config.ts       # 客户端构建配置 ├── vite.admin.config.ts        # 运营端构建配置 ├── vite.config.ts              # 共享构建配置 │ ├── index.client.html           # 客户端HTML模板 ├── index.admin.html            # 运营端HTML模板 │ ├── tsconfig.json               # TypeScript配置 ├── .env                        # 共享环境变量 ├── .env.client                 # 客户端环境变量 ├── .env.admin                  # 运营端环境变量 └── package.json                # 项目依赖</code></pre> <h2>6. 模块详细设计</h2> <h3>6.1 系统上下文</h3> <p>创建一个全局上下文,用于标识当前系统类型,便于共享模块感知当前环境:</p> <pre><code class="language-typescript">// src/shared/composables/useSystemContext.ts import { ref, inject, provide, computed } from &amp;#039;vue&amp;#039; export type SystemType = &amp;#039;client&amp;#039; | &amp;#039;admin&amp;#039; export function provideSystemType(defaultType: SystemType = &amp;#039;client&amp;#039;) {   const systemType = ref&amp;lt;SystemType&amp;gt;(defaultType)     function setSystemType(type: SystemType) {     systemType.value = type     localStorage.setItem(&amp;#039;current_system&amp;#039;, type)   }     provide(&amp;#039;systemType&amp;#039;, {     systemType,     setSystemType   })     return {     systemType,     setSystemType   } } export function useSystemType() {   const context = inject(&amp;#039;systemType&amp;#039;)   if (!context) {     throw new Error(&amp;#039;useSystemType must be used within provideSystemType&amp;#039;)   }     return {     systemType: context.systemType,     setSystemType: context.setSystemType,     isClient: computed(() =&amp;gt; context.systemType.value === &amp;#039;client&amp;#039;),     isAdmin: computed(() =&amp;gt; context.systemType.value === &amp;#039;admin&amp;#039;)   } }</code></pre> <h3>6.2 HTTP请求处理</h3> <p>封装HTTP请求,支持根据系统类型选择不同的认证信息:</p> <pre><code class="language-typescript">// src/core/request/index.ts import axios from &amp;#039;axios&amp;#039; import type { AxiosInstance, AxiosRequestConfig } from &amp;#039;axios&amp;#039; import { useSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; import { getClientToken, getAdminToken } from &amp;#039;@/core/auth/token&amp;#039; class Request {   private instance: AxiosInstance   constructor(config: AxiosRequestConfig) {     this.instance = axios.create(config)     this.setupInterceptors()   }   private setupInterceptors() {     this.instance.interceptors.request.use(config =&amp;gt; {       const { systemType } = useSystemType()       let token = &amp;#039;&amp;#039;             // 根据系统类型获取对应的Token       if (systemType.value === &amp;#039;admin&amp;#039;) {         token = getAdminToken()       } else {         token = getClientToken()       }             if (token) {         config.headers.Authorization = `Bearer ${token}`         config.headers[&amp;#039;X-System-Type&amp;#039;] = systemType.value       }             return config     })     // 响应拦截器处理     this.instance.interceptors.response.use(       response =&amp;gt; {         const res = response.data         if (res.code !== 0) {           // 处理错误           return Promise.reject(new Error(res.message || &amp;#039;请求失败&amp;#039;))         }         return res       },       error =&amp;gt; {         // 处理HTTP错误         return Promise.reject(error)       }     )   }   // 请求方法   public get&amp;lt;T = any&amp;gt;(url: string, config?: AxiosRequestConfig): Promise&amp;lt;T&amp;gt; {     return this.instance.get(url, config)   }   public post&amp;lt;T = any&amp;gt;(url: string, data?: any, config?: AxiosRequestConfig): Promise&amp;lt;T&amp;gt; {     return this.instance.post(url, data, config)   }   // ...其他方法 } export const request = new Request({   baseURL: import.meta.env.VITE_API_URL,   timeout: 15000 })</code></pre> <h3>6.3 用户认证与状态管理</h3> <p>客户端用户状态:</p> <pre><code class="language-typescript">// src/client/stores/user.ts import { defineStore } from &amp;#039;pinia&amp;#039; import { ref } from &amp;#039;vue&amp;#039; import { clientApi } from &amp;#039;@/client/api&amp;#039; export const useClientUserStore = defineStore(&amp;#039;clientUser&amp;#039;, () =&amp;gt; {   const userInfo = ref(null)   const token = ref(&amp;#039;&amp;#039;)   // 登录方法   const login = async (username, password) =&amp;gt; {     const res = await clientApi.login(username, password)     token.value = res.token     userInfo.value = res.userInfo     localStorage.setItem(&amp;#039;client_token&amp;#039;, res.token)   }   // 退出登录   const logout = () =&amp;gt; {     token.value = &amp;#039;&amp;#039;     userInfo.value = null     localStorage.removeItem(&amp;#039;client_token&amp;#039;)   }   // 获取用户信息   const getUserInfo = async () =&amp;gt; {     if (!token.value) return null     const res = await clientApi.getUserInfo()     userInfo.value = res     return res   }   return {     userInfo,     token,     login,     logout,     getUserInfo   } })</code></pre> <p>运营端用户状态:</p> <pre><code class="language-typescript">// src/admin/stores/user.ts import { defineStore } from &amp;#039;pinia&amp;#039; import { ref } from &amp;#039;vue&amp;#039; import { adminApi } from &amp;#039;@/admin/api&amp;#039; export const useAdminUserStore = defineStore(&amp;#039;adminUser&amp;#039;, () =&amp;gt; {   const userInfo = ref(null)   const token = ref(&amp;#039;&amp;#039;)   // 登录方法   const login = async (username, password) =&amp;gt; {     const res = await adminApi.login(username, password)     token.value = res.token     userInfo.value = res.userInfo     localStorage.setItem(&amp;#039;admin_token&amp;#039;, res.token)   }   // 退出登录   const logout = () =&amp;gt; {     token.value = &amp;#039;&amp;#039;     userInfo.value = null     localStorage.removeItem(&amp;#039;admin_token&amp;#039;)   }   // 获取用户信息   const getUserInfo = async () =&amp;gt; {     if (!token.value) return null     const res = await adminApi.getUserInfo()     userInfo.value = res     return res   }   return {     userInfo,     token,     login,     logout,     getUserInfo   } })</code></pre> <h3>6.4 共享页面设计</h3> <p>共享页面能够根据当前的系统上下文动态调整其行为:</p> <pre><code class="language-vue">&amp;lt;!-- src/shared/views/dashboard/index.vue --&amp;gt; &amp;lt;template&amp;gt;   &amp;lt;div class=&amp;quot;dashboard&amp;quot;&amp;gt;     &amp;lt;h1&amp;gt;{{ pageTitle }}&amp;lt;/h1&amp;gt;         &amp;lt;!-- 通用内容 --&amp;gt;     &amp;lt;DataSummary :data=&amp;quot;dashboardData&amp;quot; /&amp;gt;         &amp;lt;!-- 系统特定内容 --&amp;gt;     &amp;lt;template v-if=&amp;quot;isAdmin&amp;quot;&amp;gt;       &amp;lt;AdminSpecificCharts /&amp;gt;     &amp;lt;/template&amp;gt;     &amp;lt;template v-else&amp;gt;       &amp;lt;ClientSpecificCharts /&amp;gt;     &amp;lt;/template&amp;gt;   &amp;lt;/div&amp;gt; &amp;lt;/template&amp;gt; &amp;lt;script setup&amp;gt; import { computed } from &amp;#039;vue&amp;#039; import { useSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; import DataSummary from &amp;#039;@/shared/components/DataSummary.vue&amp;#039; import AdminSpecificCharts from &amp;#039;@/admin/components/AdminSpecificCharts.vue&amp;#039; import ClientSpecificCharts from &amp;#039;@/client/components/ClientSpecificCharts.vue&amp;#039; const { systemType, isAdmin, isClient } = useSystemType() // 根据系统类型调整页面标题 const pageTitle = computed(() =&amp;gt; {   return isAdmin.value ? &amp;#039;运营管理仪表盘&amp;#039; : &amp;#039;客户数据概览&amp;#039; }) // 获取数据 const dashboardData = computed(() =&amp;gt; {   // 可以根据系统类型请求不同的数据或处理方式   return {     // ...数据   } }) &amp;lt;/script&amp;gt;</code></pre> <h3>6.5 路由设计</h3> <p>客户端路由配置:</p> <pre><code class="language-typescript">// src/client/router/index.ts import { createRouter, createWebHistory } from &amp;#039;vue-router&amp;#039; import { provideSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; import { getClientToken } from &amp;#039;@/core/auth/token&amp;#039; // 导入布局和页面 import ClientLayout from &amp;#039;@/client/layout/index.vue&amp;#039; import Login from &amp;#039;@/client/views/login/index.vue&amp;#039; // 导入共享页面 import Dashboard from &amp;#039;@/shared/views/dashboard/index.vue&amp;#039; import Profile from &amp;#039;@/shared/views/profile/index.vue&amp;#039; const routes = [   {     path: &amp;#039;/client/login&amp;#039;,     component: Login,     meta: { requiresAuth: false }   },   {     path: &amp;#039;/client&amp;#039;,     component: ClientLayout,     meta: { requiresAuth: true },     children: [       {         path: &amp;#039;&amp;#039;,         redirect: { name: &amp;#039;client-dashboard&amp;#039; }       },       {         path: &amp;#039;dashboard&amp;#039;,         name: &amp;#039;client-dashboard&amp;#039;,         component: Dashboard,         meta: { title: &amp;#039;仪表盘&amp;#039; }       },       {         path: &amp;#039;profile&amp;#039;,         name: &amp;#039;client-profile&amp;#039;,         component: Profile,         meta: { title: &amp;#039;个人资料&amp;#039; }       },       // 客户端特有页面       {         path: &amp;#039;orders&amp;#039;,         name: &amp;#039;client-orders&amp;#039;,         component: () =&amp;gt; import(&amp;#039;@/client/views/orders/index.vue&amp;#039;),         meta: { title: &amp;#039;订单管理&amp;#039; }       },       // ...其他路由     ]   }, ] const router = createRouter({   history: createWebHistory(),   routes }) // 设置系统类型和认证守卫 router.beforeEach((to, from, next) =&amp;gt; {   const { setSystemType } = provideSystemType()   setSystemType(&amp;#039;client&amp;#039;)     if (to.meta.requiresAuth &amp;amp;&amp;amp; !getClientToken()) {     next({ path: &amp;#039;/client/login&amp;#039; })   } else {     next()   } }) export default router</code></pre> <p>运营端路由配置类似,但使用不同的路径前缀和认证逻辑。</p> <h3>6.6 构建与部署配置</h3> <p>客户端构建配置:</p> <pre><code class="language-typescript">// vite.client.config.ts import { defineConfig } from &amp;#039;vite&amp;#039; import vue from &amp;#039;@vitejs/plugin-vue&amp;#039; import { resolve } from &amp;#039;path&amp;#039; export default defineConfig({   plugins: [vue()],     // 客户端特定的配置   build: {     outDir: &amp;#039;dist/client&amp;#039;,     emptyOutDir: true,   },     server: {     port: 3000   },     resolve: {     alias: {       &amp;#039;@&amp;#039;: resolve(__dirname, &amp;#039;src&amp;#039;)     }   },     // 使用客户端环境变量   envPrefix: &amp;#039;VITE_&amp;#039;,   mode: &amp;#039;client&amp;#039; })</code></pre> <p>运营端构建配置同理。</p> <h2>7. 文件共享与代码复用策略</h2> <ol> <li><strong>共享组件</strong>:将常用UI组件放在shared/components目录,支持在两个系统中复用</li> <li><strong>共享页面</strong>:复杂的页面布局放在shared/views目录,通过系统上下文在不同系统中调整行为</li> <li><strong>工具函数</strong>:通用工具函数放在shared/utils,确保不包含特定于系统的逻辑</li> <li><strong>组合式函数</strong>:可复用的业务逻辑封装为组合式函数,放在shared/composables目录</li> <li><strong>类型定义</strong>:共享的接口类型和类型定义放在shared/types目录</li> </ol> <h2>8. 环境变量设计</h2> <p>共享环境变量:</p> <pre><code># .env VITE_API_URL=http://api.example.com VITE_APP_VERSION=1.0.0</code></pre> <p>客户端环境变量:</p> <pre><code># .env.client VITE_APP_TITLE=客户端管理系统 VITE_LOGIN_PATH=/client/login</code></pre> <p>运营端环境变量:</p> <pre><code># .env.admin VITE_APP_TITLE=运营管理系统 VITE_LOGIN_PATH=/admin/login</code></pre> <h2>9. 部署方案</h2> <p>两套系统可以分别部署到不同的域名或路径下:</p> <ul> <li>客户端后台: <code>https://client-admin.example.com</code> 或 <code>https://admin.example.com/client</code></li> <li>运营端后台: <code>https://admin.example.com</code> 或 <code>https://admin.example.com/operations</code></li> </ul> <p>部署步骤:</p> <ol> <li> <p>分别构建客户端和运营端代码    <code>    npm run build:client    npm run build:admin    </code></p> </li> <li>将构建产物部署到相应的服务器目录</li> <li>配置服务器路由规则,确保前端路由正常工作</li> <li>设置适当的CORS和安全策略</li> </ol> <h2>10. 开发工作流</h2> <ol> <li> <p><strong>分支管理</strong>:    - <code>main</code>: 主分支,包含稳定代码    - <code>develop</code>: 开发分支,新功能合并到此分支    - <code>feature/*</code>: 特性分支,用于开发新功能    - <code>client/*</code>: 客户端特定功能分支    - <code>admin/*</code>: 运营端特定功能分支</p> </li> <li> <p><strong>开发命令</strong>:    <code>json    &amp;quot;scripts&amp;quot;: {      &amp;quot;dev:client&amp;quot;: &amp;quot;vite --config vite.client.config.ts&amp;quot;,      &amp;quot;dev:admin&amp;quot;: &amp;quot;vite --config vite.admin.config.ts&amp;quot;,      &amp;quot;build:client&amp;quot;: &amp;quot;vue-tsc &amp;amp;&amp;amp; vite build --config vite.client.config.ts&amp;quot;,      &amp;quot;build:admin&amp;quot;: &amp;quot;vue-tsc &amp;amp;&amp;amp; vite build --config vite.admin.config.ts&amp;quot;    }    </code></p> </li> <li><strong>代码规范</strong>:    - 使用ESLint和Prettier保持代码风格一致    - 使用TypeScript强类型定义    - 组件和函数命名应表明其用途和所属系统 </li> </ol> <h2>11. 页面共享与身份差异处理优化</h2> <p>为了最大化页面复用并避免在共享页面中编写大量的条件判断逻辑,本项目采用以下优化策略:</p> <h3>11.1 服务层抽象与依赖注入</h3> <p>将特定于系统身份的业务逻辑和API调用封装在服务层,通过依赖注入自动选择合适的实现:</p> <pre><code class="language-typescript">// src/shared/services/types.ts export interface AuthService {   login(username: string, password: string): Promise&amp;lt;any&amp;gt;   logout(): Promise&amp;lt;void&amp;gt;   getUser(): Promise&amp;lt;any&amp;gt; } // src/client/services/auth.service.ts export class ClientAuthService implements AuthService {   // 客户端实现 } // src/admin/services/auth.service.ts export class AdminAuthService implements AuthService {   // 运营端实现 } // src/shared/composables/useServices.ts export function useServices() {   const { systemType } = useSystemType()     const authService = computed(() =&amp;gt;     systemType.value === &amp;#039;admin&amp;#039; ? new AdminAuthService() : new ClientAuthService()   )     return { authService } }</code></pre> <p>页面组件可以直接使用服务,而不用关心具体实现:</p> <pre><code class="language-typescript">// 在页面中使用 const { authService } = useServices() const login = () =&amp;gt; authService.value.login(username, password)</code></pre> <h3>11.2 API适配器模式</h3> <p>创建通用的API适配器,根据当前系统类型自动调整请求参数和URL:</p> <pre><code class="language-typescript">// src/shared/adapters/apiAdapter.ts export function createApiAdapter(endpoint: string) {   const { systemType } = useSystemType()     return {     fetch: async (params?: any) =&amp;gt; {       const prefix = systemType.value === &amp;#039;admin&amp;#039; ? &amp;#039;/admin&amp;#039; : &amp;#039;/client&amp;#039;       return request.get(`${prefix}/${endpoint}`, {         params: {           ...params,           // 添加特定于身份的参数           role: systemType.value         }       })     },         submit: async (data: any) =&amp;gt; {       const prefix = systemType.value === &amp;#039;admin&amp;#039; ? &amp;#039;/admin&amp;#039; : &amp;#039;/client&amp;#039;       return request.post(`${prefix}/${endpoint}`, {         ...data,         // 添加特定于身份的数据         role: systemType.value       })     }   } }</code></pre> <h3>11.3 配置驱动的动态组件</h3> <p>设计配置驱动的组件系统,避免在组件中使用条件渲染:</p> <pre><code class="language-typescript">// src/shared/components/ConfigurableTable.vue &amp;lt;template&amp;gt;   &amp;lt;div&amp;gt;     &amp;lt;a-table       :columns=&amp;quot;currentColumns&amp;quot;       :data-source=&amp;quot;dataSource&amp;quot;       :pagination=&amp;quot;paginationConfig&amp;quot;       @change=&amp;quot;handleTableChange&amp;quot;     /&amp;gt;   &amp;lt;/div&amp;gt; &amp;lt;/template&amp;gt; &amp;lt;script setup&amp;gt; import { computed } from &amp;#039;vue&amp;#039; import { useSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; const props = defineProps({   adminColumns: Array,   clientColumns: Array,   dataSource: Array,   pagination: Object,   onChange: Function }) const { isAdmin } = useSystemType() // 根据系统类型动态选择列配置 const currentColumns = computed(() =&amp;gt;   isAdmin.value ? props.adminColumns : props.clientColumns ) // 动态分页配置 const paginationConfig = computed(() =&amp;gt; ({   ...props.pagination,   showSizeChanger: isAdmin.value, // 只在管理端显示页大小选择器   showQuickJumper: isAdmin.value  // 只在管理端显示快速跳转 })) function handleTableChange(pagination, filters, sorter) {   props.onChange?.(pagination, filters, sorter) } &amp;lt;/script&amp;gt;</code></pre> <h3>11.4 登录页面优化示例</h3> <p>以登录页面为例,展示如何实现页面共享但逻辑分离:</p> <pre><code class="language-vue">&amp;lt;!-- src/shared/views/auth/Login.vue --&amp;gt; &amp;lt;template&amp;gt;   &amp;lt;div class=&amp;quot;login-container&amp;quot;&amp;gt;     &amp;lt;h1&amp;gt;{{ systemTitle }}&amp;lt;/h1&amp;gt;     &amp;lt;a-form       :model=&amp;quot;formState&amp;quot;       :rules=&amp;quot;rules&amp;quot;       @finish=&amp;quot;handleLogin&amp;quot;     &amp;gt;       &amp;lt;a-form-item name=&amp;quot;username&amp;quot;&amp;gt;         &amp;lt;a-input v-model:value=&amp;quot;formState.username&amp;quot; placeholder=&amp;quot;用户名&amp;quot; /&amp;gt;       &amp;lt;/a-form-item&amp;gt;             &amp;lt;a-form-item name=&amp;quot;password&amp;quot;&amp;gt;         &amp;lt;a-input-password v-model:value=&amp;quot;formState.password&amp;quot; placeholder=&amp;quot;密码&amp;quot; /&amp;gt;       &amp;lt;/a-form-item&amp;gt;             &amp;lt;!-- 只在管理端显示的额外字段 --&amp;gt;       &amp;lt;template v-if=&amp;quot;isAdmin&amp;quot;&amp;gt;         &amp;lt;a-form-item name=&amp;quot;verificationCode&amp;quot;&amp;gt;           &amp;lt;a-input v-model:value=&amp;quot;formState.verificationCode&amp;quot; placeholder=&amp;quot;验证码&amp;quot; /&amp;gt;         &amp;lt;/a-form-item&amp;gt;       &amp;lt;/template&amp;gt;             &amp;lt;a-form-item&amp;gt;         &amp;lt;a-button type=&amp;quot;primary&amp;quot; html-type=&amp;quot;submit&amp;quot;&amp;gt;登录&amp;lt;/a-button&amp;gt;       &amp;lt;/a-form-item&amp;gt;     &amp;lt;/a-form&amp;gt;   &amp;lt;/div&amp;gt; &amp;lt;/template&amp;gt; &amp;lt;script setup&amp;gt; import { reactive, computed } from &amp;#039;vue&amp;#039; import { useRouter } from &amp;#039;vue-router&amp;#039; import { useSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; import { useServices } from &amp;#039;@/shared/composables/useServices&amp;#039; const { systemType, isAdmin } = useSystemType() const router = useRouter() const { authService } = useServices() // 系统标题 const systemTitle = computed(() =&amp;gt;   isAdmin.value ? &amp;#039;运营管理系统&amp;#039; : &amp;#039;客户端管理系统&amp;#039; ) // 表单状态 const formState = reactive({   username: &amp;#039;&amp;#039;,   password: &amp;#039;&amp;#039;,   verificationCode: &amp;#039;&amp;#039; // 仅管理端使用 }) // 验证规则 const rules = computed(() =&amp;gt; {   const baseRules = {     username: [{ required: true, message: &amp;#039;请输入用户名&amp;#039; }],     password: [{ required: true, message: &amp;#039;请输入密码&amp;#039; }],   }     // 根据系统类型添加额外验证规则   if (isAdmin.value) {     baseRules.verificationCode = [{ required: true, message: &amp;#039;请输入验证码&amp;#039; }]   }     return baseRules }) // 登录处理 const handleLogin = async (values) =&amp;gt; {   try {     // authService会根据当前系统类型自动调用正确的实现     await authService.value.login(values)         // 登录成功后根据系统类型跳转到不同的首页     router.push(isAdmin.value ? &amp;#039;/admin/dashboard&amp;#039; : &amp;#039;/client/dashboard&amp;#039;)   } catch (error) {     // 处理错误   } } &amp;lt;/script&amp;gt;</code></pre> <h3>11.5 路由元数据与服务自动注入</h3> <p>利用路由元数据实现服务的自动注入:</p> <pre><code class="language-typescript">// 增强路由配置 const routes = [   {     path: &amp;#039;/users&amp;#039;,     component: () =&amp;gt; import(&amp;#039;@/shared/views/users/index.vue&amp;#039;),     meta: {       title: &amp;#039;用户管理&amp;#039;,       requiresAuth: true,       services: {         client: &amp;#039;userService&amp;#039;,         admin: &amp;#039;adminUserService&amp;#039;       },       permissions: {         client: [&amp;#039;user:view&amp;#039;],         admin: [&amp;#039;user:view&amp;#039;, &amp;#039;user:edit&amp;#039;, &amp;#039;user:delete&amp;#039;]       }     }   } ] // 创建服务自动注入钩子 export function useRouteServices() {   const route = useRoute()   const { systemType } = useSystemType()   const allServices = inject(&amp;#039;services&amp;#039;)     // 自动获取路由元数据中声明的服务   const routeServices = computed(() =&amp;gt; {     const serviceMapping = route.meta?.services || {}     const systemKey = systemType.value         // 收集该路由所需的所有服务     return Object.entries(serviceMapping)       .filter(([key, serviceName]) =&amp;gt; key === systemKey)       .reduce((acc, [_, serviceName]) =&amp;gt; {         if (typeof serviceName === &amp;#039;string&amp;#039; &amp;amp;&amp;amp; allServices[serviceName]) {           acc[serviceName] = allServices[serviceName]         }         return acc       }, {})   })     return routeServices }</code></pre> <h3>11.6 策略模式处理复杂业务逻辑差异</h3> <p>对于具有显著业务逻辑差异的操作,使用策略模式:</p> <pre><code class="language-typescript">// src/shared/strategies/userManagement.ts export interface UserManagementStrategy {   createUser(userData: any): Promise&amp;lt;any&amp;gt;   deleteUser(userId: string): Promise&amp;lt;boolean&amp;gt;   assignRole(userId: string, roleId: string): Promise&amp;lt;boolean&amp;gt; } // src/client/strategies/userManagement.ts export class ClientUserManagementStrategy implements UserManagementStrategy {   // 客户端特定的实现 } // src/admin/strategies/userManagement.ts export class AdminUserManagementStrategy implements UserManagementStrategy {   // 管理端特定的实现 } // 策略工厂 export function createUserManagementStrategy() {   const { systemType } = useSystemType()     return computed(() =&amp;gt;     systemType.value === &amp;#039;admin&amp;#039;       ? new AdminUserManagementStrategy()       : new ClientUserManagementStrategy()   ) }</code></pre> <h3>11.7 组件库与UI差异处理</h3> <p>创建智能组件库,根据系统类型自动调整UI表现:</p> <pre><code class="language-typescript">// src/shared/components/SmartButton.vue &amp;lt;template&amp;gt;   &amp;lt;a-button     :type=&amp;quot;computedType&amp;quot;     :size=&amp;quot;computedSize&amp;quot;     :disabled=&amp;quot;isDisabled&amp;quot;     @click=&amp;quot;handleClick&amp;quot;   &amp;gt;     &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;   &amp;lt;/a-button&amp;gt; &amp;lt;/template&amp;gt; &amp;lt;script setup&amp;gt; import { computed } from &amp;#039;vue&amp;#039; import { useSystemType } from &amp;#039;@/shared/composables/useSystemContext&amp;#039; import { usePermission } from &amp;#039;@/shared/composables/usePermission&amp;#039; const props = defineProps({   type: String,   size: String,   action: String,   systemSpecific: {     type: Object,     default: () =&amp;gt; ({})   } }) const emit = defineEmits([&amp;#039;click&amp;#039;]) const { systemType, isAdmin } = useSystemType() const { hasPermission } = usePermission() // 根据系统类型计算按钮类型 const computedType = computed(() =&amp;gt; {   const systemConfig = props.systemSpecific[systemType.value] || {}   return systemConfig.type || props.type || &amp;#039;default&amp;#039; }) // 根据系统类型计算按钮大小 const computedSize = computed(() =&amp;gt; {   const systemConfig = props.systemSpecific[systemType.value] || {}   return systemConfig.size || props.size || &amp;#039;middle&amp;#039; }) // 权限检查,根据系统和操作类型 const isDisabled = computed(() =&amp;gt; {   if (!props.action) return false   return !hasPermission(props.action) }) // 点击处理 function handleClick(e) {   emit(&amp;#039;click&amp;#039;, e) } &amp;lt;/script&amp;gt;</code></pre> <h3>11.8 总结与最佳实践</h3> <p>通过以上优化技术,实现以下目标:</p> <ol> <li><strong>代码复用最大化</strong>:共享页面和组件实现代码复用</li> <li><strong>业务逻辑分离</strong>:每个系统的特定逻辑封装在各自的服务层</li> <li><strong>最小化条件判断</strong>:减少页面内的if-else判断,提高代码可维护性</li> <li><strong>动态适配</strong>:页面和组件能够自动适应不同的系统环境</li> <li><strong>可扩展性</strong>:提供清晰的模式,便于后续添加更多的共享功能</li> </ol> <p>这些优化策略使得项目能够在保持两套系统独立性的同时,最大化共享代码,提高开发效率和维护性。 </p>

页面列表

ITEM_HTML