import { defineStore } from "pinia"; import { cloud115Api } from "@/api/cloud115"; import { resourceApi } from "@/api/resource"; import { quarkApi } from "@/api/quark"; import type { Resource, ShareInfoResponse, ShareInfo, ResourceItem, GetShareInfoParams, SaveFileParams, ShareFileInfoAndFolder, } from "@/types"; import { ElMessage } from "element-plus"; interface StorageListObject { list: Resource[]; lastUpdateTime?: string; } const lastResource = ( localStorage.getItem("last_resource_list") ? JSON.parse(localStorage.getItem("last_resource_list") as string) : { list: [] } ) as StorageListObject; // 定义云盘驱动配置类型 interface CloudDriveConfig { name: string; type: string; regex: RegExp; api: { getShareInfo: (params: GetShareInfoParams) => Promise; saveFile: (params: SaveFileParams) => Promise<{ code: number; message?: string }>; }; parseShareCode: (match: RegExpMatchArray) => GetShareInfoParams; getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => SaveFileParams; } // 云盘类型配置 export const CLOUD_DRIVES: CloudDriveConfig[] = [ { name: "115网盘", type: "pan115", regex: /(?:115|anxia|115cdn)\.com\/s\/([^?]+)(?:\?password=([^&#]+))?/, api: { getShareInfo: (params: GetShareInfoParams) => cloud115Api.getShareInfo(params), saveFile: async (params: SaveFileParams) => { return await cloud115Api.saveFile(params); }, }, parseShareCode: (match: RegExpMatchArray) => ({ shareCode: match[1], receiveCode: match[2] || "", }), getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => ({ shareCode: shareInfoAndFolder.shareCode || "", receiveCode: shareInfoAndFolder.receiveCode || "", fileId: shareInfoAndFolder.shareInfo.list[0].fileId, folderId: shareInfoAndFolder.folderId, fids: shareInfoAndFolder.shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""), }), }, { name: "夸克网盘", type: "quark", regex: /pan\.quark\.cn\/s\/([a-zA-Z0-9]+)/, api: { getShareInfo: (params) => quarkApi.getShareInfo(params), saveFile: async (params: SaveFileParams) => { return await quarkApi.saveFile(params); }, }, parseShareCode: (match: RegExpMatchArray) => ({ shareCode: match[1] }), getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => ({ fids: shareInfoAndFolder.shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""), fidTokens: shareInfoAndFolder.shareInfo.list.map( (item: { fileIdToken?: string }) => item.fileIdToken || "" ), folderId: shareInfoAndFolder.folderId, shareCode: shareInfoAndFolder.shareInfo.pwdId || "", receiveCode: shareInfoAndFolder.shareInfo.stoken || "", }), }, ]; export const useResourceStore = defineStore("resource", { state: () => ({ tagColor: { baiduPan: "primary", weiyun: "info", aliyun: "warning", pan115: "danger", quark: "success", }, keyword: "", resources: lastResource.list, lastUpdateTime: lastResource.lastUpdateTime || "", shareInfo: {} as ShareInfoResponse, resourceSelect: [] as ShareInfo[], loading: false, backupPlan: false, loadTree: false, }), actions: { setLoadTree(loadTree: boolean) { this.loadTree = loadTree; }, // 搜索资源 async searchResources(keyword?: string, isLoadMore = false, channelId?: string): Promise { this.loading = true; if (!isLoadMore) this.resources = []; try { let lastMessageId = ""; if (isLoadMore) { const list = this.resources.find((x) => x.id === channelId)?.list || []; lastMessageId = list[list.length - 1].messageId || ""; if (list[list.length - 1].isLastMessage) { ElMessage.warning("没有更多了~"); return; } if (!lastMessageId) { ElMessage.error("当次搜索源不支持加载更多"); return; } keyword = this.keyword; } let { data = [] } = await resourceApi.search(keyword || "", channelId, lastMessageId); this.keyword = keyword || ""; data = data .filter((item) => item.list.length > 0) .map((x) => ({ ...x, list: x.list.map((item) => ({ ...item, isSupportSave: CLOUD_DRIVES.some((drive) => drive.regex.test(item.cloudLinks[0])), })), })); console.log(data); if (isLoadMore) { const findedIndex = this.resources.findIndex((item) => item.id === data[0]?.id); if (findedIndex !== -1) { this.resources[findedIndex].list.push(...data[0].list); } if (data.length === 0) { const list = this.resources.find((item) => item.id === channelId)?.list; list && list[list.length - 1] && (list[list.length - 1]!.isLastMessage = true); ElMessage.warning("没有更多了~"); } } else { this.resources = data.map((item, index) => ({ ...item, displayList: index === 0 })); if (!keyword) { // 获取当前时间字符串 用于存储到本地 this.lastUpdateTime = new Date().toLocaleString(); localStorage.setItem( "last_resource_list", JSON.stringify({ list: this.resources, lastUpdateTime: this.lastUpdateTime }) ); } if (this.resources.length === 0) { ElMessage.warning("未搜索到相关资源"); } } } catch (error) { console.log(error); this.handleError("搜索失败,请重试", null); } finally { this.loading = false; } }, // 设置选择资源 async setSelectedResource(resourceSelect: ShareInfo[]) { this.resourceSelect = resourceSelect; }, // 转存资源 async saveResource(resource: ResourceItem, folderId: string): Promise { const savePromises: Promise[] = []; CLOUD_DRIVES.forEach((drive) => { if (resource.cloudLinks.some((link) => drive.regex.test(link))) { savePromises.push(this.saveResourceToDrive(resource, folderId, drive)); } }); await Promise.all(savePromises); }, // 保存资源到网盘 async saveResourceToDrive( resource: ResourceItem, folderId: string, drive: CloudDriveConfig ): Promise { const link = resource.cloudLinks.find((link) => drive.regex.test(link)); if (!link) return; const match = link.match(drive.regex); if (!match) throw new Error("链接解析失败"); const parsedCode = drive.parseShareCode(match); const shareInfo = { ...this.shareInfo, list: this.resourceSelect.filter((x) => x.isChecked), }; console.log(shareInfo); const params = drive.getSaveParams({ shareInfo, ...parsedCode, folderId, }); const result = await drive.api.saveFile(params); if (result.code === 0) { ElMessage.success(`${drive.name} 转存成功`); } else { ElMessage.error(result.message); } }, // 解析云盘链接 async parsingCloudLink(url: string): Promise { this.loading = true; this.resources = []; try { const matchedDrive = CLOUD_DRIVES.find((drive) => drive.regex.test(url)); if (!matchedDrive) throw new Error("不支持的网盘链接"); const match = url.match(matchedDrive.regex); if (!match) throw new Error("链接解析失败"); const parsedCode = matchedDrive.parseShareCode(match); const shareInfo = await matchedDrive.api.getShareInfo(parsedCode); if (shareInfo?.list?.length) { this.resources = [ { id: "", channelInfo: { name: "自定义搜索", channelLogo: "", channelId: "", }, displayList: true, list: [ { id: "1", title: shareInfo.list.map((item) => item.fileName).join(", "), cloudLinks: [url], cloudType: matchedDrive.type, channel: matchedDrive.name, pubDate: "", isSupportSave: true, }, ], }, ]; } else { throw new Error("解析失败,请检查链接是否正确"); } } catch (error) { this.handleError("解析失败,请重试", error); } finally { this.loading = false; } }, // 获取资源列表并选择 async getResourceListAndSelect(resource: ResourceItem): Promise { this.setSelectedResource([]); const { cloudType } = resource; const drive = CLOUD_DRIVES.find((x) => x.type === cloudType); if (!drive) { return false; } const link = resource.cloudLinks.find((link) => drive.regex.test(link)); if (!link) return false; const match = link.match(drive.regex); if (!match) throw new Error("链接解析失败"); const parsedCode = drive.parseShareCode(match); this.setLoadTree(true); let shareInfo = await drive.api.getShareInfo(parsedCode); console.log(shareInfo); this.setLoadTree(false); if (shareInfo) { shareInfo = { ...shareInfo, ...parsedCode, }; this.shareInfo = shareInfo; this.setSelectedResource(this.shareInfo.list.map((x) => ({ ...x, isChecked: true }))); return true; } else { ElMessage.error("获取资源信息失败,请先检查cookie!"); return false; } }, // 统一错误处理 handleError(message: string, error: unknown): void { console.error(message, error); ElMessage.error(error instanceof Error ? error.message : message); }, }, });