Files
senmesh-zc/backend/AGENTS.md
KodouWZF 47273ae3fd init: 信创文件安全传输系统内外网本地 Docker 部署
包含 s-file 后端、React 前端、MeshSafe 安全检测对接,以及内外网两套
compose/nginx/配置(仅前端 28180/28280 对外发布,其余端口不暴露)。

说明:deploy/config/application-iw.yml 与 application-ow.yml 按维护者
明确要求原样入库,其中含本机 Docker 用的库口令、RabbitMQ 口令与 JWT
密钥;上生产前需替换。
2026-11-02 10:59:03 +08:00

75 lines
7.4 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.
# AGENTS.md — s-file(alita-bjy-uygur)编码代理指南
信创文件传输/网盘后端服务:内网与外网之间做文件安全传输("内穿外/外传内"),附带个人网盘、分享、机构与用户管理、通知等能力。单 Maven 模块,Spring Boot 可执行 jar,Docker 部署(`src/main/resources/Dockerfile`)。
## 技术栈(务必匹配,勿升级)
- **Java 8** + Spring Boot **2.4.2**(父 POM 管理)
- ORM:**MyBatis-Plus 3.4.0**(注解/BaseMapper)+ 自研 `com.senmesh.tkmybatis` 封装 + PageHelper 1.4.6 + 自定义分页拦截器
- 数据库:**达梦 DM8**(信创主力,另有 MySQL/PG 驱动),Druid 连接池,SQL 需多库兼容
- 安全:Spring Security + 自研 JWT(`com.senmesh.security`),Redisson 分布式锁,RabbitMQ
- 文档:springfox swagger2 2.7.0;Lombok + MapStruct 1.2.0
## 常用命令
```bash
# 编译(需 JDK 8,例如本机 Zulu 1.8)
export JAVA_HOME=/Users/leijiaping/Library/Java/JavaVirtualMachines/azul-1.8.0_452/Contents/Home
mvn compile -DskipTests
# 测试目录基本为空(仅 PwdTest),项目无自动化测试,验证靠编译 + 自查
```
**已知依赖问题(重要)**:商业依赖 `e-iceblue:spire.pdf:3.7.4` 在阿里云/e-iceblue 官方仓库均不存在(官方仓库只有 9.x+)。本地仓库 `~/.m2/repository/e-iceblue/spire.pdf/3.7.4/` 现已安装一个**手工编译级 stub jar**(仅为 `PdfUtils.java` 引用的类签名生成),使 `mvn package` 可以通过;**代价是运行 PDF 盖章功能(`PdfUtils.pdfStampPerPage`)会失败**。正式发布前需从公司私服获取真实 jar 覆盖。全量快速编译验证可跳过 PdfUtils.java(详见下方命令)。
```bash
mvn dependency:build-classpath -Dmdep.outputFile=/tmp/cp.txt # 需联网
$JAVA_HOME/bin/javac -encoding UTF-8 -cp "$(cat /tmp/cp.txt)" \
-sourcepath src/main/java -d /tmp/v \
$(find src/main/java -name "*.java" ! -name "PdfUtils.java")
```
## 包结构地图(`com.senmesh`)
| 包 | 职责 |
|---|---|
| `usercenter` | 用户中心:`user`(用户/机构用户/注销)、`org`、`authority`(角色/权限)、`notice`(通知)、`auth` 等,子模块按「controller/service/impl/dto/entity/dao/mapper(XML)/constant/enums」分目录 |
| `sfile` | 文件业务:`UserFile`(上传/传输/分享记录,核心表 `x_user_file`)、`TransferUserFile`、`ShareUserFile`、`TransferFileMonitorJob`(定时扫描传输目录) |
| `component/file` | 物理文件上传组件(`xs_file_record`、`/file/upload`、`FileProperties`) |
| `common` | `AlitaResult`、`PageQueryDTO`、`BaseEntity`、`UserContextHolder`、异常体系 |
| `security` | JWT 过滤器、登录、`UserInfoDTO` |
| `frame/redis` | Redisson 封装:`RedissonUtils`、`@AutoUnLock`、`LockDTO` |
| `mybatis` / `mybatisplus` / `tkmybatis` | 分页拦截器、`@MapperScan`、`MyMapper<T>` 基类 |
| `mq`、`codesetting`、`config` 等 | 其他支撑模块 |
**注意**:源码树里有同包覆写的框架类(`org/springframework/...`、`com/senmesh/swagger`),改动前先确认是否为刻意覆写,不要删除。
## 新增一个接口的标准动作
1. **DTO**:查询 DTO 继承 `PageQueryDTO<XxxDTO>`(自带 pageNo/pageSize/needPage/pageResult);出参 DTO 继承 `BaseDTO`(用 `@SuperBuilder`);时间字段统一 `Date` + `@DateTimeFormat` + `@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")`。
2. **Entity**:继承 `BaseEntity`(带机构的继承 `OrgBaseEntity`),`@TableName` 注解,逻辑删除字段 `deleted`。
3. **Mapper**:接口继承 `MyMapper<T>`(已有 `saveEntity`/`updateEntitySelective`/`getById`/`deleteEntity`,自动填充 createBy/updateBy),放 `**/dao/`;**自定义 SQL 的 XML 放同名 java 源码目录的 `mapper/` 下**(pom 已配置打包 java 目录下 `**/*.xml`),XML 中参数一律 `@Param("param")` + `param.xxx` 引用。
4. **Service**:接口 + `impl`。权限校验用命令式断言(项目无 @PreAuthorize):
- 平台超管:`Assert.isTrue(UserContextHolder.isSuperior(), "当前用户无操作权限")`,注意字段拼写就是 `supeiror`(历史笔误,勿"修复")
- 机构管理员:`UserContextHolder.isAdministrator()`;平台机构:`checkPlatformOrg()`
5. **Controller**:返回一律 `AlitaResult<T>`(`AlitaResult.success(data)`);`@Api(tags=...)` + `@ApiOperation`;分页接口返回 `AlitaResult<Page<T>>`,模式:Service 把 queryDTO 传给 mapper 即自动分页,Controller 返回 `queryDTO.getPageResult()`。查询类用 GET + query 参数绑定,操作类用 POST + `@Validated @RequestBody`。
6. **URL 前缀有语义**:`anon/**` 匿名(清单在配置 `security.anonymous`)、`unac/**` 已登录未激活可用、`authed/**` 已实名;普通前缀 = 登录即可。
## 关键业务概念
- **用户**(`uc_user`):`status` 1待激活/2已激活/3已注销 + `enabled` 启用开关 + 逻辑删除 `deleted`,三者独立。登录侧实时校验 `enabled=TRUE and status!=3`,禁用/注销后用户下次请求即失效。注销有两套:自助申请流(`UserCancelService`,`uc_user_cancel` 表)与管理员直接注销(`user/admin_cancel`)。同一手机号可对应多个账号(企业+个人)。
- **机构**:`xs_org`(`parent_id` 树)+ `uc_org_user` 中间表(含 `administrator` 标志,一个用户可在多个机构,登录时选定 orgId)。**用户表没有 org_id**。平台机构固定 `orgId=1`(`CommonConstants.PLATFORM_ORG_ID`)。
- **文件记录**(`x_user_file`):上传/发送/接收/分享全在这一张表,靠 `root_type` 区分:`1`普通(上传)、`2`内穿外、`3`外传内、`4`我的分享;`file_status`:1正常/2失效/11解析中/12待审核/13传输中/14失败。表里只有 `user_id`,无手机号,按手机号查需 JOIN `uc_user.phone`。
- **传输方向映射**(`file.transfer.location`:1内网/2外网):发送记录 = 内网端 rootType 2 / 外网端 rootType 3;接收记录取反。手机号只在传输 ZIP 包内 `transferMetadata.json`,接收端解包时靠它反查本地用户。
## 陷阱清单
- 只能写 **Java 8** 语法(无 `var`/`Set.of`/record/switch 表达式;集合用 guava `Sets.newHashSet` 等也行)。
- SQL 要兼容 DM8:布尔字面量用 `TRUE/FALSE`(bit 列),时间用 `now()`;避免 MySQL 专属函数;分页依赖拦截器,XML 里不要手写 limit。
- XML 放错位置不会被打包——必须放 java 源码目录(与现有 `UserMapper.xml`、`UserFileMapper.xml` 同级模式)。
- 驼峰映射由 MyBatis-Plus 默认开启,XML 直接 `SELECT u.real_name` 即可映射 `realName`;列别名规避同名冲突(如 `u.type AS user_type`)。
- 注销/禁用等敏感操作要防并发:参考 `userCancel` 的 `RedissonUtils.tryLockAutomatically(LockDTO...)` + `@AutoUnLock` 模式;禁止注销/禁用自己与超管。
- 数据库初始化脚本在 `db/`(`init-table.sql` MySQL 版、`init-table-postgres-full.sql` PG 版),改表结构需同步两个版本;增量变更另建 `db/upgrade-YYYYMMDD-*.sql`(现有:`upgrade-20260914-upload-config.sql`),历史上有过 DDL 只加脚本、不改 init 的情况,新环境安装依赖 init 脚本,**改表务必 init 与 upgrade 双写**。
- 给前端的接口变更请同步维护 `docs/` 下的接口文档(现有:`接口文档-用户管理与记录查询.md`、`接口文档-机构上传配置.md`)。
- `.commandcode/` 为本地工具产物,勿提交。