# 开发规范

本文档规范 DarkM 项目的完整开发流程,包括 Git 工作流、代码审查、测试、版本管理、部署等所有开发相关事项。


# 📋 完整开发流程

# 标准开发流程

graph TD
    A[需求分析] --> B[任务拆分]
    B --> C[创建 Git 分支]
    C --> D[本地开发]
    D --> E[单元测试]
    E --> F[提交代码]
    F --> G[推送到远程]
    G --> H[创建 Merge Request]
    H --> I[CI 自动检查]
    I --> J[代码审查]
    J --> K{审查通过?}
    K -->|否 | L[修改反馈]
    L --> J
    K -->|是 | M[合并到 develop]
    M --> N[部署测试环境]
    N --> O[功能测试]
    O --> P[创建 Release 分支]
    P --> Q[回归测试]
    Q --> R[合并到 master]
    R --> S[打版本标签]
    S --> T[部署生产环境]
    T --> U[监控验证]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 各阶段详细说明

# 1. 需求分析(1-2 天)

输入: 产品需求文档(PRD)

输出:

  • 技术方案设计
  • 任务拆分清单
  • 工作量评估

参与人员: 产品经理、技术负责人、开发人员

检查清单:

  • [ ] 需求理解一致
  • [ ] 技术可行性确认
  • [ ] 依赖关系明确
  • [ ] 风险评估完成

# 2. 任务拆分(0.5 天)

用户故事格式:

作为 [角色]
我想要 [功能]
以便于 [价值]

验收标准:
1. [标准 1]
2. [标准 2]
3. [标准 3]
1
2
3
4
5
6
7
8

示例:

作为 系统管理员
我想要 批量导入用户功能
以便于 快速初始化用户数据

验收标准:
1. 支持 Excel 格式导入
2. 单次最多导入 1000 条
3. 导入失败显示详细错误信息
4. 导入完成发送通知
1
2
3
4
5
6
7
8
9

任务拆分原则:

  • 每个任务不超过 3 天工作量
  • 任务可独立测试
  • 任务之间有明确依赖关系

# 3. 开发实现(根据任务复杂度)

每日工作流:

# 早上开始工作
git checkout develop
git pull origin develop
git checkout feature/your-feature
git rebase develop  # 保持分支最新

# 开发过程中
git add .
git commit -m "feat: 完成 XXX 功能"

# 下班前
git push origin feature/your-feature
1
2
3
4
5
6
7
8
9
10
11
12

# 4. 代码审查(0.5-1 天)

审查要点:

  • 代码质量
  • 功能正确性
  • 性能影响
  • 安全性
  • 测试覆盖

# 5. 测试验证(1-2 天)

测试类型:

  • 单元测试(开发人员)
  • 集成测试(开发人员)
  • 功能测试(测试人员)
  • 回归测试(测试人员)

# 6. 部署上线(0.5 天)

部署检查:

  • 预发布环境验证
  • 生产环境部署
  • 线上功能验证
  • 监控告警配置

# 🌿 Git 工作流详解

# 分支模型

采用 Git Flow 工作流,结合 DarkM 项目特点:

master (生产环境)
  ↑
release/v* (发布分支)
  ↑
develop (开发主线)
  ↑
  ├── feature/* (功能开发)
  ├── bugfix/* (Bug 修复)
  └── hotfix/* (紧急修复)
1
2
3
4
5
6
7
8
9

# 分支详细说明

# master 分支(生产分支)

属性 说明
用途 生产环境代码,随时可发布
来源 从 develop 分支合并
保护 禁止直接提交,必须通过 MR 合并
生命周期 永久
命名 master

操作示例:

# 查看 master 分支
git checkout master
git pull origin master

# 查看版本标签
git tag -l
1
2
3
4
5
6

# develop 分支(开发分支)

属性 说明
用途 日常开发集成分支
来源 从 master 分支创建(初始)
保护 禁止直接提交,必须通过 MR 合并
生命周期 永久
命名 develop

操作示例:

# 基于 develop 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-management
1
2
3
4

# feature 分支(功能分支)

属性 说明
用途 新功能开发
来源 develop 分支
合并目标 develop 分支
生命周期 功能完成后删除
命名 feature/<功能描述>

命名示例:

feature/user-management      # 用户管理功能
feature/order-export         # 订单导出功能
feature/payment-integration  # 支付集成
1
2
3

完整操作流程:

# 1. 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-management

# 2. 开发过程中提交
git add src/
git commit -m "feat(user): 添加用户列表查询"

git add src/
git commit -m "feat(user): 实现用户新增功能"

git add src/
git commit -m "feat(user): 实现用户编辑功能"

# 3. 推送到远程
git push -u origin feature/user-management

# 4. 功能开发完成,创建 MR 合并到 develop
# 在 GitLab/GitHub 上创建 Merge Request

# 5. 合并后删除分支
git checkout develop
git pull origin develop
git branch -d feature/user-management
git push origin --delete feature/user-management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# bugfix 分支(Bug 修复分支)

属性 说明
用途 测试阶段发现的 Bug 修复
来源 develop 分支
合并目标 develop 分支
生命周期 Bug 修复后删除
命名 bugfix/<Bug 描述>

操作示例:

# 创建 Bug 修复分支
git checkout -b bugfix/login-error develop

# 修复 Bug
# ... 修改代码 ...

git add .
git commit -m "fix(auth): 修复登录页面样式错误"

git push -u origin bugfix/login-error

# 创建 MR 合并到 develop
1
2
3
4
5
6
7
8
9
10
11
12

# hotfix 分支(紧急修复分支)

属性 说明
用途 生产环境紧急 Bug 修复
来源 master 分支
合并目标 master 和 develop 分支
生命周期 修复后删除
命名 hotfix/<修复描述>

完整操作流程:

# 1. 基于 master 创建热修复分支
git checkout master
git pull origin master
git checkout -b hotfix/login-critical

# 2. 修复紧急 Bug
# ... 修改代码 ...

git add .
git commit -m "fix(auth): 修复登录崩溃问题(紧急)"

# 3. 合并到 master
git checkout master
git merge --no-ff hotfix/login-critical
git tag -a v1.2.1 -m "Hotfix: 修复登录崩溃问题"

# 4. 合并到 develop(保持同步)
git checkout develop
git merge --no-ff hotfix/login-critical

# 5. 推送
git push origin master --tags
git push origin develop
git push origin hotfix/login-critical

# 6. 删除热修复分支
git branch -d hotfix/login-critical
git push origin --delete hotfix/login-critical
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# release 分支(发布分支)

属性 说明
用途 版本发布准备和测试
来源 develop 分支
合并目标 master 和 develop 分支
生命周期 发布后删除
命名 release/v<版本号>

完整发布流程:

# 1. 创建发布分支
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0

# 2. 版本号更新
# 修改 .csproj、package.json、AssemblyInfo.cs

# 3. 更新 CHANGELOG.md
# 记录本次发布的所有变更

# 4. 最终测试
npm test
dotnet test
npm run build

# 5. 提交发布准备
git add .
git commit -m "chore: 准备发布 v1.2.0"
git push origin release/v1.2.0

# 6. 创建 MR 合并到 master(发布审查)
# 在 GitLab/GitHub 上创建 Merge Request

# 7. 合并到 master
git checkout master
git pull origin master
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"

# 8. 合并回 develop(保持同步)
git checkout develop
git merge --no-ff release/v1.2.0

# 9. 删除发布分支
git branch -d release/v1.2.0
git push origin --delete release/v1.2.0

# 10. 推送所有变更
git push origin master --tags
git push origin develop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 📝 Commit Message 规范详解

# 完整格式

<type>(<scope>): <subject>

<body>

<footer>
1
2
3
4
5

# Type 类型详解

类型 说明 使用场景 示例
feat 新功能 新增功能模块 feat: 添加用户管理模块
fix Bug 修复 修复功能缺陷 fix: 修复登录失败问题
docs 文档 文档增删改 docs: 更新 API 文档
style 格式 代码格式调整(不影响功能) style: 格式化代码
refactor 重构 代码重构(不新增功能、不修复 Bug) refactor: 重构用户服务
perf 性能 性能优化 perf: 优化数据库查询
test 测试 测试相关(新增/修改测试) test: 添加单元测试
chore 构建 构建过程或辅助工具变动 chore: 更新依赖版本
ci CI/CD 持续集成配置 ci: 添加 GitHub Actions
revert 回滚 回滚上一次提交 revert: 回滚用户管理功能
build 构建 影响构建系统或外部依赖 build: 更新 webpack 配置
config 配置 配置文件修改 config: 更新数据库配置

# Scope 范围说明

范围 说明 示例
admin 权限管理模块 feat(admin): 添加角色管理
common 通用模块 fix(common): 修复字典查询
quartz 任务调度 feat(quartz): 新增定时任务
data 数据访问层 perf(data): 优化 ORM 查询
ui 前端 UI style(ui): 调整按钮样式
utils 工具库 feat(utils): 添加加密工具
docs 文档 docs: 更新快速上手
config 配置 config: 更新端口配置
deps 依赖 chore(deps): 升级依赖版本

# Subject 主题规范

规则:

  1. 使用祈使句:"add" 而不是 "added"
  2. 首字母小写
  3. 不以句号结尾
  4. 长度不超过 50 字符
  5. 清晰简洁描述变更内容

示例:

# ✅ 推荐
feat: 添加用户列表查询功能
fix: 修复登录 token 过期问题
docs: 更新 API 接口文档

# ❌ 不推荐
feat: 添加了用户列表查询功能  # 过去式
Fix: 修复登录问题            # 首字母大写
feat: 添加了一个新的用户管理功能,包括列表查询、新增、编辑、删除等  # 太长
1
2
3
4
5
6
7
8
9

# Body 正文规范

何时需要 Body:

  • 复杂的变更需要解释
  • 说明修改原因
  • 对比修改前后
  • 记录技术决策

格式要求:

  • 每行不超过 72 字符
  • 使用第一人称现在时
  • 详细说明"为什么"而不是"是什么"

示例:

feat(user): 添加批量导入用户功能

- 实现 Excel 文件解析
- 支持单次最多 1000 条导入
- 添加数据验证(重复检查、格式验证)
- 导入失败显示详细错误信息
- 导入完成发送站内通知

技术实现:
- 使用 EPPlus 解析 Excel
- 事务处理确保数据一致性
- 异步处理提高导入性能

性能对比:
- 导入 1000 条:从 30s 优化到 5s
- 内存占用:从 500MB 降低到 50MB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

关联 Issue:

Closes #123
Fixes #456
Refs #789
1
2
3

破坏性变更:

BREAKING CHANGE: UserRepository 接口变更

- 移除 FindById 方法
- 新增 GetAsync 方法
- 所有实现类需要更新

迁移指南:
1. 替换 FindById 为 GetAsync
2. 添加 async/await 关键字
3. 更新返回值处理
1
2
3
4
5
6
7
8
9
10

完整示例:

feat(user): 重构用户服务层

- 提取公共方法到基类
- 优化异步实现
- 添加完整单元测试

BREAKING CHANGE: IUserService 接口变更

- RemoveUser 改为 DeleteUser
- 新增 BatchDelete 方法

Closes #123
Refs #456
1
2
3
4
5
6
7
8
9
10
11
12
13

# 🔍 代码审查(Code Review)详解

# 审查流程

graph TD
    A[开发者完成开发] --> B[创建 Merge Request]
    B --> C[填写 MR 描述]
    C --> D[指定 Reviewer]
    D --> E[CI 自动检查]
    E --> F{CI 通过?}
    F -->|否 | G[修复 CI 问题]
    G --> E
    F -->|是 | H[Reviewer 审查]
    H --> I{审查通过?}
    I -->|否 | J[提出修改意见]
    J --> K[开发者修改]
    K --> H
    I -->|是 | L[批准合并]
    L --> M[合并到目标分支]
    M --> N[删除功能分支]
    N --> O[触发 CI/CD]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Merge Request 模板

## 📋 变更说明

**需求链接:** [需求文档链接]
**任务编号:** [JIRA-123]

## 🎯 变更内容

### 功能新增
- [ ] 添加用户列表查询
- [ ] 实现用户新增功能
- [ ] 实现用户编辑功能

### Bug 修复
- [ ] 修复登录页面样式问题

### 性能优化
- [ ] 优化数据库查询性能

## 🧪 测试说明

### 单元测试
- [ ] 新增单元测试 10 个
- [ ] 测试覆盖率:85%

### 集成测试
- [ ] API 接口测试通过
- [ ] 数据库操作测试通过

### 手动测试
- [ ] 功能测试通过
- [ ] 边界条件测试通过

## 📸 截图/录屏

(如有 UI 变更,提供截图)

## ⚠️ 注意事项

- [ ] 数据库迁移脚本已准备
- [ ] 配置文件已更新
- [ ] 文档已更新

## 🔗 关联 Issue

Closes #123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 审查清单(Checklist)

# 代码质量(30%)

  • [ ] 遵循编码规范
  • [ ] 命名清晰易懂
  • [ ] 函数职责单一(不超过 50 行)
  • [ ] 代码重复度低
  • [ ] 注释适当且准确
  • [ ] 无死代码和调试代码

# 功能正确(30%)

  • [ ] 功能实现完整
  • [ ] 边界条件处理
  • [ ] 异常处理适当
  • [ ] 日志记录完整
  • [ ] 无安全隐患
  • [ ] 符合业务需求

# 性能优化(15%)

  • [ ] 无 N+1 查询
  • [ ] 数据库索引合理
  • [ ] 缓存使用适当
  • [ ] 无内存泄漏
  • [ ] 异步处理 I/O
  • [ ] 大数据量测试通过

# 测试覆盖(15%)

  • [ ] 单元测试通过
  • [ ] 集成测试通过
  • [ ] 测试覆盖率达标(>80%)
  • [ ] 边界用例测试
  • [ ] 回归测试通过

# 文档完整(10%)

  • [ ] API 文档更新
  • [ ] 代码注释完整
  • [ ] README 更新
  • [ ] CHANGELOG 更新
  • [ ] 部署文档更新

# 审查意见规范

# ✅ 批准(LGTM)

LGTM! 👍

代码质量很好,功能实现完整,测试覆盖充分。
建议合并。
1
2
3
4

# 💬 建议(非必须修改)

代码整体不错,有几个小建议供参考:

1. 第 35 行:可以考虑使用 async/await 替代 Promise 链
2. 第 78 行:这个魔法数字可以提取为常量
3. 建议添加空状态处理

这些不是必须修改的,你可以斟酌处理。
1
2
3
4
5
6
7

# ❌ 需要修改(必须修复)

需要修改后才能合并:

### 严重问题
1. ❌ 缺少参数验证(第 25 行)
2. ❌ 异常处理不完整(第 50 行)
3. ❌ SQL 注入风险(第 80 行)

### 测试问题
4. ❌ 缺少单元测试
5. ❌ 边界条件未测试

### 文档问题
6. ❌ API 文档未更新

请修复后重新提交审查。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# ⚠️ 询问(需要澄清)

有几个地方需要确认:

1. 第 45 行:为什么这里要加锁?
2. 第 67 行:这个超时时间设置为 30s 的原因?
3. 是否考虑过并发场景?

请澄清一下,谢谢。
1
2
3
4
5
6
7

# 审查工具

# GitLab MR

# 查看 MR 状态
glab mr list

# 查看 MR 详情
glab mr view <MR_ID>

# 批准 MR
glab mr approve <MR_ID>

# 合并 MR
glab mr merge <MR_ID>
1
2
3
4
5
6
7
8
9
10
11

# GitHub PR

# 查看 PR 状态
gh pr list

# 查看 PR 详情
gh pr view <PR_NUMBER>

# 批准 PR
gh pr review <PR_NUMBER> --approve

# 合并 PR
gh pr merge <PR_NUMBER> --merge
1
2
3
4
5
6
7
8
9
10
11

# 🧪 测试规范详解

# 测试金字塔

        /\
       /  \
      / E2E \     5%   - 端到端测试
     /--------\
    /Integration\  20%  - 集成测试
   /--------------\
  /  Unit Tests    \ 75%  - 单元测试
 /------------------\
1
2
3
4
5
6
7
8

# 单元测试规范

# 测试框架

后端(xUnit):

// UserService.Tests.cs
public class UserServiceTests : IDisposable
{
    private readonly Mock<IUserRepository> _mockRepo;
    private readonly Mock<ILogger> _mockLogger;
    private readonly UserService _userService;

    public UserServiceTests()
    {
        _mockRepo = new Mock<IUserRepository>();
        _mockLogger = new Mock<ILogger>();
        _userService = new UserService(_mockRepo.Object, _mockLogger.Object);
    }

    [Fact]
    public async Task GetUserById_UserExists_ReturnsSuccess()
    {
        // Arrange(准备)
        var userId = Guid.NewGuid();
        var user = new UserEntity 
        { 
            Id = userId, 
            Name = "张三",
            Email = "zhangsan@example.com"
        };
        _mockRepo.Setup(r => r.GetAsync(userId)).ReturnsAsync(user);

        // Act(执行)
        var result = await _userService.GetUserById(userId);

        // Assert(断言)
        Assert.True(result.Successful);
        Assert.NotNull(result.Data);
        Assert.Equal("张三", result.Data.Name);
        Assert.Equal(userId, result.Data.Id);
        _mockRepo.Verify(r => r.GetAsync(userId), Times.Once);
    }

    [Fact]
    public async Task GetUserById_UserNotExists_ReturnsFailed()
    {
        // Arrange
        var userId = Guid.NewGuid();
        _mockRepo.Setup(r => r.GetAsync(userId)).ReturnsAsync((UserEntity)null);

        // Act
        var result = await _userService.GetUserById(userId);

        // Assert
        Assert.False(result.Successful);
        Assert.Equal("用户不存在", result.Msg);
        Assert.Null(result.Data);
    }

    [Fact]
    public async Task CreateUser_NameIsNull_ReturnsFailed()
    {
        // Arrange
        var model = new UserAddModel { Name = null };

        // Act
        var result = await _userService.CreateUser(model);

        // Assert
        Assert.False(result.Successful);
        Assert.Contains("用户名", result.Msg);
    }

    public void Dispose()
    {
        _mockRepo.VerifyAll();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 测试命名规范

[Fact]
public void 方法名_场景_预期结果()
{
    // 示例
    [Fact]
    public void CreateUser_NameIsNull_ReturnsFailed()
    
    [Fact]
    public void GetUserById_UserExists_ReturnsSuccess()
    
    [Fact]
    public void DeleteUser_UserNotFound_ThrowsException()
    
    [Theory]
    [InlineData(0)]
    [InlineData(-1)]
    public void ValidateAge_InvalidAge_ReturnsFailed(int age)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 测试覆盖要求

模块类型 覆盖率要求 说明
核心业务 > 90% 关键业务逻辑
一般业务 > 80% 普通业务逻辑
工具类 > 70% 工具方法
简单 CRUD > 60% 简单增删改查

# 集成测试

// UserApi.Tests.cs
public class UserApiTests : IClassFixture<TestServerFixture>
{
    private readonly HttpClient _client;

    public UserApiTests(TestServerFixture fixture)
    {
        _client = fixture.CreateClient();
    }

    [Fact]
    public async Task GetUsers_ReturnsSuccess()
    {
        // Act
        var response = await _client.GetAsync("/api/user");
        var content = await response.Content.ReadAsStringAsync();
        var result = JsonConvert.DeserializeObject<ResultModel>(content);

        // Assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.True(result.Successful);
    }

    [Fact]
    public async Task CreateUser_InvalidData_ReturnsBadRequest()
    {
        // Arrange
        var user = new { Name = "" };
        var content = new StringContent(
            JsonConvert.SerializeObject(user),
            Encoding.UTF8,
            "application/json"
        );

        // Act
        var response = await _client.PostAsync("/api/user", content);

        // Assert
        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# E2E 测试

// cypress/e2e/user.cy.js
describe('用户管理', () => {
  beforeEach(() => {
    cy.login('admin', '******')
    cy.visit('/user')
  })

  it('显示用户列表', () => {
    cy.get('.user-table').should('be.visible')
    cy.get('.user-row').should('have.length.greaterThan', 0)
  })

  it('新增用户', () => {
    cy.get('.add-user-btn').click()
    cy.get('#name').type('测试用户')
    cy.get('#email').type('test@example.com')
    cy.get('.submit-btn').click()
    
    cy.get('.message-success').should('be.visible')
    cy.contains('测试用户').should('be.visible')
  })

  it('搜索用户', () => {
    cy.get('#search-input').type('张三')
    cy.get('#search-btn').click()
    
    cy.get('.user-row').each(($row) => {
      cy.wrap($row).should('contain', '张三')
    })
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 📦 版本管理详解

# Semantic Versioning 2.0.0

MAJOR.MINOR.PATCH
  ↑      ↑      ↑
  │      │      └─ 向后兼容的 Bug 修复
  │      └─ 向后兼容的功能新增
  └─ 不向后兼容的 API 变更
1
2
3
4
5

# 版本号规则

变更类型 版本号变更 示例
破坏性变更 MAJOR + 1 1.2.3 → 2.0.0
向后兼容新功能 MINOR + 1 1.2.3 → 1.3.0
向后兼容 Bug 修复 PATCH + 1 1.2.3 → 1.2.4
预发布版本 添加后缀 1.2.3-beta.1
构建元数据 添加 + 后缀 1.2.3+build.123

# 版本号示例

1.0.0          # 初始发布
1.0.1          # Bug 修复
1.1.0          # 新增功能
2.0.0          # 破坏性变更
2.0.0-beta.1   # 预发布版本
2.0.0+build.1  # 构建元数据
1
2
3
4
5
6

# 发布流程详解

# 1. 发布准备

# 创建发布分支
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0

# 更新版本号
# 修改以下文件:
# - Directory.Build.props (后端)
# - package.json (前端)
# - CHANGELOG.md
1
2
3
4
5
6
7
8
9
10

# 2. 更新 CHANGELOG

# [1.2.0] - 2022-08-07

## ✨ 新增
- 添加用户管理模块 (#123)
- 支持批量导入导出用户 (#124)
- 新增数据字典功能 (#125)

## 🐛 修复
- 修复登录页面样式问题 (#126)
- 修复数据库连接池泄漏 (#127)
- 修复缓存更新不及时 (#128)

## ⚡ 优化
- 优化数据库查询性能(提升 50%)
- 减少前端打包体积(从 5MB 到 3MB)
- 优化图片加载速度

## 🔧 变更
- 升级 .NET 5.0 到 6.0
- 更新 Element-UI 到 2.15.0
- 重构日志模块

## ⚠️ 破坏性变更
- UserRepository 接口变更
  - Remove `FindById` method
  - Add `GetAsync` method
- API 路径调整
  - `/api/user/list``/api/user`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 3. 测试验证

# 运行所有测试
npm test
dotnet test

# 构建
npm run build
dotnet build -c Release

# 本地验证
dotnet run
1
2
3
4
5
6
7
8
9
10

# 4. 合并发布

# 合并到 master
git checkout master
git pull origin master
git merge --no-ff release/v1.2.0 -m "Release version 1.2.0"

# 打标签
git tag -a v1.2.0 -m "Release version 1.2.0"

# 合并回 develop
git checkout develop
git merge --no-ff release/v1.2.0 -m "Merge release/v1.2.0"

# 删除发布分支
git branch -d release/v1.2.0

# 推送
git push origin master --tags
git push origin develop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 🚀 部署规范详解

# 环境说明

环境 分支 域名 用途 部署方式
开发 feature/* localhost 本地开发 手动
测试 develop test.example.com 功能测试 自动
预发布 release/* staging.example.com 上线前验证 自动
生产 master example.com 线上环境 手动确认

# 部署检查清单

# 部署前检查

  • [ ] 代码审查通过
  • [ ] 所有测试通过(单元/集成/E2E)
  • [ ] 版本号已更新
  • [ ] CHANGELOG 已更新
  • [ ] 数据库迁移脚本准备
  • [ ] 配置文件检查(测试/生产)
  • [ ] 回滚方案准备
  • [ ] 相关人员通知

# 部署后验证

  • [ ] 服务启动正常
  • [ ] 健康检查通过(/health)
  • [ ] 日志无异常
  • [ ] 核心功能验证
  • [ ] 性能指标正常
  • [ ] 监控告警正常
  • [ ] 用户反馈收集

# 部署脚本示例

#!/bin/bash
# deploy.sh

set -e

ENV=$1
VERSION=$2

if [ -z "$ENV" ] || [ -z "$VERSION" ]; then
    echo "Usage: ./deploy.sh <env> <version>"
    echo "  env: test|staging|prod"
    exit 1
fi

echo "开始部署到 $ENV 环境,版本:$VERSION"

# 1. 拉取代码
git fetch origin
git checkout $VERSION

# 2. 安装依赖
echo "安装依赖..."
npm install
dotnet restore

# 3. 构建
echo "构建项目..."
npm run build
dotnet publish -c Release -o ./publish

# 4. 备份旧版本
echo "备份旧版本..."
if [ -d "/var/www/app/current" ]; then
    cp -r /var/www/app/current /var/www/app/backup-$(date +%Y%m%d-%H%M%S)
fi

# 5. 部署新版本
echo "部署新版本..."
systemctl stop darkm-app
rm -rf /var/www/app/current
cp -r ./publish/* /var/www/app/current/
systemctl start darkm-app

# 6. 健康检查
echo "健康检查..."
sleep 5
curl -f http://localhost:6220/health || exit 1

# 7. 清理
echo "清理..."
rm -rf ./publish

echo "部署完成!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 📊 项目管理

# 用户故事模板

# 用户故事

## 故事描述
作为 [角色]
我想要 [功能]
以便于 [价值]

## 验收标准
- [ ] 标准 1
- [ ] 标准 2
- [ ] 标准 3

## 技术备注
- 技术实现要点
- 依赖关系
- 风险评估

## 工作量评估
故事点:__
预计时间:__
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 故事点估算

点数 Fibonacci 时间参考 复杂度 示例
1 1 < 2 小时 非常简单 修改文案、调整样式
2 2 2-4 小时 简单 添加简单 API 接口
3 3 4-8 小时 中等 新增 CRUD 功能
5 5 1-2 天 较复杂 集成第三方服务
8 8 2-3 天 复杂 重构核心模块
13 13 > 3 天 非常复杂 需要拆分

# 任务看板

┌─────────────┬─────────────┬─────────────┬─────────────┐
│   To Do     │  In Progress│   Testing   │   Done      │
├─────────────┼─────────────┼─────────────┼─────────────┤
│ 用户列表    │ 用户新增    │ 用户编辑    │ 登录功能    │
│ 用户导出    │ 权限配置    │             │ 角色管理    │
│             │             │             │ 菜单管理    │
└─────────────┴─────────────┴─────────────┴─────────────┘
1
2
3
4
5
6
7

# 🔒 安全规范详解

# OWASP Top 10 防护

# 1. SQL 注入

// ✅ 推荐:参数化查询
var user = await _dbSet.QueryFirstOrDefaultAsync<UserEntity>(
    "SELECT * FROM User WHERE UserName = @UserName",
    new { UserName = userName }
);

// ❌ 不推荐:SQL 拼接
var sql = $"SELECT * FROM User WHERE UserName = '{userName}'";
var user = await _dbSet.QueryFirstOrDefaultAsync<UserEntity>(sql);
1
2
3
4
5
6
7
8
9

# 2. XSS 攻击

// ✅ 推荐:Vue 自动转义
<template>
  <div>{{ userInput }}</div>  <!-- 自动转义 -->
</template>

// ❌ 不推荐:直接渲染 HTML
<template>
  <div v-html="userInput"></div>  <!-- XSS 风险 -->
</template>
1
2
3
4
5
6
7
8
9

# 3. CSRF 攻击

// ✅ 推荐:使用 AntiForgery
[ValidateAntiForgeryToken]
[HttpPost]
public async Task<IActionResult> Create(User model)
{
    // ...
}

// 前端添加 token
<form method="post">
    @Html.AntiForgeryToken()
    <!-- ... -->
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 4. 敏感信息保护

// ✅ 推荐:使用配置
var apiKey = Configuration.GetValue<string>("ApiKey");
var connectionString = Configuration.GetConnectionString("Default");

// ❌ 不推荐:硬编码
var apiKey = "sk-1234567890abcdef";
var password = "admin123";
1
2
3
4
5
6
7

# 5. 密码安全

// ✅ 推荐:使用 BCrypt
var passwordHash = BCrypt.Net.BCrypt.HashPassword(password, 12);
var isValid = BCrypt.Net.BCrypt.Verify(password, passwordHash);

// ❌ 不推荐:明文或简单哈希
user.Password = password;  // 明文
user.Password = MD5(password);  // 不安全
1
2
3
4
5
6
7

# 📚 相关文档


最后更新: 2022-08-07