Appearance
认证接口预留说明
当前前端已经预留设备绑定校验入口。未配置后端地址时,前端使用本地存储模拟“首次登录绑定当前设备”;配置后端地址后,会优先请求后端。
当前仓库已包含 Go + SQLite 后端实现,位置:backend/。本地默认接口地址为 http://127.0.0.1:8091,后台管理地址为 http://127.0.0.1:8091/xqly/admin/。
前端现有四种用户权限:
indie:独游开发者,登录后提示开通 VIP,不能进入完整 VIP 题库campus_vip:校招 VIP,可浏览进阶题库、进行笔试题测试、领取校招学习资料social_svip:社招 SVIP,可浏览进阶题库、进行笔试题测试、领取社招学习资料star_friend:星友,加入知识星球并开通后可答题刷题、领取星友专区资料,不能查看校招 VIP 或社招 SVIP 资料
设备绑定规则:
indie和star_friend:不绑定首次登录电脑,可在任意设备登录访问campus_vip和social_svip:需要绑定首次登录电脑,后续登录需校验设备
前端配置
二选一:
js
window.__UNITYKIT_AUTH_API_BASE__ = 'https://api.example.com'学习资料接口也可单独配置:
js
window.__UNITYKIT_MEMBER_API_BASE__ = 'https://api.example.com'访问 IP 与地域接口也可单独配置:
js
window.__UNITYKIT_VISITOR_API_BASE__ = 'https://api.example.com'或在构建环境中配置:
bash
VITE_AUTH_API_BASE=https://api.example.com
VITE_MEMBER_API_BASE=https://api.example.com
VITE_VISITOR_API_BASE=https://api.example.com未配置 UNITYKIT_MEMBER_API_BASE / VITE_MEMBER_API_BASE 时,会员资料接口会复用认证接口地址。都未配置时,前端展示本地预留资料。
未配置 UNITYKIT_VISITOR_API_BASE / VITE_VISITOR_API_BASE 时,访问 IP 与地域接口会复用认证接口地址。都未配置时,前端会尝试用公网 IP 查询服务进行展示兜底,但不会上传到业务后端。
设备校验接口
POST /api/auth/device/verify
请求体:
json
{
"action": "login",
"accountId": "user-id",
"email": "name@example.com",
"name": "用户昵称",
"role": "indie",
"device": {
"deviceId": "frontend-generated-device-id",
"userAgent": "browser user agent",
"language": "zh-CN",
"platform": "Win32",
"timezone": "Asia/Shanghai",
"screen": "1920x1080",
"viewport": "1280x720"
}
}action 可选值:
register:注册成功后按权限决定是否绑定当前设备login:登录时按权限决定是否校验已绑定设备
当前前端会让 indie、star_friend 直接放行,不进行设备绑定校验;除这两类外的受限权限会调用该接口。现阶段需要绑定的权限是 campus_vip、social_svip。后端完整接入登录接口后,也建议继续使用同样规则。
响应体:
json
{
"ok": true,
"message": "允许登录",
"user": {
"id": "user-id",
"name": "用户昵称",
"email": "name@example.com",
"role": "campus_vip"
}
}user.role 可选返回。返回后前端会用后端角色覆盖本地角色,用于展示独游开发者、校招 VIP、社招 SVIP 或星友权限。
拒绝登录:
json
{
"ok": false,
"message": "该账号已绑定首次登录设备,当前电脑暂不能登录。"
}后续完整认证接口建议
当前 Go 后端已经实现以下接口,并统一返回同一种用户结构,前端配置后端地址后会直接使用:
POST /api/auth/register:注册账号,默认返回role: "indie"POST /api/auth/login:登录账号,返回账号当前权限POST /api/auth/password/reset:重置密码,仍需验证码或后端短信/邮箱验证码POST /api/auth/logout:退出登录,可选
推荐成功响应:
json
{
"ok": true,
"message": "登录成功",
"token": "jwt-or-session-token",
"user": {
"id": "user-id",
"name": "用户昵称",
"email": "name@example.com",
"role": "social_svip"
}
}前端权限判断只依赖 user.role,后端之后只要返回 indie、campus_vip、social_svip、star_friend 四种值即可。
后台管理接口
后台页面:/xqly/admin/
已实现:
POST /api/admin/login:后台登录GET /api/admin/stats:数据总览GET /api/admin/users:用户列表PATCH /api/admin/users/:id:修改用户权限、状态、密码等GET /api/admin/materials/POST /api/admin/materials:学习资料列表与新增PATCH /api/admin/materials/:id/DELETE /api/admin/materials/:id:修改或删除资料GET /api/admin/questions/POST /api/admin/questions:题库列表与新增PATCH /api/admin/questions/:id/DELETE /api/admin/questions/:id:修改或删除题目POST /api/admin/import:上传文件夹并自动解析 Markdown、Word、PDF、图片、SVGGET /api/admin/categories:分类维度GET /api/admin/visitors:访问记录
学习资料接口
GET /api/member/materials?role=campus_vip
请求说明:
role可选值:campus_vip、social_svip、star_friend- 前端会附带请求头
X-UnityKit-Role - 如果登录响应以后返回
token或accessToken,前端会附带Authorization: Bearer <token> - 后端必须按当前登录用户真实权限校验,不要只相信前端传入的
role
推荐响应:
json
{
"ok": true,
"materials": [
{
"id": "campus-roadmap",
"title": "校招 Unity 客户端学习路线",
"desc": "从 C#、Unity 基础、UGUI、资源加载到简历项目的阶段计划。",
"href": "https://example.com/materials/campus-roadmap.pdf",
"actionLabel": "领取资料"
}
]
}字段说明:
title:资料标题,必填desc:资料说明,建议填写href:资料领取、下载或跳转链接,可选;不返回时前端会保留“领取资料”按钮占位actionLabel:按钮文案,可选,默认领取资料
接口失败或未配置时,前端会继续展示本地预留资料;后端接入成功后即可通过接口修改不同权限看到的学习资料。
访问 IP 与地域接口
获取访问 IP 与地域
GET /api/visitor/location
推荐由后端根据请求来源 IP 解析地域后返回,前端会优先使用这个接口结果进行显示。
推荐响应:
json
{
"ok": true,
"visitor": {
"ip": "203.0.113.10",
"country": "中国",
"province": "广东省",
"city": "深圳市",
"region": "中国 广东省 深圳市"
}
}字段说明:
ip:当前访问者公网 IPcountry/province/city:地域拆分字段,可选region:直接展示的地域文本,可选;不返回时前端会用国家、省份、城市拼接
上传访问数据
POST /api/visitor/track
前端拿到 IP 和地域后,如果配置了后端地址,会自动上传一次访问数据。推荐后端保存时再次校验请求 IP,避免只信任前端传入值。
请求体:
json
{
"ip": "203.0.113.10",
"region": "中国 广东省 深圳市",
"country": "中国",
"province": "广东省",
"city": "深圳市",
"source": "backend",
"page": "/member/",
"referrer": "",
"accountId": "user-id",
"accountName": "用户昵称",
"role": "campus_vip",
"device": {
"deviceId": "frontend-generated-device-id",
"userAgent": "browser user agent",
"language": "zh-CN",
"platform": "Win32",
"timezone": "Asia/Shanghai",
"screen": "1920x1080",
"viewport": "1280x720"
},
"visitedAt": "2026-07-24T10:00:00.000Z"
}推荐响应:
json
{
"ok": true,
"message": "已记录访问信息"
}