refactor: modularize frontend flows

This commit is contained in:
Lan
2026-06-03 02:01:57 +08:00
parent 9300607f96
commit a11e7900b4
85 changed files with 4654 additions and 4363 deletions
+15 -12
View File
@@ -1,12 +1,18 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { STORAGE_KEYS } from '@/constants'
import type { AdminUser } from '@/types'
import {
clearStoredAuth,
readStoredAdminPassword,
readStoredToken,
writeStoredAdminPassword,
writeStoredToken
} from '@/utils/auth-storage'
export const useAdminStore = defineStore('admin', () => {
// 状态
const adminPassword = ref(localStorage.getItem(STORAGE_KEYS.ADMIN_PASSWORD) || '')
const token = ref(localStorage.getItem(STORAGE_KEYS.TOKEN) || '')
const adminPassword = ref(readStoredAdminPassword())
const token = ref(readStoredToken())
const isLoggedIn = ref(false)
const userInfo = ref<AdminUser | null>(null)
@@ -14,16 +20,17 @@ export const useAdminStore = defineStore('admin', () => {
const isAuthenticated = computed(() => {
return isLoggedIn.value && !!token.value
})
const hasToken = computed(() => !!token.value)
// 方法
const updateAdminPassword = (pwd: string) => {
adminPassword.value = pwd
localStorage.setItem(STORAGE_KEYS.ADMIN_PASSWORD, pwd)
writeStoredAdminPassword(pwd)
}
const setToken = (newToken: string) => {
token.value = newToken
localStorage.setItem(STORAGE_KEYS.TOKEN, newToken)
writeStoredToken(newToken)
}
const setUserInfo = (user: AdminUser) => {
@@ -42,13 +49,11 @@ export const useAdminStore = defineStore('admin', () => {
isLoggedIn.value = false
userInfo.value = null
// 清除本地存储
localStorage.removeItem(STORAGE_KEYS.ADMIN_PASSWORD)
localStorage.removeItem(STORAGE_KEYS.TOKEN)
clearStoredAuth()
}
const initAuth = () => {
const storedToken = localStorage.getItem(STORAGE_KEYS.TOKEN)
const storedToken = readStoredToken()
if (storedToken) {
token.value = storedToken
isLoggedIn.value = true
@@ -64,6 +69,7 @@ export const useAdminStore = defineStore('admin', () => {
// 计算属性
isAuthenticated,
hasToken,
// 方法
updateAdminPassword,
@@ -74,6 +80,3 @@ export const useAdminStore = defineStore('admin', () => {
initAuth
}
})
// 保持向后兼容
export const useAdminData = useAdminStore
+21
View File
@@ -2,6 +2,8 @@ import { defineStore } from 'pinia'
import type { Alert, AlertType } from '@/types'
import { TIME_CONSTANTS } from '@/constants'
let progressTimer: ReturnType<typeof setInterval> | null = null
export const useAlertStore = defineStore('alert', {
state: () => ({
alerts: [] as Alert[]
@@ -33,6 +35,25 @@ export const useAlertStore = defineStore('alert', {
this.removeAlert(id)
}
}
},
startProgressTimer() {
if (progressTimer) {
return
}
progressTimer = setInterval(() => {
this.alerts.forEach((alert) => {
this.updateAlertProgress(alert.id)
})
}, TIME_CONSTANTS.PROGRESS_UPDATE_INTERVAL)
},
stopProgressTimer() {
if (!progressTimer) {
return
}
clearInterval(progressTimer)
progressTimer = null
}
}
})
+62
View File
@@ -0,0 +1,62 @@
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import type { ConfigState } from '@/types'
import {
DEFAULT_PUBLIC_CONFIG,
readNotifyKey,
readStoredConfig,
toPublicConfig,
writeNotifyKey,
writeStoredConfig,
type PublicConfig
} from '@/utils/config-storage'
export const useConfigStore = defineStore('config', () => {
const config = ref<PublicConfig>({
...DEFAULT_PUBLIC_CONFIG,
...toPublicConfig(readStoredConfig<Partial<ConfigState>>())
})
const uploadSizeLimit = computed(() => config.value.uploadSize)
const updateConfig = (nextConfig: Partial<ConfigState>) => {
config.value = {
...DEFAULT_PUBLIC_CONFIG,
...config.value,
...toPublicConfig(nextConfig)
}
writeStoredConfig(config.value)
}
const applyRemoteConfig = (nextConfig: Partial<ConfigState>): string | null => {
updateConfig(nextConfig)
const { notify_title: notifyTitle, notify_content: notifyContent } = nextConfig
if (!notifyTitle || !notifyContent) {
return null
}
const notifyKey = notifyTitle + notifyContent
if (readNotifyKey() === notifyKey) {
return null
}
writeNotifyKey(notifyKey)
return `${notifyTitle}: ${notifyContent}`
}
const reloadStoredConfig = () => {
config.value = {
...DEFAULT_PUBLIC_CONFIG,
...toPublicConfig(readStoredConfig<Partial<ConfigState>>())
}
}
return {
config,
uploadSizeLimit,
applyRemoteConfig,
updateConfig,
reloadStoredConfig
}
})
+17 -252
View File
@@ -1,197 +1,24 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { FileInfo, UploadProgress, UploadStatus } from '@/types'
import { UPLOAD_STATUS } from '@/constants'
import { ref } from 'vue'
import type { ReceivedFileRecord, SentFileRecord } from '@/types'
export const useFileDataStore = defineStore('fileData', () => {
// 上传相关状态
const uploadStatus = ref<UploadStatus>(UPLOAD_STATUS.IDLE)
const uploadProgress = ref<UploadProgress>({
loaded: 0,
total: 0,
percentage: 0
})
const uploadedCode = ref('')
const currentFile = ref<File | null>(null)
// 下载相关状态
const downloadCode = ref('')
const fileInfo = ref<FileInfo | null>(null)
const isDownloading = ref(false)
// 文件列表状态(管理页面使用)
const fileList = ref<FileInfo[]>([])
const totalFiles = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
const isLoadingList = ref(false)
// 接收数据状态(取件记录)
const receiveData = ref<Array<{
id: number
code: string
filename: string
size: string
downloadUrl: string | null
content: string | null
date: string
}>>([])
// 分享数据状态(发送记录)
const shareData = ref<Array<{
id: number
filename: string
date: string
size: string
expiration: string
retrieveCode: string
}>>([])
// 计算属性
const isUploading = computed(() => uploadStatus.value === UPLOAD_STATUS.UPLOADING)
const isUploadSuccess = computed(() => uploadStatus.value === UPLOAD_STATUS.SUCCESS)
const isUploadError = computed(() => uploadStatus.value === UPLOAD_STATUS.ERROR)
const hasFileInfo = computed(() => fileInfo.value !== null)
const canDownload = computed(() => hasFileInfo.value && !isDownloading.value)
const totalPages = computed(() => {
return Math.ceil(totalFiles.value / pageSize.value)
})
// 上传相关方法
const setUploadStatus = (status: UploadStatus) => {
uploadStatus.value = status
}
const setUploadProgress = (progress: UploadProgress) => {
uploadProgress.value = progress
}
const setUploadedCode = (code: string) => {
uploadedCode.value = code
}
const setCurrentFile = (file: File | null) => {
currentFile.value = file
}
const resetUpload = () => {
uploadStatus.value = UPLOAD_STATUS.IDLE
uploadProgress.value = {
loaded: 0,
total: 0,
percentage: 0
}
uploadedCode.value = ''
currentFile.value = null
}
// 下载相关方法
const setDownloadCode = (code: string) => {
downloadCode.value = code
}
const setFileInfo = (info: FileInfo | null) => {
fileInfo.value = info
}
const setDownloading = (loading: boolean) => {
isDownloading.value = loading
}
const resetDownload = () => {
downloadCode.value = ''
fileInfo.value = null
isDownloading.value = false
}
// 文件列表相关方法
const setFileList = (files: FileInfo[]) => {
fileList.value = files
}
const addFile = (file: FileInfo) => {
fileList.value.unshift(file)
totalFiles.value += 1
}
const removeFile = (fileId: string) => {
const index = fileList.value.findIndex(file => file.id === fileId)
if (index > -1) {
fileList.value.splice(index, 1)
totalFiles.value -= 1
}
}
const updateFile = (fileId: string, updates: Partial<FileInfo>) => {
const index = fileList.value.findIndex(file => file.id === fileId)
if (index > -1) {
fileList.value[index] = { ...fileList.value[index], ...updates }
}
}
const setTotalFiles = (total: number) => {
totalFiles.value = total
}
const setCurrentPage = (page: number) => {
currentPage.value = page
}
const setPageSize = (size: number) => {
pageSize.value = size
}
const setLoadingList = (loading: boolean) => {
isLoadingList.value = loading
}
const resetFileList = () => {
fileList.value = []
totalFiles.value = 0
currentPage.value = 1
isLoadingList.value = false
}
const receiveData = ref<ReceivedFileRecord[]>([])
const shareData = ref<SentFileRecord[]>([])
// 添加分享数据方法
const addShareData = (data: { code: string; name?: string }) => {
setUploadedCode(data.code)
if (data.name) {
// 如果有文件名,可以创建一个临时的 FileInfo 对象
const fileInfo: FileInfo = {
id: data.code,
name: data.name,
size: 0,
type: '',
uploadTime: new Date().toISOString(),
downloadCount: 0
}
addFile(fileInfo)
}
}
// 接收数据相关方法
const addReceiveData = (data: {
id: number
code: string
filename: string
size: string
downloadUrl: string | null
content: string | null
date: string
}) => {
receiveData.value.push(data)
const addReceiveData = (record: ReceivedFileRecord) => {
receiveData.value.push(record)
}
const removeReceiveData = (id: number) => {
const index = receiveData.value.findIndex(item => item.id === id)
if (index > -1) {
const index = receiveData.value.findIndex((record) => record.id === id)
if (index !== -1) {
receiveData.value.splice(index, 1)
}
}
const deleteReceiveData = (index: number) => {
if (index > -1 && index < receiveData.value.length) {
if (index >= 0 && index < receiveData.value.length) {
receiveData.value.splice(index, 1)
}
}
@@ -199,90 +26,28 @@ export const useFileDataStore = defineStore('fileData', () => {
const clearReceiveData = () => {
receiveData.value = []
}
// 分享数据相关方法
const addShareDataRecord = (data: {
id: number
filename: string
date: string
size: string
expiration: string
retrieveCode: string
}) => {
shareData.value.push(data)
const addShareDataRecord = (record: SentFileRecord) => {
shareData.value.push(record)
}
const deleteShareData = (index: number) => {
if (index > -1 && index < shareData.value.length) {
if (index >= 0 && index < shareData.value.length) {
shareData.value.splice(index, 1)
}
}
const clearShareData = () => {
shareData.value = []
}
return {
// 上传状态
uploadStatus,
uploadProgress,
uploadedCode,
currentFile,
// 下载状态
downloadCode,
fileInfo,
isDownloading,
// 文件列表状态
fileList,
totalFiles,
currentPage,
pageSize,
isLoadingList,
// 计算属性
isUploading,
isUploadSuccess,
isUploadError,
hasFileInfo,
canDownload,
totalPages,
// 上传方法
setUploadStatus,
setUploadProgress,
setUploadedCode,
setCurrentFile,
resetUpload,
// 下载方法
setDownloadCode,
setFileInfo,
setDownloading,
resetDownload,
// 文件列表方法
setFileList,
addFile,
removeFile,
updateFile,
setTotalFiles,
setCurrentPage,
setPageSize,
setLoadingList,
resetFileList,
addShareData,
// 接收数据状态和方法
receiveData,
shareData,
addReceiveData,
removeReceiveData,
deleteReceiveData,
clearReceiveData,
// 分享数据状态和方法
shareData,
addShareDataRecord,
deleteShareData,
clearShareData