From 0f2e0431337bae46186a8e8ecc8420eeda77b5e2 Mon Sep 17 00:00:00 2001 From: Yvan <8574526@qq,com> Date: Wed, 7 Jan 2026 19:37:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E4=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/Logo/index.tsx | 37 +++++++++++ web/src/utils/format.ts | 76 ++++++++++++++++++++++ web/src/utils/index.ts | 7 ++ web/src/utils/page.ts | 25 ++++++++ web/src/utils/storage.ts | 102 ++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 web/src/components/Logo/index.tsx create mode 100644 web/src/utils/format.ts create mode 100644 web/src/utils/index.ts create mode 100644 web/src/utils/page.ts create mode 100644 web/src/utils/storage.ts diff --git a/web/src/components/Logo/index.tsx b/web/src/components/Logo/index.tsx new file mode 100644 index 0000000..28dbc4b --- /dev/null +++ b/web/src/components/Logo/index.tsx @@ -0,0 +1,37 @@ +import React from 'react'; + +interface LogoProps { + collapsed?: boolean; +} + +const Logo: React.FC = ({ collapsed }) => { + return ( +
+ KRA Admin + {!collapsed && ( + + KRA Admin + + )} +
+ ); +}; + +export default Logo; diff --git a/web/src/utils/format.ts b/web/src/utils/format.ts new file mode 100644 index 0000000..1a12140 --- /dev/null +++ b/web/src/utils/format.ts @@ -0,0 +1,76 @@ +/** + * 格式化工具函数 - 参考GVA的format.js + */ + +/** + * 设置主题色 - 参考GVA的setBodyPrimaryColor + * @param color 主题色 + * @param mode 模式 'light' | 'dark' + */ +export function setBodyPrimaryColor(color: string, mode: 'light' | 'dark' = 'light'): void { + const root = document.documentElement; + root.style.setProperty('--primary-color', color); + + // 设置不同透明度的主题色变体 + root.style.setProperty('--primary-color-hover', adjustColor(color, mode === 'dark' ? 20 : -10)); + root.style.setProperty('--primary-color-active', adjustColor(color, mode === 'dark' ? 30 : -20)); + root.style.setProperty('--primary-color-light', adjustColor(color, mode === 'dark' ? -30 : 40)); +} + +/** + * 调整颜色亮度 + * @param color 十六进制颜色 + * @param amount 调整量(正数变亮,负数变暗) + */ +function adjustColor(color: string, amount: number): string { + const hex = color.replace('#', ''); + const num = parseInt(hex, 16); + + let r = (num >> 16) + amount; + let g = ((num >> 8) & 0x00FF) + amount; + let b = (num & 0x0000FF) + amount; + + r = Math.max(0, Math.min(255, r)); + g = Math.max(0, Math.min(255, g)); + b = Math.max(0, Math.min(255, b)); + + return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`; +} + +/** + * 格式化日期 + * @param date 日期 + * @param format 格式 + */ +export function formatDate(date: Date | string | number, format: string = 'YYYY-MM-DD HH:mm:ss'): string { + const d = new Date(date); + + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hours = String(d.getHours()).padStart(2, '0'); + const minutes = String(d.getMinutes()).padStart(2, '0'); + const seconds = String(d.getSeconds()).padStart(2, '0'); + + return format + .replace('YYYY', String(year)) + .replace('MM', month) + .replace('DD', day) + .replace('HH', hours) + .replace('mm', minutes) + .replace('ss', seconds); +} + +/** + * 格式化文件大小 + * @param bytes 字节数 + */ +export function formatFileSize(bytes: number): string { + if (bytes === 0) return '0 B'; + + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; +} diff --git a/web/src/utils/index.ts b/web/src/utils/index.ts new file mode 100644 index 0000000..07dbf65 --- /dev/null +++ b/web/src/utils/index.ts @@ -0,0 +1,7 @@ +/** + * 工具函数集合 - 参考GVA的utils + */ + +export * from './page'; +export * from './storage'; +export * from './format'; diff --git a/web/src/utils/page.ts b/web/src/utils/page.ts new file mode 100644 index 0000000..130ded5 --- /dev/null +++ b/web/src/utils/page.ts @@ -0,0 +1,25 @@ +/** + * 页面工具函数 - 参考GVA的page.js + */ + +const APP_NAME = 'KRA Admin'; + +/** + * 获取页面标题 + * @param pageTitle 页面标题 + * @returns 完整的页面标题 + */ +export function getPageTitle(pageTitle?: string): string { + if (pageTitle) { + return `${pageTitle} - ${APP_NAME}`; + } + return APP_NAME; +} + +/** + * 设置页面标题 + * @param title 页面标题 + */ +export function setPageTitle(title?: string): void { + document.title = getPageTitle(title); +} diff --git a/web/src/utils/storage.ts b/web/src/utils/storage.ts new file mode 100644 index 0000000..cfc5964 --- /dev/null +++ b/web/src/utils/storage.ts @@ -0,0 +1,102 @@ +/** + * 存储工具函数 - 参考GVA的用户存储逻辑 + */ + +const TOKEN_KEY = 'token'; +const USER_INFO_KEY = 'userInfo'; + +/** + * 获取Token + */ +export function getToken(): string | null { + return localStorage.getItem(TOKEN_KEY); +} + +/** + * 设置Token + */ +export function setToken(token: string): void { + localStorage.setItem(TOKEN_KEY, token); +} + +/** + * 移除Token + */ +export function removeToken(): void { + localStorage.removeItem(TOKEN_KEY); +} + +/** + * 获取用户信息 + */ +export function getUserInfo(): API.UserInfo | null { + const userInfo = localStorage.getItem(USER_INFO_KEY); + if (userInfo) { + try { + return JSON.parse(userInfo); + } catch (e) { + return null; + } + } + return null; +} + +/** + * 设置用户信息 + */ +export function setUserInfo(userInfo: API.UserInfo): void { + localStorage.setItem(USER_INFO_KEY, JSON.stringify(userInfo)); +} + +/** + * 移除用户信息 + */ +export function removeUserInfo(): void { + localStorage.removeItem(USER_INFO_KEY); +} + +/** + * 清除所有存储 - 参考GVA的ClearStorage + */ +export function clearStorage(): void { + removeToken(); + removeUserInfo(); + sessionStorage.clear(); + localStorage.removeItem('originSetting'); +} + +/** + * 检查是否需要跳转到首页 + */ +export function checkNeedToHome(): boolean { + const need = sessionStorage.getItem('needToHome') === 'true'; + if (need) { + sessionStorage.removeItem('needToHome'); + } + return need; +} + +/** + * 设置需要跳转到首页 + */ +export function setNeedToHome(): void { + sessionStorage.setItem('needToHome', 'true'); +} + +/** + * 检查是否需要关闭所有标签 + */ +export function checkNeedCloseAll(): boolean { + const need = sessionStorage.getItem('needCloseAll') === 'true'; + if (need) { + sessionStorage.removeItem('needCloseAll'); + } + return need; +} + +/** + * 设置需要关闭所有标签 + */ +export function setNeedCloseAll(): void { + sessionStorage.setItem('needCloseAll', 'true'); +}