学业邑规划 - 开发规范
本文档定义了 MiAssessment 项目的开发规范和编码标准,所有开发工作必须遵循这些规范。
项目概述
学业邑规划是一个基于多元智能理论的学业规划测评系统,包含微信小程序和后台管理系统。
相关文档
- 需求文档:
docs/需求文档.md
- 数据库设计:
docs/数据库设计文档.md
- 开发文档:
docs/开发文档.md
- 题库资料:
docs/题库和结论/
- UI 设计图:
docs/设计图/
- UI 切图:
docs/切图/
一、技术栈
| 层级 |
技术 |
| 后端框架 |
.NET 10 Web API (C#) |
| 数据库 |
SQL Server 2022 |
| ORM |
Entity Framework Core |
| 缓存 |
Redis |
| 接口风格 |
RPC 风格(仅 GET / POST 请求) |
| 小程序前端 |
UniApp + Vue 3 |
| 后台管理前端 |
Vue 3 + TypeScript + Vite |
二、项目结构
整体结构
mi-assessment/
├── docs/ # 文档资料
│ ├── 需求文档.md
│ ├── 数据库设计文档.md
│ ├── 开发文档.md
│ ├── 开发规范/ # 详细编码规范
│ ├── 设计图/ # UI 设计图
│ ├── 切图/ # UI 切图资源
│ └── 题库和结论/ # 测评题库与报告模板
├── server/MiAssessment/ # 后端服务
└── uniapp/ # 小程序前端
后端项目结构
server/MiAssessment/src/
├── MiAssessment.Api/ # 小程序 API 接口
├── MiAssessment.Admin/ # 后台管理系统基础模块
│ └── admin-web/ # 后台管理前端 (Vue 3)
├── MiAssessment.Admin.Business/ # 后台业务模块(主要开发区域)
├── MiAssessment.Core/ # 核心业务逻辑
├── MiAssessment.Infrastructure/ # 基础设施
└── MiAssessment.Model/ # 数据模型
Admin.Business 项目结构
MiAssessment.Admin.Business/
├── Controllers/ # 控制器(API 入口)
├── Services/ # 业务服务
│ └── Interfaces/ # 服务接口
├── Models/ # 请求/响应模型(DTO)
│ ├── Common/ # 通用模型
│ └── {Module}/ # 各模块模型
├── Entities/ # 数据库实体类
├── Data/ # 数据库上下文
└── Attributes/ # 自定义特性
三、命名规范
3.1 数据库命名
| 类型 |
规范 |
示例 |
| 表名 |
snake_case(小写下划线) |
users, assessment_records |
| 字段名 |
PascalCase |
UserId, CreateTime |
| 主键 |
Id (bigint 自增) |
Id |
| 外键 |
{表名}Id |
UserId, OrderId |
| 时间字段 |
CreateTime, UpdateTime |
- |
| 状态字段 |
Status |
- |
| 软删除 |
IsDeleted (bit) |
- |
3.2 C# 代码命名
| 类型 |
规范 |
示例 |
| 命名空间 |
PascalCase |
MiAssessment.Admin.Business.Services |
| 类名 |
PascalCase |
UserService, OrderController |
| 接口 |
I + PascalCase |
IUserService, IOrderService |
| 方法 |
PascalCase + Async 后缀 |
GetUserListAsync, CreateOrderAsync |
| 属性 |
PascalCase |
UserId, CreateTime |
| 私有字段 |
_camelCase |
_userService, _dbContext |
| 参数 |
camelCase |
userId, request |
| 常量 |
PascalCase |
MaxPageSize, DefaultStatus |
3.3 文件命名
| 类型 |
规范 |
示例 |
| 实体类 |
单数形式 |
User.cs, Order.cs |
| 服务接口 |
I + 服务名 |
IUserService.cs |
| 服务实现 |
服务名 |
UserService.cs |
| 控制器 |
模块名 + Controller |
UserController.cs |
| DTO 模型 |
功能 + Request/Dto |
CreateUserRequest.cs, UserDto.cs |
3.4 前端命名 (Vue/JavaScript)
| 类型 |
规范 |
示例 |
| 组件文件 |
PascalCase |
UserList.vue, OrderDetail.vue |
| 组合式函数 |
use + camelCase |
useUserList.js, useAuth.js |
| 工具函数 |
camelCase |
formatDate.js, request.js |
| 变量/函数 |
camelCase |
userList, handleSubmit |
| 常量 |
UPPER_SNAKE_CASE |
API_BASE_URL, MAX_PAGE_SIZE |
| CSS 类名 |
kebab-case |
user-list, order-card |
四、代码规范
4.1 实体类规范
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MiAssessment.Admin.Business.Entities;
/// <summary>
/// 用户表
/// </summary>
[Table("users")]
public class User
{
/// <summary>
/// 主键ID
/// </summary>
[Key]
public long Id { get; set; }
/// <summary>
/// 用户UID
/// </summary>
[Required]
[MaxLength(6)]
public string Uid { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime UpdateTime { get; set; }
/// <summary>
/// 软删除标记
/// </summary>
public bool IsDeleted { get; set; }
}
要点:
- 使用
[Table("表名")] 指定数据库表名
- 使用
[Key] 标记主键
- 使用
[Required] 标记必填字段
- 使用
[MaxLength(n)] 限制字符串长度
- 所有属性必须有 XML 注释
- 字符串属性使用
= null! 初始化
4.2 服务接口规范
namespace MiAssessment.Admin.Business.Services.Interfaces;
/// <summary>
/// 用户服务接口
/// </summary>
public interface IUserService
{
/// <summary>
/// 获取用户列表
/// </summary>
Task<PagedResult<UserDto>> GetUserListAsync(UserQueryRequest request);
/// <summary>
/// 获取用户详情
/// </summary>
Task<UserDetailDto?> GetUserDetailAsync(long id);
/// <summary>
/// 更新用户状态
/// </summary>
Task<bool> UpdateUserStatusAsync(long id, int status);
}
4.3 服务实现规范
namespace MiAssessment.Admin.Business.Services;
/// <summary>
/// 用户服务实现
/// </summary>
public class UserService : IUserService
{
private readonly AdminBusinessDbContext _dbContext;
private readonly ILogger<UserService> _logger;
public UserService(
AdminBusinessDbContext dbContext,
ILogger<UserService> logger)
{
_dbContext = dbContext;
_logger = logger;
}
/// <inheritdoc />
public async Task<PagedResult<UserDto>> GetUserListAsync(UserQueryRequest request)
{
var query = _dbContext.Users
.Where(u => !u.IsDeleted);
// 条件筛选
if (!string.IsNullOrEmpty(request.Phone))
{
query = query.Where(u => u.Phone.Contains(request.Phone));
}
// 获取总数
var total = await query.CountAsync();
// 分页查询
var items = await query
.OrderByDescending(u => u.CreateTime)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(u => new UserDto
{
Id = u.Id,
Uid = u.Uid,
// ...
})
.ToListAsync();
return new PagedResult<UserDto>(items, total, request.Page, request.PageSize);
}
}
4.4 控制器规范
namespace MiAssessment.Admin.Business.Controllers;
/// <summary>
/// 用户管理控制器
/// </summary>
[Route("api/admin/user")]
public class UserController : BusinessControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
/// <summary>
/// 获取用户列表
/// </summary>
[HttpGet("getList")]
public async Task<IActionResult> GetList([FromQuery] UserQueryRequest request)
{
var result = await _userService.GetUserListAsync(request);
return Ok(result);
}
/// <summary>
/// 更新用户状态
/// </summary>
[HttpPost("updateStatus")]
public async Task<IActionResult> UpdateStatus([FromBody] UpdateStatusRequest request)
{
var success = await _userService.UpdateUserStatusAsync(request.Id, request.Status);
return success ? Ok() : Error(ErrorCodes.UserNotFound, "用户不存在");
}
}
五、API 接口规范
5.1 接口风格
- 仅使用 GET 和 POST 请求
- GET:查询操作,参数通过 Query String 传递
- POST:新增、修改、删除操作,参数通过 Request Body (JSON) 传递
5.2 路由规范
小程序 API: /api/{module}/{action}
后台管理 API: /api/admin/{module}/{action}
| 操作 |
方法 |
路由示例 |
| 获取列表 |
GET |
/api/admin/user/getList |
| 获取详情 |
GET |
/api/admin/user/getDetail?id=1 |
| 创建 |
POST |
/api/admin/user/create |
| 更新 |
POST |
/api/admin/user/update |
| 删除 |
POST |
/api/admin/user/delete |
| 更新状态 |
POST |
/api/admin/user/updateStatus |
| 更新排序 |
POST |
/api/admin/user/updateSort |
5.3 响应格式
{
"code": 0,
"message": "success",
"data": {}
}
code: 0 表示成功,非 0 表示错误
message: 提示信息
data: 业务数据
5.4 分页响应
{
"code": 0,
"message": "success",
"data": {
"list": [],
"total": 100,
"page": 1,
"pageSize": 20,
"totalPages": 5
}
}
六、错误码规范
| 范围 |
说明 |
| 0 |
成功 |
| 1000-1999 |
通用错误 |
| 2000-2999 |
业务错误 |
| 3000-3099 |
配置模块错误 |
| 3100-3199 |
内容模块错误 |
| 3200-3299 |
测评模块错误 |
| 3300-3399 |
用户模块错误 |
| 3400-3499 |
订单模块错误 |
| 3500-3599 |
规划师模块错误 |
| 3600-3699 |
分销模块错误 |
| 5000-5999 |
系统错误 |
七、注释规范
7.1 XML 注释 (C#)
所有公开的类、方法、属性必须有 XML 注释:
/// <summary>
/// 获取用户列表
/// </summary>
/// <param name="request">查询参数</param>
/// <returns>分页用户列表</returns>
public async Task<PagedResult<UserDto>> GetUserListAsync(UserQueryRequest request)
7.2 JSDoc 注释 (JavaScript)
/**
* 获取用户列表
* @param {Object} params - 查询参数
* @param {number} [params.page] - 页码
* @param {number} [params.pageSize] - 每页数量
* @param {string} [params.phone] - 手机号
* @returns {Promise<Object>} 分页用户列表
*/
export async function getUserList(params) {
// ...
}
7.3 代码注释
- 使用中文注释
- 复杂逻辑需要添加说明注释
- 避免无意义的注释
八、数据库操作规范
8.1 查询规范
// 始终过滤软删除记录
var query = _dbContext.Users.Where(u => !u.IsDeleted);
// 使用 AsNoTracking 提高只读查询性能
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => !u.IsDeleted)
.ToListAsync();
8.2 软删除
// 删除操作使用软删除
public async Task<bool> DeleteAsync(long id)
{
var entity = await _dbContext.Users.FindAsync(id);
if (entity == null) return false;
entity.IsDeleted = true;
entity.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
return true;
}
8.3 更新时间
// 更新操作自动设置 UpdateTime
entity.UpdateTime = DateTime.Now;
await _dbContext.SaveChangesAsync();
九、双数据库架构规范
9.1 数据库划分
本项目采用双数据库架构,严格区分后台管理数据与业务数据:
| 数据库 |
名称 |
职责 |
| Admin 库 |
MiAssessment_Admin |
后台管理系统自身运行所需数据(RBAC、审计、运营配置) |
| Business 库 |
MiAssessment_Business |
C端用户产生的或直接服务C端的业务数据 |
9.2 Admin 库表清单
| 表名 |
说明 |
admin_users |
后台管理员 |
roles |
角色 |
menus |
菜单 |
departments |
部门 |
permissions |
权限 |
role_menus |
角色-菜单关联 |
role_permissions |
角色-权限关联 |
user_roles |
用户-角色关联 |
operation_logs |
操作日志 |
refresh_tokens |
刷新令牌 |
admin_configs |
运营配置(支付、小程序、上传、短信等) |
dict_types |
字典类型 |
dict_items |
字典项 |
9.3 Business 库表清单
| 表名 |
说明 |
configs |
业务配置(测评价格、佣金比例、提现限额、联系方式、协议等) |
banners |
轮播图 |
promotions |
宣传图 |
assessment_types |
测评类型 |
questions |
题目 |
report_categories |
报告分类 |
question_category_mappings |
题目-分类映射 |
report_conclusions |
报告结论 |
assessment_records |
测评记录 |
assessment_answers |
测评答案 |
assessment_results |
测评结果 |
users |
C端用户 |
orders |
订单 |
planners |
规划师 |
planner_bookings |
规划预约 |
invite_codes |
邀请码 |
commissions |
佣金记录 |
withdrawals |
提现记录 |
business_pages |
业务页面 |
9.4 配置数据分离规则
| 配置类型 |
所在库 |
表名 |
示例 Key |
| 运营配置 |
Admin 库 |
admin_configs |
weixinpay_setting, miniprogram_setting, upload_setting, sms_setting, app_setting, base |
| 业务配置 |
Business 库 |
configs |
assessment_price, commission_rate_direct, commission_rate_indirect, withdraw_min_amount, contact_wechat, user_agreement, privacy_policy |
9.5 DbContext 映射
| DbContext |
所在项目 |
连接数据库 |
读写权限 |
用途 |
AdminDbContext |
MiAssessment.Admin |
Admin 库 |
读写 |
后台管理系统主上下文 |
AdminBusinessDbContext |
MiAssessment.Admin.Business |
Business 库 |
读写 |
后台管理业务数据 |
AdminConfigDbContext |
MiAssessment.Admin.Business |
Admin 库 |
只读 |
Business 项目读取运营配置 |
AdminConfigReadDbContext |
MiAssessment.Model |
Admin 库 |
只读 |
Core/API 项目读取运营配置 |
MiAssessmentDbContext |
MiAssessment.Model |
Business 库 |
读写 |
小程序 API 主上下文 |
9.6 跨库访问规则
- Business 项目对 Admin 库只读:通过
AdminConfigDbContext 读取运营配置,禁止写入
- Core/API 项目对 Admin 库只读:通过
AdminConfigReadDbContext 读取运营配置,禁止写入
- Admin 库的写操作只通过 Admin 项目进行:所有运营配置的增删改必须通过
AdminDbContext
- 连接字符串命名:Admin 库使用
AdminConnection,Business 库使用 DefaultConnection
9.7 新增配置项规则
- 如果配置是运营/系统级别(支付密钥、上传凭证、短信配置等)→ 存入 Admin 库
admin_configs 表
- 如果配置是业务级别(价格、佣金比例、协议内容等)→ 存入 Business 库
configs 表
- 新增 DbContext 时必须明确标注读写权限,跨库上下文必须标注
只读
十、状态值定义
9.1 通用状态
9.2 订单状态
| 值 |
说明 |
| 1 |
待支付 |
| 2 |
已支付 |
| 3 |
已完成 |
| 4 |
退款中 |
| 5 |
已退款 |
| 6 |
已取消 |
9.3 用户等级
| 值 |
说明 |
| 1 |
普通用户 |
| 2 |
合伙人 |
| 3 |
渠道合伙人 |
十一、测试规范
10.1 测试框架
- 单元测试:xUnit + Moq
- 属性测试:FsCheck
10.2 测试命名
[Fact]
public async Task GetUserListAsync_WithValidRequest_ReturnsPagedResult()
{
// Arrange
// Act
// Assert
}
10.3 属性测试注释
/// <summary>
/// Property: 分页查询返回的记录数不超过 PageSize
/// **Validates: Requirements 9.1**
/// </summary>
[Property]
public Property PaginationReturnsCorrectCount()
{
// ...
}
十二、Git 提交规范
11.1 提交信息格式
<type>(<scope>): <subject>
<body>
11.2 Type 类型
| Type |
说明 |
| feat |
新功能 |
| fix |
修复 bug |
| docs |
文档更新 |
| style |
代码格式 |
| refactor |
重构 |
| test |
测试 |
| chore |
构建/工具 |
11.3 示例
feat(user): 添加用户列表分页查询功能
- 实现 GetUserListAsync 方法
- 支持按手机号、昵称筛选
- 添加分页参数验证
十三、前端开发规范(小程序)
12.1 Vue 组件规范
<script setup>
/**
* 用户列表组件
*/
import { ref, onMounted, defineProps, defineEmits } from 'vue'
import { getUserList } from '@/api/user'
// Props
const props = defineProps({
status: {
type: Number,
default: null
}
})
// Emits
const emit = defineEmits(['select'])
// State
const loading = ref(false)
const userList = ref([])
// Methods
async function fetchData() {
loading.value = true
try {
const res = await getUserList({ status: props.status })
userList.value = res.data.list
} finally {
loading.value = false
}
}
// Lifecycle
onMounted(() => {
fetchData()
})
</script>
<template>
<view class="user-list">
<!-- 内容 -->
</view>
</template>
<style scoped lang="scss">
.user-list {
/* 样式 */
}
</style>
12.2 API 请求规范
// api/user.js
import { get, post } from '@/api/request'
/**
* 获取用户列表
* @param {Object} params - 查询参数
* @returns {Promise<Object>}
*/
export function getUserList(params) {
return get('/user/getList', params)
}
/**
* 更新用户状态
* @param {number} id - 用户ID
* @param {number} status - 状态
* @returns {Promise<Object>}
*/
export function updateUserStatus(id, status) {
return post('/user/updateStatus', { id, status })
}
12.3 常量定义规范
// constants/user.js
/** 用户等级 */
export const USER_LEVEL = {
NORMAL: 1, // 普通用户
PARTNER: 2, // 合伙人
CHANNEL: 3 // 渠道合伙人
}
/** 订单状态 */
export const ORDER_STATUS = {
PENDING: 1, // 待支付
PAID: 2, // 已支付
COMPLETED: 3, // 已完成
REFUNDING: 4, // 退款中
REFUNDED: 5, // 已退款
CANCELLED: 6 // 已取消
}