返回 AiToEarn
utils.ts
根目录 / project / aitoearn-web / src / store / plugin / utils.ts
1 /**
2 * 浏览器插件相关工具函数
3 */
4
5 import type { ProgressEvent } from '@/store'
6 import { PluginStatus } from '@/store'
7 import { PLUGIN_STATUS_I18N_KEY, PUBLISH_STAGE_I18N_KEY } from './constants'
8
9 /**
10 * 获取插件状态的国际化 key
11 * @param status 插件状态
12 * @returns i18n key
13 */
14 export function getPluginStatusI18nKey(status: PluginStatus): string {
15 return PLUGIN_STATUS_I18N_KEY[status] || 'plugin:status.unknown'
16 }
17
18 /**
19 * 获取发布阶段的国际化 key
20 * @param stage 发布阶段
21 * @returns i18n key
22 */
23 export function getPublishStageI18nKey(stage: ProgressEvent['stage']): string {
24 return PUBLISH_STAGE_I18N_KEY[stage] || stage
25 }
26
27 /**
28 * 判断插件是否已就绪(已安装且已授权)
29 * @param status 插件状态
30 * @returns 是否已就绪
31 */
32 export function isPluginReady(status: PluginStatus): boolean {
33 return status === PluginStatus.READY
34 }
35
36 /**
37 * 判断插件是否已连接(兼容旧代码,等同于 isPluginReady)
38 * @param status 插件状态
39 * @returns 是否已连接
40 */
41 export function isPluginConnected(status: PluginStatus): boolean {
42 return status === PluginStatus.READY
43 }
44
45 /**
46 * 判断插件是否已安装但未授权
47 * @param status 插件状态
48 * @returns 是否已安装未授权
49 */
50 export function isPluginInstalledNoPermission(status: PluginStatus): boolean {
51 return status === PluginStatus.INSTALLED_NO_PERMISSION
52 }
53
54 /**
55 * 判断插件是否未安装
56 * @param status 插件状态
57 * @returns 是否未安装
58 */
59 export function isPluginNotInstalled(status: PluginStatus): boolean {
60 return status === PluginStatus.NOT_INSTALLED || status === PluginStatus.UNKNOWN
61 }
62
63 /**
64 * 格式化进度百分比
65 * @param progress 进度值(0-100)
66 * @returns 格式化的百分比文本
67 */
68 export function formatProgress(progress: number): string {
69 return `${Math.round(progress)}%`
70 }
71
72 /**
73 * 格式化文件大小
74 * @param bytes 字节数
75 * @returns 格式化的文件大小
76 */
77 export function formatFileSize(bytes: number): string {
78 if (bytes === 0)
79 return '0 B'
80
81 const k = 1024
82 const sizes = ['B', 'KB', 'MB', 'GB']
83 const i = Math.floor(Math.log(bytes) / Math.log(k))
84
85 return `${(bytes / k ** i).toFixed(2)} ${sizes[i]}`
86 }
87
88 /**
89 * 验证文件类型
90 * @param file 文件对象
91 * @param acceptTypes 接受的文件类型数组
92 * @returns 是否有效
93 */
94 export function validateFileType(file: File, acceptTypes: string[]): boolean {
95 return acceptTypes.some((type) => {
96 if (type.endsWith('/*')) {
97 const prefix = type.slice(0, -2)
98 return file.type.startsWith(prefix)
99 }
100 return file.type === type
101 })
102 }
103
104 /**
105 * 验证视频文件
106 * @param file 文件对象
107 * @returns 是否是有效的视频文件
108 */
109 export function isValidVideoFile(file: File): boolean {
110 return validateFileType(file, [
111 'video/mp4',
112 'video/mpeg',
113 'video/quicktime',
114 'video/x-msvideo',
115 'video/x-ms-wmv',
116 ])
117 }
118
119 /**
120 * 验证图片文件
121 * @param file 文件对象
122 * @returns 是否是有效的图片文件
123 */
124 export function isValidImageFile(file: File): boolean {
125 return validateFileType(file, ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/jpg'])
126 }
127
128 /**
129 * 验证文件大小
130 * @param file 文件对象
131 * @param maxSize 最大大小(字节)
132 * @returns 是否在限制内
133 */
134 export function validateFileSize(file: File, maxSize: number): boolean {
135 return file.size <= maxSize
136 }
137
138 /**
139 * 创建带重试的异步函数
140 * @param fn 异步函数
141 * @param maxRetries 最大重试次数
142 * @param delay 重试延迟(毫秒)
143 * @returns 包装后的函数
144 */
145 export function withRetry<T>(fn: () => Promise<T>, maxRetries = 3, delay = 1000): () => Promise<T> {
146 return async () => {
147 let lastError: any
148
149 for (let i = 0; i < maxRetries; i++) {
150 try {
151 return await fn()
152 }
153 catch (error) {
154 lastError = error
155
156 if (i < maxRetries - 1) {
157 await new Promise(resolve => setTimeout(resolve, delay))
158 }
159 }
160 }
161
162 throw lastError
163 }
164 }
165
165 lines TYPESCRIPT