Files
ops2/.workbuddy/memory/MEMORY.md
T
2026-04-29 11:55:56 +08:00

383 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MEMORY.md - 长效记忆
> 最后更新: 2026-04-29
---
## 项目概览
**项目名称**: OPS 运营管理系统
**技术栈**: Vue 3 + Vite (前端 Web) / uni-app (移动端) / Go + Gin + GORM (后端)
```
ops2/
├── backend/my_work/ # Go 后端(端口由 config.yaml 决定,默认 8080
├── frontend/
│ ├── ops_vue_js/ # Vue 3 Web 前端
│ └── ops2_uniapp/ # uni-app 移动端
└── DOC/
```
---
## 后端架构
### 启动流程 (`main.go`)
1. 检查 `./data/config.yaml`,不存在则复制 `./defConfig/configTemp.yaml`
2. `configed` 必须为 `true` 才能启动
3. 初始化顺序:`ReturnInit``ApiUserInit``ApiFilesInit``ApiScheduleInit``ApiPurchaseInit``ApiWorkOrderInit``ApiWarehouseInit``BindsInit`
4. 静态文件服务 `./dist`,所有非 `/api` 请求转发给前端 HTML
5. 支持 TLS(证书路径在 config 中配置)
6. 版本信息通过 `-ldflags -X` 编译注入(`GitVersion / GitCommit / BuildTime`
### 路由根 (`api.go`)
```
/api
├── /static → ApiStatic
├── /users → ApiUser
├── /files → ApiFiles
├── /purchase → ApiPurchase
├── /schedule → ApiSchedule
├── /work_order → ApiWorkOrder
├── /warehouse → ApiWarehouse
└── /admin → ApiSysAdmin
```
### 请求/响应格式
```json
// 请求体
{ "userCookieValue": "xxx", "data": { ...业务参数 } }
// 响应体
{ "err_code": 0, "err_msg": "apiOK", "return": { ... } }
```
错误码从 `./defConfig/errorCodes.json` 读取,常用:`apiOK`=0`userNoLogin`=-44`permission_denied``parameErr``dbErr`
### 认证机制
- 登录成功返回 Cookie 对象(存 `TabUserCookie` 表)
- 后续请求通过 JSON body 中 `userCookieValue` 传递
- Cookie 过期后端返回 err_code=-44,前端拦截器自动处理
- `AuthenticationAuthority(ctx)` → 分离 cookie 和 data,验证返回 `(isAuth bool, user TabUser, data map)`
---
## 用户认证模块 (`apiUsers.go`)
### 数据表
| 表 | 说明 |
|---|---|
| `TabUser` | 用户(Name 唯一索引) |
| `TabUserGroups` | 用户组 |
| `TabUserGroupBinds` | 用户-组绑定 |
| `TabUserInfo` | 用户详情(头像/昵称/性别/生日/语言等) |
| `TabUserCookie` | 登录 CookieExpiresAtRemember 字段) |
| `TabUserLoginFailLog` | 登录失败日志(24小时内聚合,累计 Count) |
### 初始化
- 自动创建 `admins` 组 + `admin` 用户(默认密码 `adminpassword`
- 密码:加盐哈希,支持 `text` / `md5` / `md5salt`config 指定)
### 权限缓存(内存)
各模块维护各自的管理员 ID 列表:
| 变量 | 所属模块 | 刷新函数 |
|---|---|---|
| `sysAdmins []uint` | apiUsers.go | `updateSysAdminsCash()` |
| `scheduleAdmins []uint` | apiSchedule.go | `ScheduleUpdateAdminsCash()` |
| `purchaseAdmins []uint` | apiPurchase.go | `PurchaseUpdateAdminsCash()` |
| `workOrderAdmins []uint` | apiWorkOrder.go | `WorkOrderUpdateAdminsCash()` |
| `warehouseAdmins []uint` | apiWarehouse.go | `WarehouseUpdateAdminsCash()` |
**修改用户组时自动刷新缓存**`apiSysAdmin.go``add_group_member``remove_group_member`):
```go
switch group.Name {
case "admins": updateSysAdminsCash()
case "schedule_admin": ScheduleUpdateAdminsCash()
case "purchase_admin": PurchaseUpdateAdminsCash()
case "work_order_admin": WorkOrderUpdateAdminsCash()
case "warehouse_admin": WarehouseUpdateAdminsCash()
}
```
### API 路由 (`/api/users/*`)
| 路由 | 用途 |
|------|------|
| `POST /login` | 登录(返回 Cookie 对象,含 Remember |
| `POST /register` | 注册 |
| `POST /getinfo` | 获取当前用户信息(含 isSysAdmin 字段) |
| `POST /changePassword` | 修改密码(oldpass/newpass |
| `POST /changeEmail` | 修改邮箱 |
| `POST /updateAvatar` | 更新头像(FormData |
| `POST /updateInfo` | 更新详情(firstName/username/birthdate/gender/region/language |
| `GET /getuserinfo/:id` | 获取指定用户信息 |
---
## 系统管理模块 (`apiSysAdmin.go`)
**路由前缀**: `/api/admin/*`,全部要求 `SysAdminCheck`
| 路由 | 用途 |
|------|------|
| `POST /sysadmins` | 获取系统管理员 ID 列表 |
| `POST /users` | 用户列表(分页+搜索,返回含头像路径) |
| `POST /groups` | 用户组列表(含成员数 + 前5个成员ID) |
| `POST /group_members` | 指定组的成员列表(分页) |
| `POST /user_detail` | 用户详情(基本信息 + userinfo |
| `POST /reset_user_password` | 重置密码(同时注销该用户所有 cookie) |
| `POST /add_group_member` | 添加用户到组(含缓存刷新) |
| `POST /remove_group_member` | 从组移除用户(含缓存刷新) |
| `POST /login_fail_logs` | 登录失败日志(分页+搜索 username/IP |
`SysAdminCheck(userID)` 直接查内存 `sysAdmins` 列表。
---
## 文件管理模块 (`api_Files.go`)
### 数据表 `TabFileInfo`
| 字段 | 说明 |
|---|---|
| `Sha256` | 唯一标识,去重键 |
| `Name` | 原始文件名 |
| `Path` | 存储路径 |
| `Mime` | MIME 类型 |
| `Type` | image/video/pdf 等 |
| `Const` | 引用计数 |
### 存储结构
```
data/
├── static/avatar/ # 用户头像(/api/static/avatar/:filename
└── upload/
├── image/ # 以 SHA256 命名
├── video/
├── music/
└── pdf/
```
### API (`/api/files/*`)
| 路由 | 用途 |
|---|---|
| `POST /upload/image` | 上传图片(FormData + SHA256 去重) |
| `GET /:mode/:hash` | `get`=下载(带文件名),`download`=预览 |
---
## 日程模块 (`apiSchedule.go`)
### 数据表
- `TabSchedule`(软删除):Title / StartDate / EndDate / BgColor(默认#3788d9) / Remark
- `TabScheduleLog`:操作日志
### API (`/api/schedule/*`)
| 路由 | 用途 |
|---|---|
| `POST /getevents` | 按日期范围查询(`start_date <= end AND end_date >= start` |
| `POST /addevent` | 新增 |
| `POST /editevent` | 编辑 |
| `POST /deleevent` | 软删除 |
---
## 采购模块 (`apiPurchase.go`)
### 数据表
| 表 | 用途 |
|---|---|
| `TabPurchaseOrder` | 采购订单(软删除) |
| `TabPurchaseCosts` | 费用明细(单价/运费,多币种) |
| `TabPurchaseFileBind` | 图片关联 |
| `TabPurchaseCommit` | 状态变更记录 |
| `TabPurchaseLog` | 操作日志 |
### 状态流
```
pending → ordered → arrived → received
lost / returned
```
### 货币:`1-CNY / 2-MOP / 3-HKD / 4-USD`
### API (`/api/purchase/*`)
| 路由 | 用途 |
|---|---|
| `POST /getorder` | 订单详情(含费用/图片/状态记录/关联工单) |
| `POST /getorders` | 列表(搜索/分页/状态筛选) |
| `POST /addorder` | 新增 |
| `POST /updateorder` | 编辑(费用/图片重建) |
| `POST /deleteorder` | 删除 |
| `POST /updatestatus` | 更新状态(可附评论/图片) |
| `POST /delete_commit` | 删除状态记录 |
| `POST /getordercount` | 各状态数量统计 |
| `POST /search_work_orders` | 搜索工单(用于关联) |
---
## 工单模块 (`apiWorkOrder.go`)
### 数据表
| 表 | 用途 |
|---|---|
| `TabWorkOrder` | 工单(软删除) |
| `TabWorkOrderFileBind` | 工单图片关联 |
| `TabWorkOrderCommit` | 进度记录 |
| `TabWorkOrderCommitFileBind` | 进度关联图片 |
| `TabWorkOrderPurchaseOrderBind` | 工单-采购订单关联(含 CommitID) |
| `TabWorkOrderLog` | 操作日志 |
### 状态流
```
pending → checked → parts_ordered → repaired → returned
unrepairable
```
### 特殊逻辑
- 状态变为 `returned` 时,自动移除物品的容器绑定(`ContainerID = nil`
- 工单 ↔ 物品:`TabWarehouseItemWorkOrderBind`
- 工单 ↔ 采购:`TabWorkOrderPurchaseOrderBind`
### API (`/api/work_order/*`)
| 路由 | 用途 |
|---|---|
| `POST /add` | 新增(可关联物品) |
| `POST /update` | 编辑 |
| `POST /list` | 列表 |
| `POST /get` | 详情(含图片/进度/关联物品/采购) |
| `POST /commit` | 提交进度(更新状态,可关联采购) |
| `POST /delete` | 删除 |
| `POST /delete_commit` | 删除进度 |
| `POST /count` | 各状态统计 |
| `POST /search_purchase_orders` | 搜索采购订单(用于关联) |
---
## 仓库模块 (`apiWarehouse.go`)
### 数据表
| 表 | 用途 |
|---|---|
| `TabWarehouseContainer` | 容器(树形,最多5层,ParentID=nil为顶级) |
| `TabWarehouseItem` | 物品(ContainerID=nil表示未入库) |
| `TabWarehouseItemCommit` | 物品移动记录 |
| `TabWarehouseLog` | 操作日志 |
### 跨模块绑定表 (`binds.go`)
| 表 | 用途 |
|---|---|
| `TabWarehouseItemWorkOrderBind` | 物品-工单 |
| `TabWarehouseItemFileBind` | 物品-图片 |
| `TabWarehouseContainerFileBind` | 容器-图片 |
| `TabPurchaseFileBind` | 采购-图片 |
| `TabWorkOrderFileBind` | 工单-图片 |
| `TabWorkOrderCommitFileBind` | 工单进度-图片 |
| `TabWorkOrderPurchaseOrderBind` | 工单-采购 |
---
## Web 前端架构 (`frontend/ops_vue_js/`)
**技术栈**: Vue 3 + Vite 7 + Pinia + Vue Router (hash 模式) + Vue I18n + Tailwind CSS v4 + Tabler Icons
### 目录结构
```
src/
├── api/
│ ├── index.js # Axios 实例,基础 URL /api,请求拦截注入 cookie,响应拦截处理 -44
│ ├── auth.js # 认证 + sysadmin 管理 API
│ ├── purchase.js # 采购 API
│ ├── warehouse.js # 仓库 API
│ ├── work_order.js # 工单 API
│ ├── schedule.js # 日程 API
│ └── users.js # 其他用户信息 API(按需加载头像/用户名)
├── components/
│ ├── AppHeader.vue # 导航栏(含系统管理入口,权限判断 isSysAdmin
│ ├── AppFooter.vue
│ ├── AppToast.vue
│ ├── ConfirmDialog.vue
│ ├── PurchaseOrderForm.vue
│ ├── SettingNav.vue
│ ├── tagadder.vue
│ ├── useDropzone.vue # 文件拖拽上传
│ ├── imageCropper.vue # 图片裁剪
│ ├── datePicker.vue
│ ├── dateTimePicker.vue
│ └── datatimePickerForFullCalendar.vue
├── composables/
├── i18n/
│ ├── en.json # 英文翻译
│ └── zh-CN.json # 中文翻译
├── layouts/
│ ├── DefaultLayout.vue # 需要登录的页面布局
│ └── AuthLayout.vue # 认证页面全屏布局
├── router/index.js
├── stores/
│ ├── user.js # 当前用户(isLoggedIn / isSysAdmin / cookie / avatarUrl
│ ├── users.js # 其他用户信息缓存(按需拉取,防重复请求)
│ └── toast.js # 全局 Toast
└── views/
├── HomeView.vue
├── ScheduleView.vue # FullCalendar
├── SysAdminView.vue # 系统管理(仅 sysAdmin 可访问,meta.requireSysAdmin
├── AdminView.vue
├── purchase/ # PurchaseList / addorder / ShowOrder / editorder
├── work_order/ # WorkOrderList / AddEditWorkOrder / ShowWorkOrder
├── warehouse/ # WarehouseOverview / ContainerList / ContainerDetail / ItemList / ItemDetail / AddItem / ItemEdit
└── settings/ # AccountView / ContactView / SecurityView
```
### 路由说明
- 公开页:`/` `/login` `/register` `/forgot_password` `/schedule` `/404`
- `/sysadmin` 需要 `meta.requireSysAdmin`,不满足跳回首页
- 未登录跳转 `/login?redirect=原路径`
### 状态管理 (`stores/user.js`)
- Cookie 持久化:`Remember=true` 存 localStorage,否则只存 sessionStorage
- `isSysAdmin``/users/getinfo` 返回的 `isSysAdmin` 字段驱动
- `fetchUserInfo()``login()` 后自动调用
### i18n 翻译节点
`week / errorpage / appname / tagadder / dropzone / cropper / purchase / work_order / warehouse / purchase_addorder / schedule / home / message / settings / button / footer / cost_type / order_status / sysadmin`
### 构建配置
- 输出目录: `../../backend/my_work/dist`(后端直接 serve
- 开发代理: `/api``http://127.0.0.1:8080`
- 路径别名: `@``./src`
---
## 移动端 (`frontend/ops2_uniapp/`)
**技术栈**: uni-app + Vue 3 + Pinia
**当前完成度**: ~40%
| 页面 | 完成度 |
|---|---|
| login | 85%(表单/验证/请求/Toast |
| settings | 90%API 地址配置/连接测试) |
| index/order/message | 5%(占位) |
| user | 20%(登录入口) |
**待完成**:
- 完善 `api/index.js`Cookie 认证,参照 Web 前端)
- 实现各功能页面(仓库/工单/采购等)
---
## 开发注意事项
1. **后端 JSON 字段命名**: 结构体字段为 PascalCase(如 `UserID / AvatarPath`),前端需对应
2. **头像**: `usersStore.getAvatarUrlFromUserID(id)` 返回 `/api/static/avatar/{path}` 或默认 `/ava.svg`
3. **i18n 修改**: 同时修改 `en.json``zh-CN.json` 两个文件
4. **同源部署**: 后端 serve `./dist` 静态资源,前端 build 直接输出到后端目录
5. **API 封装**: `api/index.js` 统一返回 `{ errCode, data, raw }`
---
## 更新记录
- 2026-04-24: 首次梳理
- 2026-04-28: 修复 SysAdminView 中 `<img .../>` 误删 bug;添加 message.sysadmin 英文翻译
- 2026-04-29: 全面重新分析代码,更新并精简记忆文档