ng / frontend /src /stores /resource.ts
epii-1
222222
f0953a4
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<ShareInfoResponse>;
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<void> {
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<void> {
const savePromises: Promise<void>[] = [];
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<void> {
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<void> {
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<boolean> {
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);
},
},
});