v0.0.3 用户管理与手机号脱敏
版本信息
| 项目 | 内容 |
|---|---|
| 版本 | v0.0.3 |
| 定位 | 新增核心用户管理模块,统一手机号脱敏能力,修复富文本全屏展示问题 |
| 发布日期 | 2026-09-25 |
本版本在不改变既有接口行为的前提下,新增管理端「用户管理」核心模块(会员用户)、统一的手机号脱敏工具,并修复管理端富文本编辑器全屏后的层级错乱问题。
升级涉及一张新表和三条菜单,增量脚本可重复执行。
主要变更
用户端(会员认证体系)
会员认证接口全部切换到
sys_member表(原/api接口错误地操作sys_user,已移除重写):方法 路由 说明 POST /api/sms/code发送短信验证码(1登录 2注册 3换绑手机号),独立于认证接口的通用能力 POST /api/auth/register手机号+验证码注册,默认昵称/头像取用户端平台配置,注册后直接登录 POST /api/auth/login_password账号密码登录,账号不存在时提示「账号不存在」 POST /api/auth/login_sms手机号+验证码登录 POST /api/auth/logout退出登录 GET /api/auth/profile当前会员资料(手机号脱敏) POST /api/auth/profile/update修改昵称、姓名、头像 POST /api/auth/account/update修改登录账号(4-32位字母数字下划线,全表唯一) POST /api/auth/password/update修改登录密码(至少6位且含字母和数字,已设密码时校验原密码,改后强制重新登录) POST /api/auth/mobile/update修改手机号(新手机号验证码校验,全表唯一) 短信验证码限流(基于 Redis 计数实现):同一手机号同一场景每分钟最多 2 条;5 分钟内累计超过 5 条则禁止发送 30 分钟,并提示用户端「账号已被限制30分钟」;验证码 5 分钟有效、错误超过 5 次作废、校验成功一次性消费。所有发送行为(成功、渠道失败、被限流拦截)均写入短信发送记录,拦截请求的错误信息记录具体拦截原因,供管理端审计。
用户编号(sn)由
pkg/sn统一生成:固定小写前缀cf+ 8 位小写字母和数字(如cfk3m9x2a),唯一索引兜底,冲突自动重试。用户端每个接口必须携带请求头:
X-Platform-Source(平台来源 1-4,缺失或非法返回 400,注册时写入注册来源)、X-App-Version(客户端版本号,仅透传不做一致性校验)。登录令牌为单会话:JWT 携带会员ID、昵称、sn、头像与会话ID(login_id);重新登录后旧令牌失效;管理端禁用会员后令牌立即失效。
新增
pkg/sms短信发送封装(阿里云/腾讯云,标准库实现无新增依赖),验证码按短信配置(sys_sms_config/签名/验证码模板)发送,发送结果写入短信发送记录;新增pkg/sn业务编号生成封装。鉴权中间件支持客户端类型限定:管理端接口仅接受 admin 令牌,用户端接口仅接受 api 令牌,两类令牌不能互调。
后端
新增会员用户模型
internal/common/model/sys_member.go,表sys_member管理C端注册用户。新增枚举
internal/common/enums/member.go:- 性别 gender:
1男、2女、3未知; - 注册来源 register_source:
1微信小程序、2微信公众号、3iOS、4Android。
- 性别 gender:
新增管理端接口(
Auth → Permission → OperationLog完整链路):方法 路由 用途 GET /admin/member/list系统用户分页列表,支持关键字、账号状态、注册来源筛选 POST /admin/member/set_status启用/禁用会员账号,同状态重复提交幂等返回成功 CheckTables核心必需表清单加入sys_member,缺表时服务拒绝启动并提示执行升级脚本。管理端禁用会员时同步删除其会话缓存,会员令牌立即失效;管理端系统用户列表增加「编号」(sn)展示并纳入关键字搜索。
新增
pkg/mask统一脱敏工具:mask.Mobile:手机号保留前 3 位与后 4 位(138****8001);空串或纯空白返回空串;非 11 位原样返回;mask.MobilePtr:可空指针版本,nil返回空串;- 已接入:会员用户列表、短信发送记录、用户端个人资料三处展示;
- 人员管理列表与个人设置保持原文返回:两处的编辑表单使用列表数据回填后提交,脱敏会把掩码串写回数据库,待修改接口支持「掩码值不更新」语义后再接入。
系统版本号改为在
config.yaml顶层version配置,作为版本号唯一来源,启动时校验必填(未配置时服务拒绝启动并给出明确提示):- 启动日志输出当前生效版本(如
管理端 API v0.0.3 启动: ...); go run . version -c config.yaml输出配置中的生效版本;/admin/platform/public与/admin/platform/admin/detail响应新增version字段,登录页底部与「系统配置 → 平台配置 → 管理端配置」展示该版本号。
- 启动日志输出当前生效版本(如
接口文档
docs/admin_openapi.yaml同步新增「系统用户」标签、两个接口与MemberItem/MemberListRes/MemberSetStatusReq结构,并补充性别、注册来源通用枚举说明。配置模板
config.example.yaml与 README 配置表同步新增version配置项。
数据库
新增表 sys_member(会员用户表),基础字段与 sys_user 一致(id、created_at、updated_at、deleted_at),业务字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| sn | varchar(32) | 用户编号,全局唯一(M+时间戳+随机数) |
| account | varchar(32) | 登录账号,可空唯一索引,未设置为 NULL |
| login_id | varchar(64) | 当前登录会话ID,重新登录后旧会话失效,配合 Redis 实现禁用即失效 |
| nickname | varchar(32) | 昵称 |
| real_name | varchar(32) | 姓名 |
| account | varchar(32) | 登录账号(普通索引) |
| mobile | varchar(16) | 手机号(唯一索引,业务必填) |
| password | varchar(128) | 登录密码 bcrypt 密文 |
| avatar | varchar(512) | 头像相对路径 |
| gender | tinyint | 性别:1男,2女,3未知 |
| age | tinyint unsigned | 年龄 |
| birthday | date | 出生日期 |
| register_ip / login_ip | varchar(64) | 注册IP / 最近登录IP |
| registered_at / logged_at | datetime(3) | 注册时间 / 最近登录时间 |
| balance | decimal(12,2) | 账户余额(Go 侧字符串承载,禁用浮点) |
| register_source | tinyint | 注册来源:1微信小程序,2微信公众号,3iOS,4Android |
| status | tinyint | 账号状态:1启用,2禁用 |
新增菜单(脚本按 path / api_path 业务键判断,可重复执行,不指定自增ID):
用户管理(目录 /user,sort 5)
└── 系统用户(页面 /user/system,GET:/admin/member/list)
└── 用户禁用(按钮,POST:/admin/member/set_status)管理端
- 新增
src/api/member.ts、src/types/member.ts、src/enums/member.ts与页面src/views/user/system/index.vue(菜单路径/user/system对应动态路由)。 - 系统用户列表展示:用户(头像+昵称+账号)、姓名、手机号(脱敏)、性别(男/女/未知三种 tag 颜色区分)、年龄、出生日期、账户余额、注册来源、账号状态、注册时间与注册IP两行展示、最近登录时间与登录IP两行展示。
- 操作列提供启用/禁用按钮(
v-perm控制权限,二次确认后提交)。 - 修复
RichTextEditor全屏问题:wangeditor 官方全屏样式只设置position:fixed不带z-index,会被顶栏(z-index:5)和 DOM 靠后的定位元素遮挡;现统一为z-index:1000,高于布局层、低于 Element Plus 弹窗(2000+)与水印(9999),并去除全屏态的圆角边框。
升级前准备
- 备份 MySQL 数据库。
- 备份当前后端二进制与管理端构建产物。
- 在
config.yaml顶层增加version: v0.0.3(本版本起版本号为必填配置,未配置时服务拒绝启动)。 - 确认已执行历史版本全部脚本(
sql/v0.0.1/cf_backend_frame.sql、sql/v0.0.2/与sql/v0.0.3/下增量脚本)。
数据库升级
mysql -uroot -p 数据库名 < sql/v0.0.3/member.sql脚本包含建表与菜单写入,均可重复执行;重复执行不会产生重复菜单。执行后检查:
SHOW CREATE TABLE sys_member;
SELECT id, name, type, path, api_path FROM sys_menu WHERE path LIKE '/user%' OR api_path LIKE '%member%';推荐部署顺序
- 停止旧版管理端 API。
- 备份数据库并执行
sql/v0.0.3/member.sql。 - 在生产
config.yaml中增加version: v0.0.3。 - 发布并启动新版管理端 API(用户端 API 如未变更可不发布,本版本用户端仅个人资料手机号脱敏一处变化)。
- 发布新版
admin_client静态资源。 - 在「角色管理」为普通角色分配「用户管理」菜单及「用户禁用」按钮权限(超级管理员默认可见)。
- 冒烟验证系统用户列表、筛选、启用/禁用。
验证命令
后端:
gofmt -l .
go vet ./...
go build ./...
go test ./...管理端:
pnpm exec vue-tsc --noEmit
pnpm build部署后至少检查:
go run . version -c config.yaml输出server_api v0.0.3,服务启动日志带版本号;- 用户端服务(
service api)正常启动,注册登录流程可用(需先在短信配置中维护真实渠道、签名与验证码模板); - 登录页底部展示版本号,「平台配置 → 管理端配置」可看到只读的系统版本;
- 服务启动不再提示缺少
sys_member表; - 「用户管理 → 系统用户」页面可以打开,列表含编号、手机号为脱敏格式;
- 禁用/启用操作生效,无权限角色看不到操作按钮且接口返回 403;
- 短信发送记录与用户端个人资料的手机号为脱敏格式;
- 文章编辑页富文本全屏后工具栏完整可见、表单不再穿透,退出全屏恢复正常。
版本边界
- 用户端注册仅支持手机号+验证码,注册后未设置登录账号与密码时需先通过短信验证码登录,再通过账号/密码修改接口设置。
- 短信验证码依赖短信配置中的真实渠道凭证,测试环境可使用本地 mock 服务地址验证全流程。
- 手机号脱敏仅覆盖展示型响应;人员管理与个人设置因编辑回填流程暂不脱敏。
- 会员账户余额仅作展示,充值、消费等资金操作未在本版本范围内。