商城入驻协议 — 技术方案
依据: 《商城入驻协议功能需求.md》v1.0
关联: 《商户管理技术方案.md》v1.4、《会员管理技术方案.md》v1.0、《首页banner设置技术方案.md》v1.0、《关联需求分析.md》v1.2;内容管理 商城服务协议(草稿,表结构可复用本模式)
范围: 全平台 单条 入驻协议配置;平台查看/保存;C 端只读拉取;无 商户/店铺表 FK。
原则: 单表单行(config_id=1);启用时正文必填;C 端 @Anonymous;平台代录入商户 不调用 本校验。
1. 技术架构
| 项 |
选型 |
| 基础框架 |
RuoYi v3.9.2(springboot2 分支) |
| 数据库 |
MySQL 5.7.39 |
| ORM / 权限 / 响应 |
MyBatis;@PreAuthorize;AjaxResult |
| 富文本 |
库字段 LONGTEXT;展示层 XSS 过滤(见 §5) |
| 日志 |
保存配置 @Log |
1.1 模块落位
baqing-shop
├── com.ruoyi.web.modules.content
│ ├── controller.MerchantEntryAgreementController # 平台单页配置
│ ├── controller.MerchantEntryAgreementAppController # C 端只读
│ ├── domain.BizMerchantEntryAgreement
│ ├── mapper.BizMerchantEntryAgreementMapper
│ ├── service.IMerchantEntryAgreementService
│ ├── constant.MerchantEntryAgreementConstants
│ └── support.AgreementContentSupport # 空内容/HTML 校验
sql/
└── biz_merchant_entry_agreement.sql
与 首页 Banner 同属 content 包;不 与 banner 共表。
1.2 业务链
biz_merchant_entry_agreement(config_id=1 · 单例)
│
├── 平台 GET/PUT /agri/merchantEntryAgreement
│
├── C 端 GET /api/merchant/entry/agreement(Anonymous)
│ └── enabled=false → 入驻入口/提交阻断(前端 + 后续入驻 API)
│
└── (预留)C 端入驻提交 API
└── 校验 agreementAccepted=true(AP3,见 §4.4)
| 模块 |
关系 |
| 商户管理 |
POST /agri/merchant 不校验 本协议(AP8) |
| 会员 / 服务协议 |
独立表、独立接口(草稿:biz_mall_service_agreement 等,可同构) |
| 店铺 / 商品 / 订单 |
无依赖;改协议不级联 |
1.3 跨模块契约(预留)
| 接口 |
提供方 |
调用方 |
方法 |
IMerchantEntryAgreementFacade |
本模块 |
未来 C 端「商家入驻」Service |
isEnabled() |
|
|
|
assertAccepted(boolean agreementAccepted) — 未勾选抛业务异常 |
|
|
|
getCheckboxLabel() — 拼接标题+版本 |
入驻提交 API 未实现前,Facade 可先落地供单测;商户模块 不引用。
1.4 状态联动
| 事件 |
biz_merchant_entry_agreement |
biz_merchant 等 |
| 保存协议/改启用 |
更新本表 |
不变 |
| 商户冻结、开店 |
— |
不变 |
2. 数据库设计
2.1 本模块表
| 表名 |
说明 |
biz_merchant_entry_agreement |
商家入驻协议 单例配置(全平台一条有效记录) |
2.2 字段
| 字段 |
类型 |
说明 |
| config_id |
bigint PK |
固定 1(应用层常量 CONFIG_ID=1) |
| agreement_title |
varchar(128) |
协议标题;非空 |
| version_label |
varchar(32) |
版本号;可空 |
| content |
longtext |
富文本 HTML;启用时非空 |
| enable_flag |
char(1) |
0 否 1 是;默认 0 |
| create_by, create_time, update_by, update_time, remark |
|
RuoYi 审计 |
无 del_flag、无 多版本行;历史审计靠 update_time / 操作日志。
2.3 单例约定
| 规则 |
实现 |
| 仅一行 |
SELECT ... WHERE config_id = 1 |
| 首次保存 |
无记录则 INSERT config_id=1;有则 UPDATE |
| 禁止 DELETE |
不提供删除接口 |
2.4 DDL
脚本:sql/biz_merchant_entry_agreement.sql
CREATE TABLE `biz_merchant_entry_agreement` (
`config_id` bigint(20) NOT NULL COMMENT '固定为1',
`agreement_title` varchar(128) NOT NULL DEFAULT '' COMMENT '协议标题',
`version_label` varchar(32) DEFAULT NULL COMMENT '版本号',
`content` longtext COMMENT '富文本正文',
`enable_flag` char(1) NOT NULL DEFAULT '0' COMMENT '0否1是',
`create_by` varchar(64) DEFAULT '',
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT '',
`update_time` datetime DEFAULT NULL,
`remark` varchar(500) DEFAULT NULL,
PRIMARY KEY (`config_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商家入驻协议配置';
INSERT INTO `biz_merchant_entry_agreement` (
`config_id`, `agreement_title`, `version_label`, `content`, `enable_flag`, `create_time`
) VALUES (
1, '农资商城商家入驻协议', 'v1.0', '', '0', NOW()
);
2.5 字典
| dict_type |
用途 |
| sys_yes_no |
enable_flag 平台页展示 |
3. 平台端接口设计
基路径: /agri/merchantEntryAgreement
权限: agri:merchantEntryAgreement:query | edit
3.1 接口一览
| 方法 |
路径 |
权限 |
说明 |
| GET |
/ |
query |
获取当前配置(无记录时返回默认空壳) |
| PUT |
/ |
edit |
保存配置(insert or update) |
3.2 获取配置 GET /
响应 data:
{
"configId": 1,
"agreementTitle": "农资商城商家入驻协议",
"versionLabel": "v1.0",
"content": "<p>协议正文...</p>",
"enableFlag": "1",
"enableFlagLabel": "是",
"updateBy": "admin",
"updateTime": "2026-05-26 10:00:00"
}
| 场景 |
行为 |
| 表无记录 |
configId=1;标题/内容空;enableFlag=0 |
3.3 保存配置 PUT /
{
"agreementTitle": "农资商城商家入驻协议",
"versionLabel": "v1.0",
"content": "<p>正文 HTML</p>",
"enableFlag": "1",
"remark": ""
}
| 字段 |
校验 |
| agreementTitle |
非空,≤128 |
| versionLabel |
可空,≤32 |
| enableFlag |
0 / 1 |
| content |
enableFlag=1 时非空且去 HTML 标签后非空;LONGTEXT 建议应用层上限 512KB |
| enableFlag=0 |
content 可空 |
成功: code=200,msg=操作成功;立即 对 C 端下一请求生效(AP9)。
3.4 错误文案(Service)
| 场景 |
msg |
| 标题空 |
请输入协议标题 |
| 启用但内容空 |
启用状态下请填写协议内容 |
| 内容仅空白标签 |
协议内容不能为空 |
| 启用参数非法 |
是否启用参数无效 |
4. C 端接口设计
基路径: /api/merchant/entry
鉴权: @Anonymous
4.1 获取入驻协议 GET /api/merchant/entry/agreement
| 项 |
说明 |
| 数据源 |
config_id=1 |
| 缓存 |
本期 不做 Redis;读库即时 |
enable_flag=1 且内容有效:
{
"code": 200,
"data": {
"enabled": true,
"agreementTitle": "农资商城商家入驻协议",
"versionLabel": "v1.0",
"content": "<p>HTML...</p>",
"checkboxLabel": "我已阅读并同意《农资商城商家入驻协议》v1.0"
}
}
checkboxLabel 规则:
我已阅读并同意《{agreementTitle}》
若 versionLabel 非空 → 我已阅读并同意《{agreementTitle}》({versionLabel})
enable_flag=0 或内容无效:
{
"code": 200,
"data": {
"enabled": false,
"message": "商家入驻暂未开放"
}
}
C 端 不返回 禁用态下的历史正文(AP4)。
4.2 与会员注册的关系
| 接口 |
用途 |
GET /api/member/... |
会员/服务协议(另模块) |
GET /api/merchant/entry/agreement |
仅 商家入驻 |
4.3 入驻开放状态(可选便捷接口)
GET /api/merchant/entry/status
{
"code": 200,
"data": {
"entryOpen": true
}
}
entryOpen = isEnabled();供 C 端控制入口显隐(可选,可与 §4.1 合并由前端读 enabled)。
4.4 未来:C 端提交入驻 POST /api/merchant/entry(预留)
| 字段 |
校验 |
agreementAccepted |
必须为 true;否则「请先阅读并同意商家入驻协议」 |
|
且 isEnabled() 为 true |
主体字段与 biz_merchant 对齐 另册;落库 不经过 POST /agri/merchant 时代录路径。
5. Service 要点
getConfig() → selectById(1) or 默认空壳 VO
saveConfig(dto) → validate → insert(1) or update(1)
getForApp() → enabled? 拼 checkboxLabel : {enabled:false}
isEnabled() → enable_flag=1 && content 非空
assertAccepted → !accepted → ServiceException
5.1 富文本与安全
| 项 |
实现建议 |
| 存储 |
原样存 content |
| C 端/平台预览输出 |
可选 HtmlUtil.clean 白名单(与 RuoYi XSS 配置一致) |
| 空内容判定 |
AgreementContentSupport.isBlankHtml(content) — 去标签后 trim 为空视为无内容 |
6. 业务规则映射
| 编号 |
实现 |
| AP1 |
单表单行 config_id=1 |
| AP2 |
仅 MerchantEntryAgreementController + 菜单权限 |
| AP3 |
assertAccepted(入驻 API / Facade) |
| AP4 |
getForApp:enable_flag=0 → enabled=false |
| AP5 |
saveConfig 启用时校验 content |
| AP6 |
无历史表;不更新已入驻商户 |
| AP7 |
独立表;路径 /merchant/entry vs 会员 /member |
| AP8 |
商户 MerchantController 不注入 Facade |
| AP9 |
无发布表;读写同一行 |
| AP10 |
无级联 UPDATE 商户/店铺 |
7. 菜单权限
| 菜单(建议) |
权限标识 |
| 商城入驻协议 |
agri:merchantEntryAgreement:query |
| 保存 |
agri:merchantEntryAgreement:edit |
上级:农资管理 → 内容管理(与 Banner、服务协议并列)。
8. 关联方案摘要
【平台】PUT /agri/merchantEntryAgreement → 维护正文与启用
↓
【C 端】GET /api/merchant/entry/agreement → 展示 + checkboxLabel
↓
【C 端】(未来)POST /api/merchant/entry + agreementAccepted=true
↓
【平台】审核/代录入 → 商户管理(不要求勾选本协议)
【并行】POST /agri/merchant → 平台代入驻,无协议校验
| 对比 |
首页 Banner |
本模块 |
| 数据形态 |
多行列表 |
单例一行 |
| 平台 API |
CRUD + 排序 |
GET + PUT |
| C 端 |
列表展示 |
富文本 + 勾选语义 |
| 启用 |
enable_flag |
enable_flag + content 有效 |
9. 非本期实现
协议版本历史表、勾选存证、强制阅读时长、PDF、多语言、sys_config 存正文、Redis 缓存。
10. 文档索引
| 文档 |
版本 |
| 商城入驻协议功能需求.md |
v1.0 |
| 商户管理功能需求/技术方案 |
v1.4 |
| 首页banner设置技术方案.md |
v1.0 |
| 关联需求分析.md |
v1.2 |
文档版本:v1.0 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《商城入驻协议功能需求.md》v1.0