将 web-admin 从子模块改为仓库内普通目录,便于单仓克隆与维护。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-05-12 16:41:08 +08:00
1 parent 2e9d020d50
commit c87732fcd5
515 files changed
+74372 -1

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
// ANSI 转义码生成网站 https://patorjk.com/software/taag/#p=display&f=Big&t=ABB%0A
const asciiArt = `
\x1b[32m欢迎使用 Art Design Pro!
\x1b[0m
\x1b[36m哇!你居然在用我的项目~ 好用的话别忘了去 GitHub 点个 ★Star 呀,你的支持就是我更新的超强动力!祝使用体验满分💯
\x1b[0m
\x1b[33mGitHub: https://github.com/Daymychen/art-design-pro
\x1b[0m
\x1b[31m技术支持(QQ群): 1038930070,和开发者一起交流~ 群里有小伙伴实时答疑,遇到问题不用慌!
\x1b[0m
`
console.log(asciiArt)
+143
View File
@@ -0,0 +1,143 @@
/**
* 全局错误处理模块
*
* 提供统一的错误捕获和处理机制
*
* ## 主要功能
*
* - Vue 运行时错误捕获(组件错误、生命周期错误等)
* - 全局脚本错误捕获(语法错误、运行时错误等)
* - Promise 未捕获错误处理(unhandledrejection)
* - 静态资源加载错误监控(图片、脚本、样式等)
* - 错误日志记录和上报
* - 统一的错误处理入口
*
* ## 使用场景
* - 应用启动时安装全局错误处理器
* - 捕获和记录所有类型的错误
* - 错误上报到监控平台
* - 提升应用稳定性和可维护性
* - 问题排查和调试
*
* ## 错误类型
*
* - VueError: Vue 组件相关错误
* - ScriptError: JavaScript 脚本错误
* - PromiseError: Promise 未捕获的 rejection
* - ResourceError: 静态资源加载失败
*
* @module utils/sys/error-handle
* @author Art Design Pro Team
*/
import type { App } from 'vue'
const IGNORABLE_SCRIPT_ERRORS = [
'ResizeObserver loop completed with undelivered notifications.',
'ResizeObserver loop limit exceeded'
]
function normalizeErrorMessage(message: Event | string): string {
if (typeof message === 'string') {
return message
}
if ('message' in message && typeof message.message === 'string') {
return message.message
}
return ''
}
function isIgnorableScriptError(message: Event | string, source?: string): boolean {
const normalizedMessage = normalizeErrorMessage(message)
if (!normalizedMessage) {
return false
}
if (IGNORABLE_SCRIPT_ERRORS.some((item) => normalizedMessage.includes(item))) {
// 浏览器/扩展在布局抖动时常见的 ResizeObserver 噪声,不作为真实异常处理
return true
}
// 浏览器扩展注入脚本偶发的跨域 Script error 也没有排查价值
if (normalizedMessage === 'Script error.' && source === '') {
return true
}
return false
}
/**
* Vue 运行时错误处理
*/
export function vueErrorHandler(err: unknown, instance: any, info: string) {
console.error('[VueError]', err, info, instance)
// 这里可以上报到服务端,比如:
// reportError({ type: 'vue', err, info })
}
/**
* 全局脚本错误处理
*/
export function scriptErrorHandler(
message: Event | string,
source?: string,
lineno?: number,
colno?: number,
error?: Error
): boolean {
if (isIgnorableScriptError(message, source)) {
return true
}
console.error('[ScriptError]', { message, source, lineno, colno, error })
// reportError({ type: 'script', message, source, lineno, colno, error })
return true // 阻止默认控制台报错,可根据需求改
}
/**
* Promise 未捕获错误处理
*/
export function registerPromiseErrorHandler() {
window.addEventListener('unhandledrejection', (event) => {
console.error('[PromiseError]', event.reason)
// reportError({ type: 'promise', reason: event.reason })
})
}
/**
* 资源加载错误处理 (img, script, css...)
*/
export function registerResourceErrorHandler() {
window.addEventListener(
'error',
(event: Event) => {
const target = event.target as HTMLElement
if (
target &&
(target.tagName === 'IMG' || target.tagName === 'SCRIPT' || target.tagName === 'LINK')
) {
console.error('[ResourceError]', {
tagName: target.tagName,
src:
(target as HTMLImageElement).src ||
(target as HTMLScriptElement).src ||
(target as HTMLLinkElement).href
})
// reportError({ type: 'resource', target })
}
},
true // 捕获阶段才能监听到资源错误
)
}
/**
* 安装统一错误处理
*/
export function setupErrorHandle(app: App) {
app.config.errorHandler = vueErrorHandler
window.onerror = scriptErrorHandler
registerPromiseErrorHandler()
registerResourceErrorHandler()
}
+6
View File
@@ -0,0 +1,6 @@
/**
* 系统管理相关工具函数统一导出
*/
export * from './upgrade'
export { default as mittBus } from './mittBus'
+63
View File
@@ -0,0 +1,63 @@
/**
* 全局事件总线模块
*
* 基于 mitt 库实现的类型安全的事件总线
*
* ## 主要功能
*
* - 跨组件通信(发布/订阅模式)
* - 类型安全的事件定义和调用
* - 全局事件管理(烟花效果、设置面板、搜索对话框等)
* - 解耦组件间的直接依赖
*
* ## 使用场景
*
* - 跨层级组件通信
* - 全局功能触发(设置、搜索、聊天、锁屏等)
* - 特效触发(烟花效果)
* - 避免 props 层层传递
*
* ## 用法示例
*
* ```typescript
* // 订阅事件
* mittBus.on('openSetting', () => { ... })
*
* // 发布事件
* mittBus.emit('openSetting')
*
* // 带参数的事件
* mittBus.emit('triggerFireworks', 'image-url')
* ```
*
* ## 已定义的事件
*
* - triggerFireworks: 触发烟花效果(可选图片URL)
* - openSetting: 打开设置面板
* - openSearchDialog: 打开搜索对话框
* - openChat: 打开聊天窗口
* - openLockScreen: 打开锁屏
*
* @module utils/sys/mittBus
* @author Art Design Pro Team
*/
import mitt, { type Emitter } from 'mitt'
// 定义事件类型映射
type Events = {
// 烟花效果事件 - 可选的图片URL参数
triggerFireworks: string | undefined
// 打开设置面板事件 - 无参数
openSetting: void
// 打开搜索对话框事件 - 无参数
openSearchDialog: void
// 打开聊天窗口事件 - 无参数
openChat: void
// 打开锁屏事件 - 无参数
openLockScreen: void
}
// 创建类型安全的事件总线实例
const mittBus: Emitter<Events> = mitt<Events>()
export default mittBus
+279
View File
@@ -0,0 +1,279 @@
/**
* 系统版本升级管理模块
*
* 提供完整的应用版本升级检测和处理功能
*
* ## 主要功能
*
* - 版本号比较和升级检测
* - 首次访问识别和处理
* - 旧版本数据自动清理
* - 升级日志展示和通知
* - 强制重新登录控制(根据升级日志配置)
* - 版本号规范化处理
* - 旧存储结构迁移和清理
* - 升级流程延迟执行(确保应用完全加载)
*
* @module utils/sys/upgrade
* @author Art Design Pro Team
*/
import { ElNotification } from 'element-plus'
import { useUserStore } from '@/store/modules/user'
import { StorageConfig } from '@/utils/storage/storage-config'
import { fetchGetLatestUpgradeLog } from '@/api/system'
interface UpgradeLog {
version: string
title: string
date: string
detail?: string[]
requireReLogin?: boolean
remark?: string
}
/**
* 版本管理器
* 负责处理版本比较、升级检测和数据清理
*/
class VersionManager {
/**
* 规范化版本号字符串,移除前缀 'v'
*/
private normalizeVersion(version: string): string {
return version.replace(/^v/, '')
}
/**
* 获取存储的版本号
*/
private getStoredVersion(): string | null {
return localStorage.getItem(StorageConfig.VERSION_KEY)
}
/**
* 设置版本号到存储
*/
private setStoredVersion(version: string): void {
localStorage.setItem(StorageConfig.VERSION_KEY, version)
}
/**
* 检查是否应该跳过升级处理
*/
private shouldSkipUpgrade(): boolean {
return StorageConfig.CURRENT_VERSION === StorageConfig.SKIP_UPGRADE_VERSION
}
/**
* 检查是否为首次访问
*/
private isFirstVisit(storedVersion: string | null): boolean {
return !storedVersion
}
/**
* 检查版本是否相同
*/
private isSameVersion(storedVersion: string): boolean {
return storedVersion === StorageConfig.CURRENT_VERSION
}
/**
* 查找旧的存储结构
*/
private findLegacyStorage(): { oldSysKey: string | null; oldVersionKeys: string[] } {
const storageKeys = Object.keys(localStorage)
const currentVersionPrefix = StorageConfig.generateStorageKey('').slice(0, -1) // 移除末尾的 '-'
// 查找旧的单一存储结构
const oldSysKey =
storageKeys.find(
(key) =>
StorageConfig.isVersionedKey(key) && key !== currentVersionPrefix && !key.includes('-')
) || null
// 查找旧版本的分离存储键
const oldVersionKeys = storageKeys.filter(
(key) =>
StorageConfig.isVersionedKey(key) &&
!StorageConfig.isCurrentVersionKey(key) &&
key.includes('-')
)
return { oldSysKey, oldVersionKeys }
}
/**
* 检查是否需要重新登录
*/
private shouldRequireReLogin(storedVersion: string, latestLog: UpgradeLog | null): boolean {
if (!latestLog) return false
const normalizedCurrent = this.normalizeVersion(StorageConfig.CURRENT_VERSION)
const normalizedStored = this.normalizeVersion(storedVersion)
const itemVersion = this.normalizeVersion(latestLog.version)
return (
latestLog.requireReLogin &&
itemVersion > normalizedStored &&
itemVersion <= normalizedCurrent
)
}
/**
* 构建升级通知消息
*/
private buildUpgradeMessage(latestLog: UpgradeLog): string {
const messageParts = [
`<p style="color: var(--art-gray-800) !important; padding-bottom: 5px;">`,
`系统已升级到 ${StorageConfig.CURRENT_VERSION} 版本,此次更新带来了以下改进:`,
`</p>`,
latestLog.title
]
if (latestLog.requireReLogin) {
messageParts.push(
`<p style="color: var(--theme-color); padding-top: 5px;">升级完成,请重新登录后继续使用。</p>`
)
}
return messageParts.join('')
}
/**
* 显示升级通知
*/
private showUpgradeNotification(message: string): void {
ElNotification({
title: '系统升级公告',
message,
duration: 0,
type: 'success',
dangerouslyUseHTMLString: true
})
}
/**
* 清理旧版本数据
*/
private cleanupLegacyData(oldSysKey: string | null, oldVersionKeys: string[]): void {
// 清理旧的单一存储结构
if (oldSysKey) {
localStorage.removeItem(oldSysKey)
console.info(`[Upgrade] 已清理旧存储: ${oldSysKey}`)
}
// 清理旧版本的分离存储
oldVersionKeys.forEach((key) => {
localStorage.removeItem(key)
console.info(`[Upgrade] 已清理旧存储: ${key}`)
})
}
/**
* 执行升级后的登出操作
*/
private performLogout(): void {
try {
useUserStore().logOut()
console.info('[Upgrade] 已执行升级后登出')
} catch (error) {
console.error('[Upgrade] 升级后登出失败:', error)
}
}
/**
* 执行升级流程
*/
private async executeUpgrade(
storedVersion: string,
legacyStorage: ReturnType<typeof this.findLegacyStorage>,
latestLog: UpgradeLog | null
): Promise<void> {
try {
if (!latestLog) {
console.warn('[Upgrade] 升级日志为空')
return
}
const requireReLogin = this.shouldRequireReLogin(storedVersion, latestLog)
const message = this.buildUpgradeMessage(latestLog)
// 显示升级通知
this.showUpgradeNotification(message)
// 更新版本号
this.setStoredVersion(StorageConfig.CURRENT_VERSION)
// 清理旧数据
this.cleanupLegacyData(legacyStorage.oldSysKey, legacyStorage.oldVersionKeys)
// 执行登出(如果需要)
if (requireReLogin) {
this.performLogout()
}
console.info(`[Upgrade] 升级完成: ${storedVersion} → ${StorageConfig.CURRENT_VERSION}`)
} catch (error) {
console.error('[Upgrade] 系统升级处理失败:', error)
}
}
/**
* 系统升级处理主流程
*/
async processUpgrade(): Promise<void> {
// 跳过特定版本
if (this.shouldSkipUpgrade()) {
console.debug('[Upgrade] 跳过版本升级检查')
return
}
const storedVersion = this.getStoredVersion()
// 首次访问处理
if (this.isFirstVisit(storedVersion)) {
this.setStoredVersion(StorageConfig.CURRENT_VERSION)
// console.info('[Upgrade] 首次访问,已设置当前版本')
return
}
// 版本相同,无需升级
if (this.isSameVersion(storedVersion!)) {
// console.debug('[Upgrade] 版本相同,无需升级')
return
}
// 检查是否有需要升级的旧数据
const legacyStorage = this.findLegacyStorage()
if (!legacyStorage.oldSysKey && legacyStorage.oldVersionKeys.length === 0) {
this.setStoredVersion(StorageConfig.CURRENT_VERSION)
console.info('[Upgrade] 无旧数据,已更新版本号')
return
}
// 获取最新升级日志
let latestLog: UpgradeLog | null = null
try {
const { data } = await fetchGetLatestUpgradeLog()
latestLog = data
} catch (error) {
console.error('[Upgrade] 获取升级日志失败:', error)
}
// 延迟执行升级流程,确保应用已完全加载
setTimeout(() => {
this.executeUpgrade(storedVersion!, legacyStorage, latestLog)
}, StorageConfig.UPGRADE_DELAY)
}
}
// 创建版本管理器实例
const versionManager = new VersionManager()
/**
* 系统升级处理入口函数
*/
export async function systemUpgrade(): Promise<void> {
await versionManager.processUpgrade()
}