# Yudao UI Admin Vben - 项目结构与开发指南 > **专注于 web-antd 项目** - 基于 Vue 3 + Vite + Ant Design Vue 的后台管理系统 ## 📋 目录 - [项目架构](#项目架构) - [目录结构详解](#目录结构详解) - [通用组件库](#通用组件库) - [配置文件说明](#配置文件说明) - [主题定制](#主题定制) - [登录布局定制](#登录布局定制) - [开发调试指南](#开发调试指南) - [本次会话修改记录](#本次会话修改记录) --- ## 🏗️ 项目架构 ### 整体结构 本项目采用 **Monorepo** 架构,使用 **pnpm workspace** 管理多个包: ``` yudao-ui-admin-vben/ ├── apps/ # 应用层 │ ├── web-antd/ # Ant Design Vue 版本 (主要使用) │ ├── web-ele/ # Element Plus 版本 │ ├── web-naive/ # Naive UI 版本 │ └── web-tdesign/ # TDesign 版本 ├── packages/ # 公共包 │ ├── @core/ # 核心包 │ ├── effects/ # 业务效果包 │ ├── locales/ # 国际化 │ ├── stores/ # 状态管理 │ └── ... # 其他工具包 ├── internal/ # 内部工具 │ ├── vite-config/ # Vite 配置 │ ├── tailwind-config/ # Tailwind 配置 │ └── lint-configs/ # 代码规范配置 └── docs/ # 文档站点 ``` ### 技术栈 | 技术 | 版本 | 说明 | | -------------- | ---- | -------------------------- | | Vue | 3.x | 渐进式 JavaScript 框架 | | Vite | 5.x | 下一代前端构建工具 | | TypeScript | 5.x | 类型安全 | | Ant Design Vue | 4.x | UI 组件库 | | Pinia | 2.x | 状态管理 | | Vue Router | 4.x | 路由管理 | | Tailwind CSS | 3.x | 原子化 CSS | | VueUse | 10.x | Vue Composition API 工具集 | --- ## 📁 目录结构详解 ### apps/web-antd/ - 主应用目录 ``` apps/web-antd/ ├── public/ # 静态资源 │ ├── favicon.ico # 网站图标 │ ├── login-illustration.svg # 登录页插图 │ ├── images/ # 图片资源 │ ├── static/ # 静态文件 │ └── tinymce/ # 富文本编辑器资源 │ ├── src/ │ ├── adapter/ # 适配器层 │ │ ├── component.ts # 组件适配器 (全局组件注册) │ │ ├── form.ts # 表单适配器 │ │ └── vxe-table.ts # 表格适配器 │ │ │ ├── api/ # API 接口层 (201 个文件) │ │ ├── core/ # 核心接口 (登录、权限等) │ │ ├── system/ # 系统管理 │ │ ├── infra/ # 基础设施 │ │ ├── bpm/ # 工作流 │ │ ├── mall/ # 商城 │ │ ├── mp/ # 公众号 │ │ ├── pay/ # 支付 │ │ ├── ai/ # AI 相关 │ │ ├── iot/ # 物联网 │ │ └── erp/ # ERP │ │ │ ├── assets/ # 资源文件 │ │ ├── images/ # 图片 │ │ └── svg/ # SVG 图标 │ │ │ ├── components/ # 业务组件 (54 个文件) │ │ ├── Bpmnjs/ # 工作流设计器 │ │ ├── Button/ # 按钮组件 │ │ ├── ContentWrap/ # 内容包裹器 │ │ ├── Crontab/ # 定时任务配置 │ │ ├── Dialog/ # 对话框 │ │ ├── Editor/ # 编辑器 │ │ ├── Form/ # 表单 │ │ ├── Icon/ # 图标 │ │ ├── ImageViewer/ # 图片查看器 │ │ ├── InputNumber/ # 数字输入框 │ │ ├── JsonEditor/ # JSON 编辑器 │ │ ├── Search/ # 搜索 │ │ ├── SimpleProcessDesignerV2/ # 流程设计器 V2 │ │ ├── Table/ # 表格 │ │ ├── UploadFile/ # 文件上传 │ │ └── UploadImg/ # 图片上传 │ │ │ ├── layouts/ # 布局组件 │ │ ├── auth.vue # 登录页布局 (自定义) │ │ ├── auth-original.vue # 原始登录页布局 (备份) │ │ ├── basic.vue # 基础布局 │ │ └── index.ts # 导出 │ │ │ ├── locales/ # 本地化 │ │ ├── langs/ # 语言包 │ │ │ ├── en-US.json # 英文 │ │ │ └── zh-CN.json # 中文 │ │ └── index.ts │ │ │ ├── plugins/ # 插件 │ │ └── form-create.ts # 表单构建器插件 │ │ │ ├── router/ # 路由配置 │ │ ├── guard.ts # 路由守卫 │ │ ├── index.ts # 路由实例 │ │ └── routes/ # 路由定义 │ │ ├── core.ts # 核心路由 (登录、404等) │ │ └── modules/ # 业务路由模块 │ │ │ ├── store/ # 状态管理 (Pinia) │ │ ├── index.ts │ │ ├── modules/ │ │ │ ├── auth.ts # 认证状态 │ │ │ ├── dict.ts # 字典状态 │ │ │ └── tenant.ts # 租户状态 │ │ │ ├── utils/ # 工具函数 │ │ ├── dict.ts # 字典工具 │ │ ├── tree.ts # 树形数据工具 │ │ └── ... │ │ │ ├── views/ # 页面视图 (1233 个文件) │ │ ├── _core/ # 核心页面 │ │ │ ├── authentication/ # 认证相关 │ │ │ │ ├── login.vue # 登录页 │ │ │ │ ├── code-login.vue # 验证码登录 │ │ │ │ ├── qrcode-login.vue # 二维码登录 │ │ │ │ └── forget-password.vue # 忘记密码 │ │ │ ├── profile/ # 个人中心 │ │ │ └── ... │ │ ├── system/ # 系统管理 │ │ ├── bpm/ # 工作流 │ │ ├── mall/ # 商城 │ │ ├── mp/ # 公众号 │ │ ├── pay/ # 支付 │ │ ├── ai/ # AI │ │ ├── iot/ # 物联网 │ │ └── erp/ # ERP │ │ │ ├── app.vue # 根组件 │ ├── bootstrap.ts # 应用启动配置 │ ├── main.ts # 应用入口 │ └── preferences.ts # 偏好设置 │ ├── index.html # HTML 模板 ├── vite.config.mts # Vite 配置 ├── tsconfig.json # TypeScript 配置 ├── tailwind.config.mjs # Tailwind 配置 ├── package.json # 依赖管理 └── LOGIN_LAYOUT_README.md # 登录布局文档 ``` --- ## 🧩 通用组件库 ### packages/@core/ - 核心组件包 #### 1. shadcn-ui (`packages/@core/ui-kit/shadcn-ui`) 基于 shadcn/ui 的 Vue 组件库,提供高质量的基础 UI 组件: ```typescript // 导入方式 import { VbenButton, VbenInput, VbenModal, VbenToast, VbenDropdown, VbenSelect, VbenPinInput, // 验证码输入框 VbenLoading, VbenSpinner, // ... 更多组件 } from '@vben-core/shadcn-ui'; ``` **常用组件**: - **按钮类**: `VbenButton`, `VbenIconButton` - **输入类**: `VbenInput`, `VbenInputPassword`, `VbenPinInput` - **选择类**: `VbenSelect`, `VbenDropdown`, `VbenCheckbox`, `VbenRadio` - **反馈类**: `VbenModal`, `VbenToast`, `VbenAlert`, `VbenLoading` - **布局类**: `VbenCard`, `VbenTabs`, `VbenCollapse` #### 2. form-ui (`packages/@core/ui-kit/form-ui`) 强大的表单构建器: ```typescript import { useVbenForm, VbenFormSchema } from '@vben-core/form-ui'; // 表单配置示例 const formSchema: VbenFormSchema[] = [ { component: 'VbenInput', fieldName: 'username', label: '用户名', rules: z.string().min(1, { message: '请输入用户名' }), }, { component: 'VbenInputPassword', fieldName: 'password', label: '密码', rules: z.string().min(6, { message: '密码至少6位' }), }, ]; const [Form, formApi] = useVbenForm({ schema: formSchema }); ``` #### 3. menu-ui (`packages/@core/ui-kit/menu-ui`) 菜单组件,支持多级菜单、收缩展开等: ```typescript import { VbenMenu } from '@vben-core/menu-ui'; ``` #### 4. layout-ui (`packages/@core/ui-kit/layout-ui`) 布局组件(Header, Sidebar, Content, Footer): ```typescript import { BasicLayout, LayoutHeader, LayoutSidebar } from '@vben-core/layout-ui'; ``` #### 5. popup-ui (`packages/@core/ui-kit/popup-ui`) 弹窗、抽屉组件: ```typescript import { VbenModal, VbenDrawer } from '@vben-core/popup-ui'; ``` --- ### packages/effects/ - 业务效果包 #### 1. layouts (`packages/effects/layouts`) 布局组件和小部件: ```typescript import { // 布局组件 AuthPageLayout, // 认证页布局 LoginIllustration, // 登录插图 (自定义新增) // 小部件 ThemeToggle, // 主题切换 LanguageToggle, // 语言切换 ColorToggle, // 颜色选择器 LayoutToggle, // 布局切换 UserDropdown, // 用户下拉菜单 Breadcrumb, // 面包屑 GlobalSearch, // 全局搜索 LockScreen, // 锁屏 Notification, // 通知 } from '@vben/layouts'; ``` **目录结构**: ``` packages/effects/layouts/src/ ├── authentication/ # 认证相关 │ ├── authentication.vue # 认证页布局 │ ├── icons/ │ │ ├── login-illustration.vue # 登录插图组件 │ │ └── slogan.vue # Logo/标语组件 │ └── index.ts # 导出 ├── basic/ # 基础布局 ├── widgets/ # 小部件 │ ├── theme-toggle.vue │ ├── language-toggle.vue │ ├── color-toggle.vue # 颜色选择器 (已修改) │ └── ... └── index.ts ``` #### 2. common-ui (`packages/effects/common-ui`) 通用 UI 组件: ```typescript import { // 认证组件 AuthenticationLogin, // 登录表单 AuthenticationCodeLogin, // 验证码登录 AuthenticationForgetPassword, // 忘记密码 AuthenticationRegister, // 注册 // 其他通用组件 Page, // 页面容器 DocAlert, // 文档提醒 Description, // 描述列表 Ellipsis, // 文本省略 Iframe, // 内嵌页面 // ... } from '@vben/common-ui'; ``` #### 3. hooks (`packages/effects/hooks`) 业务相关的 Composition API 钩子: ```typescript import { useWatermark, // 水印 useTabs, // 标签页管理 useContentHeight, // 内容高度自适应 isTenantEnable, // 租户功能是否启用 } from '@vben/hooks'; ``` #### 4. access (`packages/effects/access`) 权限控制: ```typescript import { useAccess } from '@vben/access'; // 权限检查 const { hasAccessByRoles, hasAccessByCodes } = useAccess(); // 指令方式 ``` --- ### packages/其他包 #### locales - 国际化 ```typescript import { $t, setupI18n } from '@vben/locales'; // 使用翻译 $t('authentication.login'); $t('authentication.username'); ``` **语言包位置**: - 中文: `packages/locales/src/langs/zh-CN/*.json` - 英文: `packages/locales/src/langs/en-US/*.json` #### stores - 状态管理 ```typescript import { useUserStore, // 用户信息 useAccessStore, // 权限信息 useTabsStore, // 标签页 useAppStore, // 应用配置 } from '@vben/stores'; const userStore = useUserStore(); await userStore.fetchUserInfo(); ``` #### preferences - 偏好设置 ```typescript import { preferences, // 偏好设置对象 updatePreferences, // 更新偏好设置 usePreferences, // 响应式偏好设置 } from '@vben/preferences'; // 读取 const isDark = preferences.theme.mode === 'dark'; // 更新 updatePreferences({ theme: { colorPrimary: '#FFA00A', builtinType: 'amber', }, }); ``` #### utils - 工具函数 ```typescript import { // 路由工具 mapTree, resetRoutes, // 通用工具 formatDate, formatDateTime, openWindow, // 验证器 isEmail, isPhone, isUrl, } from '@vben/utils'; ``` #### constants - 常量定义 ```typescript import { // 核心常量 LOGIN_PATH, VBEN_DOC_URL, // 业务枚举 DictEnum, SystemEnum, BpmEnum, // ... } from '@vben/constants'; ``` --- ## ⚙️ 配置文件说明 ### 1. Vite 配置 (`vite.config.mts`) ```typescript import { defineConfig } from '@vben/vite-config'; export default defineConfig(async () => { return { application: {}, vite: { server: { proxy: { '/admin-api': { target: 'http://localhost:48080/admin-api', changeOrigin: true, rewrite: (path) => path.replace(/^\/admin-api/, ''), }, }, }, }, }; }); ``` ### 2. TypeScript 配置 (`tsconfig.json`) ```json { "$schema": "https://json.schemastore.org/tsconfig", "extends": "@vben/tsconfig/web-app.json", "compilerOptions": { "baseUrl": ".", "paths": { "#/*": ["./src/*"] }, "allowJs": true }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] } ``` **路径别名**: - `#/*` → `./src/*` (应用内部) - `@vben/*` → `packages/*` (公共包) ### 3. Tailwind 配置 (`tailwind.config.mjs`) ```javascript import { defineConfig } from '@vben/tailwind-config'; export default defineConfig({ content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], // 自定义配置... }); ``` ### 4. 环境变量 (`.env.*`) ```bash # .env.development VITE_APP_TITLE=芋道管理系统 VITE_APP_BASE_API=/admin-api VITE_APP_NAMESPACE=vben-web-antd ``` --- ## 🎨 主题定制 ### 1. 新增主题色 **文件**: `packages/@core/preferences/src/constants.ts` ```typescript const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [ { color: 'hsl(37 100% 52%)', // #FFA00A type: 'amber', }, // ... 其他颜色 ]; export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 8); ``` **类型定义**: `packages/@core/base/typings/src/app.d.ts` ```typescript type BuiltinThemeType = | 'amber' // 新增 | 'default' | 'orange' | 'red' // ... | (Record & string); ``` **默认主题**: `packages/@core/preferences/src/config.ts` ```typescript const defaultPreferences: Preferences = { theme: { builtinType: 'amber', // 默认主题类型 colorPrimary: 'hsl(37 100% 52%)', // 主色调 mode: 'dark', // 暗色模式 radius: '0.5', // 圆角 }, // ... }; ``` ### 2. Loading 页面定制 **文件**: `internal/vite-config/src/plugins/inject-app-loading/default-loading.html` ```html ``` **注意**: 修改后需要**重启开发服务器**才能生效! --- ## 🔐 登录布局定制 ### 自定义登录页 **文件**: `apps/web-antd/src/layouts/auth.vue` **主要特性**: - ✅ 橙色渐变背景 (`rgb(218,125,68)` → `#FFA00A`) - ✅ 浮动插图动画(左侧) - ✅ 表单卡片居右 - ✅ 支持 Light/Dark 主题 - ✅ 响应式布局 - ✅ 快速过渡动画 **组件引用**: ```typescript import { LanguageToggle, LoginIllustration, ThemeToggle } from '@vben/layouts'; ``` **详细文档**: 参见 `apps/web-antd/LOGIN_LAYOUT_README.md` ### 登录页面 **文件**: `apps/web-antd/src/views/_core/authentication/login.vue` **功能**: - 用户名/密码登录 - 图形验证码 - 记住密码 - 第三方登录(手机、二维码) **表单配置示例**: ```typescript const formSchema = computed((): VbenFormSchema[] => [ { component: 'VbenInput', fieldName: 'username', label: $t('authentication.username'), rules: z.string().min(1), }, { component: 'VbenInputPassword', fieldName: 'password', label: $t('authentication.password'), rules: z.string().min(1), }, // ... ]); ``` ### 验证码登录/忘记密码 **文件**: - `apps/web-antd/src/views/_core/authentication/code-login.vue` - `apps/web-antd/src/views/_core/authentication/forget-password.vue` **验证码组件** (`VbenPinInput`): - ✅ 验证码长度: 6 位 - ✅ 发送前验证手机号 - ✅ 倒计时 60 秒 - ✅ 失败自动清除倒计时 **修复**: `packages/@core/ui-kit/shadcn-ui/src/components/pin-input/input.vue` ```typescript async function handleSend(e: Event) { try { e?.preventDefault(); // ✅ 先验证手机号 await handleSendCode(); // ✅ 验证成功后才开始倒计时 countdown.value = maxTime; startCountdown(); } catch (error) { // ✅ 失败清除倒计时 countdown.value = 0; clearTimeout(timer.value); } } ``` --- ## 🛠️ 开发调试指南 ### 启动项目 ```bash # 安装依赖 pnpm install # 启动开发服务器 pnpm dev # 或者只启动 web-antd pnpm --filter @vben/web-antd dev ``` ### 构建项目 ```bash # 构建所有应用 pnpm build # 只构建 web-antd pnpm --filter @vben/web-antd build ``` ### 代码规范 ```bash # ESLint 检查 pnpm lint # 格式化代码 pnpm format # 类型检查 pnpm typecheck ``` ### 常用命令 ```bash # 清理所有 node_modules pnpm clean # 清理并重新安装 pnpm clean && pnpm install # 查看依赖树 pnpm list --depth 0 # 更新依赖 pnpm update ``` ### 调试技巧 #### 1. Vue DevTools 安装 Vue DevTools 浏览器扩展,可以查看: - 组件树 - Pinia 状态 - 路由信息 - 性能分析 #### 2. 网络请求调试 打开浏览器开发者工具 Network 面板: - 查看 API 请求/响应 - 检查请求头/响应头 - 查看接口耗时 #### 3. 控制台调试 ```typescript // 在组件中使用 console console.log('当前路由:', router.currentRoute.value); console.log('用户信息:', userStore.userInfo); console.log('权限列表:', accessStore.accessCodes); ``` #### 4. 断点调试 在 VS Code 中配置 `.vscode/launch.json`: ```json { "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Launch Chrome", "url": "http://localhost:5173", "webRoot": "${workspaceFolder}/apps/web-antd" } ] } ``` #### 5. 性能分析 使用 Vue DevTools Performance 功能: - 记录组件渲染时间 - 查找性能瓶颈 - 优化重渲染 --- ## 📝 本次会话修改记录 ### 1. 主题色定制 (#FFA00A - 橙色) #### 文件: `packages/@core/preferences/src/constants.ts` ```typescript // 新增 amber 主题色 const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [ { color: 'hsl(37 100% 52%)', // #FFA00A type: 'amber', }, // ... ]; export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 8); // 7→8 ``` #### 文件: `packages/@core/base/typings/src/app.d.ts` ```typescript type BuiltinThemeType = | 'amber' // ← 新增 | 'default'; // ... ``` #### 文件: `packages/@core/preferences/src/config.ts` ```typescript const defaultPreferences: Preferences = { theme: { builtinType: 'amber', // ← 设为默认 colorPrimary: 'hsl(37 100% 52%)', // ← 设为默认 // ... }, }; ``` --- ### 2. 登录布局重构 #### 文件: `apps/web-antd/src/layouts/auth.vue` **完全重构,新增功能**: - ✅ 橙色渐变背景 (从 `rgb(218,125,68)` 到 `#FFA00A`) - ✅ 浮动插图组件 (左侧,带动画) - ✅ 白色 Logo 文字,带阴影 - ✅ 表单卡片右对齐,垂直居中 - ✅ 快速过渡动画 (0.2s/0.15s) - ✅ 响应式布局 - ✅ 保留原有 Toolbar (主题、语言切换) **关键代码**: ```vue ``` #### 备份文件: `apps/web-antd/src/layouts/auth-original.vue` 保留了原始布局,可随时切换回去。 --- ### 3. 登录插图组件 #### 文件: `packages/effects/layouts/src/authentication/icons/login-illustration.vue` **新建组件**: ```vue ``` #### 文件: `packages/effects/layouts/src/authentication/index.ts` ```typescript export { default as AuthPageLayout } from './authentication.vue'; export { default as LoginIllustration } from './icons/login-illustration.vue'; // ← 新增导出 export * from './types'; ``` #### 静态资源: `apps/web-antd/public/login-illustration.svg` 插图 SVG 文件放置在 public 目录。 --- ### 4. 登录页优化 #### 文件: `apps/web-antd/src/views/_core/authentication/login.vue` **修改内容**: - ✅ 移除内部标题,使用组件默认标题 - ✅ 新增"其他登录方式"分隔线 - ✅ 图标按钮样式统一 - ✅ 手机登录 + 二维码登录(微信已注释) - ✅ 多语言支持 **其他登录方式**: ```vue ``` --- ### 5. 验证码功能修复 #### 文件: `packages/@core/ui-kit/shadcn-ui/src/components/pin-input/input.vue` **问题**: 点击"发送验证码"后立即开始倒计时,即使手机号验证失败。 **修复**: 先验证手机号,成功后才开始倒计时。 ```typescript async function handleSend(e: Event) { try { e?.preventDefault(); // ✅ 先执行验证码发送逻辑(包含手机号验证) await handleSendCode(); // ✅ 只有成功后才开始倒计时 countdown.value = maxTime; startCountdown(); } catch (error) { console.error('Failed to send code:', error); // ✅ 如果发送失败,确保倒计时停止 countdown.value = 0; clearTimeout(timer.value); emit('sendError', error); } } ``` #### 文件: `apps/web-antd/src/views/_core/authentication/forget-password.vue` #### 文件: `apps/web-antd/src/views/_core/authentication/code-login.vue` **修改**: 验证码长度从 4 位改为 6 位。 ```typescript const CODE_LENGTH = 6; // 4 → 6 ``` --- ### 6. 国际化新增 #### 文件: `packages/locales/src/langs/zh-CN/authentication.json` ```json { "otherLoginMethods": "或使用以下方式登录", "contactSupport": "遇到问题?", "support": "联系支持" } ``` #### 文件: `packages/locales/src/langs/en-US/authentication.json` ```json { "otherLoginMethods": "Or sign in with", "contactSupport": "Need help?", "support": "Contact Support" } ``` --- ### 7. Loading 页面优化 #### 文件: `internal/vite-config/src/plugins/inject-app-loading/default-loading.html` **问题**: - Loading 动画颜色先蓝后橙(闪烁) - 标题字体粗细变化 **修复**: ```html ``` **注意**: 修改后需要**重启开发服务器**才能生效! --- ## 📚 相关文档 - [登录布局详细说明](./LOGIN_LAYOUT_README.md) - [项目官方文档](https://doc.vben.pro) - [Vite 文档](https://vitejs.dev) - [Vue 3 文档](https://vuejs.org) - [Ant Design Vue 文档](https://antdv.com) - [Tailwind CSS 文档](https://tailwindcss.com) --- ## 🔍 快速查找 ### 我要修改... | 需求 | 文件位置 | | --- | --- | | **登录页布局** | `apps/web-antd/src/layouts/auth.vue` | | **登录表单** | `apps/web-antd/src/views/_core/authentication/login.vue` | | **验证码登录** | `apps/web-antd/src/views/_core/authentication/code-login.vue` | | **忘记密码** | `apps/web-antd/src/views/_core/authentication/forget-password.vue` | | **主题色** | `packages/@core/preferences/src/constants.ts` | | **Loading 页面** | `internal/vite-config/src/plugins/inject-app-loading/default-loading.html` | | **国际化** | `packages/locales/src/langs/zh-CN/*.json` | | **路由配置** | `apps/web-antd/src/router/routes/` | | **API 接口** | `apps/web-antd/src/api/` | | **全局组件** | `apps/web-antd/src/components/` | | **工具函数** | `apps/web-antd/src/utils/` | | **状态管理** | `apps/web-antd/src/store/` | ### 常见问题 #### Q: 如何切换回原始登录布局? A: 修改路由配置,将 `auth.vue` 改为 `auth-original.vue`。 #### Q: 如何添加新的主题色? A: 参见 [主题定制](#主题定制) 章节。 #### Q: 修改 Loading 页面后不生效? A: 必须重启开发服务器 (`Ctrl+C` 然后 `pnpm dev`)。 #### Q: 如何自定义登录插图? A: 替换 `apps/web-antd/public/login-illustration.svg` 文件。 #### Q: 验证码长度如何修改? A: 修改对应页面的 `CODE_LENGTH` 常量。 ---