diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..6996edc --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VITE_API_BASE_URL = http://localhost:5222/ diff --git a/src/api/announcement.ts b/src/api/announcement.ts new file mode 100644 index 0000000..54d64f9 --- /dev/null +++ b/src/api/announcement.ts @@ -0,0 +1,87 @@ +import request from '@/utils/request' + +/** 公告数据类型 */ +export interface Announcement { + Content: string + Id: number + LastUpdateTime: number + Link: string | null + Locale: string | null + MaxPresentVersion: string | null + Severity: number + Title: string +} + +/** 公告列表响应数据类型 */ +export interface AnnouncementListResponse { + code: number + data: Announcement[] + message: string +} + +/** + * 获取公告列表 API + * POST /Announcement/List + */ +export function getAnnouncementListApi(): Promise { + return request({ + url: '/Announcement/List', + method: 'post', + }) +} + +/** 创建公告请求参数类型 */ +export interface CreateAnnouncementRequest { + Content: string + Title: string + Link?: string | null + Locale?: string | null + MaxPresentVersion?: string | null + Severity?: number | null +} + +/** 创建公告响应数据类型 */ +export interface CreateAnnouncementResponse { + code: number + data: { + Id: number + } + message: string +} + +/** + * 创建公告 API + * POST /web-api/announcement + * 注意:由于request.ts拦截器处理,实际返回的是data部分,即 { Id: number } + */ +export function createAnnouncementApi(params: CreateAnnouncementRequest): Promise<{ Id: number }> { + return request({ + url: '/web-api/announcement', + method: 'post', + data: params, + }) +} + +/** + * 编辑公告 API + * PUT /web-api/announcement/{announcement_id} + */ +export function updateAnnouncementApi(id: number, params: CreateAnnouncementRequest): Promise { + return request({ + url: `/web-api/announcement/${id}`, + method: 'put', + data: params, + }) +} + +/** + * 删除公告 API + * DELETE /web-api/announcement/{announcement_id} + */ +export function deleteAnnouncementApi(id: number): Promise { + return request({ + url: `/web-api/announcement/${id}`, + method: 'delete', + }) +} + diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..9cefb77 --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +/** 登录请求参数 */ +export interface WebLoginParams { + email: string + password: string +} + +/** 登录返回数据 */ +export interface WebLoginResult { + access_token: string + expires_in: number +} + +/** + * WEB 登录 API + * POST /web-api/login + */ +export function webLoginApi(data: WebLoginParams) { + return request({ + url: '/web-api/login', + method: 'post', + data, + }) +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..e862734 --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +/** 用户信息数据结构 */ +export interface UserInfo { + CdnExpireAt: string + GachaLogExpireAt: string + IsLicensedDeveloper: boolean + IsMaintainer: boolean + NormalizedUserName: string + UserName: string +} + +/** 用户列表中的用户数据结构 */ +export interface UserListItem { + CdnExpireAt: string + CreatedAt: string + GachaLogExpireAt: string + IsLicensedDeveloper: boolean + IsMaintainer: boolean + NormalizedUserName: string + UserName: string + _id: string + email: string +} + +/** API响应数据结构 */ +export interface ApiResponse { + code: number + data: T + message: string +} + +/** + * 获取用户信息 + * GET /Passport/v2/UserInfo + */ +export function getUserInfoApi(): Promise { + return request({ + url: '/Passport/v2/UserInfo', + method: 'get', + }) +} + +/** + * 获取用户列表 + * GET /web-api/users + * @param q 搜索参数,可搜索用户名、邮箱、_id + */ +export function getUserListApi(q?: string): Promise { + const params: Record = {} + if (q) { + params.q = q + } + + return request({ + url: '/web-api/users', + method: 'get', + params, + }) +} diff --git a/src/components/SidebarItem.vue b/src/components/SidebarItem.vue index 28b5b51..0f623a2 100644 --- a/src/components/SidebarItem.vue +++ b/src/components/SidebarItem.vue @@ -12,13 +12,13 @@ {{ item.meta?.title }} - + @@ -32,10 +32,24 @@ import type { RouteRecordRaw } from 'vue-router' import * as icons from '@element-plus/icons-vue' -defineProps<{ +interface Props { routes: RouteRecordRaw[] -}>() + parentPath?: string +} + +const props = withDefaults(defineProps(), { + parentPath: '' +}) const hasChildren = (route: RouteRecordRaw) => route.children && route.children.length > 0 + +const getFullPath = (route: RouteRecordRaw) => { + // 如果是绝对路径,直接返回 + if (route.path.startsWith('/')) { + return route.path + } + // 否则拼接父级路径 + return props.parentPath ? `/${props.parentPath}/${route.path}` : `/${route.path}` +} diff --git a/src/layouts/DefaultLayout.vue b/src/layouts/DefaultLayout.vue index 2bce8cb..422959a 100644 --- a/src/layouts/DefaultLayout.vue +++ b/src/layouts/DefaultLayout.vue @@ -34,6 +34,20 @@ @change="themeStore.toggleTheme" /> + + + + + @@ -47,14 +61,31 @@ + + \ No newline at end of file diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 05253b5..1824c22 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -1,7 +1,128 @@ - \ No newline at end of file + + + + + diff --git a/src/views/user/index.vue b/src/views/user/index.vue new file mode 100644 index 0000000..cbf1b0d --- /dev/null +++ b/src/views/user/index.vue @@ -0,0 +1,188 @@ + + + + + \ No newline at end of file