Compare commits

...

3 Commits

Author SHA1 Message Date
d9b8567b6d feat: 提示词 2026-06-16 12:12:33 +08:00
05fff65acf feat: 提示词 2026-06-16 12:02:05 +08:00
fc523e77f7 feat: 提示词 2026-06-16 12:01:13 +08:00
9 changed files with 608 additions and 15 deletions

480
docs/openapi.json Normal file
View File

@@ -0,0 +1,480 @@
{
"openapi": "3.0.3",
"info": {
"title": "WebGame 后端接口文档",
"version": "1.0.0",
"description": "WebGame 游戏后端 REST API 接口文档"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "本地开发环境"
}
],
"tags": [
{ "name": "账号", "description": "账号相关接口(登录、注册,无需认证)" },
{ "name": "用户", "description": "用户相关接口(需登录认证)" }
],
"paths": {
"/account/login": {
"post": {
"tags": ["账号"],
"summary": "用户登录",
"description": "使用用户名和密码进行登录认证,成功返回 Sa-Token 令牌。该接口无需登录即可调用。",
"operationId": "login",
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/LoginRequest" },
"example": {
"username": "testuser",
"password": "123456"
}
}
}
},
"responses": {
"200": {
"description": "登录成功,返回 token",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/ApiResponse" },
{
"type": "object",
"properties": {
"data": { "$ref": "#/components/schemas/LoginResponse" }
}
}
]
},
"example": {
"code": 0,
"message": "success",
"data": {
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
},
"400": { "$ref": "#/components/responses/BadRequest" },
"500": { "$ref": "#/components/responses/InternalError" }
}
}
},
"/account/register": {
"post": {
"tags": ["账号"],
"summary": "用户注册",
"description": "注册新账号。用户名长度 3-32 位,密码长度 6-64 位。注册成功后自动登录并返回 token。该接口无需登录即可调用。",
"operationId": "register",
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/RegisterRequest" },
"example": {
"username": "newuser",
"password": "abc123"
}
}
}
},
"responses": {
"200": {
"description": "注册成功,自动登录返回 token",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/ApiResponse" },
{
"type": "object",
"properties": {
"data": { "$ref": "#/components/schemas/LoginResponse" }
}
}
]
},
"example": {
"code": 0,
"message": "success",
"data": {
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
},
"400": { "$ref": "#/components/responses/BadRequest" },
"500": { "$ref": "#/components/responses/InternalError" }
}
}
},
"/user/info": {
"get": {
"tags": ["用户"],
"summary": "获取当前登录用户信息",
"description": "根据请求头中的 saToken 获取当前登录用户的详细信息,包括昵称、头像、个性签名、年龄、性别、生日。需登录认证。",
"operationId": "getUserInfo",
"security": [{ "saToken": [] }],
"responses": {
"200": {
"description": "查询成功,返回用户信息",
"content": {
"application/json": {
"schema": {
"allOf": [
{ "$ref": "#/components/schemas/ApiResponse" },
{
"type": "object",
"properties": {
"data": { "$ref": "#/components/schemas/UserInfoResponse" }
}
}
]
},
"example": {
"code": 0,
"message": "success",
"data": {
"nickName": "玩家001",
"avatar": "https://cdn.example.com/avatars/default.png",
"signature": "这个人很懒,什么都没写",
"age": 25,
"sex": 1,
"birthday": "2001-01-01"
}
}
}
}
},
"401": { "$ref": "#/components/responses/Unauthorized" },
"500": { "$ref": "#/components/responses/InternalError" }
}
}
}
},
"components": {
"securitySchemes": {
"saToken": {
"type": "apiKey",
"in": "header",
"name": "saToken",
"description": "Sa-Token 认证令牌。登录/注册成功后返回的 token 值,在后续请求的 Header 中携带。"
}
},
"schemas": {
"ApiResponse": {
"type": "object",
"description": "统一 API 响应信封。所有接口均使用此格式返回。",
"required": ["code", "message", "data"],
"properties": {
"code": {
"type": "integer",
"format": "int32",
"description": "业务状态码。0 表示成功,非 0 表示失败。详细错误码见 ErrorCode 枚举。"
},
"message": {
"type": "string",
"description": "响应消息。成功时固定为 \"success\",失败时为具体错误描述。"
},
"data": {
"nullable": true,
"description": "响应数据负载。成功时携带对应的业务数据对象,失败时为 null。"
}
}
},
"LoginRequest": {
"type": "object",
"description": "登录请求体",
"required": ["username", "password"],
"properties": {
"username": {
"type": "string",
"description": "用户名,不能为空",
"minLength": 1,
"example": "testuser"
},
"password": {
"type": "string",
"format": "password",
"description": "密码,不能为空",
"minLength": 1,
"example": "123456"
}
}
},
"RegisterRequest": {
"type": "object",
"description": "注册请求体",
"required": ["username", "password"],
"properties": {
"username": {
"type": "string",
"description": "用户名,长度限制 3-32 位,不能为空",
"minLength": 3,
"maxLength": 32,
"example": "newuser"
},
"password": {
"type": "string",
"format": "password",
"description": "密码,长度限制 6-64 位,不能为空",
"minLength": 6,
"maxLength": 64,
"example": "abc123"
}
}
},
"LoginResponse": {
"type": "object",
"description": "登录或注册成功时返回的认证令牌",
"required": ["token"],
"properties": {
"token": {
"type": "string",
"description": "Sa-Token 认证令牌UUID 格式)。后续请求需在 Header 中通过 saToken 字段携带此值。",
"example": "12345678-1234-1234-1234-123456789abc"
}
}
},
"UserInfoResponse": {
"type": "object",
"description": "当前登录用户的详细信息",
"properties": {
"nickName": {
"type": "string",
"description": "用户昵称",
"maxLength": 16,
"example": "玩家001"
},
"avatar": {
"type": "string",
"description": "头像图片 URL 地址,可能为 null",
"maxLength": 512,
"nullable": true,
"example": "https://cdn.example.com/avatars/default.png"
},
"signature": {
"type": "string",
"description": "个性签名,可能为 null",
"maxLength": 64,
"nullable": true,
"example": "这个人很懒,什么都没写"
},
"age": {
"type": "integer",
"format": "int32",
"description": "年龄,可能为 null",
"nullable": true,
"example": 25
},
"sex": {
"type": "integer",
"format": "int32",
"description": "性别。1=男2=女,可能为 null",
"nullable": true,
"enum": [1, 2],
"x-enum-descriptions": {
"1": "男",
"2": "女"
},
"example": 1
},
"birthday": {
"type": "string",
"format": "date",
"description": "生日ISO 8601 日期格式),可能为 null",
"nullable": true,
"example": "2001-01-01"
}
}
},
"ErrorResponse": {
"type": "object",
"description": "错误响应体模板。code 为具体错误码message 为错误描述data 恒为 null。",
"required": ["code", "message", "data"],
"properties": {
"code": {
"type": "integer",
"format": "int32",
"description": "错误码,详见 ErrorCode 枚举表"
},
"message": {
"type": "string",
"description": "人类可读的错误描述信息"
},
"data": {
"type": "null",
"description": "错误时恒为 null"
}
}
}
},
"responses": {
"BadRequest": {
"description": "请求参数校验失败或业务逻辑错误HTTP 200 但 code ≠ 0",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"examples": {
"validation": {
"summary": "参数校验失败",
"value": {
"code": 400,
"message": "username 用户名不能为空; password 密码长度6-64位",
"data": null
}
},
"usernameExists": {
"summary": "用户名已存在",
"value": {
"code": 1001,
"message": "用户名已存在",
"data": null
}
},
"badCredentials": {
"summary": "用户名或密码错误",
"value": {
"code": 1002,
"message": "用户名或密码错误",
"data": null
}
},
"userNotFound": {
"summary": "用户不存在",
"value": {
"code": 2001,
"message": "用户不存在",
"data": null
}
}
}
}
}
},
"Unauthorized": {
"description": "未登录或 token 无效HTTP 200 但 code=401",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"example": {
"code": 401,
"message": "请先登录",
"data": null
}
}
}
},
"Forbidden": {
"description": "无权限或无角色访问HTTP 200 但 code=403",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"example": {
"code": 403,
"message": "无权限",
"data": null
}
}
}
},
"NotFound": {
"description": "请求的资源不存在",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"example": {
"code": 404,
"message": "资源不存在",
"data": null
}
}
}
},
"MethodNotAllowed": {
"description": "请求方法不支持(如 GET 访问 POST 接口)",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"example": {
"code": 405,
"message": "请求方法不支持",
"data": null
}
}
}
},
"InternalError": {
"description": "服务器内部错误HTTP 200 但 code=5000",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" },
"example": {
"code": 5000,
"message": "服务器内部错误",
"data": null
}
}
}
}
},
"x-enums": {
"ErrorCode": {
"description": "业务错误码枚举com.webgame.webgamebackend.common.exception.ErrorCode",
"values": {
"SUCCESS": {
"code": 0,
"message": "success",
"description": "操作成功"
},
"BAD_REQUEST": {
"code": 400,
"message": "参数校验失败",
"description": "请求参数不符合校验规则"
},
"USERNAME_EXISTS": {
"code": 1001,
"message": "用户名已存在",
"description": "注册时用户名已被占用"
},
"BAD_CREDENTIALS": {
"code": 1002,
"message": "用户名或密码错误",
"description": "登录时用户名或密码不匹配"
},
"USER_NOT_FOUND": {
"code": 2001,
"message": "用户不存在",
"description": "查询的用户记录不存在"
},
"INTERNAL_ERROR": {
"code": 5000,
"message": "服务器内部错误",
"description": "未预期的服务器异常"
}
}
},
"Sex": {
"description": "性别枚举UserEntity.sex 字段)",
"values": {
"MALE": {
"code": 1,
"label": "男"
},
"FEMALE": {
"code": 2,
"label": "女"
}
}
}
}
}
}

8
docs/prompt.txt Normal file
View File

@@ -0,0 +1,8 @@
--- api接口文档提示词 ---
docs/openapi.json文件是后端提供的标准OpenAPI接口文档你需要完成
1. 生成统一axios请求封装
2. 自动生成全部接口的TS类型定义
3. 按模块拆分接口请求函数;
4. 严格遵循文档字段,不新增、不删减参数,区分必填/可选;
5. 按现有src/api/modules中的格式书写
6. 定义的TS类型名称interface以I开头命名type以T开头命名

View File

@@ -1,12 +1 @@
import { requestClient } from '@/api/request'
/** 账户信息 */
interface IAccountInfo {
id: number
username: string
}
/** 获取账户信息 */
function getAccountInfo() {
return requestClient.get<IAccountInfo>('/account')
}
export * from './login.ts'

View File

@@ -0,0 +1,62 @@
import { requestClient } from '@/api/request'
/**
* 登录请求参数
*
* 对应 OpenAPI: LoginRequest
*/
export interface LoginRequest {
/** 用户名,不能为空 */
username: string
/** 密码,不能为空 */
password: string
}
/**
* 注册请求参数
*
* 对应 OpenAPI: RegisterRequest
*/
export interface RegisterRequest {
/** 用户名,长度限制 3-32 位 */
username: string
/** 密码,长度限制 6-64 位 */
password: string
}
/**
* 登录/注册响应
*
* 对应 OpenAPI: LoginResponse
*/
export interface LoginResponse {
/** Sa-Token 认证令牌UUID 格式) */
token: string
}
/**
* 用户登录
*
* 使用用户名和密码进行登录认证,成功返回 Sa-Token 令牌。
* 该接口无需登录即可调用。
*
* @param req - 登录请求参数
* @returns 包含认证令牌的响应
*/
export function login(req: LoginRequest) {
return requestClient.post<LoginResponse>('/account/login', req)
}
/**
* 用户注册
*
* 注册新账号。用户名长度 3-32 位,密码长度 6-64 位。
* 注册成功后自动登录并返回 token。
* 该接口无需登录即可调用。
*
* @param req - 注册请求参数
* @returns 包含认证令牌的响应
*/
export function register(req: RegisterRequest) {
return requestClient.post<LoginResponse>('/account/register', req)
}

2
src/api/modules/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from './account/index.ts'
export * from './user/index.ts'

View File

@@ -0,0 +1 @@
export * from './info.ts'

View File

@@ -0,0 +1,51 @@
import { requestClient } from '@/api/request'
/**
* 性别枚举
*
* 对应 OpenAPI: Sex (x-enums)
* 1 = 男2 = 女
*/
export const Sex = {
/** 男 */
MALE: 1,
/** 女 */
FEMALE: 2
} as const
/** 性别类型 */
export type SexType = (typeof Sex)[keyof typeof Sex]
/**
* 用户信息响应
*
* 对应 OpenAPI: UserInfoResponse
* 所有字段均为可选,部分字段可能为 null
*/
export interface UserInfoResponse {
/** 用户昵称,最长 16 位 */
nickName?: string
/** 头像图片 URL 地址,可能为 null */
avatar?: string | null
/** 个性签名,最长 64 位,可能为 null */
signature?: string | null
/** 年龄,可能为 null */
age?: number | null
/** 性别1=男2=女,可能为 null */
sex?: SexType | null
/** 生日ISO 8601 日期格式),可能为 null */
birthday?: string | null
}
/**
* 获取当前登录用户信息
*
* 根据请求头中的 saToken 获取当前登录用户的详细信息,
* 包括昵称、头像、个性签名、年龄、性别、生日。
* 需登录认证。
*
* @returns 当前登录用户的详细信息
*/
export function getUserInfo() {
return requestClient.get<UserInfoResponse>('/user/info')
}

View File

@@ -63,11 +63,11 @@ class RequestClient {
config.url = resolvePathParams(config.url, reqConfig.pathParams)
}
// 跳过鉴权时不注入 token
// 跳过鉴权时不注入 saToken
if (!reqConfig?.skipAuth) {
const accountStore = useAccountStore()
if (accountStore.token) {
config.headers.Authorization = `Bearer ${accountStore.token}`
config.headers.saToken = accountStore.token
}
}

View File

@@ -14,7 +14,7 @@ export interface ApiResponse<T = unknown> {
export interface InternalRequestConfig extends AxiosRequestConfig {
/** 路径参数,替换 URL 中的 :param 占位符(如 /user/:id → /user/1 */
pathParams?: Record<string, string | number>
/** 跳过鉴权注入(不携带 Authorization 头) */
/** 跳过鉴权注入(不携带 saToken 头) */
skipAuth?: boolean
}