签入版本
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 12.1 API 响应规范
|
||||
|
||||
:::tip 概述
|
||||
所有接口返回统一的 JSON 结构,前端可据此判断请求结果。成功响应 `code=0`,失败响应 `code=1`(或 401/403/404/422)。
|
||||
所有接口返回统一的 JSON 结构,前端可据此判断请求结果。成功响应 `code=0`,失败响应 `code=1`(或 401/403/404/422/500)。HTTP 状态码默认 200,仅 403 例外。详细机制见 [8.1 统一响应格式](/zh/api-spec/response.html)。
|
||||
:::
|
||||
|
||||
## 统一格式
|
||||
@@ -67,7 +67,7 @@ interface ApiResponse {
|
||||
| `code` | number | 状态码,0=成功 |
|
||||
| `ok` | boolean | 是否成功 |
|
||||
| `msg` | string | 提示信息 |
|
||||
| `data` | any | 响应数据,失败时通常为 null |
|
||||
| `data` | any | 响应数据,失败时通常为 null 或错误明细 |
|
||||
| `data.records` | array | 分页数据列表 |
|
||||
| `data.total` | number | 总记录数 |
|
||||
| `data.size` | number | 每页条数 |
|
||||
@@ -84,32 +84,33 @@ interface ApiResponse {
|
||||
| `user_name` | `userName` |
|
||||
| `is_delete` | `isDelete` |
|
||||
|
||||
可通过 `config/api.php` 的 `camel_snake_convert` 配置关闭。
|
||||
可通过 `config/api.php` 的 `camel_snake_convert`(环境变量 `API_CAMEL_SNAKE_CONVERT`)关闭;需要单个接口原样返回时用 `Result::success($data, $msg, true)`。
|
||||
|
||||
## 后端构造方式
|
||||
|
||||
```php
|
||||
// Controller 中
|
||||
return $this->success($data, '操作成功'); // 成功
|
||||
return $this->success(['id' => $id], '添加成功'); // 成功(带数据)
|
||||
return $this->fail('用户名已存在'); // 失败
|
||||
return $this->_page($result); // 分页
|
||||
// Controller 中(基类方法,推荐)
|
||||
return $this->success($data, '操作成功'); // 成功
|
||||
return $this->success(['id' => $id], '添加成功'); // 成功(带数据)
|
||||
return $this->fail('用户名已存在'); // 失败(code 默认 1)
|
||||
return $this->paginate($pageListResult); // 分页(records/total/current/size/pages)
|
||||
return $this->_page($service, $where); // 分页(直接传 Service,内部调用 pageList)
|
||||
```
|
||||
|
||||
```php
|
||||
// Result 类直接调用
|
||||
// Result 类直接调用(app/Support/Result.php)
|
||||
Result::success($data, $msg);
|
||||
Result::page($records, $total, $current, $size);
|
||||
Result::page($records, $total, $current, $size, $pages = null); // 分页响应
|
||||
Result::fail($msg, $code);
|
||||
Result::unauthorized($msg); // 401
|
||||
Result::forbidden($msg); // 403
|
||||
Result::unauthorized($msg); // 401(HTTP 200 + body code)
|
||||
Result::forbidden($msg); // 403(HTTP 403)
|
||||
Result::notFound($msg); // 404
|
||||
Result::validateError($errors); // 422 参数验证失败
|
||||
```
|
||||
|
||||
### validateError 示例
|
||||
|
||||
`Result::validateError()` 用于参数验证失败场景,HTTP 状态码为 422,`data` 字段返回具体错误明细,便于前端逐字段提示:
|
||||
`Result::validateError()` 用于参数验证失败场景,`code=422`,`data` 字段返回具体错误明细,便于前端逐字段提示:
|
||||
|
||||
```php
|
||||
// 直接传字符串
|
||||
@@ -117,8 +118,8 @@ return Result::validateError('用户名不能为空');
|
||||
|
||||
// 传数组,包含多个字段错误
|
||||
return Result::validateError([
|
||||
'username' => '用户名不能为空',
|
||||
'email' => '邮箱格式不正确',
|
||||
'username' => ['用户名不能为空'],
|
||||
'email' => ['邮箱格式不正确'],
|
||||
]);
|
||||
```
|
||||
|
||||
@@ -128,8 +129,8 @@ return Result::validateError([
|
||||
"ok": false,
|
||||
"msg": "参数验证失败",
|
||||
"data": {
|
||||
"username": "用户名不能为空",
|
||||
"email": "邮箱格式不正确"
|
||||
"username": ["用户名不能为空"],
|
||||
"email": ["邮箱格式不正确"]
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,30 +1,42 @@
|
||||
# 12.6 后端编码规范
|
||||
|
||||
:::tip 概述
|
||||
本节定义后端 PHP 代码的编写规范,包括 Model、Logic、Controller、Validate 各层的命名和结构规范,确保团队代码风格统一。
|
||||
本节定义后端 PHP 代码的编写规范,包括 Model、Service、Controller、FormRequest 各层的命名和结构规范,确保团队代码风格统一。代码风格以 Laravel Pint(`./vendor/bin/pint`)为准。
|
||||
:::
|
||||
|
||||
## Model 层规范
|
||||
|
||||
```php
|
||||
// 继承 BaseModel
|
||||
class Example extends BaseModel
|
||||
// 继承 Eloquent Model(app/Models/Example.php)
|
||||
class Example extends Model
|
||||
{
|
||||
// 软删除(is_delete)+ 审计字段(create_user/create_time/update_user/update_time)
|
||||
use HasAuditColumns, SoftDeletesByFlag;
|
||||
|
||||
/**
|
||||
* 对应数据库表名(不含前缀)
|
||||
* 对应数据库表名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'example';
|
||||
protected $table = 'example';
|
||||
|
||||
/**
|
||||
* 批量赋值白名单
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = ['name', 'avatar', 'type', 'status', 'sort'];
|
||||
}
|
||||
```
|
||||
|
||||
## Logic 层规范
|
||||
## Service 层规范
|
||||
|
||||
```php
|
||||
// 系统共享模块继承 BaseLogic
|
||||
class ExampleLogic extends BaseLogic
|
||||
// 系统共享模块继承 BaseService
|
||||
class ExampleService extends BaseService
|
||||
{
|
||||
use HasCrudOperations, HasQueryScopes, HasSerializeMaps;
|
||||
|
||||
/**
|
||||
* 关联的模型类
|
||||
*
|
||||
@@ -58,63 +70,65 @@ class ExampleLogic extends BaseLogic
|
||||
}
|
||||
}
|
||||
|
||||
// 租户模块继承 BaseTenantLogic
|
||||
class UserLogic extends BaseTenantLogic { ... }
|
||||
// 租户模块继承 BaseTenantService(含 tenant_id 的业务表)
|
||||
class UserService extends BaseTenantService { ... }
|
||||
```
|
||||
|
||||
可用生命周期钩子(`HasCrudOperations`):`beforeAdd` / `afterAdd` / `beforeUpdate` / `afterUpdate` / `beforeDelete` / `afterDelete` / `beforeBatchDelete` / `afterBatchDelete` / `afterDetail` / `afterPageList`。
|
||||
|
||||
## Controller 层规范
|
||||
|
||||
```php
|
||||
class ExampleController extends BaseController
|
||||
class ExampleController extends Controller
|
||||
{
|
||||
protected ExampleLogic $logic;
|
||||
|
||||
protected function initialize(): void
|
||||
{
|
||||
$this->logic = new ExampleLogic();
|
||||
}
|
||||
// 构造函数注入 Service(不在 initialize 中手动 new)
|
||||
public function __construct(protected ExampleService $exampleService) {}
|
||||
|
||||
// 使用注解
|
||||
#[Log('模块-操作', Log::TYPE_ADD)]
|
||||
#[Permission('sys:example:add', '添加')]
|
||||
public function add(): Json
|
||||
#[OperationLog('示例管理-新增', OperationLog::TYPE_ADD)]
|
||||
#[Permission('sys:example:add', '新增示例')]
|
||||
public function add(ExampleRequest $request): JsonResponse
|
||||
{
|
||||
return parent::_add($this->logic, $this->getJsonBody());
|
||||
return $this->_add($this->exampleService, $request->validated());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Validate 层规范
|
||||
:::tip 瘦控制器
|
||||
Controller 只做三件事:参数获取(FormRequest)→ 调用 Service → 返回 JSON。业务规则一律写在 Service,不在控制器写 if/else 业务判断。
|
||||
:::
|
||||
|
||||
## FormRequest 层规范
|
||||
|
||||
```php
|
||||
class ExampleValidate extends Validate
|
||||
class ExampleRequest extends BaseRequest
|
||||
{
|
||||
protected $rule = [
|
||||
'name' => 'require',
|
||||
'categoryId' => 'require', // ✅ 驼峰命名
|
||||
// 'category_id' => 'require', // ❌ 禁止下划线
|
||||
];
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:255', // ✅ 驼峰命名
|
||||
'categoryId' => 'required|integer', // ✅ 驼峰命名
|
||||
// 'category_id' => 'required', // ❌ 禁止下划线
|
||||
];
|
||||
}
|
||||
|
||||
protected $message = [
|
||||
'name.require' => '名称不能为空',
|
||||
'categoryId.require' => '分类不能为空',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['name', 'categoryId'],
|
||||
'update' => ['name'],
|
||||
];
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'name.required' => '名称不能为空',
|
||||
'categoryId.required' => '分类不能为空',
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::warning 字段名必须使用驼峰
|
||||
Validate 中的字段名必须使用 camelCase(驼峰),与前端传参一致。
|
||||
因为校验发生在 `BaseLogic::beforeAdd` 之后、`array_camel_to_snake` 转换之前,
|
||||
此时数据键名还是驼峰形式。使用下划线会导致校验规则匹配不到字段。
|
||||
FormRequest 中的字段名必须使用 camelCase(驼峰),与前端传参一致——使用下划线会导致校验规则匹配不到字段。控制器以 `validated()` 取数原样传递,键名转换由 Service 写入入口(doAdd/doUpdate)统一完成。
|
||||
:::
|
||||
|
||||
## 注解规范
|
||||
|
||||
- 所有写操作(POST/PUT/DELETE)必须标注 `#[Log]`
|
||||
- 所有写操作(POST/PUT/DELETE)必须标注 `#[OperationLog('模块-操作', OperationLog::TYPE_XXX)]`
|
||||
- 所有需要权限控制的接口必须标注 `#[Permission]`
|
||||
- 权限码格式:`sys:{模块名}:{操作}`
|
||||
- 权限码格式:`sys:{模块名}:{操作}`
|
||||
- 演示环境放行的只读接口标注 `#[DemoAllow]`
|
||||
|
||||
@@ -8,40 +8,49 @@
|
||||
|
||||
### Model 层
|
||||
|
||||
- [ ] 继承 `BaseModel`
|
||||
- [ ] 表名 `$name` 配置正确
|
||||
- [ ] 继承 Eloquent `Model`(业务模型位于 `app/Models/`)
|
||||
- [ ] `protected $table` 显式指定表名(含前缀或与 `DB_PREFIX` 推导一致)
|
||||
- [ ] 引入 `SoftDeletesByFlag`(is_delete 软删除)与 `HasAuditColumns`(审计字段)Trait
|
||||
- [ ] `$fillable` 白名单完整(批量赋值字段)
|
||||
- [ ] 关联关系定义正确(如有)
|
||||
- [ ] 无硬编码的数据库前缀
|
||||
|
||||
### Logic 层
|
||||
### Service 层
|
||||
|
||||
- [ ] 继承正确的基类(`BaseLogic` 或 `BaseTenantLogic`)
|
||||
- [ ] 继承正确的基类(`BaseService` 或 `BaseTenantService`,树形模块不参与租户隔离)
|
||||
- [ ] `$modelClass` 配置正确
|
||||
- [ ] Trait 组合按需(`HasCrudOperations` / `HasQueryScopes` / `HasSerializeMaps` / `HasUniqueCheck` / `HasFileProcessing`)
|
||||
- [ ] 查询条件配置合理(`pageLikeFields` / `pageEqFields`)
|
||||
- [ ] 排序配置合理(`pageOrderBy`)
|
||||
- [ ] 排序配置合理(`pageOrderBy` / `orderFieldAllow` 白名单)
|
||||
- [ ] 唯一性校验配置(`uniqueFields`)
|
||||
- [ ] 枚举映射配置(`serializeMaps`)
|
||||
- [ ] 文件字段配置(`fileFields` / `fileSaveDir`)
|
||||
- [ ] 钩子方法中无 SQL 注入风险
|
||||
- [ ] 事务使用正确(`startTrans` / `commit` / `rollback`)
|
||||
- [ ] 钩子方法中无 SQL 注入风险(使用查询构造器参数绑定)
|
||||
- [ ] 写操作在事务中执行(`HasCrudOperations` 已用 `DB::transaction` 包裹,自定义逻辑需补充)
|
||||
|
||||
### Controller 层
|
||||
|
||||
- [ ] 继承 `BaseController`
|
||||
- [ ] `initialize()` 中实例化 Logic
|
||||
- [ ] 位于 `app/Http/Controllers/Api/`,瘦控制器(参数获取 → 调 Service → 返回 JSON)
|
||||
- [ ] 通过构造函数注入 Service(不手动 new)
|
||||
- [ ] 所有接口标注 `#[Permission]` 注解
|
||||
- [ ] 所有写操作标注 `#[Log]` 注解
|
||||
- [ ] 所有写操作标注 `#[OperationLog]` 注解
|
||||
- [ ] 权限码格式正确(`sys:模块名:操作`)
|
||||
- [ ] 异常处理完善(try-catch)
|
||||
- [ ] 参数校验充分
|
||||
- [ ] 返回值类型为 `JsonResponse`,使用基类 `success/fail/paginate/_page` 等方法
|
||||
- [ ] 参数格式校验由 FormRequest 完成(不在控制器手写校验)
|
||||
|
||||
### FormRequest
|
||||
|
||||
- [ ] 继承 `BaseRequest`(`failedValidation` 统一抛出 `code=1` 响应)
|
||||
- [ ] `rules()` 覆盖全部必填与格式字段
|
||||
- [ ] 场景区分(add / update)
|
||||
|
||||
### 安全
|
||||
|
||||
- [ ] 无 SQL 注入风险(使用 ORM 参数绑定)
|
||||
- [ ] 无 SQL 注入风险(使用 ORM / 查询构造器参数绑定)
|
||||
- [ ] 无 XSS 风险(输出转义)
|
||||
- [ ] 敏感数据不暴露(password、salt)
|
||||
- [ ] 文件上传有类型和大小限制
|
||||
- [ ] 权限校验覆盖所有接口
|
||||
- [ ] 敏感数据不暴露(password、salt 不在响应字段中)
|
||||
- [ ] 文件上传有类型和大小限制(`config/file.php` + FormRequest)
|
||||
- [ ] 权限校验覆盖所有接口(`#[Permission]`)
|
||||
|
||||
## 前端审查清单
|
||||
|
||||
@@ -50,7 +59,7 @@
|
||||
- [ ] 函数命名规范(`getXxxPage` / `xxxAdd` / `xxxUpdate` / `xxxDelete`)
|
||||
- [ ] HTTP 方法正确(GET/POST/PUT/DELETE)
|
||||
- [ ] 参数传递方式正确(params / data)
|
||||
- [ ] 错误处理完善
|
||||
- [ ] 错误处理完善(响应拦截器统一处理,业务代码不重复 catch)
|
||||
|
||||
### 页面组件
|
||||
|
||||
@@ -63,8 +72,8 @@
|
||||
|
||||
### 权限
|
||||
|
||||
- [ ] 按钮级权限使用 `v-perm` 指令
|
||||
- [ ] 权限码与后端一致
|
||||
- [ ] 按钮级权限使用 `v-perm` 指令(如 `v-perm="['sys:example:add']"`,多权限全满足用 `v-perms`)
|
||||
- [ ] 权限码与后端 `#[Permission]` 注解一致
|
||||
|
||||
### 性能
|
||||
|
||||
@@ -74,7 +83,8 @@
|
||||
|
||||
## Git 提交审查
|
||||
|
||||
- [ ] commit message 格式正确
|
||||
- [ ] commit message 格式正确(见 [12.3 Git 提交规范](/zh/standards/git.html))
|
||||
- [ ] 一个 commit 只做一件事
|
||||
- [ ] 无调试代码残留(console.log、dump)
|
||||
- [ ] 无敏感信息泄露(密码、密钥)
|
||||
- [ ] 无调试代码残留(console.log、dd、dump)
|
||||
- [ ] 无敏感信息泄露(密码、密钥、.env)
|
||||
- [ ] 通过 `vendor/bin/pint --test`(后端风格)与 `pnpm lint:eslint`(前端风格)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## 软删除约定
|
||||
|
||||
:::tip 核心原则
|
||||
所有业务数据统一使用软删除机制,通过 `is_delete` 字段标记记录状态,不物理删除数据。
|
||||
所有业务数据统一使用软删除机制,通过 `is_delete` 字段标记记录状态,不物理删除数据(`SoftDeletesByFlag` Trait + `SoftDeleteFlagScope` 全局范围,不使用 `deleted_at`)。
|
||||
:::
|
||||
|
||||
| is_delete 值 | 含义 |
|
||||
@@ -24,11 +24,11 @@ DELETE /api/{module}/delete/{id}
|
||||
### Controller 示例
|
||||
|
||||
```php
|
||||
#[Log('案例演示-删除记录', Log::TYPE_DELETE, '删除案例演示ID:{id}')]
|
||||
#[Permission('sys:example:delete', '删除案例演示')]
|
||||
public function delete(int $id): Json
|
||||
#[OperationLog('案例演示-删除', OperationLog::TYPE_DELETE, '删除案例ID:{id}')]
|
||||
#[Permission('sys:example:delete', '删除案例')]
|
||||
public function delete(int $id): JsonResponse
|
||||
{
|
||||
return parent::_remove($this->logic, $id);
|
||||
return $this->_delete($this->exampleService, $id);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -38,17 +38,17 @@ public function delete(int $id): Json
|
||||
Controller::delete($id)
|
||||
│
|
||||
▼
|
||||
BaseController::_remove($logic, $id)
|
||||
Controller 基类::_delete($service, $id)
|
||||
│
|
||||
▼
|
||||
BaseLogic::delete($id)
|
||||
│
|
||||
├─ beforeDelete($id) 钩子(抛异常可拦截)
|
||||
Service::delete($id) → HasCrudOperations::doDelete($id)
|
||||
│ (DB::transaction 包裹)
|
||||
├─ beforeDelete($id) 钩子(抛异常可拦截,事务回滚)
|
||||
│
|
||||
├─ $model->find($id)
|
||||
│ └─ 不存在 → return false
|
||||
│
|
||||
├─ $model->save(['is_delete' => 1])
|
||||
├─ $model->softDelete() → UPDATE SET is_delete = 1
|
||||
│
|
||||
└─ afterDelete($id) 钩子
|
||||
```
|
||||
@@ -67,12 +67,12 @@ Content-Type: application/json
|
||||
### Controller 示例
|
||||
|
||||
```php
|
||||
#[Log('案例演示-批量删除', Log::TYPE_DELETE)]
|
||||
#[Permission('sys:example:delete', '删除案例演示')]
|
||||
public function batchDelete(): Json
|
||||
#[OperationLog('案例演示-批量删除', OperationLog::TYPE_DELETE)]
|
||||
#[Permission('sys:example:batchDelete', '批量删除案例')]
|
||||
public function batchDelete(): JsonResponse
|
||||
{
|
||||
$ids = $this->getJsonBody()['ids'] ?? [];
|
||||
return parent::_batchRemove($this->logic, $ids);
|
||||
return $this->_batchDelete($this->exampleService, $ids);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,13 +82,13 @@ public function batchDelete(): Json
|
||||
Controller::batchDelete()
|
||||
│
|
||||
▼
|
||||
BaseController::_batchRemove($logic, $ids)
|
||||
Controller 基类::_batchDelete($service, $ids)
|
||||
│
|
||||
├─ ids 为空 → 返回失败 "请选择要删除的数据"
|
||||
│
|
||||
▼
|
||||
BaseLogic::batchDelete($ids)
|
||||
│
|
||||
Service::batchDelete($ids) → HasCrudOperations::doBatchDelete($ids)
|
||||
│ (DB::transaction 包裹)
|
||||
├─ beforeBatchDelete($ids) 钩子(整体校验)
|
||||
│
|
||||
├─ 逐条 beforeDelete($id) 校验
|
||||
@@ -99,12 +99,16 @@ BaseLogic::batchDelete($ids)
|
||||
└─ afterBatchDelete($ids) 钩子
|
||||
```
|
||||
|
||||
:::info 权限码区别
|
||||
单条删除权限为 `sys:{模块}:delete`,批量删除权限为 `sys:{模块}:batchDelete`(代码生成器创建菜单时分别生成),前端按钮需分别控制显隐。
|
||||
:::
|
||||
|
||||
## 删除前校验(beforeDelete 钩子)
|
||||
|
||||
在 Logic 中重写 `beforeDelete` 方法,抛异常可拦截删除:
|
||||
在 Service 中重写 `beforeDelete` 方法,抛异常可拦截删除(事务自动回滚):
|
||||
|
||||
```php
|
||||
class UserLogic extends BaseTenantLogic
|
||||
class DeptService extends BaseTenantService
|
||||
{
|
||||
protected function beforeDelete(int $id): void
|
||||
{
|
||||
@@ -123,11 +127,13 @@ class UserLogic extends BaseTenantLogic
|
||||
}
|
||||
```
|
||||
|
||||
可用钩子(均在 `HasCrudOperations` 中声明):`beforeDelete($id)`、`afterDelete($id)`、`beforeBatchDelete($ids)`、`afterBatchDelete($ids)`。
|
||||
|
||||
## 何时可物理删除
|
||||
|
||||
| 场景 | 方式 | 说明 |
|
||||
|------|------|------|
|
||||
| 日志数据清理 | 定时任务 | CleanLogTask 清理 N 天前的日志 |
|
||||
| 日志数据清理 | 定时任务 | 通过「定时任务」模块(job 表)配置清理 N 天前的日志 |
|
||||
| 临时数据 | 定时任务 | 清理过期的临时文件 |
|
||||
| 其它 | 审批 | 需经过管理员审批 |
|
||||
|
||||
@@ -153,4 +159,4 @@ class UserLogic extends BaseTenantLogic
|
||||
>
|
||||
批量删除 ({{ selectedIds.length }})
|
||||
</el-button>
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 12.7 前端编码规范
|
||||
|
||||
:::tip 概述
|
||||
前端编码规范涵盖 Vue 组件、TypeScript、API 模块、样式和代码风格等方面。
|
||||
前端编码规范涵盖 Vue 组件、TypeScript、API 模块、样式和代码风格等方面。前端工程位于 `ui/` 目录(Vue3 + TypeScript + ElementPlus + Pinia)。
|
||||
:::
|
||||
|
||||
## Vue 组件规范
|
||||
@@ -60,13 +60,13 @@ interface User {
|
||||
status: number;
|
||||
}
|
||||
|
||||
// 枚举定义
|
||||
// 枚举定义(统一放 ui/src/enums/ 下,如 pageEnum.ts、httpEnum.ts)
|
||||
enum UserStatus {
|
||||
ENABLE = 1,
|
||||
DISABLE = 2,
|
||||
}
|
||||
|
||||
// API 响应类型
|
||||
// API 响应类型(分页结构见 12.1/12.2)
|
||||
interface PageResult<T> {
|
||||
records: T[];
|
||||
total: number;
|
||||
@@ -110,21 +110,26 @@ export function userDelete(id: number) {
|
||||
}
|
||||
```
|
||||
|
||||
:::info 路径前缀
|
||||
API 函数中 `url` 不带 `/api` 前缀——由 `ui/.env.production` 的 `VITE_GLOB_API_URL_PREFIX=/api` 在请求层统一拼接。
|
||||
:::
|
||||
|
||||
## 命名规范
|
||||
|
||||
| 类型 | 规范 | 示例 |
|
||||
|------|------|------|
|
||||
| 组件文件 | PascalCase | `BasicTable.vue` |
|
||||
| API 文件 | camelCase | `user.ts` |
|
||||
| API 文件 | camelCase,按模块分目录(`ui/src/api/{模块}/`) | `system/user.ts` |
|
||||
| API 函数 | camelCase | `getUserPage` |
|
||||
| Store 文件 | camelCase | `user.ts` |
|
||||
| Store 文件 | camelCase(`ui/src/store/modules/`) | `user.ts` |
|
||||
| 枚举文件 | camelCase + Enum 后缀(`ui/src/enums/`) | `pageEnum.ts` |
|
||||
| 常量 | UPPER_SNAKE_CASE | `ACCESS_TOKEN` |
|
||||
| CSS 类 | kebab-case | `page-container` |
|
||||
|
||||
## 代码风格
|
||||
|
||||
```bash
|
||||
# ESLint 检查
|
||||
# ESLint 检查(脚本自带 --fix)
|
||||
pnpm lint:eslint
|
||||
|
||||
# Prettier 格式化
|
||||
@@ -132,6 +137,9 @@ pnpm lint:prettier
|
||||
|
||||
# Stylelint 检查
|
||||
pnpm lint:stylelint
|
||||
|
||||
# TypeScript 类型检查
|
||||
pnpm type:check
|
||||
```
|
||||
|
||||
:::warning 禁止事项
|
||||
@@ -139,4 +147,4 @@ pnpm lint:stylelint
|
||||
- 不要使用 `console.log`(生产环境)
|
||||
- 不要在模板中写复杂逻辑(提取为 computed 或方法)
|
||||
- 不要在 `setup` 外使用 Composition API
|
||||
:::
|
||||
:::
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 12.3 Git 提交规范
|
||||
|
||||
:::tip 概述
|
||||
统一的 Git 提交规范有助于代码审查、版本管理和自动化工具集成。
|
||||
统一的 Git 提交规范有助于代码审查、版本管理和自动化工具集成。前端工程提供了 commitlint 配置(`ui/commitlint.config.js`,依赖中含 husky / lint-staged),按其规范提交可通过自动化校验。
|
||||
:::
|
||||
|
||||
## Commit Message 格式
|
||||
@@ -12,18 +12,31 @@
|
||||
<body>
|
||||
```
|
||||
|
||||
:::info 中文友好
|
||||
`ui/commitlint.config.js` 的 `headerPattern` 支持中文 type、全角括号与全角冒号,如 `新增(用户): 导入导出功能` 也可通过校验;建议仍统一使用下述标准 type。头部最长 108 字符。
|
||||
:::
|
||||
|
||||
## Type 类型
|
||||
|
||||
以 `ui/commitlint.config.js` 的 `type-enum` 为准:
|
||||
|
||||
| type | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `feat` | 新功能 | `feat(user): 新增用户导入导出功能` |
|
||||
| `fix` | 修复 Bug | `fix(login): 修复验证码过期后仍可使用的问题` |
|
||||
| `docs` | 文档 | `docs: 更新 API 接口文档` |
|
||||
| `style` | 代码格式(不影响功能) | `style: 统一代码缩进` |
|
||||
| `refactor` | 重构 | `refactor(logic): 优化分页查询性能` |
|
||||
| `perf` | 性能优化 | `perf(dict): 增加字典缓存减少数据库查询` |
|
||||
| `style` | 代码格式(不影响功能) | `style: 统一代码缩进` |
|
||||
| `docs` | 文档 | `docs: 更新 API 接口文档` |
|
||||
| `test` | 测试 | `test: 添加用户模块单元测试` |
|
||||
| `chore` | 构建/工具 | `chore: 更新 Composer 依赖` |
|
||||
| `refactor` | 重构 | `refactor(service): 优化分页查询性能` |
|
||||
| `build` | 构建 | `build: 升级 Vite 构建配置` |
|
||||
| `ci` | CI 配置 | `ci: 补充后端 Pint 检查步骤` |
|
||||
| `chore` | 杂项/工具 | `chore: 更新 Composer 依赖` |
|
||||
| `revert` | 回滚 | `revert: 回滚 feat(user) 导入功能` |
|
||||
| `wip` | 进行中 | `wip(user): 导入导出开发中` |
|
||||
| `workflow` | 工作流 | `workflow: 调整分支保护规则` |
|
||||
| `types` | 类型定义 | `types: 补充前端 API 类型声明` |
|
||||
| `release` | 发版 | `release: v1.2.0` |
|
||||
|
||||
## Scope 范围
|
||||
|
||||
@@ -62,7 +75,7 @@ git commit -m "docs: 补充多数据库部署文档"
|
||||
# -----------------------------------------------------------------------------
|
||||
# 重构(refactor)
|
||||
# -----------------------------------------------------------------------------
|
||||
git commit -m "refactor(logic): 统一删除前校验逻辑"
|
||||
git commit -m "refactor(service): 统一删除前校验逻辑"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 性能优化(perf)
|
||||
@@ -73,45 +86,60 @@ git commit -m "perf(dict): 增加请求级缓存减少重复查询"
|
||||
## 注意事项
|
||||
|
||||
:::warning 禁止事项
|
||||
- 不要提交调试代码(`console.log`、`dump`、`var_dump`)
|
||||
- 不要提交敏感信息(密码、密钥、Token)
|
||||
- 不要提交调试代码(`console.log`、`dd()`、`dump`、`var_dump`)
|
||||
- 不要提交敏感信息(密码、密钥、Token、`.env`)
|
||||
- 不要提交 IDE 配置文件(`.idea/`、`.vscode/`)
|
||||
- 一个 commit 只做一件事
|
||||
:::
|
||||
|
||||
## .gitignore
|
||||
|
||||
项目根目录 `.gitignore` 关键规则:
|
||||
|
||||
```gitignore
|
||||
# =============================================================================
|
||||
# .gitignore — Git 版本控制忽略规则
|
||||
# .gitignore — Git 版本控制忽略规则(摘自项目根目录,含说明)
|
||||
# =============================================================================
|
||||
# 匹配的文件不会被 git track(不会提交到仓库)
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 运行时目录(ThinkPHP 缓存、日志、编译模板 — 自动生成,无需版本控制)
|
||||
# -----------------------------------------------------------------------------
|
||||
runtime/
|
||||
vendor/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 环境配置(包含数据库密码等敏感信息 — 绝不能提交)
|
||||
# 环境配置与备份(包含数据库密码、JWT 密钥等敏感信息 — 绝不能提交)
|
||||
# -----------------------------------------------------------------------------
|
||||
.env
|
||||
.env.backup
|
||||
.env.production
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# IDE 配置文件(每个开发者的 IDE 设置不同 — 不应互相影响)
|
||||
# 运行时与依赖(自动生成/体积庞大,通过 composer install、npm install 重建)
|
||||
# -----------------------------------------------------------------------------
|
||||
.idea/
|
||||
.vscode/
|
||||
/vendor
|
||||
/node_modules
|
||||
/storage/*.key
|
||||
/storage/pail
|
||||
/public/build
|
||||
/public/hot
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 临时上传文件(用户上传的临时文件 — 不属于代码)
|
||||
# IDE 与系统文件(每个开发者的环境不同 — 不应互相影响)
|
||||
# -----------------------------------------------------------------------------
|
||||
uploads/temp/
|
||||
/.idea
|
||||
/.vscode
|
||||
/.fleet
|
||||
/.nova
|
||||
/.zed
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 前端依赖(node_modules 体积庞大 — 通过 pnpm install 重新安装即可)
|
||||
# 测试与工具缓存
|
||||
# -----------------------------------------------------------------------------
|
||||
ui/node_modules/
|
||||
*.log
|
||||
/.phpunit.cache
|
||||
.phpunit.result.cache
|
||||
.phpactor.json
|
||||
```
|
||||
|
||||
:::info 前端依赖
|
||||
前端依赖忽略规则由 `ui/node_modules`(`.gitignore` 中 `/node_modules` 对应各前端包目录)覆盖,`pnpm-lock.yaml` **必须提交**(保证依赖版本一致)。
|
||||
:::
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 12.2 分页查询规范
|
||||
|
||||
:::tip 概述
|
||||
所有分页接口遵循统一的参数命名和返回结构,确保前后端一致性。
|
||||
所有分页接口遵循统一的参数命名和返回结构,确保前后端一致性。详细机制见 [8.3 分页查询规范](/zh/api-spec/pagination.html)。
|
||||
:::
|
||||
|
||||
## 请求参数
|
||||
@@ -9,11 +9,11 @@
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `pageNo` | number | 1 | 页码(最小为 1) |
|
||||
| `pageSize` | number | 20 | 每页条数(1~100) |
|
||||
| `pageSize` | number | 20 | 每页条数(1~100,超出自动限制) |
|
||||
| `orderField` | string | - | 排序字段(camelCase,如 `createTime`) |
|
||||
| `orderType` | string | `desc` | 排序方向(`asc` / `desc`) |
|
||||
| `fields` | string | - | 返回字段(逗号分隔,如 `id,username,status`) |
|
||||
| 其他参数 | - | - | 按 Logic 中 pageLikeFields / pageEqFields 自动匹配 |
|
||||
| 其他参数 | - | - | 按 Service 中 pageLikeFields / pageEqFields 自动匹配 |
|
||||
|
||||
## 请求示例
|
||||
|
||||
@@ -62,4 +62,8 @@ GET /api/example/page?pageNo=1&pageSize=10&fields=id,name,status
|
||||
| 前端传参 | 后端处理 | SQL |
|
||||
|---------|---------|-----|
|
||||
| `orderField=createTime&orderType=desc` | 转为 `create_time` | `ORDER BY create_time DESC` |
|
||||
| 不传 | 使用 Logic 默认排序 | 按 `pageOrderBy` 配置 |
|
||||
| 不传 | 使用 Service 默认排序 | 按 `pageOrderBy` 配置 |
|
||||
|
||||
:::warning 排序白名单
|
||||
`orderField` 只在 **`pageOrderBy` 默认字段 ∪ `orderFieldAllow`** 的并集内生效,不在白名单内的字段直接忽略(防 SQL 注入)。开放新排序字段请配置 `orderFieldAllow`。
|
||||
:::
|
||||
|
||||
Reference in New Issue
Block a user