日期:2026-10-21。本文对应当前本地后端改动,尚未完成编译、发布及在线联调。
接口均为应用路径,不含网关 /api 等前缀,沿用现有 baseURL 和后台鉴权请求配置。
后端/运维执行:
docs/sql/20261021-coupon-exchange-permissions.sql:补齐 9 个权限,默认仅授权 root。
父菜单无法自动识别时按脚本填写父菜单 id。已有权限不重复添加。docs/sql/20261021-login-audit.sql:创建登录日志表。前端不直接操作权限表。后台登录返回的 AdminInfo 已有 permissions 和 roles,
可沿用现有登录流程:/manage/admin/get/loginInfo 或 /manage/user/get/loginInfo。
/manage/menu/get/self/menu 只返回非 button 菜单,不能从这里推断完整按钮权限。
| 入口 | 显示/请求条件 | 后端接口 |
|---|---|---|
| 兑换码页、查询按钮、首次列表加载、翻页 | exchangeCode:view | GET /manage/exchange/code/get |
| 生成兑换码按钮及提交 | 同时有 exchangeCode:add 和 exchangeCode:export | GET /manage/exchange/code/createAndExport |
| 导出按钮及提交 | exchangeCode:export | GET /manage/exchange/code/export |
没有 view 时不请求列表、不渲染码明文及复制按钮,展示无权限提示。 权限异步加载完成后才决定是否首次请求;退出登录/切换账号清空列表、表单和已缓存码。 路由守卫、按钮和点击处理函数都检查权限,不能只隐藏按钮。后端仍为最终授权边界。 不要仅凭 root 字样在前端忽略权限码;应使用项目现有、与后端一致的权限匹配逻辑。
// 概念示例,接到项目现有权限工具,不另造登录或 token 存储。
const canView = hasPermission('exchangeCode:view');
const canGenerate = hasPermission('exchangeCode:add') && hasPermission('exchangeCode:export');
const canExport = hasPermission('exchangeCode:export');
| 参数 | 类型/规则 |
|---|---|
| goodsId | 商品 Long,可选 |
| skuId | 规格 Long,可选 |
| code | 完整兑换码,精确匹配,不再模糊查询 |
| userId | 用户 Long,可选 |
| useStatus | true/false 或 1/0;全部时省略,未使用必须显式传 false |
| codeType | 1 兑换码、2 兑换链接;全部时省略 |
| start | 从 1 开始的页码,默认 1 |
| limit | 1–100,默认 10 |
只发送上述字段。不要传 condition、operator、字段 -op、逻辑分组或动态排序。
不再支持透传其他历史 BeanSearcher 参数;若现有页面依赖,请列清单再联调,不恢复通用参数透传。
兑换链接筛选先解析 URL 的 code 查询参数,再传完整码本身;不要把整个 URL 直接作为 code。
查询列表返回 Result<SearchResult<ExchangeCodeView>>,沿用现有 BeanSearcher 列表解析。
导出为 xlsx,最多 10000 条,不按分页截断;超限提示缩小筛选范围。
非 root 只能查当前创建人范围;历史创建人昵称为空或重名时后端会拒绝,前端显示后端提示。
沿用 GET 查询参数(兼容现有页面,后续联合迁移 POST,不要预加载或自动重试该请求):
skuIds=[823]
number=10
type=0
codeType=1
查询沿用 Result:code、msg、flag、data,成功以现有统一拦截器判断。
不要只依据 HTTP 200 判定业务成功。二进制下载先区分 Content-Type 是否为 JSON,
JSON 错误解析后展示 msg,不生成错误 Excel。鉴权失效走现有重新登录流程;
无权限展示提示,不自动重试,不降级到 external 接口。
| 行为 | 权限 |
|---|---|
| 查询券、分类、发放记录及统计 | coupon:view |
| POST /manage/coupon 新增券 | coupon:add |
| PUT /manage/coupon 及推荐、推广码、分类、活动等配置 | coupon:edit |
| 删除券、分类、推荐、活动等记录 | coupon:delete |
| POST /manage/coupon/send 或 /corp/send | coupon:send |
其他新增配置 POST(例如分类、弹窗)目前归 coupon:edit,不是 coupon:add。
所有 /manage/coupon 接口都要求后台身份,不能用前台用户 token。
普通用户领券继续使用 /applet/coupon/**,不要改调后台接口。
新增券请求剔除 id;编辑使用 PUT 且带 id。折扣 0 < discount <= 1,立减金额 > 0,
金额沿用后端原有“分”单位,表单显示“元”时做好转换。
只允许 roles 精确包含 root 的后台账号访问;不包含则隐藏入口且禁止发请求。
当前后端使用 root 角色限制,不需要新增 loginAudit:view 权限码。
GET /manage/login/audit/get?start=1&limit=20
GET /manage/login/audit/get?loginType=user&loginId=1533797&start=1&limit=20
筛选:loginType、loginId、account、result、loginMethod、ip、from、to;空值省略。
start 从 1 开始,limit 1–100(默认 20);from/to 为 URL 编码后的 yyyy-MM-dd HH:mm:ss。
时间沿用应用环境时区,不擅自转换两次。
注意:登录日志分页不是 BeanSearcher。 返回 Result<Page<LoginAudit>>,
列表读 data.records,总数读 data.total,当前页 data.current,页大小 data.size。
建议列表列:时间、身份类型、用户 ID、账号、登录方式、结果、连接 IP、浏览器、系统、耗时。 详情抽屉:remoteIp、forwardedFor、realIp、userAgent、device、requestPath、httpMethod、reason。
| 字段 | 展示说明 |
|---|---|
| loginType | user 普通用户;login 默认后台;其他值原样显示 |
| loginMethod | sms_code 短信、email_code 邮箱、google、wechat、mini_program 小程序 |
| 其他方式 | password_check 后台密码预检查、admin_impersonation 管理员代登录、account_switch 切换账号、phone_or_email_code 未细分、other/unknown |
| result | SUCCESS 会话创建成功;FAILURE 处理异常;CHECK_SUCCESS 凭据预检查通过,不能标成已登录 |
| account/loginId | 可以为空,空值展示 —,不能据此断言异常或伪造身份 |
| remoteIp | socket 对端,经过代理时可能是网关地址 |
| forwardedFor/realIp | 未验证代理头,可能被伪造,界面明确标“代理头(未验证)” |
| durationMs | 到登录事件发生时耗时,毫秒,不是完整 HTTP 请求耗时 |
ip 筛选目前只精确匹配 remoteIp 或 realIp,不查询 forwardedFor 链。 日志从部署后开始记录,不能回溯历史;未抛异常的业务失败不保证计入 FAILURE。 不提供删除、编辑或导出日志接口。敏感字段仅按文本渲染,不使用 v-html/innerHTML。
/external/app/get/mirror:后台 root + exchangeCode:view。/external/app/refund/{id}:后台 root + exchangeCode:refund。上述为待执行验收项,不表示线上已经通过;后端当前编译被既有腾讯云 SDK 依赖缺失阻断。
PUT /manage/user/add/balance:userBalance:add。PUT /manage/user/sub/balance:userBalance:deduct。GET /manage/user/get/user/balance/sys/operate/record:userBalance:view。userId、deductBalance、remark;用户 ID 必须为正数,金额单位仍为分,必须为正整数且最多 10 位;备注必填且最多 255 字符。禁止连点提交,超时后先查账,不要自动重试增加余额。@balance_parent_override 必须设置为真实用户管理菜单 ID,执行后检查 12 个权限全部为 OK;未配置不会默认开放。root 角色。普通角色隐藏对应写按钮;只读列表仍沿用原入口。登录入口不受 root 限制。/setting/loginAudit,旧地址 /security/login-audit 保留别名。GET /manage/login/audit/get 由 root 限制改为登录且持有 loginAudit:view;响应格式不变。docs/sql/20261021-login-audit-menu.sql,核对系统管理父菜单 ID;仅默认授权 root,其他角色手工勾选菜单并刷新权限、重新登录。