Files
MrleeAdmin/.windsurf/skills/cross-fullstack-admin-crud-feature/SKILL.md
T

477 lines
12 KiB
Markdown
Raw Normal View History

2026-08-31 11:33:59 +08:00
---
name: cross-fullstack-admin-crud-feature
description: Full-stack development workflow for Madong Admin CRUD features. Covers requirement analysis, existing implementation verification, backend migration/model/DAO/service/validate/schema/controller, frontend API/page/schema, menu permissions, migration execution, validation, and skill auto-evolution.
globs:
- "backend/app/**/*.php"
- "backend/resource/database/migrations/**/*.php"
- "backend/resource/data/menu/**/*.php"
- "frontend/admin/src/api/**/*.ts"
- "frontend/admin/src/views/**/*.vue"
- "frontend/admin/src/views/**/*.tsx"
- ".windsurf/skills/**/*.md"
---
# Madong Admin 全栈 CRUD 功能开发流程
用于开发类似“应用授权”这类后台管理功能,覆盖数据库、后端、前端、菜单权限、迁移执行与校验。
## 适用场景
- 在 Admin 后台新增一个业务管理页面。
- 需要新增数据库表、后端 CRUD、前端列表/表单/API。
- 需要菜单入口和按钮权限。
- 需要参考现有模块目录结构,例如 `/tools/delegation`、`/setting/notice`。
- 需要自动生成字段或自定义操作,例如 Access Key / Secret Key 自动生成、重置密钥。
## 总原则
1. 先核对项目真实实现,再使用 skill 或模板。
2. 以现有项目代码为准,skill 与项目不一致时先更新 skill。
3. 优先复用官方现有组件和基类。
4. 不直接照搬 Laravel Artisan 命令,当前项目使用 Webman/Madong 命令体系。
5. 数据库迁移执行前必须先 dry-run,确认会执行哪些迁移。
6. 前后端路径、权限码、菜单码必须保持一致。
## 开发前检查
### 1. 确认参考模块
优先读取用户指定的参考模块。
常见参考:
- `frontend/admin/src/views/setting/notice`
- `frontend/admin/src/views/tools/delegation`
- `frontend/admin/src/api/tools/delegation`
- `backend/app/adminapi/controller/notice/NoticeController.php`
- `backend/app/adminapi/controller/plugin/PluginMadongAuthController.php`
### 2. 确认真实项目规范
至少核对以下内容:
- 后端控制器是否继承 `app\adminapi\controller\Crud`。
- 模型是否继承 `core\base\BaseModel`。
- DAO 是否继承 `core\base\BaseDao`。
- Service 是否继承 `core\base\BaseService`。
- Validate 是否继承 `core\base\BaseValidate`。
- 前端 CRUD 是否使用 `useCrud`、`CrudSchema`、`BasicCrud`。
- 前端 API 是否使用 `BaseService` 和 `@/utils/http`。
- 表单组件名是否存在于 `frontend/admin/src/components/form/components`。
- 菜单数据是否维护在 `backend/resource/data/menu/admin.php`。
## 后端开发流程
### 1. 数据库迁移
路径:
```text
backend/resource/database/migrations/{timestamp}_create_{table}_table.php
```
当前项目雪花 ID 主键写法:
```php
$table->bigInteger('id')->primary()->comment('主键');
```
不要使用 Laravel 默认的:
```php
$table->id();
```
字段设计要求:
- 主键使用雪花 ID。
- 按需增加唯一索引、普通索引。
- 状态字段常用 `enabled`,默认 `1`。
- 时间字段按项目迁移写法使用 `timestamps()` 或项目已有封装。
- 如果模型使用软删除,迁移需包含软删除字段。
### 2. Model
路径:
```text
backend/app/model/{module}/{Model}.php
```
要求:
- 继承 `core\base\BaseModel`。
- 设置 `$table`。
- 设置 `$fillable`。
- 设置 `$casts`。
- 如项目同类模型使用软删除,则保持一致。
### 3. DAO
路径:
```text
backend/app/dao/{module}/{Model}Dao.php
```
要求:
- 继承 `core\base\BaseDao`。
- `setModel()` 返回模型类。
- 如需关键字搜索,按项目已有 DAO 实现 `getKeywordFields()`。
### 4. Service
路径:
```text
backend/app/service/admin/{module}/{Model}Service.php
```
要求:
- 继承 `core\base\BaseService`。
- 构造函数注入 DAO。
- 自定义业务逻辑放在 Service。
- 自动生成字段在 `save()` / `create()` 入口处理。
- 自定义操作单独暴露方法,例如 `resetSecret()`。
应用授权类功能示例:
- 新增时自动生成 `access_key`。
- 新增时自动生成 `secret_key`。
- 重置时只更新 `secret_key`。
- 密钥生成应使用安全随机源,例如 `random_bytes()`。
### 5. Validate
路径:
```text
backend/app/adminapi/validate/{module}/{Model}Validate.php
```
要求:
- 继承 `core\base\BaseValidate`。
- 定义 `$rule`、`$message`、`$scene`。
- `store` 场景不要求 `id`。
- `update` 场景要求 `id`。
- 自动生成字段不要暴露为必填输入。
### 6. Request / Response Schema
请求路径:
```text
backend/app/adminapi/schema/request/{module}/{Model}FormRequest.php
backend/app/adminapi/schema/request/{module}/{Model}QueryRequest.php
```
响应路径:
```text
backend/app/adminapi/schema/response/{module}/{Model}Response.php
```
要求:
- FormRequest 继承项目实际存在的表单基类。
- QueryRequest 使用项目实际存在的 `BaseQueryRequest`。
- 不要引用不存在的 `PageRequest`。
- OpenAPI 属性需与控制器 `x: [SchemaConstants::X_SCHEMA_REQUEST => ...]` 对应。
### 7. Controller
路径:
```text
backend/app/adminapi/controller/{module}/{Model}Controller.php
```
要求:
- 继承 `Crud`。
- 构造函数注入 Service 和 Validate。
- 标准接口调用 `parent::index()`、`parent::show()`、`parent::store()`、`parent::update()`、`parent::destroy()`。
- 路由通过 OpenAPI Attribute 标注。
- 权限码与前端和菜单保持一致。
推荐路由格式:
```text
GET /{module}/{resource}
GET /{module}/{resource}/{id}
POST /{module}/{resource}
PUT /{module}/{resource}/{id}
DELETE /{module}/{resource}/{id}
POST /{module}/{resource}/{id}/{custom-action}
```
应用授权示例:
```text
/plugin/application-auth
/plugin/application-auth/{id}
/plugin/application-auth/{id}/reset-secret
```
## 前端开发流程
### 1. API
路径参考用户指定目录结构。
例如参考 `/tools/delegation` 时:
```text
frontend/admin/src/api/tools/{feature}/index.ts
frontend/admin/src/api/tools/{feature}/types.ts
```
要求:
- 使用 `BaseService`。
- 使用 `@/utils/http`。
- 基础路径与后端路由一致。
- 自定义接口单独封装方法。
示例:
```ts
const baseUrl = '/plugin/application-auth'
```
### 2. 页面
路径参考用户指定目录结构。
例如参考 `/tools/delegation` 时:
```text
frontend/admin/src/views/tools/{feature}/index.vue
frontend/admin/src/views/tools/{feature}/schemas/index.tsx
```
要求:
- 使用 `useCrud` 和 `BasicCrud`。
- CRUD 配置写在 `schemas/index.tsx`。
- 不要使用项目未注册的表单组件。
- 当前项目日期时间选择使用 `DatePicker` + `componentProps.type = 'datetime'`。
- 当前项目 `CrudSchema` 列类型不支持 `type: 'operate'`,操作列由 `BasicCrud` 根据 `tableActions` / `dropDownActions` 自动生成。
### 3. 列表字段
按照用户需求定义:
- 序号:`type: 'index'`
- 名称:普通列
- Access Key:建议列表遮罩显示
- Secret Key:建议列表遮罩显示
- 失效时间:使用 `formatDateTime`
- 状态:使用 `ApiDict`
- 描述:`showOverflowTooltip`
- 创建时间:优先使用后端格式化字段,或 `formatDateTime(created_at)`
- 操作:通过 CRUD 操作配置生成
### 4. 表单字段
自动生成字段不要出现在新增表单中。
应用授权示例:
- `name`:必填
- `expired_at`:可选
- `enabled`:必填,默认 `1`
- `description`:可选
- `access_key`:后端自动生成,不手填
- `secret_key`:后端自动生成,不手填
### 5. 自定义操作
例如重置 Secret Key:
- 前端按钮放在 `dropDownActions` 或项目实际支持的操作配置中。
- 按钮增加 `auth`。
- 操作前使用 `ElMessageBox.confirm` 二次确认。
- 成功后提示新密钥并刷新列表。
## 菜单与权限
菜单数据路径:
```text
backend/resource/data/menu/admin.php
```
页面菜单示例字段:
```php
"title" => "应用授权",
"code" => "plugin:application-auth:list",
"type" => 2,
"path" => "/tools/application-auth",
"component" => "/tools/application-auth/index",
"methods" => "GET",
```
按钮权限建议补齐:
```text
plugin:application-auth:create
plugin:application-auth:delete
plugin:application-auth:update
plugin:application-auth:read
plugin:application-auth:reset-secret
```
按钮节点:
- `type` 使用 `3`。
- `is_show` 使用 `0`。
- `path`、`component`、`icon` 通常为 `null`。
- `methods` 与接口方法保持一致。
## 迁移执行流程
当前项目没有 Laravel `artisan` 文件,不使用:
```bash
php artisan migrate
php artisan migrate:status
```
当前项目使用:
```bash
php webman madong-migrate status
php webman madong-migrate up --dry-run
php webman madong-migrate up
```
### 执行前必须 dry-run
```bash
php webman madong-migrate up --dry-run
```
确认输出中将执行的迁移文件。
注意:
- `madong-migrate up` 会执行所有未执行迁移。
- 当前命令不支持 Laravel 的 `--path=` 单文件迁移参数。
- 如果只允许迁移单个文件,不要直接执行 `madong-migrate up`。
### 事务异常注意事项
如果执行迁移时出现:
```text
There is no active transaction
```
常见原因:
- MySQL DDL 会隐式提交事务。
- 迁移命令将多个 DDL 包在事务中,可能导致事务管理器提交时发现事务已结束。
处理流程:
1. 先不要重复执行迁移。
2. 检查数据表是否已经创建成功。
3. 执行 `php webman madong-migrate status` 查看迁移日志状态。
4. 如果表已创建但日志未写入,需要谨慎补齐迁移日志或修复迁移命令事务逻辑后再处理。
5. 不要盲目回滚或再次执行全部迁移,避免表已存在导致二次错误。
## 校验清单
### 后端校验
对新增 PHP 文件执行语法检查:
```bash
php -l app/model/{module}/{Model}.php
php -l app/dao/{module}/{Model}Dao.php
php -l app/service/admin/{module}/{Model}Service.php
php -l app/adminapi/validate/{module}/{Model}Validate.php
php -l app/adminapi/schema/request/{module}/{Model}FormRequest.php
php -l app/adminapi/schema/request/{module}/{Model}QueryRequest.php
php -l app/adminapi/schema/response/{module}/{Model}Response.php
php -l app/adminapi/controller/{module}/{Model}Controller.php
php -l resource/database/migrations/{migration_file}.php
php -l resource/data/menu/admin.php
```
### 前端校验
只检查新增文件:
```bash
pnpm exec eslint src/views/{module}/{feature}/index.vue src/views/{module}/{feature}/schemas/index.tsx src/api/{module}/{feature}/index.ts src/api/{module}/{feature}/types.ts
```
### 路径一致性校验
检查以下内容必须一致:
- 后端 Controller OpenAPI path。
- 前端 API `baseUrl`。
- 菜单 `path`。
- 菜单 `component`。
- 前端 view 文件路径。
- 权限码。
## Skill 自动进化规则
开发过程中如果发现 skill 与真实项目不一致,必须先更新 skill,再继续使用。
需要自动进化的典型情况:
- 迁移主键写法与项目不一致。
- 前端 API 模板导入路径不一致。
- 表单组件名不存在。
- CRUD 列类型与 TypeScript 类型不一致。
- 菜单权限结构与项目实际不一致。
- 路由路径或权限码规则与项目实际不一致。
更新要求:
- 只更新已验证的不一致点。
- 不做无关重写。
- 最终总结中说明更新了哪些 skill。
## 完整输出清单
完成一个 Admin 全栈 CRUD 功能后,应至少包含:
```text
backend/resource/database/migrations/{migration}.php
backend/app/model/{module}/{Model}.php
backend/app/dao/{module}/{Model}Dao.php
backend/app/service/admin/{module}/{Model}Service.php
backend/app/adminapi/validate/{module}/{Model}Validate.php
backend/app/adminapi/schema/request/{module}/{Model}FormRequest.php
backend/app/adminapi/schema/request/{module}/{Model}QueryRequest.php
backend/app/adminapi/schema/response/{module}/{Model}Response.php
backend/app/adminapi/controller/{module}/{Model}Controller.php
frontend/admin/src/api/{section}/{feature}/index.ts
frontend/admin/src/api/{section}/{feature}/types.ts
frontend/admin/src/views/{section}/{feature}/index.vue
frontend/admin/src/views/{section}/{feature}/schemas/index.tsx
backend/resource/data/menu/admin.php
```
## 最终回复模板
完成后向用户说明:
- 新增了哪些后端文件。
- 新增了哪些前端文件。
- 菜单和权限是否已配置。
- 迁移是否执行,执行结果如何。
- 校验命令和结果。
- 是否自动进化了 skill。
- 是否有需要用户后续处理的事项。