This commit is contained in:
2026-02-03 21:35:57 +08:00
parent 93b42a277a
commit 3922409a25
105 changed files with 14758 additions and 5861 deletions

View File

@@ -0,0 +1,761 @@
# Uni-App-X 工程化最佳实践
## 📚 概述
本文档介绍了 mall 项目的工程化实践,包括项目结构、开发流程、构建配置、代码规范等内容,参考 CRMEB 的工程化标准。
---
## 1. 项目结构
### 1.1 推荐目录结构
```
mall/
├── ai/ # AI 相关配置
├── components/
│ ├── analytics/ # 分析组件
│ ├── basic/ # ✨ 基础组件 (新增)
│ │ ├── Button.uvue
│ │ ├── Input.uvue
│ │ ├── Select.uvue
│ │ ├── Checkbox.uvue
│ │ ├── Radio.uvue
│ │ ├── Toggle.uvue
│ │ └── DatePicker.uvue
│ ├── container/ # ✨ 容器组件 (新增)
│ │ ├── Card.uvue
│ │ ├── Modal.uvue
│ │ ├── Drawer.uvue
│ │ ├── Collapse.uvue
│ │ ├── Tabs.uvue
│ │ └── Pagination.uvue
│ ├── data/ # ✨ 数据展示组件 (新增)
│ │ ├── Table.uvue
│ │ ├── List.uvue
│ │ ├── Tree.uvue
│ │ ├── Tag.uvue
│ │ ├── Badge.uvue
│ │ └── Avatar.uvue
│ ├── form/ # ✨ 表单组件 (新增)
│ │ ├── Form.uvue
│ │ ├── FormItem.uvue
│ │ ├── FormGroup.uvue
│ │ ├── Upload.uvue
│ │ └── RichEditor.uvue
│ ├── feedback/ # ✨ 反馈组件 (新增)
│ │ ├── Message.uvue
│ │ ├── Alert.uvue
│ │ ├── Tooltip.uvue
│ │ ├── Loading.uvue
│ │ ├── Empty.uvue
│ │ └── Error.uvue
│ ├── navigation/ # ✨ 导航组件 (新增)
│ │ ├── Breadcrumb.uvue
│ │ ├── Menu.uvue
│ │ ├── Navbar.uvue
│ │ └── Sidebar.uvue
│ ├── supadb/ # 数据库组件
│ └── ...
├── docs/
│ ├── STYLE_SPECIFICATION.md # ✨ 样式规范
│ ├── PAGE_STRUCTURE_SPECIFICATION.md # ✨ 页面结构规范
│ ├── COMPONENT_SPECIFICATION.md # ✨ 组件规范
│ ├── IMPLEMENTATION_ROADMAP.md # ✨ 实现路线图
│ ├── ENGINEERING_BEST_PRACTICES.md # ✨ 工程化最佳实践
│ └── ...
├── layouts/
│ ├── admin/
│ │ ├── AdminLayout.uvue # 增强版
│ │ └── utils/
│ │ ├── menu.uts
│ │ ├── nav.uts
│ │ └── state.uts
│ └── ...
├── pages/
│ ├── templates/ # ✨ 页面模板 (新增)
│ │ ├── ListPage.uvue
│ │ ├── FormPage.uvue
│ │ └── DetailPage.uvue
│ ├── mall/
│ │ ├── admin/
│ │ │ ├── maintain/
│ │ │ │ └── system-info.uvue
│ │ │ └── ...
│ │ └── ...
│ └── ...
├── styles/ # ✨ 全局样式 (优化)
│ ├── common.scss # 通用样式
│ ├── utilities.scss # 工具类
│ └── variables.scss # 变量(引用 uni.scss
├── uni_modules/
│ ├── ak-req/
│ ├── charts/
│ └── ...
├── utils/
│ ├── request.uts # 网络请求
│ ├── store.uts # 状态管理
│ ├── validators.uts # ✨ 验证器工具
│ ├── format.uts # ✨ 格式化工具
│ └── ...
├── uni.scss # ✨ 设计变量系统 (已更新)
├── App.uvue
├── main.js
├── main.uts
├── manifest.json
├── package.json
├── tsconfig.json
├── pages.json
├── platformConfig.json
└── README.md
```
### 1.2 新增目录说明
| 目录 | 用途 | 说明 |
| ------------------------ | -------- | ------------------------------ |
| `components/basic/` | 基础组件 | Button, Input, Select 等 |
| `components/container/` | 容器组件 | Card, Modal, Pagination 等 |
| `components/data/` | 数据展示 | Table, List, Tree 等 |
| `components/form/` | 表单组件 | Form, FormItem, Upload 等 |
| `components/feedback/` | 反馈组件 | Message, Alert, Loading 等 |
| `components/navigation/` | 导航组件 | Breadcrumb, Menu, Navbar 等 |
| `pages/templates/` | 页面模板 | ListPage, FormPage, DetailPage |
| `styles/` | 全局样式 | 共享样式和工具类 |
---
## 2. 开发规范
### 2.1 文件命名规范
| 类型 | 规范 | 示例 |
| -------- | ------------------ | ---------------------------------- |
| 组件文件 | PascalCase | `Button.uvue`, `FormItem.uvue` |
| 业务页面 | kebab-case | `system-info.uvue` |
| 工具脚本 | camelCase + .uts | `validators.uts`, `formatters.uts` |
| 样式文件 | kebab-case + .scss | `common.scss`, `utilities.scss` |
| 配置文件 | camelCase + .uts | `config.uts` |
| 常量文件 | UPPER_SNAKE_CASE | `CONSTANTS.uts` |
### 2.2 导入规范
```typescript
// ✅ 正确用法
// 1. 组件导入
import Button from '@/components/basic/Button.uvue'
import Card from '@/components/container/Card.uvue'
import Table from '@/components/data/Table.uvue'
// 2. 工具导入
import { validateEmail, validatePhone } from '@/utils/validators.uts'
import { formatDate, formatTime } from '@/utils/format.uts'
// 3. 类型导入 (UTS)
import type { MenuConfig } from '@/types/mall-types.uts'
// 4. 样式导入
import '@/styles/common.scss'
// ❌ 错误用法
// 不要使用相对路径
import Button from '../../../components/basic/Button.uvue' // ❌
// 不要混乱地导入
import * from '@/components/basic/Button.uvue' // ❌
// 不要导入 node_modules 中的代码(除非必要)
import { ref } from 'vue' // 这是可以的,但应该在文件顶部
```
### 2.3 TypeScript 规范
虽然使用 UTSUni-App TypeScript但也遵循 TypeScript 最佳实践:
```typescript
// ✅ 正确用法
// 1. 定义类型接口
interface ButtonProps {
type?: "primary" | "default" | "danger";
size?: "sm" | "md" | "lg";
label: string;
disabled?: boolean;
loading?: boolean;
}
// 2. 使用类型标注
const props = withDefaults(defineProps<ButtonProps>(), {
type: "primary",
size: "md",
disabled: false,
loading: false,
});
// 3. 定义事件类型
const emit = defineEmits<{
click: [];
change: [value: string];
submit: [formData: Record<string, any>];
}>();
// 4. 使用类型断言(谨慎)
const element = event.target as HTMLInputElement;
// ❌ 错误用法
// 不要使用 any 类型
const data: any = {
// ❌
name: "test",
};
// 不要忽略类型检查
const props = defineProps({
// ❌ 无类型定义
label: String,
});
// 不要过度使用 as
const value = data as unknown as string as number; // ❌
```
### 2.4 代码注释规范
```typescript
// ✅ 正确用法
/**
* Button 组件
* 支持多种类型、尺寸和状态
*
* @example
* <Button type="primary" label="创建" @click="handleCreate" />
*/
export default {
name: "Button",
// ...
};
// 方法注释
/**
* 处理按钮点击事件
* @param event - 点击事件
* @returns 无返回值
*/
const handleClick = (event: Event) => {
// ...
};
// 复杂逻辑注释
if (loading.value) {
// 加载中时显示加载指示器
return showLoadingIndicator();
}
// ❌ 错误用法
// 不要写无用的注释
const name = ref(""); // 设置 name ❌
// 不要注释掉代码
// const oldWay = () => { ... } ❌
// 不要写过时的注释
// TODO: 这个任务已经完成了 ❌
```
---
## 3. Git 工作流
### 3.1 分支策略
采用 Git Flow 分支模式:
```
main (生产分支)
release/v1.0.0 (发布分支)
develop (开发分支)
feature/component-button (功能分支)
feature/page-list (功能分支)
bugfix/sidebar-display (缺陷分支)
```
### 3.2 分支命名规范
| 分支类型 | 命名规范 | 示例 |
| -------- | ------------------------ | -------------------------- |
| 功能分支 | `feature/<feature-name>` | `feature/component-button` |
| 缺陷分支 | `bugfix/<bug-name>` | `bugfix/sidebar-display` |
| 热修复 | `hotfix/<issue>` | `hotfix/security-issue` |
| 发布分支 | `release/v<version>` | `release/v1.0.0` |
### 3.3 提交消息规范
遵循 Conventional Commits 规范:
```
<type>(<scope>): <subject>
<body>
<footer>
```
#### 类型 (type)
| 类型 | 说明 |
| -------- | ---------------------- |
| feat | 新功能 |
| fix | 缺陷修复 |
| docs | 文档更新 |
| style | 代码格式(不影响功能) |
| refactor | 代码重构 |
| perf | 性能优化 |
| test | 添加测试 |
| chore | 构建/依赖/工具 |
#### 示例
```
feat(components): add Button component with 4 types and 3 sizes
- Support primary, default, danger, success types
- Support sm, md, lg sizes
- Support disabled and loading states
- Add unit tests and documentation
Closes #123, #124
```
### 3.4 代码审查清单
推送 PR 前检查:
- [ ] 代码遵循样式规范
- [ ] 所有变量使用 uni.scss 设计变量
- [ ] 添加了必要的注释
- [ ] 编写了单元测试
- [ ] 文档已更新
- [ ] 无 console.log 和调试代码
- [ ] 无未使用的导入
- [ ] 类型检查无错误
---
## 4. 构建和打包
### 4.1 打包命令
```bash
# 开发模式
npm run dev
# 生产打包
npm run build
# 预览生产构建
npm run preview
# 类型检查
npm run type-check
# 代码格式化
npm run format
# 代码检查
npm run lint
```
### 4.2 环境配置
`.env` 文件中配置:
```env
# .env.development
VITE_API_BASE_URL=http://localhost:3000
VITE_APP_ENV=development
# .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_ENV=production
```
### 4.3 构建优化
#### 代码分割
```typescript
// 路由懒加载
const routes = [
{
path: "/admin/system-info",
component: () => import("@/pages/mall/admin/maintain/system-info.uvue"),
},
];
```
#### 资源优化
```typescript
// 图片优化
const image = 'image.webp' // 使用现代格式
// CSS 优化
// 在 uni.scss 中定义所有常用颜色和尺寸变量
$primary-color: #1890ff
$space-md: 16px
```
---
## 5. 测试规范
### 5.1 单元测试
```typescript
// Button.test.ts
import { describe, it, expect, vi } from "vitest";
import { mount } from "@vue/test-utils";
import Button from "@/components/basic/Button.uvue";
describe("Button Component", () => {
it("renders button with label", () => {
const wrapper = mount(Button, {
props: { label: "Click me" },
});
expect(wrapper.text()).toBe("Click me");
});
it("emits click event when clicked", async () => {
const wrapper = mount(Button, {
props: { label: "Click" },
});
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("click")).toBeTruthy();
});
it("disables button when disabled prop is true", () => {
const wrapper = mount(Button, {
props: { label: "Click", disabled: true },
});
expect(wrapper.find("button").attributes("disabled")).toBeDefined();
});
it("applies correct class based on type prop", () => {
const wrapper = mount(Button, {
props: { label: "Click", type: "danger" },
});
expect(wrapper.find("button").classes()).toContain("btn-danger");
});
});
```
### 5.2 测试覆盖率目标
| 类型 | 目标 |
| -------- | ----- |
| 语句覆盖 | ≥ 80% |
| 分支覆盖 | ≥ 75% |
| 函数覆盖 | ≥ 80% |
| 行覆盖 | ≥ 80% |
### 5.3 测试运行命令
```bash
# 运行所有测试
npm run test
# 运行特定文件的测试
npm run test Button
# 生成覆盖率报告
npm run test:coverage
# 监视模式
npm run test:watch
```
---
## 6. 性能优化
### 6.1 加载性能目标
| 指标 | 目标 | 当前 |
| ------------------ | ------ | ---- |
| FCP (首次内容绘制) | < 1.5s | TBD |
| LCP (最大内容绘制) | < 2.5s | TBD |
| CLS (累积布局偏移) | < 0.1 | TBD |
| TTI (可交互时间) | < 3s | TBD |
### 6.2 优化技巧
```typescript
// 1. 虚拟滚动(大列表)
<virtual-scroller :items="largeList" :item-height="50">
<template #default="{ item }">
<div>{{ item }}</div>
</template>
</virtual-scroller>
// 2. 图片懒加载
<img v-lazy="imageUrl" />
// 3. 路由懒加载
const routes = [
{
path: '/admin',
component: () => import('@/layouts/admin/AdminLayout.uvue'),
},
]
// 4. 代码分割
const Table = defineAsyncComponent(() =>
import('@/components/data/Table.uvue')
)
// 5. 防抖和节流
import { debounce, throttle } from 'lodash-es'
const handleSearch = debounce(() => {
// 搜索逻辑
}, 300)
```
---
## 7. 监测和日志
### 7.1 日志记录
```typescript
// 使用结构化日志
import { logger } from "@/utils/logger.uts";
// 不同级别
logger.debug("调试信息"); // 开发使用
logger.info("信息"); // 正常操作
logger.warn("警告"); // 可能的问题
logger.error("错误"); // 出现问题
```
### 7.2 错误跟踪
```typescript
// 全局错误处理
app.config.errorHandler = (err, instance, info) => {
logger.error("应用错误:", err);
// 发送到错误追踪服务
trackError(err);
};
// 未捕获的 Promise 拒绝
window.addEventListener("unhandledrejection", (event) => {
logger.error("未处理的 Promise 拒绝:", event.reason);
});
```
### 7.3 性能监测
```typescript
// 性能标记
performance.mark("page-load-start");
// ... 页面加载逻辑 ...
performance.mark("page-load-end");
performance.measure("page-load", "page-load-start", "page-load-end");
const measure = performance.getEntriesByName("page-load")[0];
logger.info(`页面加载时间: ${measure.duration}ms`);
```
---
## 8. 依赖管理
### 8.1 package.json 脚本
```json
{
"scripts": {
"dev": "uni dev:h5",
"build": "uni build:h5",
"preview": "vite preview",
"type-check": "tsc --noEmit",
"format": "prettier --write .",
"lint": "eslint . --ext .vue,.ts,.uts",
"test": "vitest",
"test:coverage": "vitest --coverage"
}
}
```
### 8.2 依赖最小化
- 避免重复的依赖
- 定期更新依赖
- 移除未使用的依赖
- 选择轻量级替代品
```bash
# 检查未使用的依赖
npm ls --depth=0
# 检查过时的依赖
npm outdated
```
---
## 9. 文档维护
### 9.1 文档位置
所有文档都放在 `docs/` 目录:
```
docs/
├── STYLE_SPECIFICATION.md
├── PAGE_STRUCTURE_SPECIFICATION.md
├── COMPONENT_SPECIFICATION.md
├── IMPLEMENTATION_ROADMAP.md
├── ENGINEERING_BEST_PRACTICES.md
└── README.md
```
### 9.2 文档更新频率
| 文档 | 更新频率 | 维护者 |
| -------------- | -------- | ---------- |
| 样式规范 | 半年 | 设计团队 |
| 页面结构规范 | 每月 | 前端团队 |
| 组件规范 | 每月 | 前端团队 |
| 实现路线图 | 每周 | 项目经理 |
| 工程化最佳实践 | 按需 | 技术负责人 |
### 9.3 README 模板
每个模块都应有 README.md
```markdown
# Module Name
## 描述
简明扼要的模块描述
## 结构
```
module/
├── Component.uvue
├── types.uts
└── utils.uts
```
## 使用方法
代码示例
## 贡献指南
如何贡献
## 许可证
MIT
```
---
## 10. 发布流程
### 10.1 版本管理
使用语义化版本 (Semantic Versioning):
```
MAJOR.MINOR.PATCH
v1.2.3
```
- **MAJOR**: 不兼容的改动
- **MINOR**: 新增功能(向后兼容)
- **PATCH**: 缺陷修复
### 10.2 发布检查清单
在发布新版本前:
- [ ] 所有测试通过
- [ ] 文档更新
- [ ] CHANGELOG 更新
- [ ] 版本号更新 (package.json)
- [ ] Git 标签创建
- [ ] 构建成功
- [ ] 性能检测通过
- [ ] 安全审计通过
### 10.3 CHANGELOG 格式
```markdown
# Changelog
## [1.2.0] - 2026-02-28
### Added
- 新增 Button 组件
- 新增 Input 组件
- 新增表单验证器
### Changed
- 更新设计变量系统
- 改进性能40% 更快)
### Fixed
- 修复 Modal 动画闪烁问题
- 修复移动端布局问题
### Deprecated
- 弃用旧的 Button 样式
### Security
- 修复 XSS 漏洞
```
---
## 📝 总结
**工程化核心原则**:
1. **代码一致性** - 遵循命名和格式规范
2. **自动化** - 使用脚本和工具自动化重复任务
3. **可维护性** - 清晰的代码和充分的文档
4. **可测试性** - 编写可测试的代码
5. **性能** - 不断监测和优化
**禁止做法**:
- 不要不遵循 Git 工作流
- 不要提交到 main 分支(使用 PR
- 不要忽视代码审查
- 不要发布前没有测试
- 不要创建无文档的代码
---
**文档版本**: 1.0
**最后更新**: 2026-01-31
**维护者**: AI Assistant