diff --git a/src/api/gitea.ts b/src/api/gitea.ts new file mode 100644 index 0000000..7d117f5 --- /dev/null +++ b/src/api/gitea.ts @@ -0,0 +1,69 @@ +import { get, post } from './request' + +/** Gitea 连接配置 */ +export interface GiteaSessionConfig { + BaseUrl: string + Org: string + OwnerRole: string +} + +/** 我的 Gitea 账号信息 */ +export interface GiteaAccountInfo { + GiteaLogin: string + Email: string + Status: number + HomeUrl: string + Org: string + CreateTime: string | null +} + +/** 我的 Gitea 接口响应 */ +export interface MyGiteaResult { + Account: GiteaAccountInfo | null + Session: GiteaSessionConfig +} + +/** 管理员 Gitea 账号列表项 */ +export interface GiteaAdminItem { + UserGiteaAccountUUID: string + UserName: string + GiteaLogin: string + Email: string + Status: number + CreateTime: string | null +} + +/** 申请结果 */ +export interface GiteaApplyResult { + GiteaLogin: string + Org: string + IsOwner: boolean + Claimed: boolean + Email: string +} + +/** Gitea 对接 API 客户端(与"我的邮箱"同模式:请求全部走后端,管理 Token 存服务端) */ +export const giteaApi = { + /** 获取 Gitea 连接配置 */ + session: (): Promise => get('/API/Gitea/Session'), + + /** 我的 Gitea 账号信息 */ + myAccount: (): Promise => get('/API/Gitea/MyAccount'), + + /** 申请 Gitea 账号(自选用户名 + 自设密码,创建后加入组织,负责人自动成为 Owner) */ + apply: (data: { GiteaLogin: string; Password: string }): Promise => + post('/API/Gitea/Apply', data), + + /** 修改 Gitea 账号密码(管理员 API,无需旧密码) */ + changePassword: (NewPassword: string): Promise => post('/API/Gitea/ChangePassword', { NewPassword }), + + /** 一键迁移 GERP 头像到 Gitea(需输入 Gitea 密码,Basic Auth 认证,密码仅此一次传输) */ + uploadAvatar: (Password: string): Promise => post('/API/Gitea/Avatar', { Password }), + + /** 管理员:全部账号列表 */ + adminList: (): Promise<{ list: GiteaAdminItem[]; total: number }> => + get<{ list: GiteaAdminItem[]; total: number }>('/API/Gitea/AdminList'), + + /** 管理员:禁用账号(删除 Gitea 用户) */ + disable: (UserGiteaAccountUUID: string): Promise => post('/API/Gitea/Disable', { UserGiteaAccountUUID }), +} diff --git a/src/api/request.ts b/src/api/request.ts index 9a906f3..c42ab83 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -50,6 +50,10 @@ const request: AxiosInstance = axios.create({ request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { config.headers['X-User-Timezone'] = Intl.DateTimeFormat().resolvedOptions().timeZone || 'Asia/Shanghai' + // 动态接口禁止 HTTP 缓存:后端接口均无 Cache-Control,浏览器可能启发式缓存 + // (如菜单树变更后刷新仍返回旧数据),统一加 no-cache 头保证实时性 + config.headers['Cache-Control'] = 'no-cache' + config.headers['Pragma'] = 'no-cache' // 合并 server 作用域参数到 query(不覆盖调用方已显式传入的同名参数) const scopeParams = getServerScopeParams() if (Object.keys(scopeParams).length) { diff --git a/src/router/index.ts b/src/router/index.ts index 1b2206d..d3f9e2d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -186,6 +186,19 @@ export const staticRoutes: RouteRecordRaw[] = [ component: () => import('@/views/mail/MailAdmin.vue'), meta: { title: '邮箱管理', icon: 'Message', requiresAuth: true, menuGuarded: true }, }, + // === Gitea 代码托管对接 === + { + path: 'gitea/mine', + name: 'GiteaMine', + component: () => import('@/views/gitea/Gitea.vue'), + meta: { title: '我的 Gitea', icon: 'Connection', requiresAuth: true, menuGuarded: true }, + }, + { + path: 'gitea/admin', + name: 'GiteaAdmin', + component: () => import('@/views/gitea/GiteaAdmin.vue'), + meta: { title: 'Gitea 账号管理', icon: 'Connection', requiresAuth: true, menuGuarded: true }, + }, { path: 'system/tenant-create', name: 'SystemTenantCreate', diff --git a/src/views/gitea/Gitea.vue b/src/views/gitea/Gitea.vue new file mode 100644 index 0000000..c989463 --- /dev/null +++ b/src/views/gitea/Gitea.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/src/views/gitea/GiteaAdmin.vue b/src/views/gitea/GiteaAdmin.vue new file mode 100644 index 0000000..3318bb9 --- /dev/null +++ b/src/views/gitea/GiteaAdmin.vue @@ -0,0 +1,102 @@ + + + + +