--- title: "13-用户标签接口" created: 2025-12-02 tags: - 项目 aliases: - 用户标签接口 --- # 用户标签接口 没讲用户怎么定义自己的标签 这里自己来实现一下 ## 两种方案: ### 方案一:多对多关系设计 (同user和team) 利用 tag 表和用户-标签的多对多关系设计 数据库设计: user表 tag表 再创建一个 user\_tag 表,存储用户与标签的关联关系 ```sql CREATE TABLE user_tag ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键', userId BIGINT NOT NULL COMMENT '用户ID', tagId BIGINT NOT NULL COMMENT '标签ID', createTime DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updateTime DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', isDelete TINYINT DEFAULT 0 COMMENT '是否删除', UNIQUE KEY `uk_user_tag` (userId, tagId), CONSTRAINT fk_user FOREIGN KEY (userId) REFERENCES user (id), CONSTRAINT fk_tag FOREIGN KEY (tagId) REFERENCES tag (id) ) COMMENT '用户-标签关联表'; ``` 优点: 标准化存储:标签可以独立维护,避免重复存储 灵活性高:增加新功能(如全局标签管理、统计功能)更容易 高效搜索:可以直接通过 SQL 查询用户的标签或具有相同标签的用户 ### 方案二:继续将标签保存在用户表的 tags 字段中 实现方式: 将 tags 字段设计为一个 JSON 数组存储标签。 在增删改时,直接操作 tags 字段的 JSON 数据,避免与 tag 表的关联操作。 优点: 简单易行:避免多表关联操作,代码实现较简单。 性能提升:无需涉及多表 join 操作,适合小规模数据存储。 缺点: 数据冗余:多个用户的重复标签会造成数据冗余。 扩展性较差:难以实现全局标签管理或统计功能。 虽然推荐方案是一 但是还是希望尝试一下第二种实现方式 因为team已经写过关联表的形式了 这里想用一种不同的方式 因为标签从逻辑上来看 貌似更符合user的一个属性 user有哪些标签 user可以自定义标签 ## 分析 思考一个问题 tags是user的一个属性作为一个字符串存储在数据库中 考虑用户体验 在前端应该是设计成 在用户中心页面 标签板块 提供很多按钮供选择 已有的标签标蓝 未有的标签正常 要添加或者修改标签 实际上是点击标签进行选择 或者自定义标签 自己写标签内容 到最后我们做的事情是拼接成字符串整个传到后端 对原有数据进行替换 所以貌似增删改都是一种操作 等待用户操作完点击提交 将拼接好的字符串传给后端 进行字段替换 貌似只需要实现两个功能 一个是查询当前用户的tag 在前端页面给他标蓝一下 一个是更新当前用户的tag 增删改都是拼接完成后进行修改 统一成”改“ ### 核心逻辑: **用户在前端选择或定义标签:** 显示所有可选择的标签列表; 用户已有标签(从后端查询的结果)标蓝; 用户通过点击标签进行选择、取消选择,或添加新的自定义标签; 最终将所有选中的标签统一拼接成字符串或列表,并一并提交到后端。 **后端完成一个职责:** 查询接口:返回当前用户的标签; 更新接口:直接替换整个 tags 字段为提交的新数据,统一 "增/删/改" 动作为一个操作。 ### **优点:** 1. 前端交互更直观: - 前端展示所有可用标签,并以直观的方式(例如按钮高亮)提示哪些已经被选中。 - 用户可以直接点击已有标签来取消选择,新选择或自定义标签一并处理,体验较为流畅。 2. 后端逻辑简单,易于维护: - 只需关注两件事情:查询标签 和 更新(直接覆盖保存)标签; - 前端拼接好数据后传给后端,后端只需做一次性替换,无需关注具体的增删改细节。 - 对于已经用字符串存储 tags 到数据库的场景,这种简化方法是非常实用的。 ### **此方案是否有问题** 虽然从逻辑上没问题,但潜在可能有以下问题需要注意: #### 潜在问题:并发一致性问题 **场景:** 用户 A 正在更改自己的标签页面,但尚未提交; 此时用户 A 在另一设备上也更改了自己的标签,并提交成功; 回到第一个设备,用户 A 提交未更新的标签数据,可能会覆盖掉第二次改动。 **解决思路:** 可以对 tags 字段添加版本号机制,防止并发冲突覆盖。 例如,利用乐观锁 (@Version) 模式,如果版本号不同,则提示用户刷新页面: ```text @Version private Long version; // 数据库中的版本号 ``` #### 潜在问题:前端输入不规范 **场景:** 用户在自定义标签输入时,输入了超长的标签或者非法字符,影响数据库存储或后续业务逻辑。 **解决思路:** 前端:限制条件,建议标签字符长度不超过固定值(如 10 个字符),限制标签总数(如不超过 10 个); 后端:在接收数据时校验标签长度与数量,避免非法数据进入系统。 #### 已有标签管理问题 如果系统中已经有预定义的标签集合(用于推荐或统计),而用户添加了完全自定义的标签,可能会引入混乱。 解决思路: 约束用户输入: 自定义标签只能选择或创建有限集合中的选项(例如关键字库),而不是完全自由输入。 前后端配合: 前端限制选择/输入的标签总数; 后端做标签的规范化存储和校验。此外,可以提供一个 "推荐标签" 的接口,供前端展示。 ## 实现 --- **项目分区导航**:⬅️ [[12-搜索标签serviceimpl|12-搜索标签serviceimpl]] | 13-用户标签接口 | ➡️ [[14-组队功能|14-组队功能]]