# 畜牧科技资源管理 — 技术方案 > 依据:`畜牧科技资源管理功能需求.md`(同目录) --- ## 1. 技术架构 | 层级 | 说明 | | --- | --- | | **整体** | RuoYi **v3.9.2**(**springboot2** 分支)单体后端 + 若依 **Vue2** 前端(与分支配套) | | **运行时** | JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,存储引擎 InnoDB,字符集 **utf8mb4** | | **文件** | 复用 RuoYi **`/common/upload`**;业务表存 **URL + 存储路径**(`photo_*` / `cover_*` / `video_*`) | | **外部系统** | 平台 **用户/角色**(分配账号);**移动端** 查询 `publish_status=1` 且 `del_flag=0` 展示(接口由移动端或网关实现) | **后端分层** | 层 | 职责 | | --- | --- | | `Controller` | 参数接收、`@PreAuthorize`、返回 `AjaxResult` / `TableDataInfo` | | `Service` | 按 `resource_type` 校验、发布状态机、分配账号、替换附件删旧文件 | | `Mapper` + XML | 持久化、列表三态筛选 | | `domain` + `support` | 实体;`TechResourceRules`、`TechResourceValidation`、`TechResourceAccountAssigner` 等 | **代码包(建议)**:`com.ruoyi.web.modules.technology` **初始化脚本**:`sql/biz_tech_resource.sql` **一致性策略(与需求对齐)** | 规则 | 实现要点 | | --- | --- | | 单表四类 | `resource_type` 区分;保存后**不可改类型** | | 改删 / 发布 | 仅 `publish_status=0` 且 `del_flag=0`(已下架 = `publish_status=0` 且 `offline_time` 非空) | | 下架 | 仅 `publish_status=1` → `publish_status=0`、`offline_time=now()`;**保留** `publish_time` | | 再次发布 | `publish_status=1`、`publish_time=now()`、**清空** `offline_time` | | 分配账号 | 仅 `resource_type=004005`、`account_assigned=0`、`publish_status=0`;成功一次;登录名=姓名拼音**首字母**+`id`;角色 `role_key=exp`;登录名冲突**不**置已分配 | | 移动端可见 | `publish_status=1` 且 `del_flag=0` | --- ## 2. 数据库设计 ### 2.1 表:`biz_tech_resource`(畜牧科技资源主表) 单表承载四类共用字段 + 差异化可空列;逻辑删除 `del_flag`。 | 字段名 | 类型 | 非空 | 默认 | 说明 | | --- | --- | --- | --- | --- | | `id` | `bigint(20)` | Y | 自增 | 主键 | | `resource_type` | `varchar(32)` | Y | — | 资讯类别编码(`parentCode=004`、`categoryType=7`),见 **2.2** | | `resource_name` | `varchar(64)` | Y | — | 展示名称(专家姓名/成果名称/仪器名称/课程标题) | | `photo_file_url` | `varchar(512)` | N | NULL | 主图 URL(专家照片、仪器照片) | | `photo_file_path` | `varchar(512)` | N | NULL | 主图存储路径(`/profile/...`) | | `cover_file_url` | `varchar(512)` | N | NULL | 封面 URL(技术成果、视频课程,选填) | | `cover_file_path` | `varchar(512)` | N | NULL | 封面存储路径 | | `video_file_url` | `varchar(512)` | N | NULL | 视频 URL(视频课程) | | `video_file_path` | `varchar(512)` | N | NULL | 视频存储路径 | | `introduction` | `varchar(500)` | N | NULL | 介绍/简介(专家、仪器、课程) | | `achievement_summary` | `varchar(500)` | N | NULL | 成果摘要(技术成果) | | `key_tech_principle` | `varchar(500)` | N | NULL | 关键技术原理 | | `tech_advantage` | `varchar(500)` | N | NULL | 技术优势 | | `research_direction` | `varchar(32)` | N | NULL | 研究方向(可输入下拉落库文本) | | `completion_unit` | `varchar(64)` | N | NULL | 完成单位 | | `contact_phone` | `varchar(20)` | N | NULL | 联系电话 | | `affiliated_unit` | `varchar(64)` | N | NULL | 隶属单位 | | `detail_address` | `varchar(200)` | N | NULL | 详细地址(专家) | | `service_area` | `varchar(200)` | N | NULL | 服务区域(专家) | | `fee_standard` | `decimal(10,2)` | N | NULL | 收费标准,元/小时(专家) | | `expert_rating` | `decimal(2,1)` | N | NULL | 专家评分 1.0~5.0;**仅专家**新增时默认 `5.0`,其它类型为 NULL;管理端不展示 | | `borrow_fee` | `decimal(10,2)` | N | NULL | 借用金额,元/小时(共享仪器) | | `service_start_time` | `varchar(8)` | N | NULL | 服务开始 `HH:mm` | | `service_end_time` | `varchar(8)` | N | NULL | 服务结束 `HH:mm` | | `service_weekdays` | `varchar(32)` | N | NULL | 服务周日,逗号分隔 `1`~`7` | | `instrument_model` | `varchar(32)` | N | NULL | 仪器型号 | | `storage_location` | `varchar(200)` | N | NULL | 存放地点 | | `reservation_process` | `varchar(500)` | N | NULL | 预约流程 | | `person_in_charge` | `varchar(32)` | N | NULL | 负责人 | | `course_topic` | `varchar(32)` | N | NULL | 课程主题(资讯类别编码 parentCode=005,见 **2.5**) | | `longitude` | `decimal(10,6)` | N | NULL | 经度(地图标点预留) | | `latitude` | `decimal(10,6)` | N | NULL | 纬度(预留) | | `publish_status` | `tinyint(4)` | Y | `0` | 发布状态,见 **2.3** | | `publish_time` | `datetime` | N | NULL | 最近发布时间 | | `offline_time` | `datetime` | N | NULL | 最近下架时间 | | `account_assigned` | `tinyint(4)` | Y | `0` | 是否已分配账号 | | `sys_user_id` | `bigint(20)` | N | NULL | 关联 `sys_user.user_id` | | `assigned_login_name` | `varchar(64)` | N | NULL | 已分配登录名 | | `del_flag` | `char(1)` | Y | `'0'` | `0` 正常 / `2` 删除 | | `create_by` / `create_time` / `update_by` / `update_time` / `remark` | — | — | — | 若依惯例 | **索引**:`PRIMARY KEY (id)`;`idx_type (resource_type)`;`idx_name (resource_name)`;`idx_publish (publish_status)`;`idx_del (del_flag)`。 **DDL(MySQL 5.7)** ```sql CREATE TABLE `biz_tech_resource` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `resource_type` varchar(32) NOT NULL COMMENT '资讯类别编码(parentCode=004,categoryType=7)', `resource_name` varchar(64) NOT NULL COMMENT '资源名称', `photo_file_url` varchar(512) DEFAULT NULL COMMENT '主图URL', `photo_file_path` varchar(512) DEFAULT NULL COMMENT '主图路径', `cover_file_url` varchar(512) DEFAULT NULL COMMENT '封面URL', `cover_file_path` varchar(512) DEFAULT NULL COMMENT '封面路径', `video_file_url` varchar(512) DEFAULT NULL COMMENT '视频URL', `video_file_path` varchar(512) DEFAULT NULL COMMENT '视频路径', `introduction` varchar(500) DEFAULT NULL COMMENT '介绍/课程简介', `achievement_summary` varchar(500) DEFAULT NULL COMMENT '成果摘要', `key_tech_principle` varchar(500) DEFAULT NULL COMMENT '关键技术原理', `tech_advantage` varchar(500) DEFAULT NULL COMMENT '技术优势', `research_direction` varchar(32) DEFAULT NULL COMMENT '研究方向', `completion_unit` varchar(64) DEFAULT NULL COMMENT '完成单位', `contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话', `affiliated_unit` varchar(64) DEFAULT NULL COMMENT '隶属单位', `detail_address` varchar(200) DEFAULT NULL COMMENT '详细地址', `service_area` varchar(200) DEFAULT NULL COMMENT '服务区域', `fee_standard` decimal(10,2) DEFAULT NULL COMMENT '收费标准元/小时', `expert_rating` decimal(2,1) DEFAULT NULL COMMENT '专家评分1.0-5.0(仅专家)', `borrow_fee` decimal(10,2) DEFAULT NULL COMMENT '借用金额元/小时', `service_start_time` varchar(8) DEFAULT NULL COMMENT '服务开始HH:mm', `service_end_time` varchar(8) DEFAULT NULL COMMENT '服务结束HH:mm', `service_weekdays` varchar(32) DEFAULT NULL COMMENT '服务周日1-7', `instrument_model` varchar(32) DEFAULT NULL COMMENT '仪器型号', `storage_location` varchar(200) DEFAULT NULL COMMENT '存放地点', `reservation_process` varchar(500) DEFAULT NULL COMMENT '预约流程', `person_in_charge` varchar(32) DEFAULT NULL COMMENT '负责人', `course_topic` varchar(32) DEFAULT NULL COMMENT '课程主题(资讯类别编码,parentCode=005,categoryType=8)', `longitude` decimal(10,6) DEFAULT NULL COMMENT '经度预留', `latitude` decimal(10,6) DEFAULT NULL COMMENT '纬度预留', `publish_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0非发布态1已发布', `publish_time` datetime DEFAULT NULL COMMENT '发布时间', `offline_time` datetime DEFAULT NULL COMMENT '下架时间', `account_assigned` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0未分配1已分配', `sys_user_id` bigint(20) DEFAULT NULL COMMENT '关联用户ID', `assigned_login_name` varchar(64) DEFAULT NULL COMMENT '分配登录名', `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '0正常2删除', `create_by` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar(64) DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar(500) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_type` (`resource_type`), KEY `idx_name` (`resource_name`), KEY `idx_publish` (`publish_status`), KEY `idx_del` (`del_flag`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='畜牧科技资源'; ``` **界面三态与查询映射** | 界面状态 | `publish_status` | `offline_time` | 列表 `publishStatus` 参数 | | --- | --- | --- | --- | | 未发布 | `0` | `NULL` | `0` | | 已发布 | `1` | 任意 | `1` | | 已下架 | `0` | **非** `NULL` | `2` | **类型与字段落库矩阵(应用层强校验)** | 字段 | 专家(004005) | 技术成果(004006) | 共享仪器(004007) | 视频课程(004008) | | --- | --- | --- | --- | --- | | `resource_name` | ✓ | ✓ | ✓ | ✓ | | `photo_*` | ○ | — | ○ | — | | `cover_*` | — | ○ | — | ○ | | `video_*` | — | — | — | ✓ | | `introduction` | ○ | — | ○ | ○ | | `achievement_summary` / `key_tech_principle` / `tech_advantage` | — | ○ | — | — | | `research_direction` / `completion_unit` | — | ✓/○ | — | — | | `contact_phone` | ○ | — | ○ | — | | `affiliated_unit` | ○ | — | ○ | — | | `detail_address` / `service_area` / `fee_standard` | ○ | — | — | — | | `service_start_time` / `service_end_time` / `service_weekdays` | ○ | — | ○ | — | | `borrow_fee` / `instrument_model` / `storage_location` / `reservation_process` / `person_in_charge` | — | — | ○ | — | | `course_topic` | — | — | — | ✓ | > **○** 选填;**✓** 该类型必填(应用层)。 ### 2.2 资源类型 `resource_type` 数据来自 `GET /category/informationCategory/children?parentCode=004&categoryType=7`(响应 `code`、`name`)。落库与接口传 **叶子 `code`**。 | `code` | 含义 | | --- | --- | | `004005` | 专家 | | `004006` | 技术成果 | | `004007` | 共享仪器 | | `004008` | 视频课程 | 保存校验:`TechResourceTypeValidator` 以上述 children 返回的 `code` 集合为准。历史 `tinyint` 迁移见 `sql/biz_tech_resource_alter_resource_type.sql`(`1`→`004005` … `4`→`004008`)。 ### 2.5 课程主题 `course_topic`(仅 `resource_type=004008`) 数据来自 `GET /category/informationCategory/children?parentCode=005&categoryType=8`。落库与接口传 **叶子 `code`**。 | `code` | 含义 | | --- | --- | | `005001` | 基础养殖 | | `005002` | 疫病防治 | | `005003` | 繁育技术 | | `005004` | 政策解读 | 保存校验:`TechResourceCourseTopicValidator`(`resource_type=004008` 时调用)。历史中文主题迁移见 `sql/biz_tech_resource_alter_course_topic.sql`。 ### 2.3 发布状态 `publish_status` | 值 | 含义 | | --- | --- | | `0` | 非发布态(未发布或已下架,由 `offline_time` 区分) | | `1` | 已发布 | - **发布**:`publish_status=1`,`publish_time=now()`,`offline_time=NULL`。 - **下架**:`publish_status=0`,`offline_time=now()`;**不改** `publish_time`。 ### 2.4 其他枚举 | 项 | 约定 | | --- | --- | | `service_weekdays` | 多选入库,逗号分隔 `1`~`7`(周一=1) | | `account_assigned` | `0` 未分配 / `1` 已分配 | | `del_flag` | `0` 正常 / `2` 逻辑删除 | | 分配账号角色 | 专家(`resource_type=004005`)按 `sys_role.role_key=**exp**` 解析 `role_id` 并绑定(库中常见 `role_id=101`,以配置为准) | | 登录名 | 专家姓名汉语拼音**首字母**(小写)+ `id`;实现类 `TechResourceLoginNameGenerator`(委托 `TradingPartnerLoginNameGenerator`) | **研究方向**:库内存**文本**;前端可输入下拉,预设项由前端常量维护。**课程主题**见 **§2.5**,存资讯类别 `code`。 ### 2.6 分配账号(`TechResourceAccountAssigner`) | 项 | 说明 | | --- | --- | | 范围 | 仅 `resource_type=004005`(专家) | | 前置 | `account_assigned=0`;`publish_status=0`(未发布或已下架) | | 登录名 | 对 `resource_name` 逐字取汉语拼音**首字母**(小写);ASCII 字母数字原样小写拼接;再拼接 `id`(如「张专家」、id=12 → `zzj12`) | | 角色 | `SysRoleMapper.checkRoleKeyUnique("exp")`;未配置则「未配置权限字符为「exp」的角色,无法分配账号」 | | 落库 | `account_assigned=1`、`sys_user_id`、`assigned_login_name`、`update_by` | | 次数 | 每条仅成功一次;重复调用返回「该资源已分配账号,不可重复分配」 | | 删除联动 | 逻辑删除专家且已分配时 `deleteUserById(sys_user_id)` | --- ## 3. 接口设计 **统一响应**:`AjaxResult`(`code` / `msg` / `data`)或分页 `TableDataInfo`(`rows` / `total`)。 **权限标识**:`techService:techResource:list|query|add|edit|remove|publish|offline|assignAccount` **Base Path**:`/techService/techResource` ### 3.1 分页列表 | 项 | 说明 | | --- | --- | | **Method / URI** | `GET /techService/techResource/list` | | **权限** | `techService:techResource:list` | | **Query** | `pageNum`(默认 1)、`pageSize`(默认 **20**)、`resourceType`(**必填**,精确)、`resourceName`(模糊,可空)、`publishStatus`(`0`/`1`/`2`,可空,映射见 **§2.1**) | | **排序** | `create_time DESC`, `id DESC` | | **条件** | `del_flag='0'` | | **响应** | 行字段含 `id`、`resourceType`、`resourceName`、`introduction`(可截断)、`displayPublishStatus`、`displayPublishStatusName`、`publishStatus`、`accountAssigned`、`createTime` 及类型相关列;`serviceWeekdays` 列表场景可不展开 | ### 3.2 详情 | 项 | 说明 | | --- | --- | | **Method / URI** | `GET /techService/techResource/{id}` | | **权限** | `techService:techResource:query` | | **响应** | 全业务字段(驼峰);`serviceWeekdays` 以 **数组** 返回;含展示用发布三态、`canEdit` / `canPublish` / `canOffline` / `canAssignAccount` 等(可选);仅 `del_flag=0` | ### 3.3 新增 | 项 | 说明 | | --- | --- | | **Method / URI** | `POST /techService/techResource` | | **权限** | `techService:techResource:add` | | **Body** | JSON:`resourceType`、`resourceName` 及按类型字段;`serviceWeekdays` 为数组;图片/视频须先 `/common/upload` | | **校验** | `TechResourceValidation` 按 **§2.1** 矩阵;手机号、时段、正数金额;图片 jpg/jpeg/png;视频 mp4 | | **落库** | `publish_status=0`,`offline_time=NULL`,`account_assigned=0`,`del_flag=0` | ### 3.4 修改 | 项 | 说明 | | --- | --- | | **Method / URI** | `PUT /techService/techResource` | | **权限** | `techService:techResource:edit` | | **前置** | `publish_status=0` 且 `del_flag=0`;否则「已发布资源请先下架后再编辑」 | | **Body** | 含 `id`;可改各业务字段及附件路径;**不可改** `resourceType` | | **逻辑** | 替换 `photo_*` / `cover_*` / `video_*` 时删除旧物理文件;不自动发布 | ### 3.5 删除 | 项 | 说明 | | --- | --- | | **Method / URI** | `DELETE /techService/techResource/{ids}` | | **权限** | `techService:techResource:remove` | | **规则** | `publish_status=1` 禁止;仅 `publish_status=0` 可逻辑删除;存在下游引用时 `TechResourceReferenceChecker` 拒绝(若实现) | | **结果** | `del_flag='2'`;删除 `photo_*`/`cover_*`/`video_*` 物理文件;**若 `account_assigned=1` 且 `sys_user_id` 非空**,调用 `ISysUserService.deleteUserById` 删除平台账号 | | **顺序** | 校验 → 引用检查 → `TechResourceAccountAssigner.deleteLinkedAccount` → 删附件 → 逻辑删除 | ### 3.6 发布 | 项 | 说明 | | --- | --- | | **Method / URI** | `POST /techService/techResource/publish/{id}` | | **权限** | `techService:techResource:publish` | | **前置** | `publish_status=0`;全量校验通过 | | **结果** | `publish_status=1`,`publish_time=now()`,`offline_time=NULL` | ### 3.7 下架 | 项 | 说明 | | --- | --- | | **Method / URI** | `POST /techService/techResource/offline/{id}` | | **权限** | `techService:techResource:offline` | | **前置** | `publish_status=1` | | **结果** | `publish_status=0`,`offline_time=now()`;保留 `publish_time` | ### 3.8 分配账号 | 项 | 说明 | | --- | --- | | **Method / URI** | `POST /techService/techResource/assignAccount/{id}` | | **权限** | `techService:techResource:assignAccount` | | **前置** | `resource_type=004005`;`account_assigned=0`;`publish_status=0` | | **结果** | 创建 `sys_user`、绑定 `role_key=**exp**` 对应角色;写 `sys_user_id`、`assigned_login_name`、`account_assigned=1` | | **失败** | 登录名冲突等返回明确 `msg`,**不**置 `account_assigned=1` | > **地图标点**:本期无接口。 --- ## 4. 附件上传(实现提示) | 类型 | 前端上传 | 落库字段 | 服务端校验 | | --- | --- | --- | --- | | 图片 | `/common/upload` → `url`、`fileName` | `photo_*` 或 `cover_*` | jpg/jpeg/png;路径 `/profile` 前缀;≤10MB(前端+可选后端) | | 视频 | 同上(或扩展视频上传配置) | `video_*` | mp4;≤30MB | --- ## 5. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 畜牧科技资源管理 | `techService:techResource:list` | | 按钮 | 查询 | `techService:techResource:query` | | 按钮 | 新增 | `techService:techResource:add` | | 按钮 | 修改 | `techService:techResource:edit` | | 按钮 | 删除 | `techService:techResource:remove` | | 按钮 | 发布 | `techService:techResource:publish` | | 按钮 | 下架 | `techService:techResource:offline` | | 按钮 | 分配账号 | `techService:techResource:assignAccount` | 组件路径:`techService/techResource/index`(挂载「牧业养殖科技服务」目录下)。 --- ## 6. 交付清单 - [ ] `sql/biz_tech_resource.sql` - [ ] Domain / Mapper / Service / Controller(`technology` 包) - [ ] `TechResourceValidation`、`TechResourceRules`、分配账号组件 - [ ] 菜单与按钮权限 SQL - [ ] 单元测试 / MockMvc:四类校验、发布三态、专家分配账号、已发布不可改删 --- ## 7. 修订记录 | 日期 | 说明 | | --- | --- | | — | 初稿,对齐 `畜牧科技资源管理功能需求.md` v2.0 | | — | 单表 `biz_tech_resource`;`/techService/techResource`;专家角色 101;技术成果/视频分字段与封面、视频列 | | — | 删除接口:专家已分配账号时联动 `deleteUserById`(对齐草稿 §10) | | 1.2 | 专家分配账号:登录名拼音首字母+`id`;角色按 `role_key=exp` 解析;仅一次;§2.6、`§3.8` |