## Dify 閮ㄧ讲瀹屾垚 鉁? ### 瀹屾垚鐨勫伐浣?1. Docker 闀滃儚鍔犻€熷櫒閰嶇疆 - 閰嶇疆 5 涓浗鍐呴暅鍍忔簮 - 澶у箙鎻愬崌涓嬭浇閫熷害鍜屾垚鍔熺巼 2. Dify 闀滃儚鎷夊彇 (鍏?11 涓湇鍔? - langgenius/dify-api:1.9.1 - langgenius/dify-web:1.9.1 - postgres, redis, weaviate, nginx 绛? - 鎬诲ぇ灏忕害 2GB锛岃€楁椂绾?15 鍒嗛挓 3. Dify 鏈嶅姟鍚姩 - 鉁?nginx (80/443) - 鉁?api, worker, worker_beat - 鉁?web (3000) - 鉁?db (PostgreSQL), redis - 鉁?weaviate (鍚戦噺鏁版嵁搴? - 鉁?sandbox, plugin_daemon, ssrf_proxy 4. Dify 鍒濆鍖栭厤缃? - 鍒涘缓绠$悊鍛樿处鍙? - 鍒涘缓搴旂敤: AI Clinical Research - 鑾峰彇 API Key: app-VZRn0vMXdmltEJkvatHVGv5j 5. 鍚庣鐜閰嶇疆 - DIFY_API_URL=http://localhost/v1 - DIFY_API_KEY 宸查厤缃? ### 鏂囨。鏇存柊 - 鏂板: docs/05-姣忔棩杩涘害/Day18-Dify閮ㄧ讲瀹屾垚.md - 鏇存柊: docs/04-寮€鍙戣鍒?寮€鍙戦噷绋嬬.md (Day 18 鏍囪涓哄畬鎴? ### 涓嬩竴姝?Day 19-24: 鐭ヨ瘑搴撶郴缁熷紑鍙?- Dify 瀹㈡埛绔皝瑁?- 鐭ヨ瘑搴撶鐞?CRUD - 鏂囨。涓婁紶涓庡鐞?- @鐭ヨ瘑搴撻泦鎴?- RAG 闂瓟楠岃瘉 --- Progress: 閲岀▼纰?1 (MVP) 85% -> 鐭ヨ瘑搴撶郴缁熷紑鍙戜腑
817 lines
17 KiB
Markdown
817 lines
17 KiB
Markdown
# 代码规范
|
||
|
||
> **版本:** v1.0
|
||
> **创建日期:** 2025-10-10
|
||
> **适用范围:** 前端(React/TypeScript)+ 后端(Node.js/TypeScript)
|
||
|
||
---
|
||
|
||
## 📋 目录
|
||
|
||
1. [通用规范](#通用规范)
|
||
2. [TypeScript规范](#typescript规范)
|
||
3. [React规范](#react规范)
|
||
4. [Node.js后端规范](#nodejs后端规范)
|
||
5. [命名规范](#命名规范)
|
||
6. [注释规范](#注释规范)
|
||
7. [Git提交规范](#git提交规范)
|
||
|
||
---
|
||
|
||
## 通用规范
|
||
|
||
### 代码风格
|
||
- ✅ 使用ESLint和Prettier统一代码风格
|
||
- ✅ 缩进:2个空格
|
||
- ✅ 字符串:优先使用单引号 `'`
|
||
- ✅ 行尾:不加分号(除非必要)
|
||
- ✅ 单行最大长度:100字符
|
||
- ✅ 使用尾随逗号(对象、数组)
|
||
|
||
### 文件组织
|
||
- ✅ 一个文件一个组件/类
|
||
- ✅ 相关文件放在同一目录
|
||
- ✅ 使用barrel exports(index.ts)
|
||
- ✅ 测试文件与源文件同目录
|
||
|
||
```
|
||
src/
|
||
├── components/
|
||
│ ├── Button/
|
||
│ │ ├── Button.tsx
|
||
│ │ ├── Button.test.tsx
|
||
│ │ ├── Button.styles.ts
|
||
│ │ └── index.ts # export { Button } from './Button'
|
||
```
|
||
|
||
### 代码注释
|
||
- ✅ 复杂逻辑必须注释
|
||
- ✅ 公共API必须注释
|
||
- ✅ 避免无用注释
|
||
- ✅ 使用JSDoc格式
|
||
|
||
---
|
||
|
||
## TypeScript规范
|
||
|
||
### 类型定义
|
||
|
||
**✅ 推荐:**
|
||
```typescript
|
||
// 使用interface定义对象结构
|
||
interface User {
|
||
id: string
|
||
email: string
|
||
name?: string
|
||
}
|
||
|
||
// 使用type定义联合类型
|
||
type Status = 'active' | 'inactive' | 'suspended'
|
||
|
||
// 使用enum定义常量集合
|
||
enum UserRole {
|
||
USER = 'user',
|
||
ADMIN = 'admin',
|
||
}
|
||
```
|
||
|
||
**❌ 避免:**
|
||
```typescript
|
||
// 不要使用any
|
||
function process(data: any) { // ❌
|
||
// ...
|
||
}
|
||
|
||
// 应该明确类型
|
||
function process(data: ProcessData) { // ✅
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### 类型导入导出
|
||
|
||
```typescript
|
||
// types.ts
|
||
export interface Project {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
}
|
||
|
||
export type ProjectStatus = 'active' | 'archived'
|
||
|
||
// project.service.ts
|
||
import type { Project, ProjectStatus } from './types'
|
||
```
|
||
|
||
### 严格模式
|
||
```json
|
||
// tsconfig.json
|
||
{
|
||
"compilerOptions": {
|
||
"strict": true,
|
||
"noImplicitAny": true,
|
||
"strictNullChecks": true,
|
||
"strictFunctionTypes": true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## React规范
|
||
|
||
### 组件定义
|
||
|
||
**✅ 推荐:函数组件 + Hooks**
|
||
```tsx
|
||
import { useState } from 'react'
|
||
|
||
interface ButtonProps {
|
||
label: string
|
||
onClick: () => void
|
||
variant?: 'primary' | 'secondary'
|
||
disabled?: boolean
|
||
}
|
||
|
||
export function Button({
|
||
label,
|
||
onClick,
|
||
variant = 'primary',
|
||
disabled = false
|
||
}: ButtonProps) {
|
||
const [isLoading, setIsLoading] = useState(false)
|
||
|
||
const handleClick = async () => {
|
||
setIsLoading(true)
|
||
try {
|
||
await onClick()
|
||
} finally {
|
||
setIsLoading(false)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<button
|
||
onClick={handleClick}
|
||
disabled={disabled || isLoading}
|
||
className={`btn btn-${variant}`}
|
||
>
|
||
{isLoading ? 'Loading...' : label}
|
||
</button>
|
||
)
|
||
}
|
||
```
|
||
|
||
**❌ 避免:类组件**
|
||
```tsx
|
||
// 除非有特殊需求,否则不使用类组件
|
||
class Button extends React.Component { ... } // ❌
|
||
```
|
||
|
||
### Hooks规范
|
||
|
||
**✅ 推荐:自定义Hooks**
|
||
```typescript
|
||
// useProjects.ts
|
||
import { useState, useEffect } from 'react'
|
||
import { projectService } from '@/services'
|
||
import type { Project } from '@/types'
|
||
|
||
export function useProjects() {
|
||
const [projects, setProjects] = useState<Project[]>([])
|
||
const [loading, setLoading] = useState(false)
|
||
const [error, setError] = useState<Error | null>(null)
|
||
|
||
useEffect(() => {
|
||
loadProjects()
|
||
}, [])
|
||
|
||
const loadProjects = async () => {
|
||
setLoading(true)
|
||
setError(null)
|
||
try {
|
||
const data = await projectService.getProjects()
|
||
setProjects(data)
|
||
} catch (err) {
|
||
setError(err as Error)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
return { projects, loading, error, reload: loadProjects }
|
||
}
|
||
|
||
// 使用
|
||
function ProjectList() {
|
||
const { projects, loading, error } = useProjects()
|
||
|
||
if (loading) return <Loading />
|
||
if (error) return <Error message={error.message} />
|
||
|
||
return (
|
||
<ul>
|
||
{projects.map(project => (
|
||
<li key={project.id}>{project.name}</li>
|
||
))}
|
||
</ul>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 组件组织
|
||
|
||
```tsx
|
||
// ✅ 推荐的组件结构
|
||
import { useState, useEffect, useMemo, useCallback } from 'react'
|
||
import { useNavigate } from 'react-router-dom'
|
||
import { SomeComponent } from '@/components'
|
||
import { useCustomHook } from '@/hooks'
|
||
import type { SomeType } from '@/types'
|
||
|
||
interface ComponentProps {
|
||
// props定义
|
||
}
|
||
|
||
export function Component({ prop1, prop2 }: ComponentProps) {
|
||
// 1. Hooks
|
||
const navigate = useNavigate()
|
||
const [state, setState] = useState()
|
||
const { data } = useCustomHook()
|
||
|
||
// 2. 派生状态(useMemo)
|
||
const computedValue = useMemo(() => {
|
||
return heavyComputation(data)
|
||
}, [data])
|
||
|
||
// 3. 事件处理(useCallback)
|
||
const handleClick = useCallback(() => {
|
||
// 处理逻辑
|
||
}, [])
|
||
|
||
// 4. Effects
|
||
useEffect(() => {
|
||
// 副作用
|
||
}, [])
|
||
|
||
// 5. 早期返回(Loading/Error)
|
||
if (!data) return <Loading />
|
||
|
||
// 6. 渲染
|
||
return (
|
||
<div>
|
||
{/* JSX */}
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 条件渲染
|
||
|
||
**✅ 推荐:**
|
||
```tsx
|
||
// 简单条件:使用 &&
|
||
{isLoggedIn && <UserMenu />}
|
||
|
||
// if-else:使用三元运算符
|
||
{isLoggedIn ? <UserMenu /> : <LoginButton />}
|
||
|
||
// 多条件:提取为函数或组件
|
||
function renderContent() {
|
||
if (loading) return <Loading />
|
||
if (error) return <Error />
|
||
if (data.length === 0) return <Empty />
|
||
return <DataList data={data} />
|
||
}
|
||
|
||
return <div>{renderContent()}</div>
|
||
```
|
||
|
||
**❌ 避免:**
|
||
```tsx
|
||
// 避免复杂的嵌套三元运算符
|
||
{condition1 ? (
|
||
condition2 ? <A /> : <B />
|
||
) : (
|
||
condition3 ? <C /> : <D />
|
||
)} // ❌ 难以理解
|
||
```
|
||
|
||
---
|
||
|
||
## Node.js后端规范
|
||
|
||
### 文件组织
|
||
|
||
```
|
||
backend/src/
|
||
├── routes/ # 路由定义
|
||
│ ├── auth.routes.ts
|
||
│ └── project.routes.ts
|
||
├── services/ # 业务逻辑
|
||
│ ├── auth.service.ts
|
||
│ └── project.service.ts
|
||
├── controllers/ # 控制器(可选)
|
||
├── models/ # Prisma模型
|
||
├── utils/ # 工具函数
|
||
├── config/ # 配置加载
|
||
├── types/ # 类型定义
|
||
└── server.ts # 入口文件
|
||
```
|
||
|
||
### 路由定义
|
||
|
||
```typescript
|
||
// routes/project.routes.ts
|
||
import { FastifyInstance } from 'fastify'
|
||
import { projectService } from '../services/project.service'
|
||
import { authMiddleware } from '../middleware/auth'
|
||
|
||
export async function projectRoutes(server: FastifyInstance) {
|
||
// 获取项目列表
|
||
server.get(
|
||
'/api/v1/projects',
|
||
{
|
||
preHandler: [authMiddleware],
|
||
schema: {
|
||
querystring: {
|
||
type: 'object',
|
||
properties: {
|
||
page: { type: 'number' },
|
||
pageSize: { type: 'number' },
|
||
},
|
||
},
|
||
},
|
||
},
|
||
async (request, reply) => {
|
||
const { page = 1, pageSize = 20 } = request.query as any
|
||
const userId = request.user.id
|
||
|
||
const result = await projectService.getProjects(userId, {
|
||
page,
|
||
pageSize,
|
||
})
|
||
|
||
return reply.send({
|
||
success: true,
|
||
data: result,
|
||
})
|
||
}
|
||
)
|
||
|
||
// 创建项目
|
||
server.post(
|
||
'/api/v1/projects',
|
||
{
|
||
preHandler: [authMiddleware],
|
||
schema: {
|
||
body: {
|
||
type: 'object',
|
||
required: ['name', 'description'],
|
||
properties: {
|
||
name: { type: 'string', minLength: 1, maxLength: 200 },
|
||
description: { type: 'string', minLength: 1 },
|
||
},
|
||
},
|
||
},
|
||
},
|
||
async (request, reply) => {
|
||
const userId = request.user.id
|
||
const data = request.body as CreateProjectDto
|
||
|
||
const project = await projectService.createProject(userId, data)
|
||
|
||
return reply.code(201).send({
|
||
success: true,
|
||
data: project,
|
||
})
|
||
}
|
||
)
|
||
}
|
||
```
|
||
|
||
### Service层
|
||
|
||
```typescript
|
||
// services/project.service.ts
|
||
import { prisma } from '../lib/prisma'
|
||
import type { CreateProjectDto, UpdateProjectDto } from '../types'
|
||
|
||
export class ProjectService {
|
||
/**
|
||
* 获取用户的项目列表
|
||
*/
|
||
async getProjects(userId: string, options: PaginationOptions) {
|
||
const { page, pageSize } = options
|
||
|
||
const [items, total] = await Promise.all([
|
||
prisma.project.findMany({
|
||
where: { userId },
|
||
skip: (page - 1) * pageSize,
|
||
take: pageSize,
|
||
orderBy: { createdAt: 'desc' },
|
||
}),
|
||
prisma.project.count({ where: { userId } }),
|
||
])
|
||
|
||
return {
|
||
items,
|
||
pagination: {
|
||
page,
|
||
pageSize,
|
||
total,
|
||
totalPages: Math.ceil(total / pageSize),
|
||
hasNext: page * pageSize < total,
|
||
hasPrev: page > 1,
|
||
},
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建项目
|
||
*/
|
||
async createProject(userId: string, data: CreateProjectDto) {
|
||
return prisma.project.create({
|
||
data: {
|
||
userId,
|
||
name: data.name,
|
||
description: data.description,
|
||
},
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 更新项目
|
||
*/
|
||
async updateProject(
|
||
userId: string,
|
||
projectId: string,
|
||
data: UpdateProjectDto
|
||
) {
|
||
// 验证权限
|
||
const project = await prisma.project.findFirst({
|
||
where: { id: projectId, userId },
|
||
})
|
||
|
||
if (!project) {
|
||
throw new Error('Project not found or unauthorized')
|
||
}
|
||
|
||
return prisma.project.update({
|
||
where: { id: projectId },
|
||
data,
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 删除项目
|
||
*/
|
||
async deleteProject(userId: string, projectId: string) {
|
||
// 验证权限
|
||
const project = await prisma.project.findFirst({
|
||
where: { id: projectId, userId },
|
||
})
|
||
|
||
if (!project) {
|
||
throw new Error('Project not found or unauthorized')
|
||
}
|
||
|
||
await prisma.project.delete({
|
||
where: { id: projectId },
|
||
})
|
||
}
|
||
}
|
||
|
||
export const projectService = new ProjectService()
|
||
```
|
||
|
||
### 错误处理
|
||
|
||
```typescript
|
||
// utils/errors.ts
|
||
export class AppError extends Error {
|
||
constructor(
|
||
public code: string,
|
||
public message: string,
|
||
public statusCode: number = 400,
|
||
public details?: any
|
||
) {
|
||
super(message)
|
||
this.name = 'AppError'
|
||
}
|
||
}
|
||
|
||
export class ValidationError extends AppError {
|
||
constructor(message: string, details?: any) {
|
||
super('VALIDATION_ERROR', message, 422, details)
|
||
}
|
||
}
|
||
|
||
export class UnauthorizedError extends AppError {
|
||
constructor(message: string = 'Unauthorized') {
|
||
super('UNAUTHORIZED', message, 401)
|
||
}
|
||
}
|
||
|
||
export class NotFoundError extends AppError {
|
||
constructor(resource: string) {
|
||
super('NOT_FOUND', `${resource} not found`, 404)
|
||
}
|
||
}
|
||
|
||
// 使用
|
||
async function getProject(id: string) {
|
||
const project = await prisma.project.findUnique({ where: { id } })
|
||
|
||
if (!project) {
|
||
throw new NotFoundError('Project')
|
||
}
|
||
|
||
return project
|
||
}
|
||
```
|
||
|
||
### 错误处理中间件
|
||
|
||
```typescript
|
||
// middleware/error-handler.ts
|
||
import { FastifyError, FastifyReply, FastifyRequest } from 'fastify'
|
||
import { AppError } from '../utils/errors'
|
||
|
||
export async function errorHandler(
|
||
error: FastifyError | AppError,
|
||
request: FastifyRequest,
|
||
reply: FastifyReply
|
||
) {
|
||
// 记录错误
|
||
request.log.error(error)
|
||
|
||
// 自定义错误
|
||
if (error instanceof AppError) {
|
||
return reply.code(error.statusCode).send({
|
||
success: false,
|
||
error: {
|
||
code: error.code,
|
||
message: error.message,
|
||
details: error.details,
|
||
},
|
||
timestamp: new Date().toISOString(),
|
||
})
|
||
}
|
||
|
||
// Prisma错误
|
||
if (error.name === 'PrismaClientKnownRequestError') {
|
||
// 处理Prisma特定错误
|
||
return reply.code(400).send({
|
||
success: false,
|
||
error: {
|
||
code: 'DATABASE_ERROR',
|
||
message: 'Database operation failed',
|
||
},
|
||
timestamp: new Date().toISOString(),
|
||
})
|
||
}
|
||
|
||
// 默认错误
|
||
return reply.code(500).send({
|
||
success: false,
|
||
error: {
|
||
code: 'INTERNAL_ERROR',
|
||
message: 'Internal server error',
|
||
},
|
||
timestamp: new Date().toISOString(),
|
||
})
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 命名规范
|
||
|
||
### 文件命名
|
||
|
||
| 类型 | 命名方式 | 示例 |
|
||
|------|---------|------|
|
||
| React组件 | PascalCase | `Button.tsx`, `ProjectList.tsx` |
|
||
| Hooks | camelCase + use前缀 | `useProjects.ts`, `useAuth.ts` |
|
||
| 工具函数 | camelCase | `formatDate.ts`, `api.ts` |
|
||
| 类型定义 | camelCase + .types | `user.types.ts`, `api.types.ts` |
|
||
| 常量 | camelCase + .constants | `routes.constants.ts` |
|
||
| 测试文件 | 同源文件 + .test | `Button.test.tsx` |
|
||
|
||
### 变量命名
|
||
|
||
```typescript
|
||
// ✅ 推荐
|
||
const userName = 'John' // camelCase
|
||
const USER_ROLE = 'admin' // 常量用UPPER_SNAKE_CASE
|
||
const isLoading = false // 布尔值用is/has/can前缀
|
||
const hasPermission = true
|
||
const canEdit = false
|
||
|
||
// ❌ 避免
|
||
const user_name = 'John' // 不用snake_case
|
||
const loading = false // 布尔值缺少is前缀
|
||
const x = 10 // 无意义的变量名
|
||
```
|
||
|
||
### 函数命名
|
||
|
||
```typescript
|
||
// ✅ 推荐
|
||
function getUser() { } // get: 获取数据
|
||
function fetchProjects() { } // fetch: 异步获取
|
||
function createProject() { } // create: 创建
|
||
function updateProject() { } // update: 更新
|
||
function deleteProject() { } // delete: 删除
|
||
function handleClick() { } // handle: 事件处理
|
||
function validateEmail() { } // validate: 验证
|
||
function formatDate() { } // format: 格式化
|
||
|
||
// ❌ 避免
|
||
function data() { } // 不清楚功能
|
||
function doSomething() { } // 太模糊
|
||
function process() { } // 不明确
|
||
```
|
||
|
||
### 组件命名
|
||
|
||
```typescript
|
||
// ✅ 推荐
|
||
<Button /> // 基础组件
|
||
<UserProfile /> // 业务组件
|
||
<ProjectList /> // 列表组件
|
||
<CreateProjectModal /> // 弹窗组件
|
||
|
||
// ❌ 避免
|
||
<button /> // 不用小写
|
||
<user_profile /> // 不用snake_case
|
||
<ListProjects /> // 动词不要在前
|
||
```
|
||
|
||
---
|
||
|
||
## 注释规范
|
||
|
||
### JSDoc注释
|
||
|
||
```typescript
|
||
/**
|
||
* 创建新项目
|
||
* @param userId - 用户ID
|
||
* @param data - 项目数据
|
||
* @returns 创建的项目对象
|
||
* @throws {ValidationError} 当数据验证失败时
|
||
*/
|
||
async function createProject(
|
||
userId: string,
|
||
data: CreateProjectDto
|
||
): Promise<Project> {
|
||
// 实现...
|
||
}
|
||
```
|
||
|
||
### 代码注释
|
||
|
||
```typescript
|
||
// ✅ 好的注释:解释为什么
|
||
// 使用setTimeout避免阻塞UI渲染
|
||
setTimeout(() => {
|
||
processLargeData()
|
||
}, 0)
|
||
|
||
// 等待Dify处理文档,最多重试10次
|
||
for (let i = 0; i < 10; i++) {
|
||
const status = await checkStatus()
|
||
if (status === 'completed') break
|
||
await sleep(2000)
|
||
}
|
||
|
||
// ❌ 坏的注释:重复代码
|
||
// 设置loading为true
|
||
setLoading(true)
|
||
|
||
// 调用API
|
||
await api.getData()
|
||
```
|
||
|
||
---
|
||
|
||
## Git提交规范
|
||
|
||
### Commit Message格式
|
||
|
||
```
|
||
<type>(<scope>): <subject>
|
||
|
||
<body>
|
||
|
||
<footer>
|
||
```
|
||
|
||
### Type类型
|
||
|
||
| 类型 | 说明 |
|
||
|------|------|
|
||
| feat | 新功能 |
|
||
| fix | Bug修复 |
|
||
| docs | 文档更新 |
|
||
| style | 代码格式(不影响功能) |
|
||
| refactor | 重构 |
|
||
| perf | 性能优化 |
|
||
| test | 测试相关 |
|
||
| chore | 构建/工具变动 |
|
||
|
||
### 示例
|
||
|
||
```bash
|
||
# 好的提交
|
||
git commit -m "feat(auth): 实现用户登录功能"
|
||
git commit -m "fix(project): 修复项目删除权限问题"
|
||
git commit -m "docs(api): 更新API文档"
|
||
git commit -m "refactor(chat): 优化消息组件结构"
|
||
|
||
# 不好的提交
|
||
git commit -m "update" # ❌ 太模糊
|
||
git commit -m "fix bug" # ❌ 没有说明是什么bug
|
||
git commit -m "完成功能" # ❌ 没有说明是什么功能
|
||
```
|
||
|
||
---
|
||
|
||
## ESLint配置
|
||
|
||
```javascript
|
||
// .eslintrc.js
|
||
module.exports = {
|
||
extends: [
|
||
'eslint:recommended',
|
||
'plugin:@typescript-eslint/recommended',
|
||
'plugin:react/recommended',
|
||
'plugin:react-hooks/recommended',
|
||
'prettier',
|
||
],
|
||
rules: {
|
||
'@typescript-eslint/no-explicit-any': 'error',
|
||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||
'react/react-in-jsx-scope': 'off',
|
||
'react/prop-types': 'off',
|
||
},
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Prettier配置
|
||
|
||
```json
|
||
{
|
||
"semi": false,
|
||
"singleQuote": true,
|
||
"tabWidth": 2,
|
||
"trailingComma": "es5",
|
||
"printWidth": 100,
|
||
"arrowParens": "avoid"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 代码Review检查清单
|
||
|
||
### 功能
|
||
- [ ] 功能是否完整实现
|
||
- [ ] 是否有遗漏的边界情况
|
||
- [ ] 错误处理是否完善
|
||
|
||
### 代码质量
|
||
- [ ] 代码是否易读易理解
|
||
- [ ] 是否有重复代码
|
||
- [ ] 函数是否过长(建议<50行)
|
||
- [ ] 是否遵守命名规范
|
||
|
||
### 性能
|
||
- [ ] 是否有性能问题
|
||
- [ ] 是否有不必要的重渲染
|
||
- [ ] 数据库查询是否优化
|
||
|
||
### 安全
|
||
- [ ] 是否有SQL注入风险
|
||
- [ ] 是否有XSS风险
|
||
- [ ] 权限验证是否完善
|
||
|
||
### 测试
|
||
- [ ] 是否有单元测试
|
||
- [ ] 测试覆盖率是否足够
|
||
|
||
---
|
||
|
||
**文档维护:** 规范更新需同步此文档
|
||
**最后更新:** 2025-10-10
|
||
**维护者:** 技术负责人
|
||
|
||
|
||
|