383 lines
13 KiB
Markdown
383 lines
13 KiB
Markdown
# 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` | 登录 Cookie(ExpiresAt,Remember 字段) |
|
||
| `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: 全面重新分析代码,更新并精简记忆文档
|