diff --git a/napcat.webui/src/controllers/qq_manager.ts b/napcat.webui/src/controllers/qq_manager.ts index 9375afc2..040eefb4 100644 --- a/napcat.webui/src/controllers/qq_manager.ts +++ b/napcat.webui/src/controllers/qq_manager.ts @@ -73,4 +73,17 @@ export default class QQManager { ) return data.data.data } + + public static async getQuickLoginQQ() { + const { data } = await serverRequest.post>( + '/QQLogin/GetQuickLoginQQ' + ) + return data.data + } + + public static async setQuickLoginQQ(uin: string) { + await serverRequest.post>('/QQLogin/SetQuickLoginQQ', { + uin + }) + } } diff --git a/napcat.webui/src/controllers/webui_manager.ts b/napcat.webui/src/controllers/webui_manager.ts index 35cb4ed4..ac472126 100644 --- a/napcat.webui/src/controllers/webui_manager.ts +++ b/napcat.webui/src/controllers/webui_manager.ts @@ -59,6 +59,20 @@ export default class WebUIManager { return data.data } + public static async getThemeConfig() { + const { data } = + await serverRequest.get>('/base/Theme') + return data.data + } + + public static async setThemeConfig(theme: ThemeConfig) { + const { data } = await serverRequest.post>( + '/base/SetTheme', + { theme } + ) + return data.data + } + public static async getLogList() { const { data } = await serverRequest.get>('/Log/GetLogList') diff --git a/napcat.webui/src/types/server.d.ts b/napcat.webui/src/types/server.d.ts index 28096eba..59005c22 100644 --- a/napcat.webui/src/types/server.d.ts +++ b/napcat.webui/src/types/server.d.ts @@ -48,3 +48,136 @@ interface SystemStatus { } arch: string } + +interface ThemeConfigItem { + '--heroui-background': string + '--heroui-foreground-50': string + '--heroui-foreground-100': string + '--heroui-foreground-200': string + '--heroui-foreground-300': string + '--heroui-foreground-400': string + '--heroui-foreground-500': string + '--heroui-foreground-600': string + '--heroui-foreground-700': string + '--heroui-foreground-800': string + '--heroui-foreground-900': string + '--heroui-foreground': string + '--heroui-focus': string + '--heroui-overlay': string + '--heroui-divider': string + '--heroui-divider-opacity': string + '--heroui-content1': string + '--heroui-content1-foreground': string + '--heroui-content2': string + '--heroui-content2-foreground': string + '--heroui-content3': string + '--heroui-content3-foreground': string + '--heroui-content4': string + '--heroui-content4-foreground': string + '--heroui-default-50': string + '--heroui-default-100': string + '--heroui-default-200': string + '--heroui-default-300': string + '--heroui-default-400': string + '--heroui-default-500': string + '--heroui-default-600': string + '--heroui-default-700': string + '--heroui-default-800': string + '--heroui-default-900': string + '--heroui-default-foreground': string + '--heroui-default': string + // 新增 danger + '--heroui-danger-50': string + '--heroui-danger-100': string + '--heroui-danger-200': string + '--heroui-danger-300': string + '--heroui-danger-400': string + '--heroui-danger-500': string + '--heroui-danger-600': string + '--heroui-danger-700': string + '--heroui-danger-800': string + '--heroui-danger-900': string + '--heroui-danger-foreground': string + '--heroui-danger': string + // 新增 primary + '--heroui-primary-50': string + '--heroui-primary-100': string + '--heroui-primary-200': string + '--heroui-primary-300': string + '--heroui-primary-400': string + '--heroui-primary-500': string + '--heroui-primary-600': string + '--heroui-primary-700': string + '--heroui-primary-800': string + '--heroui-primary-900': string + '--heroui-primary-foreground': string + '--heroui-primary': string + // 新增 secondary + '--heroui-secondary-50': string + '--heroui-secondary-100': string + '--heroui-secondary-200': string + '--heroui-secondary-300': string + '--heroui-secondary-400': string + '--heroui-secondary-500': string + '--heroui-secondary-600': string + '--heroui-secondary-700': string + '--heroui-secondary-800': string + '--heroui-secondary-900': string + '--heroui-secondary-foreground': string + '--heroui-secondary': string + // 新增 success + '--heroui-success-50': string + '--heroui-success-100': string + '--heroui-success-200': string + '--heroui-success-300': string + '--heroui-success-400': string + '--heroui-success-500': string + '--heroui-success-600': string + '--heroui-success-700': string + '--heroui-success-800': string + '--heroui-success-900': string + '--heroui-success-foreground': string + '--heroui-success': string + // 新增 warning + '--heroui-warning-50': string + '--heroui-warning-100': string + '--heroui-warning-200': string + '--heroui-warning-300': string + '--heroui-warning-400': string + '--heroui-warning-500': string + '--heroui-warning-600': string + '--heroui-warning-700': string + '--heroui-warning-800': string + '--heroui-warning-900': string + '--heroui-warning-foreground': string + '--heroui-warning': string + // 其它配置 + '--heroui-code-background': string + '--heroui-strong': string + '--heroui-code-mdx': string + '--heroui-divider-weight': string + '--heroui-disabled-opacity': string + '--heroui-font-size-tiny': string + '--heroui-font-size-small': string + '--heroui-font-size-medium': string + '--heroui-font-size-large': string + '--heroui-line-height-tiny': string + '--heroui-line-height-small': string + '--heroui-line-height-medium': string + '--heroui-line-height-large': string + '--heroui-radius-small': string + '--heroui-radius-medium': string + '--heroui-radius-large': string + '--heroui-border-width-small': string + '--heroui-border-width-medium': string + '--heroui-border-width-large': string + '--heroui-box-shadow-small': string + '--heroui-box-shadow-medium': string + '--heroui-box-shadow-large': string + '--heroui-hover-opacity': string +} + +interface ThemeConfig { + dark: ThemeConfigItem + light: ThemeConfigItem +} diff --git a/src/webui/index.ts b/src/webui/index.ts index 5bde50e1..bb4d8949 100644 --- a/src/webui/index.ts +++ b/src/webui/index.ts @@ -73,9 +73,9 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp // 如果是webui字体文件,挂载字体文件 app.use('/webui/fonts/AaCute.woff', async (_req, res, next) => { - const isFontExist = await WebUiConfigWrapper.CheckWebUIFontExist(); + const isFontExist = await WebUiConfig.CheckWebUIFontExist(); if (isFontExist) { - res.sendFile(WebUiConfigWrapper.GetWebUIFontPath()); + res.sendFile(WebUiConfig.GetWebUIFontPath()); } else { next(); } diff --git a/src/webui/src/api/BaseInfo.ts b/src/webui/src/api/BaseInfo.ts index 12a5fd1f..43df485b 100644 --- a/src/webui/src/api/BaseInfo.ts +++ b/src/webui/src/api/BaseInfo.ts @@ -2,14 +2,25 @@ import { RequestHandler } from 'express'; import { WebUiDataRuntime } from '@webapi/helper/Data'; import { sendSuccess } from '@webapi/utils/response'; +import { WebUiConfig } from '@/webui'; export const PackageInfoHandler: RequestHandler = (_, res) => { const data = WebUiDataRuntime.getPackageJson(); sendSuccess(res, data); }; - export const QQVersionHandler: RequestHandler = (_, res) => { const data = WebUiDataRuntime.getQQVersion(); sendSuccess(res, data); }; + +export const GetThemeConfigHandler: RequestHandler = (_, res) => { + const data = WebUiConfig.GetTheme(); + sendSuccess(res, data); +}; + +export const SetThemeConfigHandler: RequestHandler = (req, res) => { + const { theme } = req.body; + const data = WebUiConfig.UpdateTheme(theme); + sendSuccess(res, data); +}; diff --git a/src/webui/src/api/File.ts b/src/webui/src/api/File.ts index 1bf5cf8c..db5e27b4 100644 --- a/src/webui/src/api/File.ts +++ b/src/webui/src/api/File.ts @@ -7,9 +7,9 @@ import os from 'os'; import compressing from 'compressing'; import { PassThrough } from 'stream'; import multer from 'multer'; -import { WebUiConfigWrapper } from '../helper/config'; import webUIFontUploader from '../uploader/webui_font'; import diskUploader from '../uploader/disk'; +import { WebUiConfig } from '@/webui'; const isWindows = os.platform() === 'win32'; @@ -384,8 +384,8 @@ export const UploadWebUIFontHandler: RequestHandler = async (req, res) => { // 删除WebUI字体文件处理方法 export const DeleteWebUIFontHandler: RequestHandler = async (_req, res) => { try { - const fontPath = WebUiConfigWrapper.GetWebUIFontPath(); - const exists = await WebUiConfigWrapper.CheckWebUIFontExist(); + const fontPath = WebUiConfig.GetWebUIFontPath(); + const exists = await WebUiConfig.CheckWebUIFontExist(); if (!exists) { return sendSuccess(res, true); diff --git a/src/webui/src/api/Log.ts b/src/webui/src/api/Log.ts index a531d275..4e66ee3e 100644 --- a/src/webui/src/api/Log.ts +++ b/src/webui/src/api/Log.ts @@ -1,8 +1,8 @@ import type { RequestHandler } from 'express'; import { sendError, sendSuccess } from '../utils/response'; -import { WebUiConfigWrapper } from '../helper/config'; import { logSubscription } from '@/common/log'; import { terminalManager } from '../terminal/terminal_manager'; +import { WebUiConfig } from '@/webui'; // 判断是否是 macos const isMacOS = process.platform === 'darwin'; // 日志记录 @@ -15,13 +15,13 @@ export const LogHandler: RequestHandler = async (req, res) => { if (filename.includes('..')) { return sendError(res, 'ID不合法'); } - const logContent = await WebUiConfigWrapper.GetLogContent(filename); + const logContent = await WebUiConfig.GetLogContent(filename); return sendSuccess(res, logContent); }; // 日志列表 export const LogListHandler: RequestHandler = async (_, res) => { - const logList = await WebUiConfigWrapper.GetLogsList(); + const logList = await WebUiConfig.GetLogsList(); return sendSuccess(res, logList); }; diff --git a/src/webui/src/api/QQLogin.ts b/src/webui/src/api/QQLogin.ts index 4f324d22..7da2000e 100644 --- a/src/webui/src/api/QQLogin.ts +++ b/src/webui/src/api/QQLogin.ts @@ -3,9 +3,10 @@ import { RequestHandler } from 'express'; import { WebUiDataRuntime } from '@webapi/helper/Data'; import { isEmpty } from '@webapi/utils/check'; import { sendError, sendSuccess } from '@webapi/utils/response'; +import { WebUiConfig } from '@/webui'; // 获取QQ登录二维码 -export const QQGetQRcodeHandler: RequestHandler = async (req, res) => { +export const QQGetQRcodeHandler: RequestHandler = async (_, res) => { // 判断是否已经登录 if (WebUiDataRuntime.getQQLoginStatus()) { // 已经登录 @@ -25,7 +26,7 @@ export const QQGetQRcodeHandler: RequestHandler = async (req, res) => { }; // 获取QQ登录状态 -export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => { +export const QQCheckLoginStatusHandler: RequestHandler = async (_, res) => { const data = { isLogin: WebUiDataRuntime.getQQLoginStatus(), qrcodeurl: WebUiDataRuntime.getQQLoginQrcodeURL(), @@ -74,3 +75,16 @@ export const getQQLoginInfoHandler: RequestHandler = async (_, res) => { const data = WebUiDataRuntime.getQQLoginInfo(); return sendSuccess(res, data); }; + +// 获取自动登录QQ账号 +export const getAutoLoginAccountHandler: RequestHandler = async (_, res) => { + const data = WebUiConfig.getAutoLoginAccount(); + return sendSuccess(res, data); +}; + +// 设置自动登录QQ账号 +export const setAutoLoginAccountHandler: RequestHandler = async (req, res) => { + const { uin } = req.body; + await WebUiConfig.UpdateAutoLoginAccount(uin); + return sendSuccess(res, null); +}; diff --git a/src/webui/src/helper/config.ts b/src/webui/src/helper/config.ts index b9ef685e..5e4e982e 100644 --- a/src/webui/src/helper/config.ts +++ b/src/webui/src/helper/config.ts @@ -14,11 +14,280 @@ const WebUiConfigSchema = Type.Object({ token: Type.String({ default: 'napcat' }), loginRate: Type.Number({ default: 10 }), autoLoginAccount: Type.String({ default: '' }), + theme: Type.Object({ + dark: Type.Object({ + '--heroui-background': Type.String({ default: '0 0% 0%' }), + '--heroui-foreground-50': Type.String({ default: '240 5.88% 10%' }), + '--heroui-foreground-100': Type.String({ default: '240 3.7% 15.88%' }), + '--heroui-foreground-200': Type.String({ default: '240 5.26% 26.08%' }), + '--heroui-foreground-300': Type.String({ default: '240 5.2% 33.92%' }), + '--heroui-foreground-400': Type.String({ default: '240 3.83% 46.08%' }), + '--heroui-foreground-500': Type.String({ default: '240 5.03% 64.9%' }), + '--heroui-foreground-600': Type.String({ default: '240 4.88% 83.92%' }), + '--heroui-foreground-700': Type.String({ default: '240 5.88% 90%' }), + '--heroui-foreground-800': Type.String({ default: '240 4.76% 95.88%' }), + '--heroui-foreground-900': Type.String({ default: '0 0% 98.04%' }), + '--heroui-foreground': Type.String({ default: '210 5.56% 92.94%' }), + '--heroui-focus': Type.String({ default: '212.01999999999998 100% 46.67%' }), + '--heroui-overlay': Type.String({ default: '0 0% 0%' }), + '--heroui-divider': Type.String({ default: '0 0% 100%' }), + '--heroui-divider-opacity': Type.String({ default: '0.15' }), + '--heroui-content1': Type.String({ default: '240 5.88% 10%' }), + '--heroui-content1-foreground': Type.String({ default: '0 0% 98.04%' }), + '--heroui-content2': Type.String({ default: '240 3.7% 15.88%' }), + '--heroui-content2-foreground': Type.String({ default: '240 4.76% 95.88%' }), + '--heroui-content3': Type.String({ default: '240 5.26% 26.08%' }), + '--heroui-content3-foreground': Type.String({ default: '240 5.88% 90%' }), + '--heroui-content4': Type.String({ default: '240 5.2% 33.92%' }), + '--heroui-content4-foreground': Type.String({ default: '240 4.88% 83.92%' }), + '--heroui-default-50': Type.String({ default: '240 5.88% 10%' }), + '--heroui-default-100': Type.String({ default: '240 3.7% 15.88%' }), + '--heroui-default-200': Type.String({ default: '240 5.26% 26.08%' }), + '--heroui-default-300': Type.String({ default: '240 5.2% 33.92%' }), + '--heroui-default-400': Type.String({ default: '240 3.83% 46.08%' }), + '--heroui-default-500': Type.String({ default: '240 5.03% 64.9%' }), + '--heroui-default-600': Type.String({ default: '240 4.88% 83.92%' }), + '--heroui-default-700': Type.String({ default: '240 5.88% 90%' }), + '--heroui-default-800': Type.String({ default: '240 4.76% 95.88%' }), + '--heroui-default-900': Type.String({ default: '0 0% 98.04%' }), + '--heroui-default-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-default': Type.String({ default: '240 5.26% 26.08%' }), + '--heroui-danger-50': Type.String({ default: '301.89 82.61% 22.55%' }), + '--heroui-danger-100': Type.String({ default: '308.18 76.39% 28.24%' }), + '--heroui-danger-200': Type.String({ default: '313.85 70.65% 36.08%' }), + '--heroui-danger-300': Type.String({ default: '319.73 65.64% 44.51%' }), + '--heroui-danger-400': Type.String({ default: '325.82 69.62% 53.53%' }), + '--heroui-danger-500': Type.String({ default: '331.82 75% 65.49%' }), + '--heroui-danger-600': Type.String({ default: '337.84 83.46% 73.92%' }), + '--heroui-danger-700': Type.String({ default: '343.42 90.48% 83.53%' }), + '--heroui-danger-800': Type.String({ default: '350.53 90.48% 91.76%' }), + '--heroui-danger-900': Type.String({ default: '324 90.91% 95.69%' }), + '--heroui-danger-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-danger': Type.String({ default: '325.82 69.62% 53.53%' }), + '--heroui-primary-50': Type.String({ default: '340 84.91% 10.39%' }), + '--heroui-primary-100': Type.String({ default: '339.33 86.54% 20.39%' }), + '--heroui-primary-200': Type.String({ default: '339.11 85.99% 30.78%' }), + '--heroui-primary-300': Type.String({ default: '339 86.54% 40.78%' }), + '--heroui-primary-400': Type.String({ default: '339.2 90.36% 51.18%' }), + '--heroui-primary-500': Type.String({ default: '339 90% 60.78%' }), + '--heroui-primary-600': Type.String({ default: '339.11 90.6% 70.78%' }), + '--heroui-primary-700': Type.String({ default: '339.33 90% 80.39%' }), + '--heroui-primary-800': Type.String({ default: '340 91.84% 90.39%' }), + '--heroui-primary-900': Type.String({ default: '339.13 92% 95.1%' }), + '--heroui-primary-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-primary': Type.String({ default: '339.2 90.36% 51.18%' }), + // 新增 secondary + '--heroui-secondary-50': Type.String({ default: '270 66.67% 9.41%' }), + '--heroui-secondary-100': Type.String({ default: '270 66.67% 18.82%' }), + '--heroui-secondary-200': Type.String({ default: '270 66.67% 28.24%' }), + '--heroui-secondary-300': Type.String({ default: '270 66.67% 37.65%' }), + '--heroui-secondary-400': Type.String({ default: '270 66.67% 47.06%' }), + '--heroui-secondary-500': Type.String({ default: '270 59.26% 57.65%' }), + '--heroui-secondary-600': Type.String({ default: '270 59.26% 68.24%' }), + '--heroui-secondary-700': Type.String({ default: '270 59.26% 78.82%' }), + '--heroui-secondary-800': Type.String({ default: '270 59.26% 89.41%' }), + '--heroui-secondary-900': Type.String({ default: '270 61.54% 94.9%' }), + '--heroui-secondary-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-secondary': Type.String({ default: '270 59.26% 57.65%' }), + // 新增 success + '--heroui-success-50': Type.String({ default: '145.71 77.78% 8.82%' }), + '--heroui-success-100': Type.String({ default: '146.2 79.78% 17.45%' }), + '--heroui-success-200': Type.String({ default: '145.79 79.26% 26.47%' }), + '--heroui-success-300': Type.String({ default: '146.01 79.89% 35.1%' }), + '--heroui-success-400': Type.String({ default: '145.96 79.46% 43.92%' }), + '--heroui-success-500': Type.String({ default: '146.01 62.45% 55.1%' }), + '--heroui-success-600': Type.String({ default: '145.79 62.57% 66.47%' }), + '--heroui-success-700': Type.String({ default: '146.2 61.74% 77.45%' }), + '--heroui-success-800': Type.String({ default: '145.71 61.4% 88.82%' }), + '--heroui-success-900': Type.String({ default: '146.67 64.29% 94.51%' }), + '--heroui-success-foreground': Type.String({ default: '0 0% 0%' }), + '--heroui-success': Type.String({ default: '145.96 79.46% 43.92%' }), + // 新增 warning + '--heroui-warning-50': Type.String({ default: '37.14 75% 10.98%' }), + '--heroui-warning-100': Type.String({ default: '37.14 75% 21.96%' }), + '--heroui-warning-200': Type.String({ default: '36.96 73.96% 33.14%' }), + '--heroui-warning-300': Type.String({ default: '37.01 74.22% 44.12%' }), + '--heroui-warning-400': Type.String({ default: '37.03 91.27% 55.1%' }), + '--heroui-warning-500': Type.String({ default: '37.01 91.26% 64.12%' }), + '--heroui-warning-600': Type.String({ default: '36.96 91.24% 73.14%' }), + '--heroui-warning-700': Type.String({ default: '37.14 91.3% 81.96%' }), + '--heroui-warning-800': Type.String({ default: '37.14 91.3% 90.98%' }), + '--heroui-warning-900': Type.String({ default: '54.55 91.67% 95.29%' }), + '--heroui-warning-foreground': Type.String({ default: '0 0% 0%' }), + '--heroui-warning': Type.String({ default: '37.03 91.27% 55.1%' }), + // 其它配置 + '--heroui-code-background': Type.String({ default: '240 5.56% 7.06%' }), + '--heroui-strong': Type.String({ default: '190.14 94.67% 44.12%' }), + '--heroui-code-mdx': Type.String({ default: '190.14 94.67% 44.12%' }), + '--heroui-divider-weight': Type.String({ default: '1px' }), + '--heroui-disabled-opacity': Type.String({ default: '.5' }), + '--heroui-font-size-tiny': Type.String({ default: '0.75rem' }), + '--heroui-font-size-small': Type.String({ default: '0.875rem' }), + '--heroui-font-size-medium': Type.String({ default: '1rem' }), + '--heroui-font-size-large': Type.String({ default: '1.125rem' }), + '--heroui-line-height-tiny': Type.String({ default: '1rem' }), + '--heroui-line-height-small': Type.String({ default: '1.25rem' }), + '--heroui-line-height-medium': Type.String({ default: '1.5rem' }), + '--heroui-line-height-large': Type.String({ default: '1.75rem' }), + '--heroui-radius-small': Type.String({ default: '8px' }), + '--heroui-radius-medium': Type.String({ default: '12px' }), + '--heroui-radius-large': Type.String({ default: '14px' }), + '--heroui-border-width-small': Type.String({ default: '1px' }), + '--heroui-border-width-medium': Type.String({ default: '2px' }), + '--heroui-border-width-large': Type.String({ default: '3px' }), + '--heroui-box-shadow-small': Type.String({ + default: + '0px 0px 5px 0px rgba(0, 0, 0, .05), 0px 2px 10px 0px rgba(0, 0, 0, .2), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)', + }), + '--heroui-box-shadow-medium': Type.String({ + default: + '0px 0px 15px 0px rgba(0, 0, 0, .06), 0px 2px 30px 0px rgba(0, 0, 0, .22), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)', + }), + '--heroui-box-shadow-large': Type.String({ + default: + '0px 0px 30px 0px rgba(0, 0, 0, .07), 0px 30px 60px 0px rgba(0, 0, 0, .26), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)', + }), + '--heroui-hover-opacity': Type.String({ default: '.9' }), + }), + light: Type.Object({ + '--heroui-background': Type.String({ default: '0 0% 100%' }), + '--heroui-foreground-50': Type.String({ default: '240 5.88% 95%' }), + '--heroui-foreground-100': Type.String({ default: '240 3.7% 90%' }), + '--heroui-foreground-200': Type.String({ default: '240 5.26% 80%' }), + '--heroui-foreground-300': Type.String({ default: '240 5.2% 70%' }), + '--heroui-foreground-400': Type.String({ default: '240 3.83% 60%' }), + '--heroui-foreground-500': Type.String({ default: '240 5.03% 50%' }), + '--heroui-foreground-600': Type.String({ default: '240 4.88% 40%' }), + '--heroui-foreground-700': Type.String({ default: '240 5.88% 30%' }), + '--heroui-foreground-800': Type.String({ default: '240 4.76% 20%' }), + '--heroui-foreground-900': Type.String({ default: '0 0% 10%' }), + '--heroui-foreground': Type.String({ default: '210 5.56% 7.06%' }), + '--heroui-focus': Type.String({ default: '212.01999999999998 100% 53.33%' }), + '--heroui-overlay': Type.String({ default: '0 0% 100%' }), + '--heroui-divider': Type.String({ default: '0 0% 0%' }), + '--heroui-divider-opacity': Type.String({ default: '0.85' }), + '--heroui-content1': Type.String({ default: '240 5.88% 95%' }), + '--heroui-content1-foreground': Type.String({ default: '0 0% 10%' }), + '--heroui-content2': Type.String({ default: '240 3.7% 90%' }), + '--heroui-content2-foreground': Type.String({ default: '240 4.76% 20%' }), + '--heroui-content3': Type.String({ default: '240 5.26% 80%' }), + '--heroui-content3-foreground': Type.String({ default: '240 5.88% 30%' }), + '--heroui-content4': Type.String({ default: '240 5.2% 70%' }), + '--heroui-content4-foreground': Type.String({ default: '240 4.88% 40%' }), + '--heroui-default-50': Type.String({ default: '240 5.88% 95%' }), + '--heroui-default-100': Type.String({ default: '240 3.7% 90%' }), + '--heroui-default-200': Type.String({ default: '240 5.26% 80%' }), + '--heroui-default-300': Type.String({ default: '240 5.2% 70%' }), + '--heroui-default-400': Type.String({ default: '240 3.83% 60%' }), + '--heroui-default-500': Type.String({ default: '240 5.03% 50%' }), + '--heroui-default-600': Type.String({ default: '240 4.88% 40%' }), + '--heroui-default-700': Type.String({ default: '240 5.88% 30%' }), + '--heroui-default-800': Type.String({ default: '240 4.76% 20%' }), + '--heroui-default-900': Type.String({ default: '0 0% 10%' }), + '--heroui-default-foreground': Type.String({ default: '0 0% 0%' }), + '--heroui-default': Type.String({ default: '240 5.26% 80%' }), + '--heroui-danger-50': Type.String({ default: '324 90.91% 95.69%' }), + '--heroui-danger-100': Type.String({ default: '350.53 90.48% 91.76%' }), + '--heroui-danger-200': Type.String({ default: '343.42 90.48% 83.53%' }), + '--heroui-danger-300': Type.String({ default: '337.84 83.46% 73.92%' }), + '--heroui-danger-400': Type.String({ default: '331.82 75% 65.49%' }), + '--heroui-danger-500': Type.String({ default: '325.82 69.62% 53.53%' }), + '--heroui-danger-600': Type.String({ default: '319.73 65.64% 44.51%' }), + '--heroui-danger-700': Type.String({ default: '313.85 70.65% 36.08%' }), + '--heroui-danger-800': Type.String({ default: '308.18 76.39% 28.24%' }), + '--heroui-danger-900': Type.String({ default: '301.89 82.61% 22.55%' }), + '--heroui-danger-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-danger': Type.String({ default: '325.82 69.62% 53.53%' }), + '--heroui-primary-50': Type.String({ default: '339.13 92% 95.1%' }), + '--heroui-primary-100': Type.String({ default: '340 91.84% 90.39%' }), + '--heroui-primary-200': Type.String({ default: '339.33 90% 80.39%' }), + '--heroui-primary-300': Type.String({ default: '339.11 90.6% 70.78%' }), + '--heroui-primary-400': Type.String({ default: '339 90% 60.78%' }), + '--heroui-primary-500': Type.String({ default: '339.2 90.36% 51.18%' }), + '--heroui-primary-600': Type.String({ default: '339 86.54% 40.78%' }), + '--heroui-primary-700': Type.String({ default: '339.11 85.99% 30.78%' }), + '--heroui-primary-800': Type.String({ default: '339.33 86.54% 20.39%' }), + '--heroui-primary-900': Type.String({ default: '340 84.91% 10.39%' }), + '--heroui-primary-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-primary': Type.String({ default: '339.2 90.36% 51.18%' }), + // 新增 secondary + '--heroui-secondary-50': Type.String({ default: '270 61.54% 94.9%' }), + '--heroui-secondary-100': Type.String({ default: '270 59.26% 89.41%' }), + '--heroui-secondary-200': Type.String({ default: '270 59.26% 78.82%' }), + '--heroui-secondary-300': Type.String({ default: '270 59.26% 68.24%' }), + '--heroui-secondary-400': Type.String({ default: '270 59.26% 57.65%' }), + '--heroui-secondary-500': Type.String({ default: '270 66.67% 47.06%' }), + '--heroui-secondary-600': Type.String({ default: '270 66.67% 37.65%' }), + '--heroui-secondary-700': Type.String({ default: '270 66.67% 28.24%' }), + '--heroui-secondary-800': Type.String({ default: '270 66.67% 18.82%' }), + '--heroui-secondary-900': Type.String({ default: '270 66.67% 9.41%' }), + '--heroui-secondary-foreground': Type.String({ default: '0 0% 100%' }), + '--heroui-secondary': Type.String({ default: '270 66.67% 47.06%' }), + // 新增 success + '--heroui-success-50': Type.String({ default: '146.67 64.29% 94.51%' }), + '--heroui-success-100': Type.String({ default: '145.71 61.4% 88.82%' }), + '--heroui-success-200': Type.String({ default: '146.2 61.74% 77.45%' }), + '--heroui-success-300': Type.String({ default: '145.79 62.57% 66.47%' }), + '--heroui-success-400': Type.String({ default: '146.01 62.45% 55.1%' }), + '--heroui-success-500': Type.String({ default: '145.96 79.46% 43.92%' }), + '--heroui-success-600': Type.String({ default: '146.01 79.89% 35.1%' }), + '--heroui-success-700': Type.String({ default: '145.79 79.26% 26.47%' }), + '--heroui-success-800': Type.String({ default: '146.2 79.78% 17.45%' }), + '--heroui-success-900': Type.String({ default: '145.71 77.78% 8.82%' }), + '--heroui-success-foreground': Type.String({ default: '0 0% 0%' }), + '--heroui-success': Type.String({ default: '145.96 79.46% 43.92%' }), + // 新增 warning + '--heroui-warning-50': Type.String({ default: '54.55 91.67% 95.29%' }), + '--heroui-warning-100': Type.String({ default: '37.14 91.3% 90.98%' }), + '--heroui-warning-200': Type.String({ default: '37.14 91.3% 81.96%' }), + '--heroui-warning-300': Type.String({ default: '36.96 91.24% 73.14%' }), + '--heroui-warning-400': Type.String({ default: '37.01 91.26% 64.12%' }), + '--heroui-warning-500': Type.String({ default: '37.03 91.27% 55.1%' }), + '--heroui-warning-600': Type.String({ default: '37.01 74.22% 44.12%' }), + '--heroui-warning-700': Type.String({ default: '36.96 73.96% 33.14%' }), + '--heroui-warning-800': Type.String({ default: '37.14 75% 21.96%' }), + '--heroui-warning-900': Type.String({ default: '37.14 75% 10.98%' }), + '--heroui-warning-foreground': Type.String({ default: '0 0% 0%' }), + '--heroui-warning': Type.String({ default: '37.03 91.27% 55.1%' }), + // 其它配置 + '--heroui-code-background': Type.String({ default: '221.25 17.39% 18.04%' }), + '--heroui-strong': Type.String({ default: '316.95 100% 65.29%' }), + '--heroui-code-mdx': Type.String({ default: '316.95 100% 65.29%' }), + '--heroui-divider-weight': Type.String({ default: '1px' }), + '--heroui-disabled-opacity': Type.String({ default: '.5' }), + '--heroui-font-size-tiny': Type.String({ default: '0.75rem' }), + '--heroui-font-size-small': Type.String({ default: '0.875rem' }), + '--heroui-font-size-medium': Type.String({ default: '1rem' }), + '--heroui-font-size-large': Type.String({ default: '1.125rem' }), + '--heroui-line-height-tiny': Type.String({ default: '1rem' }), + '--heroui-line-height-small': Type.String({ default: '1.25rem' }), + '--heroui-line-height-medium': Type.String({ default: '1.5rem' }), + '--heroui-line-height-large': Type.String({ default: '1.75rem' }), + '--heroui-radius-small': Type.String({ default: '8px' }), + '--heroui-radius-medium': Type.String({ default: '12px' }), + '--heroui-radius-large': Type.String({ default: '14px' }), + '--heroui-border-width-small': Type.String({ default: '1px' }), + '--heroui-border-width-medium': Type.String({ default: '2px' }), + '--heroui-border-width-large': Type.String({ default: '3px' }), + '--heroui-box-shadow-small': Type.String({ + default: + '0px 0px 5px 0px rgba(0, 0, 0, .02), 0px 2px 10px 0px rgba(0, 0, 0, .06), 0px 0px 1px 0px rgba(0, 0, 0, .3)', + }), + '--heroui-box-shadow-medium': Type.String({ + default: + '0px 0px 15px 0px rgba(0, 0, 0, .03), 0px 2px 30px 0px rgba(0, 0, 0, .08), 0px 0px 1px 0px rgba(0, 0, 0, .3)', + }), + '--heroui-box-shadow-large': Type.String({ + default: + '0px 0px 30px 0px rgba(0, 0, 0, .04), 0px 30px 60px 0px rgba(0, 0, 0, .12), 0px 0px 1px 0px rgba(0, 0, 0, .3)', + }), + '--heroui-hover-opacity': Type.String({ default: '.8' }), + }), + }), }); export type WebUiConfigType = Static; - // 读取当前目录下名为 webui.json 的配置文件,如果不存在则创建初始化配置文件 export class WebUiConfigWrapper { WebUiConfigData: WebUiConfigType | undefined = undefined; @@ -29,7 +298,10 @@ export class WebUiConfigWrapper { } private async ensureConfigFileExists(configPath: string): Promise { - const configExists = await fs.access(configPath, constants.F_OK).then(() => true).catch(() => false); + const configExists = await fs + .access(configPath, constants.F_OK) + .then(() => true) + .catch(() => false); if (!configExists) { await fs.writeFile(configPath, JSON.stringify(this.validateAndApplyDefaults({}), null, 4)); } @@ -41,7 +313,10 @@ export class WebUiConfigWrapper { } private async writeConfig(configPath: string, config: WebUiConfigType): Promise { - const hasWritePermission = await fs.access(configPath, constants.W_OK).then(() => true).catch(() => false); + const hasWritePermission = await fs + .access(configPath, constants.W_OK) + .then(() => true) + .catch(() => false); if (hasWritePermission) { await fs.writeFile(configPath, JSON.stringify(config, null, 4)); } else { @@ -82,24 +357,32 @@ export class WebUiConfigWrapper { } // 获取日志文件夹路径 - public static async GetLogsPath(): Promise { + async GetLogsPath(): Promise { return resolve(webUiPathWrapper.logsPath); } // 获取日志列表 - public static async GetLogsList(): Promise { + async GetLogsList(): Promise { const logsPath = resolve(webUiPathWrapper.logsPath); - const logsExist = await fs.access(logsPath, constants.F_OK).then(() => true).catch(() => false); + const logsExist = await fs + .access(logsPath, constants.F_OK) + .then(() => true) + .catch(() => false); if (logsExist) { - return (await fs.readdir(logsPath)).filter(file => file.endsWith('.log')).map(file => file.replace('.log', '')); + return (await fs.readdir(logsPath)) + .filter((file) => file.endsWith('.log')) + .map((file) => file.replace('.log', '')); } return []; } // 获取指定日志文件内容 - public static async GetLogContent(filename: string): Promise { + async GetLogContent(filename: string): Promise { const logPath = resolve(webUiPathWrapper.logsPath, `${filename}.log`); - const logExists = await fs.access(logPath, constants.R_OK).then(() => true).catch(() => false); + const logExists = await fs + .access(logPath, constants.R_OK) + .then(() => true) + .catch(() => false); if (logExists) { return await fs.readFile(logPath, 'utf-8'); } @@ -107,27 +390,53 @@ export class WebUiConfigWrapper { } // 获取字体文件夹内的字体列表 - public static async GetFontList(): Promise { + async GetFontList(): Promise { const fontsPath = resolve(webUiPathWrapper.configPath, './fonts'); - const fontsExist = await fs.access(fontsPath, constants.F_OK).then(() => true).catch(() => false); + const fontsExist = await fs + .access(fontsPath, constants.F_OK) + .then(() => true) + .catch(() => false); if (fontsExist) { - return (await fs.readdir(fontsPath)).filter(file => file.endsWith('.ttf')); + return (await fs.readdir(fontsPath)).filter((file) => file.endsWith('.ttf')); } return []; } // 判断字体是否存在(webui.woff) - public static async CheckWebUIFontExist(): Promise { + async CheckWebUIFontExist(): Promise { const fontsPath = resolve(webUiPathWrapper.configPath, './fonts'); - return await fs.access(resolve(fontsPath, './webui.woff'), constants.F_OK).then(() => true).catch(() => false); + return await fs + .access(resolve(fontsPath, './webui.woff'), constants.F_OK) + .then(() => true) + .catch(() => false); } // 获取webui字体文件路径 - public static GetWebUIFontPath(): string { + GetWebUIFontPath(): string { return resolve(webUiPathWrapper.configPath, './fonts/webui.woff'); } - public getAutoLoginAccount(): string | undefined { + getAutoLoginAccount(): string | undefined { return this.WebUiConfigData?.autoLoginAccount; } -} \ No newline at end of file + + // 获取自动登录账号 + async GetAutoLoginAccount(): Promise { + return (await this.GetWebUIConfig()).autoLoginAccount; + } + + // 更新自动登录账号 + async UpdateAutoLoginAccount(uin: string): Promise { + await this.UpdateWebUIConfig({ autoLoginAccount: uin }); + } + + // 获取主题内容 + async GetTheme(): Promise { + return (await this.GetWebUIConfig()).theme; + } + + // 更新主题内容 + async UpdateTheme(theme: WebUiConfigType['theme']): Promise { + await this.UpdateWebUIConfig({ theme: theme }); + } +} diff --git a/src/webui/src/router/Base.ts b/src/webui/src/router/Base.ts index 0ec78532..f79975cf 100644 --- a/src/webui/src/router/Base.ts +++ b/src/webui/src/router/Base.ts @@ -1,5 +1,5 @@ import { Router } from 'express'; -import { PackageInfoHandler, QQVersionHandler } from '../api/BaseInfo'; +import { GetThemeConfigHandler, PackageInfoHandler, QQVersionHandler, SetThemeConfigHandler } from '../api/BaseInfo'; import { StatusRealTimeHandler } from '@webapi/api/Status'; import { GetProxyHandler } from '../api/Proxy'; @@ -9,4 +9,7 @@ router.get('/QQVersion', QQVersionHandler); router.get('/PackageInfo', PackageInfoHandler); router.get('/GetSysStatusRealTime', StatusRealTimeHandler); router.get('/proxy', GetProxyHandler); +router.get('/Theme', GetThemeConfigHandler); +router.post('/SetTheme', SetThemeConfigHandler); + export { router as BaseRouter }; diff --git a/src/webui/src/router/QQLogin.ts b/src/webui/src/router/QQLogin.ts index 5fd4ef18..aecb5b44 100644 --- a/src/webui/src/router/QQLogin.ts +++ b/src/webui/src/router/QQLogin.ts @@ -7,6 +7,8 @@ import { QQSetQuickLoginHandler, QQGetLoginListNewHandler, getQQLoginInfoHandler, + getAutoLoginAccountHandler, + setAutoLoginAccountHandler, } from '@webapi/api/QQLogin'; const router = Router(); @@ -22,5 +24,9 @@ router.post('/GetQQLoginQrcode', QQGetQRcodeHandler); router.post('/SetQuickLogin', QQSetQuickLoginHandler); // router:获取QQ登录信息 router.post('/GetQQLoginInfo', getQQLoginInfoHandler); +// router:获取快速登录QQ账号 +router.post('/GetQuickLoginQQ', getAutoLoginAccountHandler); +// router:设置自动登录QQ账号 +router.post('/SetQuickLoginQQ', setAutoLoginAccountHandler); export { router as QQLoginRouter };