瀏覽代碼

Add Postman collection for TG Live Game API, update API endpoints in Vite config, enhance login functionality with token management, and disable captcha feature.

yb 3 周之前
父節點
當前提交
9be672f412
共有 6 個文件被更改,包括 1810 次插入36 次删除
  1. 24 7
      src/api/login.ts
  2. 22 7
      src/store/user.ts
  3. 13 0
      src/utils/auth.ts
  4. 3 14
      src/views/login/index.vue
  5. 1745 0
      tg-live-game.postman_collection.json
  6. 3 8
      vite.config.ts

+ 24 - 7
src/api/login.ts

@@ -1,22 +1,39 @@
 import { get, post } from '@/utils/request'
 import type { LoginParams, ApiResponse, UserInfo } from '@/types'
 
+// Hono API 认证响应类型
+interface AuthResponse {
+  accessToken: string
+  refreshToken: string
+  expiresIn: number
+  user: {
+    id: string
+    username: string
+    role: string
+  }
+}
+
 // 登录
-export function login(data: LoginParams): Promise<ApiResponse<{ token: string }>> {
-  return post('/login', data)
+export function login(data: LoginParams): Promise<ApiResponse<AuthResponse>> {
+  return post('/auth/login', data)
 }
 
 // 获取用户信息
 export function getInfo(): Promise<ApiResponse<UserInfo>> {
-  return get('/getInfo')
+  return get('/auth/me')
 }
 
 // 退出登录
 export function logout(): Promise<ApiResponse<null>> {
-  return post('/logout')
+  return post('/auth/logout')
+}
+
+// 刷新 Token
+export function refreshToken(refreshToken: string): Promise<ApiResponse<AuthResponse>> {
+  return post('/auth/refresh', { refreshToken })
 }
 
-// 获取验证码
-export function getCodeImg(): Promise<ApiResponse<{ captchaEnabled: boolean; uuid: string; img: string }>> {
-  return get('/captchaImage')
+// 修改密
+export function changePassword(data: { oldPassword: string; newPassword: string }): Promise<ApiResponse<null>> {
+  return post('/auth/change-password', data)
 }

+ 22 - 7
src/store/user.ts

@@ -1,7 +1,7 @@
 import { defineStore } from 'pinia'
 import { ref } from 'vue'
 import type { UserInfo } from '@/types'
-import { getToken, setToken, removeToken } from '@/utils/auth'
+import { getToken, setToken, removeToken, setRefreshToken, removeRefreshToken } from '@/utils/auth'
 import { login, logout, getInfo } from '@/api/login'
 import type { LoginParams } from '@/types'
 
@@ -11,18 +11,31 @@ export const useUserStore = defineStore('user', () => {
 
   async function loginAction(loginForm: LoginParams) {
     const res = await login(loginForm)
-    if (res.code === 200) {
-      const newToken = res.data?.token || res.token || ''
-      token.value = newToken
-      setToken(newToken)
+    if (res.code === 200 && res.data) {
+      // Hono API 返回 accessToken 和 refreshToken
+      const { accessToken, refreshToken, user } = res.data
+      token.value = accessToken
+      setToken(accessToken)
+      if (refreshToken) {
+        setRefreshToken(refreshToken)
+      }
+      // 直接设置用户信息
+      if (user) {
+        userInfo.value = {
+          userId: user.id,
+          userName: user.username,
+          nickName: user.username,
+          roles: [user.role]
+        } as UserInfo
+      }
     }
     return res
   }
 
   async function getUserInfo() {
     const res = await getInfo()
-    if (res.code === 200) {
-      userInfo.value = res.data || res.user
+    if (res.code === 200 && res.data) {
+      userInfo.value = res.data
     }
     return res
   }
@@ -34,6 +47,7 @@ export const useUserStore = defineStore('user', () => {
       token.value = ''
       userInfo.value = null
       removeToken()
+      removeRefreshToken()
     }
   }
 
@@ -41,6 +55,7 @@ export const useUserStore = defineStore('user', () => {
     token.value = ''
     userInfo.value = null
     removeToken()
+    removeRefreshToken()
   }
 
   return {

+ 13 - 0
src/utils/auth.ts

@@ -1,4 +1,5 @@
 const TOKEN_KEY = 'Admin-Token'
+const REFRESH_TOKEN_KEY = 'Admin-Refresh-Token'
 
 export function getToken(): string | null {
   return localStorage.getItem(TOKEN_KEY)
@@ -11,3 +12,15 @@ export function setToken(token: string): void {
 export function removeToken(): void {
   localStorage.removeItem(TOKEN_KEY)
 }
+
+export function getRefreshToken(): string | null {
+  return localStorage.getItem(REFRESH_TOKEN_KEY)
+}
+
+export function setRefreshToken(token: string): void {
+  localStorage.setItem(REFRESH_TOKEN_KEY, token)
+}
+
+export function removeRefreshToken(): void {
+  localStorage.removeItem(REFRESH_TOKEN_KEY)
+}

+ 3 - 14
src/views/login/index.vue

@@ -69,7 +69,6 @@ import { useRouter, useRoute } from 'vue-router'
 import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
 import { User, Lock, Key } from '@element-plus/icons-vue'
 import { useUserStore } from '@/store/user'
-import { getCodeImg } from '@/api/login'
 
 const router = useRouter()
 const route = useRoute()
@@ -94,19 +93,9 @@ const loginRules: FormRules = {
   code: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
 }
 
-async function getCode() {
-  try {
-    const res = await getCodeImg()
-    if (res.code === 200) {
-      captchaEnabled.value = res.data.captchaEnabled
-      if (captchaEnabled.value) {
-        codeUrl.value = 'data:image/gif;base64,' + res.data.img
-        loginForm.uuid = res.data.uuid
-      }
-    }
-  } catch (error) {
-    console.error('获取验证码失败', error)
-  }
+// Hono API 不支持验证码,禁用验证码功能
+function getCode() {
+  captchaEnabled.value = false
 }
 
 async function handleLogin() {

+ 1745 - 0
tg-live-game.postman_collection.json

@@ -0,0 +1,1745 @@
+{
+	"info": {
+		"_postman_id": "a670efda-9591-4304-af67-a8eb87c8b938",
+		"name": "tg-live-game",
+		"description": "TG Live Game Backend API Collection",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+		"_exporter_id": "42537936"
+	},
+	"item": [
+		{
+			"name": "tg-live-game-hono",
+			"item": [
+				{
+					"name": "auth",
+					"item": [
+						{
+							"name": "register",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"pm.environment.set(\"accessToken\", pm.response.json().data.accessToken);",
+											"pm.environment.set(\"refreshToken\", pm.response.json().data.refreshToken);"
+										],
+										"type": "text/javascript",
+										"packages": {},
+										"requests": {}
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"username\": \"pwtk003\",\n  \"password\": \"test123456\",\n  \"email\": \"pwtk003@pwtk.cc\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/register",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"register"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "login",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"var jsonData = pm.response.json();",
+											"if (jsonData.code === 200 && jsonData.data) {",
+											"    pm.collectionVariables.set('accessToken', jsonData.data.accessToken);",
+											"    pm.collectionVariables.set('refreshToken', jsonData.data.refreshToken);",
+											"}"
+										],
+										"type": "text/javascript",
+										"packages": {},
+										"requests": {}
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"username\": \"pwtk001\",\n  \"password\": \"test123456\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/login",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"login"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "refresh",
+							"event": [
+								{
+									"listen": "test",
+									"script": {
+										"exec": [
+											"var jsonData = pm.response.json();",
+											"if (jsonData.code === 200 && jsonData.data) {",
+											"    pm.collectionVariables.set('accessToken', jsonData.data.accessToken);",
+											"    pm.collectionVariables.set('refreshToken', jsonData.data.refreshToken);",
+											"}"
+										],
+										"type": "text/javascript"
+									}
+								}
+							],
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"refreshToken\": \"{{refreshToken}}\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/refresh",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"refresh"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "me",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/me",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"me"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "change-password",
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"oldPassword\": \"admin123\",\n  \"newPassword\": \"newpassword123\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/change-password",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"change-password"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "logout",
+							"request": {
+								"method": "POST",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/auth/logout",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"auth",
+										"logout"
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "users",
+					"item": [
+						{
+							"name": "permissions",
+							"item": [
+								{
+									"name": "list",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/users/:id/permissions",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"users",
+												":id",
+												"permissions"
+											],
+											"variable": [
+												{
+													"key": "id",
+													"value": "69270add987591d84a5385ecea3d5ab0"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "add",
+									"request": {
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"camera_id\": \"camera_id_here\",\n  \"permission\": \"view\"\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/users/:id/permissions",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"users",
+												":id",
+												"permissions"
+											],
+											"variable": [
+												{
+													"key": "id",
+													"value": "user_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "delete",
+									"request": {
+										"method": "DELETE",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/users/:id/permissions/:permissionId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"users",
+												":id",
+												"permissions",
+												":permissionId"
+											],
+											"variable": [
+												{
+													"key": "id",
+													"value": "user_id_here"
+												},
+												{
+													"key": "permissionId",
+													"value": "permission_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								}
+							]
+						},
+						{
+							"name": "list",
+							"request": {
+								"auth": {
+									"type": "bearer",
+									"bearer": [
+										{
+											"key": "token",
+											"value": "{{accessToken}}",
+											"type": "string"
+										}
+									]
+								},
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/users?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"users"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										},
+										{
+											"key": "role",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "status",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "search",
+											"value": "",
+											"disabled": true
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "get",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/users/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"users",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "cdee69f27a05ae30d7b7622879ce1ddf"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "create",
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"username\": \"newuser1\",\n  \"password\": \"password123\",\n  \"email\": \"newuser@example.com\",\n  \"role\": \"viewer\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/users",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"users"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "update",
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"email\": \"updated@example.com\",\n  \"role\": \"operator\",\n  \"status\": \"active\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/users/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"users",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "db09b553ed4e1070be2f065c12e4fe81"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "delete",
+							"request": {
+								"method": "DELETE",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/users/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"users",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "db09b553ed4e1070be2f065c12e4fe81"
+										}
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "cameras",
+					"item": [
+						{
+							"name": "list",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										},
+										{
+											"key": "status",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "type",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "search",
+											"value": "",
+											"disabled": true
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "get",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "camera_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "create",
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"name\": \"Camera 1\",\n  \"type\": \"rtsp\",\n  \"protocol\": \"rtmps\",\n  \"rtsp_url\": \"rtsp://example.com/stream\",\n  \"location\": \"Room 101\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "update",
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"name\": \"Camera 1 Updated\",\n  \"location\": \"Room 102\",\n  \"status\": \"online\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "camera_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "delete",
+							"request": {
+								"method": "DELETE",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "camera_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "sessions",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/cameras/:id/sessions?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"cameras",
+										":id",
+										"sessions"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										},
+										{
+											"key": "status",
+											"value": "",
+											"disabled": true
+										}
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "camera_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "sessions",
+					"item": [
+						{
+							"name": "list",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										},
+										{
+											"key": "status",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "camera_id",
+											"value": "",
+											"disabled": true
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "live",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/live",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										"live"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "get",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "start",
+							"request": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"camera_id\": \"camera_id_here\",\n  \"live_input_id\": \"live_input_id_here\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions"
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "end",
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"recording_id\": \"recording_id_here\"\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/:id/end",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										":id",
+										"end"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "update-viewers",
+							"request": {
+								"method": "PUT",
+								"header": [
+									{
+										"key": "Content-Type",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"viewer_count\": 100\n}"
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/:id/viewers",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										":id",
+										"viewers"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "stats",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/:id/stats",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										":id",
+										"stats"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "delete",
+							"request": {
+								"method": "DELETE",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/sessions/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"sessions",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "stats",
+					"item": [
+						{
+							"name": "view",
+							"item": [
+								{
+									"name": "start",
+									"request": {
+										"auth": {
+											"type": "noauth"
+										},
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"video_id\": \"video_id_here\"\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stats/view/start",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stats",
+												"view",
+												"start"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "end",
+									"request": {
+										"auth": {
+											"type": "noauth"
+										},
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"view_id\": \"view_id_here\",\n  \"watch_duration\": 300\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stats/view/end",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stats",
+												"view",
+												"end"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "heartbeat",
+									"request": {
+										"auth": {
+											"type": "noauth"
+										},
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"view_id\": \"view_id_here\",\n  \"watch_duration\": 60\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stats/view/heartbeat",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stats",
+												"view",
+												"heartbeat"
+											]
+										}
+									},
+									"response": []
+								}
+							]
+						},
+						{
+							"name": "video",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/stats/video/:videoId",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"stats",
+										"video",
+										":videoId"
+									],
+									"variable": [
+										{
+											"key": "videoId",
+											"value": "video_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "session",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/stats/session/:sessionId",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"stats",
+										"session",
+										":sessionId"
+									],
+									"variable": [
+										{
+											"key": "sessionId",
+											"value": "session_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "overview",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/stats/overview?days=7",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"stats",
+										"overview"
+									],
+									"query": [
+										{
+											"key": "days",
+											"value": "7"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "views",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/stats/views?page=1&pageSize=50",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"stats",
+										"views"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "50"
+										},
+										{
+											"key": "video_id",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "session_id",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "user_id",
+											"value": "",
+											"disabled": true
+										}
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "audit-logs",
+					"item": [
+						{
+							"name": "stats",
+							"item": [
+								{
+									"name": "summary",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/audit-logs/stats/summary?days=7",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"audit-logs",
+												"stats",
+												"summary"
+											],
+											"query": [
+												{
+													"key": "days",
+													"value": "7"
+												}
+											]
+										}
+									},
+									"response": []
+								}
+							]
+						},
+						{
+							"name": "list",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/audit-logs?page=1&pageSize=50",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"audit-logs"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "50"
+										},
+										{
+											"key": "action",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "resource",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "user_id",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "start_date",
+											"value": "",
+											"disabled": true
+										},
+										{
+											"key": "end_date",
+											"value": "",
+											"disabled": true
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "get",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/audit-logs/:id",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"audit-logs",
+										":id"
+									],
+									"variable": [
+										{
+											"key": "id",
+											"value": "log_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "user",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/audit-logs/user/:userId?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"audit-logs",
+										"user",
+										":userId"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										}
+									],
+									"variable": [
+										{
+											"key": "userId",
+											"value": "user_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						},
+						{
+							"name": "resource",
+							"request": {
+								"method": "GET",
+								"header": [],
+								"url": {
+									"raw": "{{baseUrl}}/api/audit-logs/resource/:resource/:resourceId?page=1&pageSize=20",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"audit-logs",
+										"resource",
+										":resource",
+										":resourceId"
+									],
+									"query": [
+										{
+											"key": "page",
+											"value": "1"
+										},
+										{
+											"key": "pageSize",
+											"value": "20"
+										}
+									],
+									"variable": [
+										{
+											"key": "resource",
+											"value": "camera"
+										},
+										{
+											"key": "resourceId",
+											"value": "resource_id_here"
+										}
+									]
+								}
+							},
+							"response": []
+						}
+					]
+				},
+				{
+					"name": "stream",
+					"item": [
+						{
+							"name": "video",
+							"item": [
+								{
+									"name": "list",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/list",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												"list"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "get",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/:videoId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												":videoId"
+											],
+											"variable": [
+												{
+													"key": "videoId",
+													"value": "video_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "delete",
+									"request": {
+										"method": "DELETE",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/:videoId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												":videoId"
+											],
+											"variable": [
+												{
+													"key": "videoId",
+													"value": "video_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "import",
+									"request": {
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"url\": \"https://example.com/video.mp4\",\n  \"meta\": {\n    \"name\": \"My Video\"\n  }\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/import",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												"import"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "upload-url",
+									"request": {
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"maxDurationSeconds\": 3600,\n  \"meta\": {\n    \"name\": \"My Upload\"\n  }\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/upload-url",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												"upload-url"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "playback",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/video/:videoId/playback",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"video",
+												":videoId",
+												"playback"
+											],
+											"variable": [
+												{
+													"key": "videoId",
+													"value": "video_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								}
+							]
+						},
+						{
+							"name": "live",
+							"item": [
+								{
+									"name": "list",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/list",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												"list"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "create",
+									"request": {
+										"method": "POST",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"meta\": {\n    \"name\": \"My Live Stream\"\n  },\n  \"recording\": {\n    \"mode\": \"automatic\"\n  }\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live"
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "get",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/:liveInputId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												":liveInputId"
+											],
+											"variable": [
+												{
+													"key": "liveInputId",
+													"value": "live_input_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "update",
+									"request": {
+										"method": "PUT",
+										"header": [
+											{
+												"key": "Content-Type",
+												"value": "application/json"
+											}
+										],
+										"body": {
+											"mode": "raw",
+											"raw": "{\n  \"meta\": {\n    \"name\": \"Updated Live Stream\"\n  }\n}"
+										},
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/:liveInputId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												":liveInputId"
+											],
+											"variable": [
+												{
+													"key": "liveInputId",
+													"value": "live_input_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "delete",
+									"request": {
+										"method": "DELETE",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/:liveInputId",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												":liveInputId"
+											],
+											"variable": [
+												{
+													"key": "liveInputId",
+													"value": "live_input_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "playback",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/:liveInputId/playback",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												":liveInputId",
+												"playback"
+											],
+											"variable": [
+												{
+													"key": "liveInputId",
+													"value": "live_input_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								},
+								{
+									"name": "recordings",
+									"request": {
+										"method": "GET",
+										"header": [],
+										"url": {
+											"raw": "{{baseUrl}}/api/stream/live/:liveInputId/recordings",
+											"host": [
+												"{{baseUrl}}"
+											],
+											"path": [
+												"api",
+												"stream",
+												"live",
+												":liveInputId",
+												"recordings"
+											],
+											"variable": [
+												{
+													"key": "liveInputId",
+													"value": "live_input_id_here"
+												}
+											]
+										}
+									},
+									"response": []
+								}
+							]
+						}
+					]
+				}
+			]
+		}
+	],
+	"auth": {
+		"type": "bearer",
+		"bearer": [
+			{
+				"key": "token",
+				"value": "{{accessToken}}",
+				"type": "string"
+			}
+		]
+	},
+	"event": [
+		{
+			"listen": "prerequest",
+			"script": {
+				"type": "text/javascript",
+				"packages": {},
+				"requests": {},
+				"exec": [
+					""
+				]
+			}
+		},
+		{
+			"listen": "test",
+			"script": {
+				"type": "text/javascript",
+				"packages": {},
+				"requests": {},
+				"exec": [
+					""
+				]
+			}
+		}
+	],
+	"variable": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:8787"
+		},
+		{
+			"key": "accessToken",
+			"value": ""
+		},
+		{
+			"key": "refreshToken",
+			"value": ""
+		}
+	]
+}

+ 3 - 8
vite.config.ts

@@ -14,16 +14,11 @@ export default defineConfig({
     port: 3000,
     open: true,
     proxy: {
-      // Hono 后端 API(Cloudflare Stream)
-      '/api/stream': {
-        target: 'http://localhost:8787',
-        changeOrigin: true
-      },
-      // 其他后端 API(如若依)
+      // Hono 后端 API (Cloudflare Workers)
       '/api': {
-        target: 'http://localhost:8080',
+        target: 'https://tg-live-game-api.ifoodme.com',
         changeOrigin: true,
-        rewrite: (path) => path.replace(/^\/api/, '')
+        secure: true
       }
     }
   },