服务端
Some checks failed
CI / init (push) Has been cancelled
CI / Frontend node 18.16.0 (push) Has been cancelled
CI / Backend go (1.22) (push) Has been cancelled
CI / devops-test (1.22, 18.16.0) (push) Has been cancelled
CI / release-pr (push) Has been cancelled
CI / release-please (push) Has been cancelled
CI / devops-prod (1.22, 18.x) (push) Has been cancelled
CI / docker (push) Has been cancelled
Some checks failed
CI / init (push) Has been cancelled
CI / Frontend node 18.16.0 (push) Has been cancelled
CI / Backend go (1.22) (push) Has been cancelled
CI / devops-test (1.22, 18.16.0) (push) Has been cancelled
CI / release-pr (push) Has been cancelled
CI / release-please (push) Has been cancelled
CI / devops-prod (1.22, 18.x) (push) Has been cancelled
CI / docker (push) Has been cancelled
This commit is contained in:
96
server/.ai-specs/coding-specs/api-auth-control.md
Normal file
96
server/.ai-specs/coding-specs/api-auth-control.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# API 鉴权与权限修改规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 新增接口时,需要判定它是“公开访问”“仅登录可访问”还是“登录且有权限才可访问”时,使用本文。
|
||||
- 已有接口在“不需要登录 / 需要登录 / 需要权限”之间切换时,使用本文。
|
||||
|
||||
## 现有鉴权基线
|
||||
|
||||
- `initialize/router.go` 当前只创建两类顶层路由组:
|
||||
- `PublicGroup`:不挂鉴权中间件。
|
||||
- `PrivateGroup`:统一挂 `middleware.JWTAuth()` 和 `middleware.CasbinHandler()`。
|
||||
- `JWTAuth` 定义在 `middleware/jwt.go`。
|
||||
- `CasbinHandler` 定义在 `middleware/casbin_rbac.go`。
|
||||
- 结论:
|
||||
- 挂到 `PublicGroup` = 不需要登录。
|
||||
- 挂到 `PrivateGroup` = 需要登录,且需要角色权限。
|
||||
- 当前仓库没有默认内置的“只登录、不校验权限”公共组。
|
||||
- 不存在“只校验权限、不登录”的合法模式;`CasbinHandler` 依赖 `JWTAuth` 写入的用户 claims。
|
||||
|
||||
## 权限模式判定
|
||||
|
||||
| 模式 | 路由挂载方式 | JWT | Casbin | 后续要求 |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 不需要登录 | `PublicGroup` / `PublicRouter` | 否 | 否 | 默认不作为角色权限点长期维护 |
|
||||
| 需要登录,不需要权限 | 基于 `PublicRouter` 单独加 `middleware.JWTAuth()` | 是 | 否 | 默认不进入角色权限维护 |
|
||||
| 需要登录且需要权限 | `PrivateGroup` / `Router` | 是 | 是 | 必须进入 `sys_apis` 并分配角色 |
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 同一个 `path + method` 只能落一种鉴权模式;禁止同时注册到公开组和鉴权组。
|
||||
- `middleware.OperationRecord()` 只负责操作审计,不改变登录与权限判定。
|
||||
- 鉴权逻辑统一落在 `router` 层;禁止在 `API` 或 `Service` 中靠 `if token != ""`、`if authorityId == ...` 兜底模拟权限。
|
||||
- 修改接口鉴权时,Swagger 注解必须同步:
|
||||
- 不需要登录:移除 `@Security ApiKeyAuth`
|
||||
- 需要登录:保留 `@Security ApiKeyAuth`
|
||||
- 业务路由统一在 `router/<module>` 调整;业务模块接入点统一在 `initialize/router_biz.go` 注册。
|
||||
|
||||
## 改成不需要登录
|
||||
|
||||
- 把路由挂载从 `PrivateGroup` 或“仅登录组”移到 `PublicRouter`。
|
||||
- 如果只是业务模块内部路由调整,不要改 `API`、`Service` 方法签名。
|
||||
- 该接口如果不再作为后台角色权限点维护,必须把对应 `path + method` 从权限维护中移走,二选一即可:
|
||||
- 删除对应 `sys_apis` 记录。
|
||||
- 加入 `sys_ignore_apis`,避免后续 `SyncApi` 再次纳入权限页。
|
||||
- 若历史上已经给该接口分配过角色,必须同步清理对应 Casbin 规则,避免后台权限配置出现“看起来要授权、实际上公开可调”的假象。
|
||||
|
||||
## 改成需要登录,不需要权限
|
||||
|
||||
- 当前项目没有全局现成的 `LoginGroup`;少量接口优先在对应 router 中基于 `PublicRouter` 单独挂 `JWTAuth`,不要为了一两个接口改全局入口。
|
||||
- 推荐写法:
|
||||
|
||||
```go
|
||||
func (r *BookRouter) InitBookRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||
bookLoginRouter := PublicRouter.Group("book").Use(middleware.JWTAuth())
|
||||
{
|
||||
bookLoginRouter.GET("profile", bookApi.GetProfile)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 同一模块里如果“仅登录接口”很多,再考虑在 `initialize/router.go` 新增单独的 `LoginGroup`,并把它显式传入对应 router 初始化函数。
|
||||
- 这类接口禁止挂 `middleware.CasbinHandler()`。
|
||||
- 这类接口默认不进入 `sys_apis` 的角色权限维护;如果历史上已经进入,必须删除或加入 `sys_ignore_apis`,不要继续让后台把它当作“需要分配角色”的接口。
|
||||
|
||||
## 改成需要登录且需要权限
|
||||
|
||||
- 把路由挂到 `PrivateGroup` 或业务 router 的 `Router` 参数上。
|
||||
- 只把路由挪进 `PrivateGroup` 还不够;`CasbinHandler` 按 `path + method` 校验权限,没有角色策略就会直接返回“权限不足”。
|
||||
- 因此必须同时完成以下动作:
|
||||
- 确保该 `path + method` 存在于 `sys_apis`。
|
||||
- 确保该接口已分配允许访问的角色。
|
||||
- 刷新 Casbin 策略缓存。
|
||||
- 系统现成接口的完整路径 = `<router-prefix>/api/...`;如果 `router-prefix` 为空,则完整路径就是 `/api/...`。不要把是否存在额外前缀写死成项目事实。
|
||||
- 常用管理接口:
|
||||
- `GET <router-prefix>/api/syncApi`:对比内存路由和 `sys_apis`
|
||||
- `POST <router-prefix>/api/enterSyncApi`:确认把新增路由写入 `sys_apis`
|
||||
- `POST <router-prefix>/api/setApiRoles`:全量覆盖某个接口的角色列表
|
||||
- `GET <router-prefix>/api/freshCasbin`:刷新 Casbin 策略缓存
|
||||
- 若接口此前在 `sys_ignore_apis` 中,改成“需要权限”前必须先取消 ignore,再同步到 `sys_apis`。
|
||||
- 若不给任何角色分配该接口,则结果不是“仅登录可访问”,而是“所有已登录用户都权限不足”。
|
||||
|
||||
## 验证要求
|
||||
|
||||
- 修改完成后,至少验证下面三类请求结果:
|
||||
- 公开接口:不带 token 可访问成功。
|
||||
- 仅登录接口:不带 token 返回未登录;带有效 token 可访问成功。
|
||||
- 权限接口:不带 token 返回未登录;带无权角色 token 返回“权限不足”;带有权角色 token 可访问成功。
|
||||
- 如果改了接口鉴权方式,同时该接口出现在 Swagger、前端权限配置页、角色配置页,也必须同步核对展示结果是否一致。
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止只改 `sys_apis` 或 `casbin_rule`,却不改真实 router 挂载。
|
||||
- 禁止只把路由从 `PublicGroup` 挪到 `PrivateGroup`,却不补 `sys_apis` 和角色策略。
|
||||
- 禁止把“仅登录接口”偷懒挂到 `PrivateGroup`,再靠给所有角色放权来模拟“无权限限制”。
|
||||
- 禁止让公开接口长期保留在角色权限维护页里,造成权限含义失真。
|
||||
42
server/.ai-specs/coding-specs/module-admin-app-split.md
Normal file
42
server/.ai-specs/coding-specs/module-admin-app-split.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 同模块 admin/app 接口分层规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 同一业务模块同时存在 `admin` 管理端接口和 `app` 用户端接口时,使用本文。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 顶层目录一律按业务模块落点;禁止因为有 `app` 端,就单独新建顶层 `router/app`、`api/v1/app`、`service/app`、`model/app` 来承载 `book`、`order`、`author` 这类业务。
|
||||
- 同一业务模块的实体仍统一放在 `model/<module>`;只有接口入参、出参和流程按 `admin` / `app` 分开。
|
||||
- `router/<module>`、`api/v1/<module>`、`service/<module>` 内,`admin` 与 `app` 接口必须分文件或分承载结构体;禁止长期混写在同一个大文件里。
|
||||
- 可复用逻辑优先下沉到 `service/<module>` 的公共方法;公共逻辑只抽业务共性,不要把 `admin` / `app` 的鉴权、返回、分页口径硬揉成一套。
|
||||
|
||||
## 推荐落点
|
||||
|
||||
- 推荐文件名:`<module>_admin.go`、`<module>_app.go`、`enter.go`。
|
||||
- 示例:
|
||||
- `router/book/book_admin.go`
|
||||
- `router/book/book_app.go`
|
||||
- `api/v1/book/book_admin.go`
|
||||
- `api/v1/book/book_app.go`
|
||||
- `service/book/book_admin.go`
|
||||
- `service/book/book_app.go`
|
||||
- `service/book/book_common.go`
|
||||
- `model/book/book.go`
|
||||
- `model/book/request/book_admin.go`
|
||||
- `model/book/request/book_app.go`
|
||||
- `model/book/response/book_admin.go`
|
||||
- `model/book/response/book_app.go`
|
||||
|
||||
## 路由与鉴权
|
||||
|
||||
- `admin` 接口默认挂业务 router 的 `PrivateGroup`,走后台 `JWT + Casbin`。
|
||||
- `app` 公开接口挂 `PublicGroup`。
|
||||
- `app` 仅登录接口,基于 `PublicGroup` 单独加 `middleware.JWTAuth()`;不要直接挂 `PrivateGroup`。
|
||||
- 如果 `app` 用户体系不等于 `sys_users`,禁止直接复用后台登录、claims、角色权限链路;必须单独实现用户端认证链路。
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止把“同一业务模块的 app 端接口”误建成独立业务模块。
|
||||
- 禁止为了省事,把所有 `app` 接口都挂到 `PrivateGroup`,再用后台角色权限去模拟用户端登录态。
|
||||
- 禁止同一个业务实体在 `model` 层拆出两套重复表结构,仅因接口面向 `admin` / `app` 不同。
|
||||
54
server/.ai-specs/coding-specs/module-admin-crud-default.md
Normal file
54
server/.ai-specs/coding-specs/module-admin-crud-default.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# 业务 admin 端默认 CRUD 接口规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 新增业务模块的 `admin` 端管理接口时,使用本文。
|
||||
- 判断某个业务模块默认应该提供哪些后台 CRUD 接口时,使用本文。
|
||||
- 业务模块没有明确说明“只读”“无详情”“禁止批量删除”等例外时,默认按本文落地。
|
||||
|
||||
## 默认接口基线
|
||||
|
||||
- 默认 CRUD = `创建`、`单删`、`批量删除`、`更新`、`详情`、`分页列表` 6 个接口。
|
||||
- 完整路径 = `<router-prefix>/<abbreviation>/...`;如果 `router-prefix` 为空,则完整路径不带额外前缀。禁止把 `/api` 写死为项目事实。
|
||||
- `admin` 接口默认挂 `PrivateGroup`,统一走后台 `JWT + Casbin`。
|
||||
- 写操作默认挂 `middleware.OperationRecord()`;读操作默认不挂操作审计。
|
||||
|
||||
| 动作 | Method | 默认路径 | API 方法名 | Service 方法名 |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 创建 | `POST` | `/<abbreviation>/create<StructName>` | `Create<StructName>` | `Create<StructName>` |
|
||||
| 单删 | `DELETE` | `/<abbreviation>/delete<StructName>` | `Delete<StructName>` | `Delete<StructName>` |
|
||||
| 批量删除 | `DELETE` | `/<abbreviation>/delete<StructName>ByIds` | `Delete<StructName>ByIds` | `Delete<StructName>ByIds` |
|
||||
| 更新 | `PUT` | `/<abbreviation>/update<StructName>` | `Update<StructName>` | `Update<StructName>` |
|
||||
| 详情 | `GET` | `/<abbreviation>/find<StructName>` | `Find<StructName>` | `Get<StructName>` |
|
||||
| 分页列表 | `GET` | `/<abbreviation>/get<StructName>List` | `Get<StructName>List` | `Get<StructName>InfoList` |
|
||||
|
||||
## 参数约定
|
||||
|
||||
- `Create`、`Update` 默认使用 `body` 传实体或业务 `request`。
|
||||
- `Delete` 默认用主键 query 参数删除;主键名必须和实体主键字段保持一致。
|
||||
- `DeleteByIds` 默认用主键数组 query 参数删除,格式统一为 `<primaryField>s[]`。
|
||||
- `Find` 默认用主键 query 参数查询详情。
|
||||
- `GetList` 默认接收 `model/<module>/request` 下的搜索结构;普通列表返回分页结果,树形列表可不接分页参数,但接口名仍保持 `get<StructName>List`。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 新增业务 `admin` 模块时,如无明确例外,先提供这 6 个接口,再叠加业务特有接口。
|
||||
- 路由统一放在 `router/<module>`,接口统一放在 `api/v1/<module>`,业务统一放在 `service/<module>`,模型统一放在 `model/<module>`。
|
||||
- 新增业务路由后,必须同步在 `initialize/router_biz.go` 注册。
|
||||
- 同一模块如果同时有 `admin/app` 两套接口,目录仍按业务模块落点,`admin` 与 `app` 必须分文件或分承载结构体,不能长期混写。
|
||||
- Swagger 注解里的 `@Router`、`@Security ApiKeyAuth`、`Method` 必须和真实 router 挂载一致。
|
||||
|
||||
## 允许例外
|
||||
|
||||
- 业务天然只读时,可以不做 `Create`、`Update`、`Delete`、`DeleteByIds`,但必须在对应业务文档或接口文档中明确说明。
|
||||
- 业务明确禁止批量删除时,可以去掉 `DeleteByIds`,但 `router`、`api`、`service`、前端调用、权限点必须同步移除,不能只删单层。
|
||||
- 树形实体的列表接口可以返回整棵树,不强制分页;但接口名仍保持 `get<StructName>List`,不要随意改成 `tree`、`all`、`queryList`。
|
||||
- 配置型场景如果本质不是独立业务实体,优先复用已有能力,例如 `sys_params`;不要为了凑 CRUD 强行建完整业务模块。
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止把默认 `admin` CRUD 直接挂到 `PublicGroup`。
|
||||
- 禁止同一批后台 CRUD 同时出现 `createXxx`、`addXxx`、`saveXxx` 多套命名。
|
||||
- 禁止把列表接口随意命名成 `page`、`list`、`query`,导致不同模块接口风格漂移。
|
||||
- 禁止只新增 `API` 或只新增 `Router`,不补齐 `Service`、`Model`、注册入口。
|
||||
- 禁止因为有 `app` 端,就把 `admin` 端默认 CRUD 改落到 `router/app`、`api/v1/app` 这类顶层目录。
|
||||
158
server/.ai-specs/coding-specs/sys-params.md
Normal file
158
server/.ai-specs/coding-specs/sys-params.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# 系统参数(SysParams)使用规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 需要读取或写入 `sys_params` 表中的系统参数时,使用本文。
|
||||
- 需要给某一个固定参数提供独立业务 API,但底层仍保存到 `sys_params` 时,使用本文。
|
||||
|
||||
## 现有落点
|
||||
|
||||
- 表结构:`model/system/sys_params.go`
|
||||
- Service:`service/system/sys_params.go`
|
||||
- API:`api/v1/system/sys_params.go`
|
||||
- Router:`router/system/sys_params.go`
|
||||
|
||||
## 现有接口
|
||||
|
||||
- 实际完整路径 = `<router-prefix>/sysParams/...`。
|
||||
- 如果环境把 `router-prefix` 配成 `/api`,则完整路径就是 `/api/sysParams/...`。
|
||||
- 当前仓库 `config.yaml` 中 `router-prefix` 默认值为空字符串;不要把 `/api` 写死为项目事实。
|
||||
- 这组路由在 `initialize/router.go` 中挂到 `PrivateGroup`,默认需要鉴权。
|
||||
- `GET /sysParams/getSysParam?key=xxx`:按 `key` 读取单条参数。
|
||||
- `GET /sysParams/getSysParamsList`:分页读取参数列表。
|
||||
- `POST /sysParams/createSysParams`:创建参数。
|
||||
- `PUT /sysParams/updateSysParams`:按 `ID` 更新参数。
|
||||
- `DELETE /sysParams/deleteSysParams`:按 `ID` 删除参数。
|
||||
- 结论:这组接口适合“通用参数管理页”,不适合业务围绕某一个固定参数直接做长期读写。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 后端代码禁止通过 HTTP 反调自己的 `/sysParams` 接口;统一在 `Service` 层直接调用 `service.ServiceGroupApp.SystemServiceGroup.SysParamsService`。
|
||||
- `API` 层禁止直接操作 `global.GVA_DB`。
|
||||
- `Value` 是字符串存储;简单值可直接存字符串,结构化配置必须由业务 `Service` 负责 `json.Marshal` / `json.Unmarshal`。
|
||||
- 不要把 `sys_params` 的 `ID` 暴露给前端,作为某个固定配置的长期主键。
|
||||
- 固定配置统一按 `key` 识别;`key` 必须稳定、唯一、可读,建议使用 `<module>.<scene>`,例如 `device.runtimeConfig`。
|
||||
- 参数不存在时必须显式处理:返回业务错误、初始化默认值、或创建后再返回;禁止静默吞掉。
|
||||
- 通用参数管理页面可以直接调用 `/sysParams`;具体业务页面优先调用该业务自己的独立 API。
|
||||
- 参数属于某个业务模块时,落点放到该业务模块;只有平台级通用参数才继续放在 `system` 模块。
|
||||
|
||||
## 代码内直接读取
|
||||
|
||||
- 读取动作统一放在 `service/<module>`。
|
||||
- 调用入口:
|
||||
|
||||
```go
|
||||
param, err := service.ServiceGroupApp.SystemServiceGroup.SysParamsService.GetSysParam("device.runtimeConfig")
|
||||
```
|
||||
|
||||
- `param.Value` 就是最终存储值。
|
||||
- 如果 `Value` 存的是 JSON,必须先反序列化为业务结构体,再继续使用。
|
||||
|
||||
```go
|
||||
package device
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
)
|
||||
|
||||
type RuntimeConfig struct {
|
||||
Enable bool `json:"enable"`
|
||||
Mode string `json:"mode"`
|
||||
}
|
||||
|
||||
func (s *DeviceService) GetRuntimeConfig() (RuntimeConfig, error) {
|
||||
param, err := service.ServiceGroupApp.SystemServiceGroup.SysParamsService.GetSysParam("device.runtimeConfig")
|
||||
if err != nil {
|
||||
return RuntimeConfig{}, err
|
||||
}
|
||||
|
||||
var cfg RuntimeConfig
|
||||
if err = json.Unmarshal([]byte(param.Value), &cfg); err != nil {
|
||||
return RuntimeConfig{}, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
```
|
||||
|
||||
## 代码内直接写入
|
||||
|
||||
- 当前 `SysParamsService` 没有“按 `key` 直接写入”的现成能力。
|
||||
- 现在只有 `CreateSysParams`、`UpdateSysParams`、`GetSysParam`。
|
||||
- 这意味着:业务写入固定参数时,必须先按 `key` 查询,再决定 `create` 还是 `update`。
|
||||
- 这段逻辑必须收口到业务 `Service`,不要放在 `API`,也不要交给前端拼 `ID`。
|
||||
|
||||
```go
|
||||
package device
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const runtimeConfigKey = "device.runtimeConfig"
|
||||
|
||||
func (s *DeviceService) SaveRuntimeConfig(cfg RuntimeConfig) error {
|
||||
valueBytes, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sysParamsSvc := service.ServiceGroupApp.SystemServiceGroup.SysParamsService
|
||||
param, err := sysParamsSvc.GetSysParam(runtimeConfigKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return sysParamsSvc.CreateSysParams(&system.SysParams{
|
||||
Name: "设备运行配置",
|
||||
Key: runtimeConfigKey,
|
||||
Value: string(valueBytes),
|
||||
Desc: "device 模块运行配置",
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
param.Value = string(valueBytes)
|
||||
param.Name = "设备运行配置"
|
||||
param.Desc = "device 模块运行配置"
|
||||
return sysParamsSvc.UpdateSysParams(param)
|
||||
}
|
||||
```
|
||||
|
||||
## 什么时候必须写独立 API
|
||||
|
||||
- 前端只关心某一个固定参数,不应该先查列表、拿 `ID`、再更新时。
|
||||
- 参数值是 JSON,需要强类型请求体和响应体时。
|
||||
- 这个参数有明确业务语义,例如“设备运行配置”“首页配置”“第三方回调配置”时。
|
||||
- 该参数需要单独做权限控制、默认值处理、字段校验、审计说明时。
|
||||
|
||||
## 独立 API 规范
|
||||
|
||||
- 独立 API 仍按 `Router → API → Service → GORM → Database` 分层实现。
|
||||
- 底层存储仍使用 `sys_params`;不要因为一个配置项就单独建表,除非它已经演变成独立业务实体。
|
||||
- 对外接口暴露业务语义,不暴露 `sys_params` 的 `ID`、通用 CRUD 细节。
|
||||
- `Service` 负责固定 `key`、处理 JSON 转换、决定 create/update、处理不存在时的策略。
|
||||
- 参数属于业务模块时,文件落点统一为 `model/<module>/request`、`model/<module>/response`、`service/<module>`、`api/v1/<module>`、`router/<module>`。
|
||||
- 新增业务路由统一注册到 `initialize/router_biz.go`。
|
||||
|
||||
## 推荐落地方式
|
||||
|
||||
- 对外提供两个独立接口即可:一个“获取配置”,一个“保存配置”。
|
||||
- 接口名使用业务语义,不使用 `sysParams` 命名。
|
||||
- 示例接口:`GET <router-prefix>/deviceConfig/getRuntimeConfig`、`PUT <router-prefix>/deviceConfig/updateRuntimeConfig`。
|
||||
- `GET` 接口返回业务结构体。
|
||||
- `PUT` 接口接收业务结构体。
|
||||
- 底层统一在 `service/device` 中转成 `sys_params.value` 的 JSON 字符串。
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止在业务代码里直接写 SQL 操作 `sys_params`,绕开现有 `Service` 分层。
|
||||
- 禁止在业务 `API` 中直接处理 `sys_params` 的 `ID`。
|
||||
- 禁止让前端把一个固定配置当成“参数管理列表中的某一行”去长期维护。
|
||||
- 禁止把结构化 JSON 配置直接裸透传为字符串给业务页面,除非该页面本身就是通用参数管理页。
|
||||
54
server/.ai-specs/coding-specs/vo-model-request-response.md
Normal file
54
server/.ai-specs/coding-specs/vo-model-request-response.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Model / Request / Response 组织规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 判断项目中的 `vo`、实体、接口入参、接口出参应该落在哪一层时,使用本文。
|
||||
- 新增或修改业务模块的 `model/<module>`、`model/<module>/request`、`model/<module>/response` 时,使用本文。
|
||||
- 判断某个 API 是直接复用实体,还是新增 `request/response` 结构时,使用本文。
|
||||
|
||||
## 结论基线
|
||||
|
||||
- 本项目不单独维护顶层 `vo` 目录。
|
||||
- 项目里的数据载体统一归到 `model` 体系,不额外拆一套平行 `vo` 层。
|
||||
- 标准落点如下:
|
||||
|
||||
| 场景 | 落点 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| 数据库实体 / 业务实体 | `model/<module>` | 承载表结构映射、业务实体字段 |
|
||||
| API 入参 | `model/<module>/request` | 承载查询条件、分页条件、保存参数等 |
|
||||
| API 出参 | `model/<module>/response` | 承载详情包装、列表项包装、聚合展示结构等 |
|
||||
| 跨模块通用入参 | `model/common/request` | 例如 `PageInfo`、`GetById`、`IdsReq` |
|
||||
| 跨模块通用出参 | `model/common/response` | 例如统一响应壳、分页结果 |
|
||||
|
||||
## 判定规则
|
||||
|
||||
- 请求参数如果就是业务实体本身,且不会引入多余字段、敏感字段或语义歧义,可以直接复用 `model/<module>` 实体。
|
||||
- 请求参数如果只是“分页 + 条件筛选 + 排序”这类接口 contract,应定义到 `model/<module>/request`。
|
||||
- 返回结果如果只是直接返回实体本身,可以直接返回实体或列表,不强制为了“像 VO”再包一层空结构。
|
||||
- 返回结果如果需要额外包装、聚合字段、嵌套结构、展示字段转换,应定义到 `model/<module>/response`。
|
||||
- 多个 API 只要 contract 一致,可以共用同一个 `request` 或 `response` 结构;不是每个 API 都必须单独建一份。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 新增业务模块时,实体统一放 `model/<module>`;禁止把实体落到 `api`、`service`、`router`。
|
||||
- `API` 层入参、出参需要独立结构时,统一放 `model/<module>/request`、`model/<module>/response`;禁止在 `API` 文件里长期维护临时匿名结构体当正式 contract。
|
||||
- 跨模块都能稳定复用的分页、主键、统一响应、分页结果等结构,统一复用 `model/common/request`、`model/common/response`;不要每个模块各复制一份。
|
||||
- 同一业务模块如果同时存在 `admin/app` 两套接口,实体仍统一放 `model/<module>`;只有 `request/response` 按 `admin` / `app` 分文件区分。
|
||||
- 新增 `request/response` 前,先检查同模块现有结构是否可复用;只有接口字段、校验语义、返回语义明显不同,才新增结构。
|
||||
- 改实体字段时,必须同步检查 `service` 查询/写入、`API` 绑定/返回、`doc-sql` 是否仍一致。
|
||||
- 改 `request/response` 时,必须同步检查 `API` 绑定、`Service` 方法签名、`doc-api` 是否仍一致。
|
||||
|
||||
## 推荐做法
|
||||
|
||||
- `Create`、`Update` 这类保存接口,如果直接面向实体字段,可优先复用实体。
|
||||
- `GetList`、搜索、筛选、排序接口,优先使用 `request` 结构,不要把分页筛选字段硬塞进实体。
|
||||
- `Find`、详情、聚合展示、树结构、联表结果等返回,优先使用 `response` 结构,不要把纯展示字段反向塞进数据库实体。
|
||||
- `response` 结构命名优先体现业务语义,例如 `BookDetailResponse`、`BookListItem`、`AuthorOption`;不要机械统一叫 `XxxVO`。
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 禁止单独新建顶层 `vo` 目录,与 `model` 并行维护两套数据结构体系。
|
||||
- 禁止为了“每个 API 都有专属 VO”而机械性给每个接口复制一份几乎相同的 `request/response`。
|
||||
- 禁止把分页、排序、筛选字段直接加进数据库实体,只为了省掉 `request` 结构。
|
||||
- 禁止把纯展示字段、聚合字段、临时返回字段长期塞进实体,只为了省掉 `response` 结构。
|
||||
- 禁止 `API`、`Service` 长期返回 `map[string]interface{}`、`gin.H` 充当正式业务出参,导致 contract 漂移。
|
||||
9
server/.ai-specs/doc-dict/book_author_status.md
Normal file
9
server/.ai-specs/doc-dict/book_author_status.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 作者状态
|
||||
|
||||
- 模块:book
|
||||
- 字典编码:`book_author_status`
|
||||
|
||||
| Label | Value | Sort | Status | Desc |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 启用 | `enabled` | 10 | true | 作者可正常展示,并可被书籍继续关联 |
|
||||
| 禁用 | `disabled` | 20 | true | 作者不再对外展示,且不应再被新增书籍关联 |
|
||||
9
server/.ai-specs/doc-dict/book_completion_status.md
Normal file
9
server/.ai-specs/doc-dict/book_completion_status.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 书籍完结状态
|
||||
|
||||
- 模块:book
|
||||
- 字典编码:`book_completion_status`
|
||||
|
||||
| Label | Value | Sort | Status | Desc |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 完结 | `completed` | 10 | true | 书籍内容已全部发布完成,不再持续新增章节 |
|
||||
| 连载 | `serializing` | 20 | true | 书籍内容仍在持续发布,后续还会新增章节 |
|
||||
39
server/.ai-specs/doc-sql/book_author.md
Normal file
39
server/.ai-specs/doc-sql/book_author.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 书籍作者表
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 模块:book
|
||||
- 表名:`book_author`
|
||||
- 模型:`model/book/book_author.go`
|
||||
- 迁移接入:`initialize/gorm_biz.go`
|
||||
- 状态字典:`book_author_status`
|
||||
- 职责:承载书籍作者主体信息,用于作者资料展示、书籍作者关联和后台作者管理。
|
||||
|
||||
## 建议 SQL
|
||||
|
||||
> 以下 SQL 以当前项目 PostgreSQL 为准,主要表达字段、约束和索引语义;实际落库以 `GORM Model` 和 `initialize/gorm_biz.go` 为准。
|
||||
|
||||
```sql
|
||||
CREATE TABLE book_author (
|
||||
id bigserial PRIMARY KEY,
|
||||
created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
name varchar(128) NOT NULL,
|
||||
author_status varchar(32) NOT NULL DEFAULT 'enabled',
|
||||
intro text,
|
||||
cover_url varchar(500)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE book_author IS '书籍作者表';
|
||||
COMMENT ON COLUMN book_author.id IS '主键';
|
||||
COMMENT ON COLUMN book_author.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN book_author.updated_at IS '更新时间';
|
||||
COMMENT ON COLUMN book_author.name IS '作者名称';
|
||||
COMMENT ON COLUMN book_author.author_status IS '作者状态字典值,对应 book_author_status';
|
||||
COMMENT ON COLUMN book_author.intro IS '作者简介';
|
||||
COMMENT ON COLUMN book_author.cover_url IS '作者封面图片 URL';
|
||||
|
||||
CREATE UNIQUE INDEX uk_book_author_name ON book_author (name);
|
||||
CREATE INDEX idx_book_author_author_status ON book_author (author_status);
|
||||
CREATE INDEX idx_book_author_created_at ON book_author (created_at);
|
||||
```
|
||||
47
server/.ai-specs/logic-specs/book.md
Normal file
47
server/.ai-specs/logic-specs/book.md
Normal file
@@ -0,0 +1,47 @@
|
||||
书名:
|
||||
子标题
|
||||
书籍类型:字典
|
||||
书籍标签 : 字典 ,标签是多个 要考虑用标签搜索书籍的性能问题
|
||||
书有系列:第一部 第二部, 上部 下部 , 所以有排序功能
|
||||
章节名: 章节是否能观看
|
||||
文件路径:oss url
|
||||
封面图片: url
|
||||
作者名(非id): 多个名字用,隔开
|
||||
出版社:
|
||||
出版时间:
|
||||
简介:
|
||||
热度:
|
||||
评分: 0-10分
|
||||
点评数:
|
||||
字数:
|
||||
书籍完结状态: 字典, 完结/连载
|
||||
- 书籍系列Id
|
||||
|
||||
# 书籍系列表
|
||||
- 名字
|
||||
- 封面图片
|
||||
|
||||
# 书籍作者表
|
||||
- 名字
|
||||
- 状态:字典
|
||||
- 简介
|
||||
- 封面图片: url
|
||||
|
||||
# 用户观看书籍历史表
|
||||
- 会员用户Id
|
||||
- 观看书籍进度 : 前端显示 50%
|
||||
- 观看章节Id
|
||||
- 观看章节行数
|
||||
|
||||
|
||||
# 用户收藏书籍历
|
||||
- 会员用户Id
|
||||
- 书籍Id
|
||||
|
||||
# 书籍评论表
|
||||
- 评论书籍id
|
||||
- 评论章节id
|
||||
- 评论章节行数 : 比如第二章第5行
|
||||
- 评论内容
|
||||
- 评论点赞数
|
||||
- 作者是否点赞
|
||||
53
server/.ai-specs/sys-specs/business-dictionary-spec.md
Normal file
53
server/.ai-specs/sys-specs/business-dictionary-spec.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 业务字典规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 当任务是新增业务状态、类型、级别、来源、模式、分类等值域时,先读本文件。
|
||||
- 本文件只规定新增业务字典怎么写,不重复说明系统字典实现细节。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 业务枚举就是业务字典。禁止在代码中脱离字典单独发明枚举值域。
|
||||
- 新增业务值域时,先写字典文档,再写表结构、接口、校验和前端展示。
|
||||
- 具体业务字典必须写到 `.ai-specs/doc-dict/` 下。
|
||||
- 一个 `.md` 文件只能写一个字典。
|
||||
- 字典文件名必须等于字典编码,推荐路径:`.ai-specs/doc-dict/<dict-code>.md`。
|
||||
- 字典编码使用 `snake_case`,固定格式 `<module>_<field>`,例如 `device_status`。
|
||||
- `<dict-code>` 就是 `<module>_<field>`。
|
||||
- 字典项 `Value` 使用稳定 machine value;代码常量值必须与字典项 `Value` 完全一致。
|
||||
- 代码判断统一使用字典项 `Value`;禁止使用 `Label` 做逻辑分支。
|
||||
- 已上线字典的编码和字典项 `Value` 默认不可变;下线优先禁用,不直接删除。
|
||||
- 禁止出现数据库存 `1/2/3`,但没有对应字典文档说明语义。
|
||||
- 禁止代码新增枚举值,但未同步字典文档和字典数据。
|
||||
|
||||
## MD 模板
|
||||
|
||||
.ai-specs/doc-dict/<dict-code>.md
|
||||
```md
|
||||
# <字典中文名>
|
||||
|
||||
- 模块:<module>
|
||||
- 字典编码:`<module>_<field>`
|
||||
|
||||
| Label | Value | Sort | Status | Desc |
|
||||
|:---|:---|:---|:---|:---|
|
||||
| <中文名> | `<machine_value>` | 10 | true | <说明> |
|
||||
```
|
||||
|
||||
## 代码模板
|
||||
|
||||
```go
|
||||
package <module>
|
||||
|
||||
type <TypeName> string
|
||||
|
||||
const (
|
||||
<TypeName><Item1> <TypeName> = "<value_1>"
|
||||
<TypeName><Item2> <TypeName> = "<value_2>"
|
||||
)
|
||||
```
|
||||
|
||||
## 与 SQL 的关系
|
||||
|
||||
- 值域字段先有字典定义,再进入表设计。
|
||||
- 值域字段如何落库,按 `.ai-specs/sys-specs/business-table-spec.md` 执行。
|
||||
77
server/.ai-specs/sys-specs/business-table-spec.md
Normal file
77
server/.ai-specs/sys-specs/business-table-spec.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# 业务表 SQL 规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 当任务是新增/修改 `.ai-specs/doc-sql/*.md` 时,先读本文件。
|
||||
- 当前项目关系型数据库默认是 `PostgreSQL`,`doc-sql` 的 `建议 SQL` 默认输出 `PostgreSQL` 写法。
|
||||
- 涉及状态、类型、级别、来源、模式、分类等值域字段时,必须先读 `.ai-specs/sys-specs/business-dictionary-spec.md`,并先补 `.ai-specs/doc-dict/<dict-code>.md`。
|
||||
|
||||
## 强制输出
|
||||
|
||||
- 文档路径固定:`.ai-specs/doc-sql/<table_name>.md`
|
||||
- 文档结构固定只保留:`# 标题`、`## 基本信息`、`## 建议 SQL`
|
||||
- `## 基本信息` 固定顺序:`模块` → `表名` → `模型` → `迁移接入` → 按需补 `字典` 行 → `职责`
|
||||
- 有字典字段时,每个字典单独占一行:`- <字段中文名>字典:\`<dict-code>\``
|
||||
- `## 建议 SQL` 前的说明固定写为:`> 以下 SQL 以当前项目 PostgreSQL 为准,主要表达字段、约束和索引语义;实际落库以 \`GORM Model\` 和 \`initialize/gorm_biz.go\` 为准。`
|
||||
- `SQL` 代码块固定按这个顺序组织:`CREATE TABLE` → `COMMENT ON TABLE` → `COMMENT ON COLUMN` → `CREATE UNIQUE INDEX` / `CREATE INDEX`
|
||||
- 表名、字段名、索引名统一使用 `snake_case`
|
||||
- 唯一索引命名固定:`uk_<table_name>_<field>`
|
||||
- 普通索引命名固定:`idx_<table_name>_<field>`
|
||||
- 字典字段只存字典项 `Value`,禁止存 `Label`
|
||||
- 文档只写已确认字段、约束、索引;禁止再补 `字段设计`、`索引设计`、`关联关系`、`删除与兼容`、`自检` 等重复章节
|
||||
|
||||
## PostgreSQL 写法
|
||||
|
||||
- 主键自增优先写 `bigserial PRIMARY KEY`
|
||||
- 时间字段优先写 `timestamp with time zone`
|
||||
- 注释统一写 `COMMENT ON TABLE`、`COMMENT ON COLUMN`
|
||||
- 索引统一单独写 `CREATE UNIQUE INDEX`、`CREATE INDEX`
|
||||
- 禁止混入 `AUTO_INCREMENT`、反引号、`ENGINE=InnoDB`、行内 `COMMENT`、`UNIQUE KEY`、`KEY ...` 等 `MySQL` 方言
|
||||
|
||||
## 输出模板
|
||||
|
||||
````md
|
||||
# <表中文名>
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 模块:<module>
|
||||
- 表名:`<table_name>`
|
||||
- 模型:`model/<module>/<file>.go`
|
||||
- 迁移接入:`initialize/gorm_biz.go`
|
||||
- <字段中文名>字典:`<dict-code>`
|
||||
- 职责:<一句话职责>
|
||||
|
||||
## 建议 SQL
|
||||
|
||||
> 以下 SQL 以当前项目 PostgreSQL 为准,主要表达字段、约束和索引语义;实际落库以 `GORM Model` 和 `initialize/gorm_biz.go` 为准。
|
||||
|
||||
```sql
|
||||
CREATE TABLE <table_name> (
|
||||
id bigserial PRIMARY KEY,
|
||||
created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
<field_1> <type> <constraint>,
|
||||
<field_2> <type>
|
||||
);
|
||||
|
||||
COMMENT ON TABLE <table_name> IS '<表中文名>';
|
||||
COMMENT ON COLUMN <table_name>.id IS '主键';
|
||||
COMMENT ON COLUMN <table_name>.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN <table_name>.updated_at IS '更新时间';
|
||||
COMMENT ON COLUMN <table_name>.<field_1> IS '<字段说明>';
|
||||
COMMENT ON COLUMN <table_name>.<field_2> IS '<字段说明>';
|
||||
|
||||
CREATE UNIQUE INDEX uk_<table_name>_<field_1> ON <table_name> (<field_1>);
|
||||
CREATE INDEX idx_<table_name>_<field_2> ON <table_name> (<field_2>);
|
||||
```
|
||||
````
|
||||
|
||||
- 没有字典字段,就删除对应“字典”行
|
||||
- 没有唯一索引或普通索引,就删除对应 SQL 行
|
||||
- 如果字段默认值来自字典,直接写字典项 `Value`,例如 `DEFAULT 'enabled'`
|
||||
|
||||
## 复刻目标
|
||||
|
||||
- 只看本文件,应能直接写出类似 `.ai-specs/doc-sql/book_author.md` 的文档
|
||||
- 先定字典,再写 `doc-sql`,再进入 `Model`、迁移和业务代码
|
||||
20
server/.ai-specs/sys-specs/module-naming-spec.md
Normal file
20
server/.ai-specs/sys-specs/module-naming-spec.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# 模块命名规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
- 当任务涉及新增/修改业务模块命名、中英文对照、目录命名、表前缀、字典编码时,先读本文件。
|
||||
|
||||
## 强制规则
|
||||
|
||||
- 模块中文名与英文名的映射统一登记在本文件;禁止同一业务出现多个英文命名。
|
||||
- 同一业务模块在 `router`、`api`、`service`、`model`、表名、字典编码、接口路径中必须使用同一英文词根;禁止混用近义词或复数变体。
|
||||
- 模块英文名统一使用小写登记值;需要拼接时,按目标位置使用既有规范展开,不单独发明新缩写。
|
||||
- 新增模块词汇时,必须先更新本文件,再进入代码实现。
|
||||
- 已登记模块命名默认视为稳定约束;如需改名,必须先更新本文件并评估受影响目录、表、接口、字典和文档。
|
||||
|
||||
## 模块词汇
|
||||
|
||||
| 中文 | 英文 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| 书籍 | book | 书籍与章节相关业务模块 |
|
||||
| 设备 | device | 设备管理模块 |
|
||||
141
server/AGENTS.md
Normal file
141
server/AGENTS.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# AI 开发入口 [!IMPORTANT]
|
||||
|
||||
- **本文档要求**:本文档为项目级别规范和重要导航,必须严格参考
|
||||
- **本文档要求**:本文档只允许在已有的结构上CURD,不允许增加其他标题区
|
||||
- **本文档要求**:.ai-specs 目录下新增/删除任何文档的时候都应该 在本文档中修改 `## 项目文档`
|
||||
- **文档要求**:规范型文档是给 AI 的顶层入口文档,不是“解释得更全”就更好,而是要 更短、更硬、更可判定
|
||||
- **代码优化**:先复用再新增,允许抽公共逻辑,但公共逻辑必须保证边界仍清晰。
|
||||
- **代码优化**:优化代码时必须同时考虑冗余、孤岛代码、代码清晰度、复杂度、边界条件和兼容性,不能只追求功能跑通。不要修改ui/ux 视觉效果,除非明确要求。
|
||||
- **代码默认遵循**:业务流程需要遵循 `主流做法` `工业级正规`
|
||||
- **代码默认遵循**:强制工作流:按`## 项目文档`定位需要的文档 → 读取匹配文档 → 进入源码
|
||||
|
||||
## 工具使用规则
|
||||
|
||||
- **搜索范围限制**:Grep/Glob 严禁全盘搜索,绝对禁止扫描 `.gitignore` 忽略的目录,以避免性能卡顿。
|
||||
- **读写**:所有文件读取/写入统一使用 UTF-8(建议无 BOM)
|
||||
- **读写**:PowerShell/脚本读取项目文件必须显式指定 `-Encoding utf8`
|
||||
- **画图**:优先使用 `mermaid flowchart `
|
||||
- **对话/文档编写**:必须是 中文为主体语言,技术术语保留英文原文
|
||||
|
||||
## 项目架构
|
||||
- **技术栈**:本项目为 `Go` 服务端,基于 `gin-vue-admin` 体系;Web 框架使用 `Gin`,ORM 使用 `GORM`,配置使用 `Viper`,日志使用 `Zap`,鉴权与权限控制使用 `JWT + Casbin`,接口文档使用 `Swagger`,缓存优先使用 `Redis`;关系型数据库统一通过 `GORM` 接入,数据库使用 `PostgreSQL` ;按配置可启用 `MongoDB`、`cron`、`Excelize`、多云 `OSS/S3`,部署默认支持 `Docker`。
|
||||
- **代码链路**:本项目采用 `Router → API → Service → GORM → Database` 分层。
|
||||
- `Model` 不作为独立调用层,负责承载实体、`request`、`response`,贯穿 `API`、`Service`、数据库映射全过程。
|
||||
|
||||
├── server
|
||||
├── api (api层)
|
||||
│ └── v1 (v1版本接口)
|
||||
├── config (配置包)
|
||||
├── core (核心文件)
|
||||
├── docs (swagger文档目录)
|
||||
├── global (全局对象)
|
||||
├── initialize (初始化)
|
||||
│ └── internal (初始化内部函数)
|
||||
├── middleware (中间件层)
|
||||
├── model (模型层)
|
||||
│ ├── request (入参结构体)
|
||||
│ └── response (出参结构体)
|
||||
├── packfile (静态文件打包)
|
||||
├── resource (静态资源文件夹)
|
||||
│ ├── excel (excel导入导出默认路径)
|
||||
│ ├── page (表单生成器)
|
||||
│ └── template (模板)
|
||||
├── router (路由层)
|
||||
├── service (service层)
|
||||
├── source (source层)
|
||||
└── utils (工具包)
|
||||
├── timer (定时器接口封装)
|
||||
└── upload (oss接口封装)
|
||||
|
||||
| 层级 | 职责 | 命名规范 |
|
||||
|:---|:---|:---|
|
||||
| Router | 定义路由、路由分组、中间件、接口挂载关系;禁止承载业务逻辑 | 目录固定 `router/<module>`;聚合入口固定 `enter.go`;路由承载结构体使用 `*Router` |
|
||||
| API | 接收请求、参数绑定、基础校验、调用 `Service`、返回统一响应 | 目录固定 `api/v1/<module>`;聚合入口固定 `enter.go`;接口承载结构体使用 `*Api` |
|
||||
| Service | 实现业务规则、流程编排、事务控制、数据库读写;禁止把复杂业务长期堆在 `API` | 目录固定 `service/<module>`;聚合入口固定 `enter.go`;服务承载结构体使用 `*Service` |
|
||||
| Model | 定义表结构、`request`、`response` 结构体,作为分层之间的数据载体 | 实体放在 `model/<module>`;入参放在 `model/<module>/request`;出参放在 `model/<module>/response`;结构体名使用 PascalCase |
|
||||
| Database | 持久化存储,由 `Service` 通过 `GORM` 直接访问 | 数据库访问统一走 `global.GVA_DB`;表迁移统一在 `initialize/gorm_biz.go` 注册 |
|
||||
|
||||
- 新增业务模块时,主落点一律放在 `service/<module>`。
|
||||
- 新增业务模块时,接口配套放在 `api/v1/<module>`。
|
||||
- 新增业务模块时,路由配套放在 `router/<module>`。
|
||||
- 新增业务模块时,数据模型配套放在 `model/<module>`。
|
||||
- 新增业务路由时,统一在 `initialize/router_biz.go` 注册。
|
||||
- 涉及表结构变更时,统一在 `initialize/gorm_biz.go` 注册迁移。
|
||||
- 本项目有`admin/app` 2套接口,一般默认是admin接口,app接口按需增加
|
||||
|
||||
### 架构关系
|
||||
- 关系总线:`doc-sql / doc-dict → Model → Service → API → Router`,其中 `Model` 贯穿 `API`、`Service` 与数据库映射;`doc-sql` 约束表结构,`doc-dict` 约束值域与枚举。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
DOCSQL["doc-sql<br/>表结构/字段/索引/约束"] --> Model
|
||||
DOCDICT["doc-dict<br/>状态/类型/枚举值域"] --> Model
|
||||
DOCDICT --> Service
|
||||
DOCDICT --> API
|
||||
Model --> Service
|
||||
Service --> API
|
||||
API --> Router 无法显示出图像啊
|
||||
```
|
||||
|
||||
|
||||
- 改 `doc-sql`:不能只改文档;必须同步检查并修改 `model/<module>` 实体字段、`service/<module>` 读写逻辑、`initialize/gorm_biz.go` 迁移注册。若字段名、类型、默认值、索引、唯一约束变化,相关查询条件、排序、唯一性校验、兼容逻辑都要一起改。
|
||||
- 改 `doc-dict`:必须同步修改代码里的枚举/常量、`Model` 字段注释与值域约束、`API` 参数校验、`Service` 分支判断与展示转换。若接口出入参暴露该值域,相关 `doc-api` 也必须同步。
|
||||
- 改 `Model`:必须区分是改实体、`request` 还是 `response`。改实体时,同步检查 `Service` 的查询/写入/扫描字段,以及 `doc-sql` 是否仍一致;改 `request/response` 时,同步检查 `API` 绑定、返回和 `doc-api`。
|
||||
- 改 `Service`:同步检查 `Model` 是否足够承载新字段/新状态,`API` 调用参数和返回值是否需要变化。若业务规则新增状态、类型、来源等值域,必须回头修改 `doc-dict`;若涉及落库结构变化,必须回头修改 `doc-sql` 与迁移注册。
|
||||
- 改 `API`:同步检查 `Router` 挂载的方法、路径、鉴权与分组是否一致;同步检查 `Model/request`、`Model/response` 和 `Service` 方法签名。若接口 contract 变化,`doc-api` 必须同步。
|
||||
- 改 `Router`:同步检查 `API` 是否已有对应处理函数;新增或调整业务路由时,必须同步修改 `initialize/router_biz.go` 注册。若分组、版本、权限中间件变化,相关接口文档与调用方也要一起检查。
|
||||
- 新增/修改业务功能时,默认顺序是:先定 `doc-sql` / `doc-dict`,再落 `Model`,再写 `Service`,再接 `API`,最后挂 `Router`;禁止只改链路中的单点而不回查上下游。
|
||||
|
||||
## 项目文档
|
||||
|
||||
- **根目录**:.ai-specs
|
||||
- **要求**:开始写代码前,根据任务类型先定位目录,再读取对应文档;有对应文档必须先读。
|
||||
- **兜底**:索引表无匹配时,按本文件通用规则和现有同层代码风格实现
|
||||
|
||||
### coding-specs 存放对功能代码的说明/限制/要求
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| `.ai-specs\coding-specs\api-auth-control.md` | 规定 API 在“不需要登录 / 需要登录 / 需要权限”之间切换时的路由挂载与权限同步方式 | 涉及接口鉴权方式调整、公开接口、仅登录接口、角色权限接口时必读 |
|
||||
| `.ai-specs\coding-specs\module-admin-crud-default.md` | 规定业务模块 `admin` 端默认 CRUD 接口集合、命名、Method 与挂载方式 | 涉及新增业务后台 CRUD、判断默认后台接口应该有哪些时必读 |
|
||||
| `.ai-specs\coding-specs\module-admin-app-split.md` | 规定同一业务模块下 `admin` 管理端接口与 `app` 用户端接口的目录落点、分层方式与鉴权边界 | 涉及 `book` 等同模块同时提供 `admin/app` 两套接口时必读 |
|
||||
| `.ai-specs\coding-specs\sys-params.md` | 规定 `sys_params` 的读写方式与单参数独立 API 的封装方式 | 涉及系统参数读写、基于 `sys_params` 封装业务配置接口时必读 |
|
||||
| `.ai-specs\coding-specs\vo-model-request-response.md` | 规定项目中实体、API 入参、API 出参与通用结构在 `model` 体系内的落点与复用边界 | 涉及 `vo` 放置方式、是否复用实体、何时新增 `request/response` 结构时必读 |
|
||||
|
||||
### logic-specs 存放业务说明文档不设计代码
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| `.ai-specs\logic-specs\book.md` | 记录书籍相关主体与字段草案 | 涉及书籍、书籍系列、书籍作者、书籍评论等业务设计时先读 |
|
||||
|
||||
### sys-specs 存放系统级文档
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| `.ai-specs\sys-specs\business-table-spec.md` | 规定新增业务表的 SQL 设计、索引、约束、迁移和兼容要求 | 涉及新增/修改业务表、字段、索引、唯一约束、迁移注册时必读 |
|
||||
| `.ai-specs\sys-specs\business-dictionary-spec.md` | 规定新增业务字典的定义方式,以及代码枚举与字典值的一一对应关系 | 涉及新增业务状态、类型、级别、来源、模式、分类等值域时必读 |
|
||||
| `.ai-specs\sys-specs\module-naming-spec.md` | 规定业务模块中文名与英文名的统一登记方式 | 涉及新增/修改业务模块命名、中英文对照、目录命名时必读 |
|
||||
|
||||
### doc-api <admin or app or `平台`>
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
|
||||
### doc-sql 存放具体业务表文档
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| `.ai-specs\doc-sql\book_author.md` | 定义书籍作者表的字段、索引、SQL 基线和兼容要求 | 涉及书籍作者表建模、迁移、唯一性约束和书籍作者关系改造时必读 |
|
||||
|
||||
### doc-dict 存放具体业务字典文档
|
||||
|
||||
| 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| `.ai-specs\doc-dict\book_author_status.md` | 定义作者状态的标准值域 | 涉及作者状态的存储、校验、展示和接口出入参时必读 |
|
||||
| `.ai-specs\doc-dict\book_completion_status.md` | 定义书籍完结状态的标准值域 | 涉及书籍完结状态的存储、校验、展示和接口出入参时必读 |
|
||||
|
||||
|
||||
## 可复用代码/组件
|
||||
|
||||
| 中文 | 代码文件名 | 说明 |
|
||||
|:---|:---|:---|
|
||||
@@ -1,3 +1,10 @@
|
||||
|
||||
# 下载并整理依赖
|
||||
go mod tidy
|
||||
# 在 server 目录下运行
|
||||
go run main.go
|
||||
|
||||
|
||||
## server项目结构
|
||||
|
||||
```shell
|
||||
|
||||
@@ -1,212 +1,3 @@
|
||||
# github.com/flipped-aurora/gin-vue-admin/server Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: qmPlus
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: info
|
||||
format: console
|
||||
prefix: "[github.com/flipped-aurora/gin-vue-admin/server]"
|
||||
director: log
|
||||
show-line: true
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
log-in-console: true
|
||||
retention-day: -1
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
#是否使用redis集群模式
|
||||
useCluster: false
|
||||
#使用集群模式addr和db默认无效
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
db: 0
|
||||
clusterAddrs:
|
||||
- "172.21.0.3:7000"
|
||||
- "172.21.0.4:7001"
|
||||
- "172.21.0.2:7002"
|
||||
|
||||
# redis-list configuration
|
||||
redis-list:
|
||||
- name: cache # 数据库的名称,注意: name 需要在 redis-list 中唯一
|
||||
useCluster: false # 是否使用redis集群模式
|
||||
addr: 127.0.0.1:6379 # 使用集群模式addr和db默认无效
|
||||
password: ""
|
||||
db: 0
|
||||
clusterAddrs:
|
||||
- "172.21.0.3:7000"
|
||||
- "172.21.0.4:7001"
|
||||
- "172.21.0.2:7002"
|
||||
|
||||
# mongo configuration
|
||||
mongo:
|
||||
coll: ''
|
||||
options: ''
|
||||
database: ''
|
||||
username: ''
|
||||
password: ''
|
||||
auth-source: ''
|
||||
min-pool-size: 0
|
||||
max-pool-size: 100
|
||||
socket-timeout-ms: 0
|
||||
connect-timeout-ms: 0
|
||||
is-zap: false
|
||||
hosts:
|
||||
- host: ''
|
||||
port: ''
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
port: 465
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
is-ssl: true
|
||||
secret: xxx
|
||||
nickname: test
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
env: local # 修改为public可以关闭路由日志输出
|
||||
addr: 8888
|
||||
db-type: mysql
|
||||
oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-redis: false # 使用redis
|
||||
use-mongo: false # 使用mongo
|
||||
use-multipoint: false
|
||||
# IP限制次数 一个小时15000次
|
||||
iplimit-count: 15000
|
||||
# IP限制一个小时
|
||||
iplimit-time: 3600
|
||||
# 路由全局前缀
|
||||
router-prefix: ""
|
||||
# 严格角色模式 打开后权限将会存在上下级关系
|
||||
use-strict-auth: false
|
||||
# 禁用自动迁移数据库表结构,生产环境建议设为true,手动迁移
|
||||
disable-auto-migrate: false
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0 # 0代表一直开启,大于0代表限制次数
|
||||
open-captcha-timeout: 3600 # open-captcha大于0时才生效
|
||||
|
||||
# mysql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
mysql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# pgsql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
pgsql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
oracle:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
mssql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
sqlite:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
db-list:
|
||||
- disable: true # 是否禁用
|
||||
type: "" # 数据库的类型,目前支持mysql、pgsql、mssql、oracle
|
||||
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
|
||||
# autocode configuration
|
||||
autocode:
|
||||
web: web/src
|
||||
root: "" # root 自动适配项目根目录, 请不要手动配置,他会在项目加载的时候识别出根路径
|
||||
server: server
|
||||
module: 'github.com/flipped-aurora/gin-vue-admin/server'
|
||||
ai-path: "" # AI服务路径
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: ZoneHuaDong
|
||||
bucket: ""
|
||||
img-path: ""
|
||||
use-https: false
|
||||
access-key: ""
|
||||
secret-key: ""
|
||||
use-cdn-domains: false
|
||||
|
||||
# minio oss configuration
|
||||
minio:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
use-ssl: false
|
||||
base-path: ""
|
||||
bucket-url: "http://host:9000/yourBucketName"
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
@@ -214,29 +5,28 @@ aliyun-oss:
|
||||
bucket-name: yourBucketName
|
||||
bucket-url: yourBucketUrl
|
||||
base-path: yourBasePath
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# aws s3 configuration (minio compatible)
|
||||
autocode:
|
||||
web: web/src
|
||||
root: D:\Code3\wdp\xuanzhi-service
|
||||
server: server
|
||||
module: github.com/flipped-aurora/gin-vue-admin/server
|
||||
ai-path: ""
|
||||
aws-s3:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
endpoint: ""
|
||||
s3-force-path-style: false
|
||||
disable-ssl: false
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# cloudflare r2 configuration
|
||||
s3-force-path-style: false
|
||||
disable-ssl: false
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0
|
||||
open-captcha-timeout: 3600
|
||||
cloudflare-r2:
|
||||
bucket: xxxx0bucket
|
||||
base-url: https://gin.vue.admin.com
|
||||
@@ -244,40 +34,223 @@ cloudflare-r2:
|
||||
account-id: xxx_account_id
|
||||
access-key-id: xxx_key_id
|
||||
secret-access-key: xxx_secret_key
|
||||
|
||||
# huawei obs configuration
|
||||
cors:
|
||||
mode: strict-whitelist
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-methods: POST, GET
|
||||
allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true
|
||||
- allow-origin: example2.com
|
||||
allow-methods: GET, POST
|
||||
allow-headers: content-type
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true
|
||||
db-list:
|
||||
- type: ""
|
||||
alias-name: ""
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
disable: true
|
||||
disk-list:
|
||||
- mount-point: /
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
secret: xxx
|
||||
nickname: test
|
||||
port: 465
|
||||
is-ssl: true
|
||||
is-loginauth: false
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
hua-wei-obs:
|
||||
path: you-path
|
||||
bucket: you-bucket
|
||||
endpoint: you-endpoint
|
||||
access-key: you-access-key
|
||||
secret-key: you-secret-key
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
|
||||
# disk usage configuration
|
||||
disk-list:
|
||||
- mount-point: "/"
|
||||
|
||||
# 跨域配置
|
||||
# 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用
|
||||
cors:
|
||||
mode: strict-whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id
|
||||
allow-methods: POST, GET
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
- allow-origin: example2.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
jwt:
|
||||
signing-key: 725c9404-a8d2-4a4c-9496-745d11b65b3d
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
mcp:
|
||||
name: GVA_MCP
|
||||
version: v1.0.0
|
||||
path: ""
|
||||
addr: 8889
|
||||
base_url: ""
|
||||
upstream_base_url: ""
|
||||
auth_header: ""
|
||||
request_timeout: 0
|
||||
sse_path: ""
|
||||
message_path: ""
|
||||
url_prefix: ""
|
||||
separate: false
|
||||
minio:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
use-ssl: false
|
||||
base-path: ""
|
||||
bucket-url: http://host:9000/yourBucketName
|
||||
mongo:
|
||||
coll: ""
|
||||
options: ""
|
||||
database: ""
|
||||
username: ""
|
||||
password: ""
|
||||
auth-source: ""
|
||||
min-pool-size: 0
|
||||
max-pool-size: 100
|
||||
socket-timeout-ms: 0
|
||||
connect-timeout-ms: 0
|
||||
is-zap: false
|
||||
hosts:
|
||||
- host: ""
|
||||
port: ""
|
||||
mssql:
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
mysql:
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
oracle:
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
pgsql:
|
||||
prefix: ""
|
||||
port: "5432"
|
||||
config: sslmode=disable TimeZone=Asia/Shanghai
|
||||
db-name: xuanzhi
|
||||
username: admin
|
||||
password: admin@123456
|
||||
path: 10.1.0.1
|
||||
engine: ""
|
||||
log-mode: error
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
qiniu:
|
||||
zone: ZoneHuaDong
|
||||
bucket: ""
|
||||
img-path: ""
|
||||
access-key: ""
|
||||
secret-key: ""
|
||||
use-https: false
|
||||
use-cdn-domains: false
|
||||
redis:
|
||||
name: ""
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
db: 0
|
||||
useCluster: false
|
||||
clusterAddrs:
|
||||
- 172.21.0.3:7000
|
||||
- 172.21.0.4:7001
|
||||
- 172.21.0.2:7002
|
||||
redis-list:
|
||||
- name: cache
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
db: 0
|
||||
useCluster: false
|
||||
clusterAddrs:
|
||||
- 172.21.0.3:7000
|
||||
- 172.21.0.4:7001
|
||||
- 172.21.0.2:7002
|
||||
sqlite:
|
||||
prefix: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
path: ""
|
||||
engine: ""
|
||||
log-mode: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
singular: false
|
||||
log-zap: false
|
||||
system:
|
||||
db-type: pgsql
|
||||
oss-type: local
|
||||
router-prefix: ""
|
||||
addr: 8888
|
||||
iplimit-count: 15000
|
||||
iplimit-time: 3600
|
||||
use-multipoint: false
|
||||
use-redis: false
|
||||
use-mongo: false
|
||||
use-strict-auth: false
|
||||
disable-auto-migrate: false
|
||||
tencent-cos:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
zap:
|
||||
level: info
|
||||
prefix: '[github.com/flipped-aurora/gin-vue-admin/server]'
|
||||
format: console
|
||||
director: log
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
show-line: true
|
||||
log-in-console: true
|
||||
retention-day: -1
|
||||
|
||||
@@ -50,6 +50,7 @@ require (
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/text v0.24.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/datatypes v1.2.5
|
||||
@@ -192,7 +193,6 @@ require (
|
||||
golang.org/x/image v0.23.0 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.29.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
|
||||
73
web/AGENTS.md
Normal file
73
web/AGENTS.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# AI 开发入口 [!IMPORTANT]
|
||||
|
||||
- 本文档为项目级别规范和重要导航,必须严格参考
|
||||
- 对我的回复/文档编写 ,必须是 中文为主体语言,技术术语保留英文原文
|
||||
- 强制工作流:按下方索引表定位需要的文档 → 读取匹配文档 → 进入源码
|
||||
- 禁止跳过文档检查直接写复杂业务;禁止已有对应文档却不读
|
||||
- 索引表无匹配时,按本文件通用规则和现有同层代码风格实现
|
||||
- 业务流程需要遵循 `主流做法` `工业级正规`
|
||||
- 规范型文档是给 AI 的顶层入口文档,不是“解释得更全”就更好,而是要 更短、更硬、更可判定
|
||||
- 本文档只允许在已有的结构上CURD,不允许增加其他标题区
|
||||
|
||||
|
||||
## 工具使用规则
|
||||
|
||||
- **搜索范围限制**:Grep/Glob 严禁全盘搜索,绝对禁止扫描 `.gitignore` 忽略的目录,以避免性能卡顿。
|
||||
- **读写**:所有文件读取/写入统一使用 UTF-8(建议无 BOM)
|
||||
- **读写**:PowerShell/脚本读取项目文件必须显式指定 `-Encoding utf8`
|
||||
|
||||
## 当前项目代码要求
|
||||
|
||||
### 通用要求
|
||||
|
||||
- 优化代码时必须同时考虑冗余、孤岛代码、代码清晰度、复杂度、边界条件和兼容性,不能只追求功能跑通。
|
||||
- 优化代码时不要修改ui/ux 视觉效果,除非明确要求。
|
||||
- 先复用再新增
|
||||
- 允许抽公共逻辑,但公共逻辑必须放在根级共享目录,并保证边界仍清晰。
|
||||
|
||||
### 项目偏好
|
||||
-
|
||||
|
||||
## 文档体系
|
||||
|
||||
开始写代码前,根据下表判断当前任务涉及哪些文档,有对应文档必须先读。
|
||||
- .ai-specs 为规范根目录
|
||||
- .ai-specs\coding-specs
|
||||
- .ai-specs\logic-specs
|
||||
|
||||
### 目录索引表
|
||||
|
||||
| 类型 | 路径 | 用途 | 说明 |
|
||||
|:---|:---|:---|:---|
|
||||
|
||||
## 项目架构
|
||||
|
||||
### 模块说明
|
||||
|
||||
|
||||
### 业务流转
|
||||
|
||||
#### 1. xxx
|
||||
|
||||
-
|
||||
|
||||
## 命名规范
|
||||
|
||||
-
|
||||
|
||||
|
||||
### 模块词汇
|
||||
|
||||
| 中文 | 英文 | 说明 |
|
||||
|:---|:---|:---|
|
||||
| 设备 | device | 设备管理模块 |
|
||||
|
||||
|
||||
## 可复用组件
|
||||
|
||||
-
|
||||
|
||||
## 技术栈专项规范
|
||||
|
||||
### xxx
|
||||
-
|
||||
@@ -1,3 +1,15 @@
|
||||
# 安装项目依赖
|
||||
npm install
|
||||
|
||||
# 或使用 yarn(如果已安装)
|
||||
yarn install
|
||||
|
||||
# 或使用 pnpm(推荐,速度更快)
|
||||
pnpm install
|
||||
|
||||
|
||||
|
||||
|
||||
# gin-vue-admin web
|
||||
|
||||
## Project setup
|
||||
|
||||
Reference in New Issue
Block a user