366 lines
23 KiB
Markdown
366 lines
23 KiB
Markdown
# EasyGoAdmin_GoFrame_EleVue 全栈架构设计(最终定稿)
|
||
|
||
> 本文件为后端服务实施的唯一权威设计文档(定稿)。实施过程中的任何偏差以本文档为准。
|
||
|
||
## 0. 定稿变更清单
|
||
|
||
| # | 变更 | 状态 |
|
||
|---|---|---|
|
||
| 1 | `is_delete` → **`del_flag`** 全量统一(含索引名 `idx_*_del_flag`、唯一键 `(…, del_flag)`) | ✅ 定稿 |
|
||
| 2 | 每张数据表对应一个模块,给出全套文件(api/controller/logic/生成物) | ✅ §3 |
|
||
| 3 | 标准接口七件套:分页/列表/详情/新增/修改/删除/批量删除,+ 导入导出 | ✅ §1.3 |
|
||
| 4 | 路由与方法命名对齐 `ui/src/api` 与 PHP 参考控制器 | ✅ 全量提取 |
|
||
| 5 | 集成操作日志中间件 + 登录日志 + 两个查询模块 | ✅ §4 |
|
||
| 6 | 前端位于根目录 `ui/`(同仓库,后端 API 前缀与之逐条对齐) | ✅ §2 |
|
||
| 7 | `utility/` 保留顶层(官方案例一致) | ✅ |
|
||
| 8 | **主键统一 int 数据库自增,停用雪花算法**(2026-10-13 定稿:插入后 `LastInsertId()` 回读;`utility/id` 已移除) | ✅ 定稿 |
|
||
|
||
## 1. 全局设计规范
|
||
|
||
### 1.1 分层与调用链
|
||
|
||
```
|
||
main.go(5驱动) → internal/cmd(启动) → internal/router(注册+元数据)
|
||
→ middleware: CORS → Response → JWT → Tenant → Permission → OperationLog
|
||
→ controller(薄) → service接口(生成) → logic实现(sXxx) → dao → gdb → DB
|
||
```
|
||
|
||
### 1.2 标准接口七件套(所有模块统一)
|
||
|
||
| 方法名 | HTTP | 路由模板 | 说明 |
|
||
|---|---|---|---|
|
||
| `Page` | GET | `/{prefix}/page` | 分页,入参 `pageNo/pageSize` + 筛选 |
|
||
| `List` | GET | `/{prefix}/list` | 全量/树形列表(下拉、树选择) |
|
||
| `Detail` | GET | `/{prefix}/detail/:id` | 详情 |
|
||
| `Add` | POST | `/{prefix}/add` | 新增,返回 `{id}` |
|
||
| `Update` | PUT | `/{prefix}/update` | 修改(body 含 `id`) |
|
||
| `Delete` | DELETE | `/{prefix}/delete/:id` | 删除(软删 `del_flag=1`) |
|
||
| `BatchDelete` | DELETE | `/{prefix}/batchDelete` | 批量删除,body `{ids:[]}` |
|
||
| `Import` | POST | `/{prefix}/import` | 导入(multipart `file`,xls/xlsx) |
|
||
| `Export` | GET | `/{prefix}/export` | 导出(返回文件路径/流) |
|
||
|
||
**结构体命名**:`{Mod}{Action}Req` / `{Mod}{Action}Res`(如 `UserPageReq`、`LevelExportRes`)。
|
||
**controller 方法名 = logic 方法名 = 上表方法名**(与 PHP 控制器一致);logic 结构体命名 `sUser/sRole/…`,供 `gf gen service` 生成 `IUser/IRole` 接口。
|
||
|
||
### 1.3 注解规范(Go 版 `#[Log]`/`#[Permission]`,gmeta 扩展标签)
|
||
|
||
```go
|
||
type UserPageReq struct {
|
||
gmeta.Meta `method:"get" path:"/user/page" summary:"用户分页" permission:"sys:user:page" log:"用户管理-查询分页记录" logType:"query"`
|
||
common.PageReq // pageNo/pageSize
|
||
Keyword string `json:"keyword" dc:"关键词"`
|
||
Status int `json:"status" dc:"状态"`
|
||
}
|
||
```
|
||
|
||
`internal/router/bind.go` 在注册时反射解析上述标签 → 生成**路由元数据表** `map["GET /user/page"]{Permission, Log, LogType}`,供 `permission` 与 `operation_log` 中间件查表使用(等价 PHP 属性切面)。
|
||
|
||
### 1.4 权限码与日志标题规则(从参考项目提取后统一)
|
||
|
||
- 权限码:`sys:{module}:{action}`,module 用小驼峰(`fileTemplate/loginLog/operLog/configItem/dictItem/jobLog`),action 同方法名。`permission` 标签留空 = **仅登录即可**。
|
||
- 日志标题:`{模块中文名}-{动作}`,动作映射:
|
||
|
||
| action | 日志动作 | action | 日志动作 |
|
||
|---|---|---|---|
|
||
| page | 查询分页记录 | update | 修改记录 |
|
||
| list | 查询列表 | delete | 删除记录 |
|
||
| detail | 查询详情 | batchDelete | 批量删除记录 |
|
||
| add | 新增记录 | import/export | 导入数据 / 导出数据 |
|
||
|
||
(覆盖参考项目中“查询全量列表/查询树形列表”等混用写法,统一为上表;特殊日志标题在 §3 各模块单列。)
|
||
- `logType` 枚举(`consts/log_type.go`):`query/add/update/delete/import/export/reset`。
|
||
|
||
### 1.5 统一响应与分页
|
||
|
||
```json
|
||
{ "code": 0, "msg": "操作成功", "data": { } }
|
||
{ "list": [ ], "total": 0 }
|
||
```
|
||
|
||
错误码经 `consts/biz_err.go` 中 `gcode.Register` 注册;响应封装在 `utility/response` + `middleware/response.go`。
|
||
|
||
## 2. 模块总表(25 表 ↔ 27 模块)
|
||
|
||
| 域 | 模块 | 表 | 路由前缀 | api / controller / logic 文件(`{m}`=模块名全小写) |
|
||
|---|---|---|---|---|
|
||
| **auth** | auth | —(写 login_log) | 顶层 `/login /logout /captcha …` | `api/v1/auth/auth.go` | `controller/auth/auth.go` | `logic/auth/auth.go` |
|
||
| **index** | index | —(聚合 user/menu) | `/index/*` | `api/v1/index/index.go` | `controller/index/index.go` | `logic/index/index.go` |
|
||
| **system** | user | goframe_user | `/user` | `api/v1/system/user.go` | `controller/system/user.go` | `logic/system/user.go` |
|
||
| | role | goframe_role + **role_menu** | `/role` | `…/system/role.go` ×3 |
|
||
| | menu | goframe_menu | `/menu` | `…/system/menu.go` ×3 |
|
||
| | dept | goframe_dept | `/dept` | `…/system/dept.go` ×3 |
|
||
| | level | goframe_level | `/level` | `…/system/level.go` ×3 |
|
||
| | position | goframe_position | `/position` | `…/system/position.go` ×3 |
|
||
| | tenant | goframe_tenant | `/tenant` | `…/system/tenant.go` ×3 |
|
||
| **data** | config | goframe_config | `/config` | `…/data/config.go` ×3 |
|
||
| | configitem | goframe_config_item | `/config/item` | `…/data/configitem.go` ×3 |
|
||
| | param | goframe_param | `/param` | `…/data/param.go` ×3 |
|
||
| | dict | goframe_dict | `/dict` | `…/data/dict.go` ×3 |
|
||
| | dictitem | goframe_dict_item | `/dict/item` | `…/data/dictitem.go` ×3 |
|
||
| | notice | goframe_notice | `/notice` | `…/data/notice.go` ×3 |
|
||
| | city | goframe_city | `/city`(别名 `/area`) | `…/data/city.go` ×3 |
|
||
| **content** | article | goframe_article | `/article` | `…/content/article.go` ×3 |
|
||
| | category | goframe_category | `/category`(树形) | `…/content/category.go` ×3 |
|
||
| | link | goframe_link | `/link` | `…/content/link.go` ×3 |
|
||
| **monitor** | operlog | goframe_operation_log | `/oper/log` | `…/monitor/operlog.go` ×3 |
|
||
| | loginlog | goframe_login_log | `/login/log` | `…/monitor/loginlog.go` ×3 |
|
||
| | job | goframe_job | `/job` | `…/monitor/job.go` ×3 |
|
||
| | joblog | goframe_job_log | `/job/log` | `…/monitor/joblog.go` ×3 |
|
||
| **tool** | example | goframe_example | `/example` | `…/tool/example.go` ×3 |
|
||
| | filetemplate | goframe_file_template | `/file/template` | `…/tool/filetemplate.go` ×3 |
|
||
| | generator | —(读 information_schema) | `/generator` | `…/tool/generator.go` ×3 |
|
||
| | upload | —(存 resource/upload) | `/upload` | `…/tool/upload.go` ×3 |
|
||
|
||
> `user_role` 关联表不单列模块:归 `user` logic(保存用户-角色);`role_menu` 归 `role` logic(§3 扩展接口)。
|
||
> 生成物(每表一套,`make gen` 产出):`internal/dao/{m}.go`(可扩展)+ `internal/dao/internal/{m}.go`、`internal/model/entity/{m}.go`、`internal/model/do/{m}.go`、`internal/service/{m}.go`。以下各模块不再重复列出生成物。
|
||
|
||
**标准七件套启用矩阵**(✓=启用,—=豁免):
|
||
|
||
| 模块 | page | list | detail | add | update | delete | batchDelete | 导入 | 导出 |
|
||
|---|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|
||
| user | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | **✓** | **✓** |
|
||
| level | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | **✓** | **✓** |
|
||
| example | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | **✓** | **✓** |
|
||
| role / position / tenant / config / configitem / param / dict / notice / article / category / link / city / filetemplate | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | — |
|
||
| menu / dept | ✓(新增权限点) | ✓(树形) | ✓ | ✓ | ✓ | ✓ | ✓(新增权限点) | — | — |
|
||
| operlog / loginlog / joblog | ✓ | ✓ | ✓ | **—**(日志不可增改) | **—** | ✓ | ✓ | — | — |
|
||
| job | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | — |
|
||
|
||
> 导入导出定稿启用模块:**user、level** + **example**(前端已调用,PHP 参考亦有 `sys:example:import/export`)。
|
||
> 新增权限点(参考项目没有、本期补齐):`sys:menu:page`、`sys:menu:batchDelete`、`sys:dept:page`、`sys:dept:batchDelete`、`sys:city:page` 等——须同步写入 `goframe_menu` 初始化数据。
|
||
|
||
## 3. 模块文件明细(按域)
|
||
|
||
### 3.1 auth 认证域(无表)
|
||
|
||
**文件**:`api/v1/auth/auth.go`|`internal/controller/auth/auth.go`|`internal/logic/auth/auth.go`
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| Login | POST | `/login` | 公开 | 写 **login_log**(logType=1) | `{username,password,tenantCode?,captcha?,uuid?}` → 校验租户 status/expire → 签发 access+refresh |
|
||
| Logout | GET | `/logout` | 登录 | 写 login_log(logType=2) | jti 入缓存黑名单 |
|
||
| Captcha | GET | `/captcha` | 公开 | — | 图形码,缓存 `captcha:{uuid}` TTL 300s |
|
||
| Refresh | POST | `/oauth2/token` | 公开(refresh_token) | — | 前端 `common/user.ts` 既有路由;轮换 token、旧 jti 拉黑 |
|
||
| CheckToken | GET | `/oauth2/check/token` | 登录 | — | 前端 `common/index.ts` 调用 |
|
||
| RemoveToken | DELETE | `/oauth2/remove/:token` | 登录 | — | 指定 token 拉黑 |
|
||
| Register | POST | `/register` | 公开 | — | 白名单已放行,路由未注册(启用时补实现) |
|
||
|
||
**api 结构体**:`LoginReq/LoginRes`(含 `accessToken/refreshToken/expiresIn/userInfo`)、`CaptchaRes`、`RefreshReq`、`CheckTokenRes`。
|
||
**logic 职责**:bcrypt 校验(`utility/crypto`)、租户校验(缓存)、双 token 签发(`utility/jwt`)、黑名单、login_log 落库。
|
||
|
||
### 3.2 index 个人中心/菜单聚合域(无表)
|
||
|
||
**文件**:`api/v1/index/index.go`|`controller/index/index.go`|`logic/index/index.go`
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志标题(取自 PHP 参考) |
|
||
|---|---|---|---|---|
|
||
| GetUser | GET | `/index/getUser` | 登录 | 个人中心-查询用户信息 |
|
||
| GetMenus | GET | `/index/getMenus` **和** `/index/getMenus/:id` | 登录 | 个人中心-查询菜单 |
|
||
| UpdatePassword | PUT | `/index/updatePassword` | 登录 | 个人中心-修改密码(旧密码校验+bcrypt) |
|
||
| UpdateProfile | PUT | `/index/updateProfile` | 登录 | 个人设置-更新个人信息 |
|
||
|
||
> `getMenus` 注册两条路由(`common/menu.ts` 无参、`system/menu.ts` 带 `/1`),同一 handler。
|
||
|
||
### 3.3 system 域
|
||
|
||
#### user 用户模块|表 `goframe_user`
|
||
**文件**:`api/v1/system/user.go`|`controller/system/user.go`|`logic/system/user.go`
|
||
**七件套**:全部启用(含 import/export)。扩展:
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志标题 |
|
||
|---|---|---|---|---|
|
||
| ResetPwd | PUT | `/user/resetPwd` | `sys:user:resetPwd` | 用户管理-重置密码 |
|
||
| Import | POST | `/user/import` | `sys:user:import` | 用户管理-导入数据 |
|
||
| Export | GET | `/user/export` | `sys:user:export` | 用户管理-导出数据(chunkList 分批防 OOM) |
|
||
|
||
**logic 私有方法**:`sUser.AssignRoles(userId, roleIds)`(写 `goframe_user_role`)、`checkTenantUserMax`(`tenant.max_user_num`)、手机号/用户名租户内唯一校验(走 uk)。
|
||
|
||
#### role 角色模块|表 `goframe_role` + `goframe_role_menu`
|
||
**文件**:`api/v1/system/role.go`|`controller/system/role.go`|`logic/system/role.go`
|
||
**七件套**:全部启用。扩展:
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志标题 |
|
||
|---|---|---|---|---|
|
||
| MenuList | GET | `/role/menu/list/:roleId` | `sys:role:list` | 角色管理-查询角色菜单 |
|
||
| SavePermission | POST | `/role/menu/save` | `sys:role:savePermission` | 角色管理-保存权限(重写 role_menu,清缓存) |
|
||
|
||
#### menu 菜单模块|表 `goframe_menu`
|
||
**文件**:`…/system/menu.go` ×3。七件套全启用;`List` 返回**树形**(日志:菜单管理-查询树形列表)。logic 含 `GetUserMenuTree(userId)`(供 index.GetMenus:user→role→role_menu→menu)。
|
||
|
||
#### dept 部门模块|表 `goframe_dept`
|
||
**文件**:`…/system/dept.go` ×3。七件套全启用;`List` 返回树形;禁止删除有子部门/用户的部门。
|
||
|
||
#### level 职级模块|表 `goframe_level`
|
||
**文件**:`…/system/level.go` ×3。七件套 + **Import/Export**:
|
||
`POST /level/import`、`GET /level/export`。
|
||
|
||
#### position 岗位模块|表 `goframe_position`
|
||
**文件**:`…/system/position.go` ×3。七件套全启用。
|
||
|
||
#### tenant 租户模块|表 `goframe_tenant`
|
||
**文件**:`…/system/tenant.go` ×3。七件套全启用。扩展:
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志标题 |
|
||
|---|---|---|---|---|
|
||
| Account | POST | `/tenant/account` | `sys:tenant:add` | 租户管理-创建租户账号(建租户+初始管理员,code=T+4位ID) |
|
||
| Users | GET | `/tenant/users/:tenantId` | `sys:tenant:list` | 租户管理-查询租户用户 |
|
||
|
||
### 3.4 data 域
|
||
|
||
| 模块 | 文件(`data/` 下三件套) | 扩展接口 |
|
||
|---|---|---|
|
||
| **config** | `config.go` ×3 | `GET /config/web/index`(设置页读取)、`POST /config/web/save`(Log:网站设置-保存,perm `sys:config:update`) |
|
||
| **configitem** | `configitem.go` ×3 | 七件套(路由前缀 `/config/item`) |
|
||
| **param** | `param.go` ×3 | 七件套 |
|
||
| **dict** | `dict.go` ×3 | 七件套 + `POST /dict/refreshCache`(Log:字典管理-刷新缓存,perm `sys:dict:update`)+ 别名 `GET /dictionary/list`、`GET /dictionary/info`(前端 `system/dictionary.ts`,**登录即可**) |
|
||
| **dictitem** | `dictitem.go` ×3 | 七件套 + 快捷 `GET /dict/item/getDictItemList/:code`(登录即可,缓存 `dict:item:{code}`) |
|
||
| **notice** | `notice.go` ×3 | 七件套 |
|
||
| **city** | `city.go` ×3 | 七件套 + `GET /city/getCityList/:parentCode`(Log:城市管理-查询下级城市)+ 别名 `GET /area/getParent`(Log:查询省份列表)、`GET /area/findByParentCode`(Log:查询城市列表)——均登录即可 |
|
||
|
||
### 3.5 content 域
|
||
|
||
| 模块 | 文件(`content/` 下三件套) | 说明 |
|
||
|---|---|---|
|
||
| article | `article.go` ×3 | 七件套,`List` 支持 `categoryId/status/keyword` |
|
||
| category | `category.go` ×3 | 七件套,`List` 返回**树形**(Log:分类管理-查询树形列表) |
|
||
| link | `link.go` ×3 | 七件套 |
|
||
|
||
### 3.6 monitor 域
|
||
|
||
#### operlog 操作日志|表 `goframe_operation_log`
|
||
**文件**:`…/monitor/operlog.go` ×3。启用 `page/list/detail/delete/batchDelete`(增改豁免)。
|
||
路由前缀 `/oper/log`:`GET /oper/log/page`、`GET /oper/log/list`、`GET /oper/log/detail/:id`、`DELETE /oper/log/delete/:id`、`DELETE /oper/log/batchDelete`。权限 `sys:operLog:{page|list|detail|delete|batchDelete}`。
|
||
|
||
#### loginlog 登录日志|表 `goframe_login_log`
|
||
**文件**:`…/monitor/loginlog.go` ×3。同上五件,前缀 `/login/log`,权限 `sys:loginLog:*`。
|
||
|
||
#### job 定时任务|表 `goframe_job`
|
||
**文件**:`…/monitor/job.go` ×3。七件套 + 控制接口(与 `monitor/job.ts` 逐条对齐):
|
||
|
||
| 方法 | HTTP | 路由 | 权限 | 日志标题 |
|
||
|---|---|---|---|---|
|
||
| RunOnce | GET | `/job/runOnce/:id` | `sys:job:execute` | 定时任务-执行任务 |
|
||
| Pause | GET | `/job/pause/:id` | `sys:job:pause` | 定时任务-暂停任务 |
|
||
| Resume | GET | `/job/resume/:id` | `sys:job:resume` | 定时任务-恢复任务 |
|
||
| Status | POST | `/job/status` | `sys:job:update` | 定时任务-设置状态 |
|
||
| DaemonStatus | GET | `/job/daemonStatus` | 登录即可 | 定时任务-查询调度器状态 |
|
||
|
||
**实现**:`internal/logic/job/daemon.go` — 基于 `gctrl` 的常驻调度器,启动时加载 `goframe_job` 中 `status=1` 任务,按 `cron_expression` 触发 `url+params`(HTTP 调用自身接口),执行结果写 `goframe_job_log`。
|
||
|
||
#### joblog 任务日志|表 `goframe_job_log`
|
||
**文件**:`…/monitor/joblog.go` ×3。五件套,前缀 `/job/log`,权限 `sys:jobLog:*`。
|
||
|
||
### 3.7 tool 域
|
||
|
||
| 模块 | 文件 | 接口 |
|
||
|---|---|---|
|
||
| **example** | `…/tool/example.go` ×3 | 七件套 + `POST /example/import`、`GET /example/export`(perm `sys:example:import/export`) |
|
||
| **filetemplate** | `…/tool/filetemplate.go` ×3 | 七件套(前缀 `/file/template`)+ `GET /file/template/getTemplateByCode/:code`(Log:文件模板-查询模板详情,登录即可) |
|
||
| **generator** | `…/tool/generator.go` ×3 | `GET /generator/page`(Log:代码生成-查询数据表,`sys:generator:page`)、`GET /generator/preview`(预览代码)、`POST /generator/generate`、`POST /generator/batchGenerate`(`sys:generator:generate`) |
|
||
| **upload** | `…/tool/upload.go` ×3 | `POST /upload/uploadFile`(Log:文件上传-上传文件,`sys:upload:file`;存 `resource/upload/`,返回相对 URL) |
|
||
|
||
## 4. 日志体系集成
|
||
|
||
### 4.1 操作日志(自动,中间件)
|
||
|
||
`internal/middleware/operation_log.go`:
|
||
|
||
1. 请求前记录 `start`;请求后查**路由元数据表**(§1.3 注册时生成),无 `log` 标签的路由(登录、公共查询别名)跳过;
|
||
2. 组装记录:`title`(log 标签)、`type`(logType)、`source=0`、`method`、`url`、`param`(JSON,**password/salt 脱敏**)、`result`(截断 8KB)、`ip`(gip)、`os/browser`(gclient)、`consume_time`、`status`(0 正常/1 异常,按 `code!=0`)、`error`;
|
||
3. **异步落库**:`chan` + 单 goroutine 批量写(100 条或 1s flush),失败降级 `glog`error,绝不阻塞业务;
|
||
4. 配置开关:`operationLog.enable=true`、`operationLog.logQuery=true`。
|
||
|
||
### 4.2 登录日志(业务写入)
|
||
|
||
`logic/auth` 内直接写 `goframe_login_log`:登录成功/失败(`log_type=1`,失败 `status=1` 存 `error`)、退出(`log_type=2`);记录 `username/ip/location/os/browser/consume_time`。
|
||
|
||
### 4.3 查询模块
|
||
|
||
即 §3.6 的 `operlog`、`loginlog` 两个模块(page/list/detail/delete/batchDelete)。
|
||
|
||
## 5. 认证 · 多租户 · 数据库(定稿要点)
|
||
|
||
- **JWT claims**:`user_id / tenant_id / jti / username / exp`;access 2h + refresh 7d 轮换;黑名单 `blacklist:token:{jti}` TTL=剩余时效。
|
||
- **ctx 键**(`consts/context_key.go`):`CtxUserID / CtxTenantID / CtxUsername / CtxRoles / CtxPerms`。
|
||
- **租户过滤**:`internal/model/hooks/hooks.go`(gdb model hook)——Insert 自动填 `create_user/create_time/del_flag=0/tenant_id`(主键交数据库自增);Select 自动 `del_flag=0` 且租户表追加 `tenant_id IN (0,当前)`;Update 填 `update_user/update_time`+租户条件;Delete 改写软删。**业务层禁止手写这些条件**。
|
||
- **中间件链**:`CORS → Response → JWT → Tenant(status/expire 缓存) → Permission(对照路由元数据表,超管放行) → OperationLog`。
|
||
- **五库驱动**(main.go blank import):`github.com/gogf/gf/contrib/drivers/{mysql,pgsql,mssql,oracle,sqlite}/v2`;切换只改 `database.default.type/link`。
|
||
- **DDL**:`resource/sql/{mysql,pgsql,mssql,oracle,sqlite}.sql`,表前缀 `goframe_`;MySQL 为规范基准;MSSQL 时间列 `datetime2`;主键自增(int),不用 ORM 回填主键。
|
||
- **红线**:禁方言 SQL、禁 `InsertIgnore/Replace`;主键由数据库自增(int),新增后经 `LastInsertId()` 回读(Oracle 方言差异由后续人工处理);删除一律软删、查询必经 dao。
|
||
|
||
## 6. 代码生成与工程文件
|
||
|
||
```yaml
|
||
# hack/config.yaml(键名已对 gf v2.10.3 源码核实)
|
||
gfcli:
|
||
gen:
|
||
dao:
|
||
link: "mysql:root:root@tcp(127.0.0.1:3306)/easygoadmin.goframe.elevue"
|
||
removePrefix: "goframe_"
|
||
jsonCase: "CamelLower"
|
||
descriptionTag: true
|
||
service:
|
||
srcFolder: "internal/logic"
|
||
dstFolder: "internal/service"
|
||
clear: true
|
||
```
|
||
|
||
```makefile
|
||
gen: ## 表结构变更后:重新生成 dao/service
|
||
gf gen dao -c hack/config.yaml && gf gen service -c hack/config.yaml
|
||
run: ; go run main.go
|
||
build: ; go build -o bin/admin-server main.go
|
||
test: ; go test ./...
|
||
```
|
||
|
||
前置:`go install github.com/gogf/gf/cmd/gf/v2@latest`。
|
||
|
||
## 7. 前端遗留与未启用项
|
||
|
||
| 项 | 前端路由 | 处理 |
|
||
|---|---|---|
|
||
| 站内信 message | `/message/*` | 前端废弃功能,后端无表无模块,不实现 |
|
||
| 数据源管理 | `/data/source/*` | 前端废弃功能,后端无表无模块,不实现 |
|
||
| 主控台统计 | `dashboard/console.ts` | **纯前端 mock,无需接口** ✅ |
|
||
| 短信/OSS/WebSocket | `/sms/*` `/aliyun/*` `/websocket/*` | 后端桩接口已删除;前端遗留调用为废弃代码 |
|
||
| 注册 | `/register` | 白名单已放行、路由未注册;启用时补建表逻辑+开放策略+租户归属规则 |
|
||
|
||
## 8. 落地实施顺序
|
||
|
||
1. **P0 骨架**:目录 + `main.go` 驱动 + config + Makefile + `hack/config.yaml` + router/bind + 6 中间件 + `utility/{jwt,response,crypto}` + `model/hooks` + MySQL DDL(`goframe_` 前缀、`del_flag`)
|
||
2. **P0**:auth + index(登录闭环)
|
||
3. **P1**:system 域 7 模块(含 RBAC、导入导出)
|
||
4. **P1**:data + content 域
|
||
5. **P1**:monitor(operation_log 中间件 + 双日志模块 + job 调度)
|
||
6. **P2**:tool 域(example/fileTemplate/upload/generator)
|
||
7. **P2**:其余 4 份方言 DDL + SQLite 内存库集成测试
|
||
|
||
## 9. 环境信息
|
||
|
||
- MySQL:`127.0.0.1:3306`,账号 `root`/`root`,数据库 `easygoadmin.goframe.elevue`(注意库名含点,DSN 直接使用,DDL 中引用需反引号)
|
||
- 参考表结构源:`document/easygoadmin.goframe.elevue.sql`(`think_` 前缀、`is_delete` 字段)
|
||
- 前端 API 定义:`ui/src/api/**`;方法命名参考:`D:\xampp8.2\htdocs\v3\RXThinkCMF_ThinkPhp8_EleVue\app\controller`
|
||
|
||
## 10. 文件与富文本处理契约
|
||
|
||
### 10.1 上传两段式
|
||
- 上传接口(POST /api/upload/uploadFile)先落 `resource/upload/temp/{日期}/{随机名}`,返回 `/upload/temp/**` URL(可直接预览);
|
||
- 表单提交保存时由 `SaveFileField/SaveFileFields`(internal/logic/base.go)把 temp 文件移动到正式子目录(如 `user/20261013/时分秒_随机.ext`),库中与响应统一存 `/upload/**` URL;
|
||
- 校验:扩展名白名单(file.imageExt / file.fileExt)、单文件上限(file.maxSize MB)、图片魔数嗅探;
|
||
- 运营闭环:每日 03:30 自动清理超过 `file.tempExpireDays` 天的 temp 日期目录;`/upload/**` 静态访问由 `SetServerRoot("resource")` 提供;`.svg` 响应强制 `Content-Disposition: attachment` + `nosniff`(防存储型 XSS)。
|
||
|
||
### 10.2 富文本占位符(持久化契约)
|
||
- 正文(如 article.content)存库前经 `LocalizeContentFields` 处理:
|
||
- 本站 `/upload/temp/**` 引用 → 转正并替换为 `[IMG_URL]/{相对路径}`;
|
||
- 本站 `/upload/**` 正式引用 → 去域名替换为 `[IMG_URL]/{相对路径}`;
|
||
- 外站 URL 不处理(规避 SSRF);
|
||
- 匹配范围:`img|video|source|embed` 的 src 与 `a` 的 href(带文件后缀);
|
||
- 读取侧统一经 `ExpandContentFields` 还原为 `/upload/**`(唯一还原出口,禁止业务代码手写字符串替换);
|
||
- `[IMG_URL]` 为持久化格式的一部分:库内 content 字段不供第三方系统直接消费。
|
||
|
||
### 10.3 logic 共享能力层(internal/logic/base.go)
|
||
- 分区:文件字段 / 富文本 / 枚举文本(DictGetText/SerializeMapOnRead)/ 唯一校验 / 事务 / 分块查询 / 树 / 临时目录清理;
|
||
- 纪律:只依赖 dao/utility/consts;导出函数上限15个,超出按能力拆子包;
|
||
- `CheckUnique` 仅为 UX 快速报错(先查后插存在 TOCTOU),并发唯一性以数据库唯一索引为准——调用点必须有对应 `uk_*` 索引(config/dict/param/file_template 已补 `uk_code`);
|
||
- `WithTrans` 用于多写原子性(如租户开户),事务内禁止 HTTP/文件IO,bcrypt 等 CPU 操作须在事务外预计算。
|