mirror of
https://github.com/jiangrui1994/CloudSaver.git
synced 2026-01-10 23:28:46 +08:00
Refactor the backend
This commit is contained in:
32
backend/src/controllers/BaseCloudController.ts
Normal file
32
backend/src/controllers/BaseCloudController.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import { BaseController } from "./BaseController";
|
||||||
|
import { ICloudStorageService } from "@/types/services";
|
||||||
|
|
||||||
|
export abstract class BaseCloudController extends BaseController {
|
||||||
|
constructor(protected cloudService: ICloudStorageService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getShareInfo(req: Request, res: Response): Promise<void> {
|
||||||
|
await this.handleRequest(req, res, async () => {
|
||||||
|
const { shareCode, receiveCode } = req.query;
|
||||||
|
await this.cloudService.setCookie(req);
|
||||||
|
return await this.cloudService.getShareInfo(shareCode as string, receiveCode as string);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFolderList(req: Request, res: Response): Promise<void> {
|
||||||
|
await this.handleRequest(req, res, async () => {
|
||||||
|
const { parentCid } = req.query;
|
||||||
|
await this.cloudService.setCookie(req);
|
||||||
|
return await this.cloudService.getFolderList(parentCid as string);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveFile(req: Request, res: Response): Promise<void> {
|
||||||
|
await this.handleRequest(req, res, async () => {
|
||||||
|
await this.cloudService.setCookie(req);
|
||||||
|
return await this.cloudService.saveSharedFile(req.body);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,13 @@ export abstract class BaseController {
|
|||||||
protected async handleRequest<T>(
|
protected async handleRequest<T>(
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
action: () => Promise<ApiResponseData<T>>
|
action: () => Promise<ApiResponseData<T> | void>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const result = await action();
|
const result = await action();
|
||||||
res.json(ApiResponse.success(result.data, result.message));
|
if (result) {
|
||||||
|
res.json(ApiResponse.success(result.data, result.message));
|
||||||
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error instanceof Error ? error.message : "未知错误";
|
const errorMessage = error instanceof Error ? error.message : "未知错误";
|
||||||
res.status(200).json(ApiResponse.error(errorMessage));
|
res.status(200).json(ApiResponse.error(errorMessage));
|
||||||
|
|||||||
@@ -1,41 +1,11 @@
|
|||||||
import { Request, Response } from "express";
|
|
||||||
import { Cloud115Service } from "../services/Cloud115Service";
|
import { Cloud115Service } from "../services/Cloud115Service";
|
||||||
import { BaseController } from "./BaseController";
|
|
||||||
import { injectable, inject } from "inversify";
|
import { injectable, inject } from "inversify";
|
||||||
import { TYPES } from "../core/types";
|
import { TYPES } from "../core/types";
|
||||||
|
import { BaseCloudController } from "./BaseCloudController";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class Cloud115Controller extends BaseController {
|
export class Cloud115Controller extends BaseCloudController {
|
||||||
constructor(@inject(TYPES.Cloud115Service) private cloud115Service: Cloud115Service) {
|
constructor(@inject(TYPES.Cloud115Service) cloud115Service: Cloud115Service) {
|
||||||
super();
|
super(cloud115Service);
|
||||||
}
|
|
||||||
|
|
||||||
async getShareInfo(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
const { shareCode, receiveCode } = req.query;
|
|
||||||
await this.cloud115Service.setCookie(req);
|
|
||||||
return await this.cloud115Service.getShareInfo(shareCode as string, receiveCode as string);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFolderList(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
const { parentCid } = req.query;
|
|
||||||
await this.cloud115Service.setCookie(req);
|
|
||||||
return await this.cloud115Service.getFolderList(parentCid as string);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async saveFile(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
const { shareCode, receiveCode, fileId, folderId } = req.body;
|
|
||||||
await this.cloud115Service.setCookie(req);
|
|
||||||
return await this.cloud115Service.saveSharedFile({
|
|
||||||
shareCode,
|
|
||||||
receiveCode,
|
|
||||||
fileId,
|
|
||||||
cid: folderId,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,34 +2,11 @@ import { Request, Response } from "express";
|
|||||||
import { injectable, inject } from "inversify";
|
import { injectable, inject } from "inversify";
|
||||||
import { TYPES } from "../core/types";
|
import { TYPES } from "../core/types";
|
||||||
import { QuarkService } from "../services/QuarkService";
|
import { QuarkService } from "../services/QuarkService";
|
||||||
import { BaseController } from "./BaseController";
|
import { BaseCloudController } from "./BaseCloudController";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class QuarkController extends BaseController {
|
export class QuarkController extends BaseCloudController {
|
||||||
constructor(@inject(TYPES.QuarkService) private quarkService: QuarkService) {
|
constructor(@inject(TYPES.QuarkService) quarkService: QuarkService) {
|
||||||
super();
|
super(quarkService);
|
||||||
}
|
|
||||||
|
|
||||||
async getShareInfo(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
const { shareCode, receiveCode } = req.query;
|
|
||||||
await this.quarkService.setCookie(req);
|
|
||||||
return await this.quarkService.getShareInfo(shareCode as string, receiveCode as string);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFolderList(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
const { parentCid } = req.query;
|
|
||||||
await this.quarkService.setCookie(req);
|
|
||||||
return await this.quarkService.getFolderList(parentCid as string);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async saveFile(req: Request, res: Response): Promise<void> {
|
|
||||||
await this.handleRequest(req, res, async () => {
|
|
||||||
await this.quarkService.setCookie(req);
|
|
||||||
return await this.quarkService.saveSharedFile(req.body);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,19 @@ export class ImageController extends BaseController {
|
|||||||
|
|
||||||
async getImages(req: Request, res: Response): Promise<void> {
|
async getImages(req: Request, res: Response): Promise<void> {
|
||||||
await this.handleRequest(req, res, async () => {
|
await this.handleRequest(req, res, async () => {
|
||||||
const url = req.query.url as string;
|
const url = decodeURIComponent((req.query.url as string) || "");
|
||||||
return await this.imageService.getImages(url);
|
const response = await this.imageService.getImages(url);
|
||||||
|
|
||||||
|
// 设置正确的响应头
|
||||||
|
res.setHeader("Content-Type", response.headers["content-type"]);
|
||||||
|
res.setHeader("Cache-Control", "no-cache");
|
||||||
|
|
||||||
|
// 确保清除任何可能导致304响应的头信息
|
||||||
|
res.removeHeader("etag");
|
||||||
|
res.removeHeader("last-modified");
|
||||||
|
|
||||||
|
// 直接传输图片数据
|
||||||
|
response.data.pipe(res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import {
|
|
||||||
ShareInfoResponse,
|
|
||||||
FolderListResponse,
|
|
||||||
SaveFileParams,
|
|
||||||
SaveFileResponse,
|
|
||||||
} from "../types/cloud";
|
|
||||||
|
|
||||||
export interface ICloudService {
|
|
||||||
getShareInfo(shareCode: string, receiveCode?: string): Promise<ShareInfoResponse>;
|
|
||||||
getFolderList(parentCid?: string): Promise<FolderListResponse>;
|
|
||||||
saveSharedFile(params: SaveFileParams): Promise<SaveFileResponse>;
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@ export const authMiddleware = async (
|
|||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
): Promise<void | Response> => {
|
): Promise<void | Response> => {
|
||||||
console.log(req.path);
|
|
||||||
if (req.path === "/user/login" || req.path === "/user/register" || req.path === "/tele-images/") {
|
if (req.path === "/user/login" || req.path === "/user/register" || req.path === "/tele-images/") {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
|
const excludePaths = ["/tele-images/"];
|
||||||
|
|
||||||
export const requestLogger = () => {
|
export const requestLogger = () => {
|
||||||
return (req: Request, res: Response, next: NextFunction) => {
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
res.on("finish", () => {
|
res.on("finish", () => {
|
||||||
|
if (excludePaths.includes(req.path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const duration = Date.now() - start;
|
const duration = Date.now() - start;
|
||||||
logger.info({
|
logger.info({
|
||||||
method: req.method,
|
method: req.method,
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import express from "express";
|
|
||||||
import { settingController } from "../controllers/setting";
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.get("/get", settingController.get);
|
|
||||||
router.post("/save", settingController.save);
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// backend/src/routes/user.ts
|
|
||||||
import express from "express";
|
|
||||||
import { userController } from "../controllers/user";
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.post("/register", userController.register);
|
|
||||||
router.post("/login", userController.login);
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { AxiosHeaders, AxiosInstance } from "axios"; // 导入 AxiosHeaders
|
import { AxiosHeaders, AxiosInstance } from "axios"; // 导入 AxiosHeaders
|
||||||
import { createAxiosInstance } from "../utils/axiosInstance";
|
import { createAxiosInstance } from "../utils/axiosInstance";
|
||||||
import { ShareInfoResponse } from "../types/cloud115";
|
import { ShareInfoResponse, FolderListResponse, SaveFileParams } from "../types/cloud";
|
||||||
import { injectable } from "inversify";
|
import { injectable } from "inversify";
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
import { ICloudService } from "../types/services";
|
import { ICloudStorageService } from "@/types/services";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
interface Cloud115ListItem {
|
interface Cloud115ListItem {
|
||||||
@@ -19,13 +19,8 @@ interface Cloud115FolderItem {
|
|||||||
ns: number;
|
ns: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Cloud115PathItem {
|
|
||||||
cid: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class Cloud115Service implements ICloudService {
|
export class Cloud115Service implements ICloudStorageService {
|
||||||
private api: AxiosInstance;
|
private api: AxiosInstance;
|
||||||
private cookie: string = "";
|
private cookie: string = "";
|
||||||
|
|
||||||
@@ -80,19 +75,21 @@ export class Cloud115Service implements ICloudService {
|
|||||||
});
|
});
|
||||||
if (response.data?.state && response.data.data?.list?.length > 0) {
|
if (response.data?.state && response.data.data?.list?.length > 0) {
|
||||||
return {
|
return {
|
||||||
data: response.data.data.list.map((item: Cloud115ListItem) => ({
|
data: {
|
||||||
fileId: item.cid,
|
list: response.data.data.list.map((item: Cloud115ListItem) => ({
|
||||||
fileName: item.n,
|
fileId: item.cid,
|
||||||
fileSize: item.s,
|
fileName: item.n,
|
||||||
})),
|
fileSize: item.s,
|
||||||
|
})),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
logger.error("未找到文件信息:", response.data);
|
||||||
|
throw new Error("未找到文件信息");
|
||||||
}
|
}
|
||||||
throw new Error("未找到文件信息");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFolderList(
|
async getFolderList(parentCid = "0"): Promise<FolderListResponse> {
|
||||||
parentCid = "0"
|
|
||||||
): Promise<{ data: { cid: string; name: string; path: Cloud115PathItem[] }[] }> {
|
|
||||||
const response = await this.api.get("/files", {
|
const response = await this.api.get("/files", {
|
||||||
params: {
|
params: {
|
||||||
aid: 1,
|
aid: 1,
|
||||||
@@ -128,17 +125,12 @@ export class Cloud115Service implements ICloudService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSharedFile(params: {
|
async saveSharedFile(params: SaveFileParams): Promise<{ message: string; data: unknown }> {
|
||||||
cid: string;
|
|
||||||
shareCode: string;
|
|
||||||
receiveCode: string;
|
|
||||||
fileId: string;
|
|
||||||
}): Promise<{ message: string; data: unknown }> {
|
|
||||||
const param = new URLSearchParams({
|
const param = new URLSearchParams({
|
||||||
cid: params.cid,
|
cid: params.folderId || "",
|
||||||
share_code: params.shareCode,
|
share_code: params.shareCode || "",
|
||||||
receive_code: params.receiveCode,
|
receive_code: params.receiveCode || "",
|
||||||
file_id: params.fileId,
|
file_id: params.fids?.[0] || "",
|
||||||
});
|
});
|
||||||
const response = await this.api.post("/share/receive", param.toString());
|
const response = await this.api.post("/share/receive", param.toString());
|
||||||
logger.info("保存文件:", response.data);
|
logger.info("保存文件:", response.data);
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import { Sequelize, QueryTypes } from "sequelize";
|
import { Sequelize, QueryTypes } from "sequelize";
|
||||||
|
import GlobalSetting from "../models/GlobalSetting";
|
||||||
|
import { Searcher } from "./Searcher";
|
||||||
|
import sequelize from "../config/database";
|
||||||
|
|
||||||
|
// 全局设置默认值
|
||||||
|
const DEFAULT_GLOBAL_SETTINGS = {
|
||||||
|
httpProxyHost: "127.0.0.1",
|
||||||
|
httpProxyPort: 7890,
|
||||||
|
isProxyEnabled: false,
|
||||||
|
CommonUserCode: 9527,
|
||||||
|
AdminUserCode: 230713,
|
||||||
|
};
|
||||||
|
|
||||||
export class DatabaseService {
|
export class DatabaseService {
|
||||||
private sequelize: Sequelize;
|
private sequelize: Sequelize;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.sequelize = new Sequelize({
|
this.sequelize = sequelize;
|
||||||
dialect: "sqlite",
|
|
||||||
storage: "./data/database.sqlite",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
@@ -16,11 +25,26 @@ export class DatabaseService {
|
|||||||
await this.cleanupBackupTables();
|
await this.cleanupBackupTables();
|
||||||
await this.sequelize.sync({ alter: true });
|
await this.sequelize.sync({ alter: true });
|
||||||
await this.sequelize.query("PRAGMA foreign_keys = ON");
|
await this.sequelize.query("PRAGMA foreign_keys = ON");
|
||||||
|
await this.initializeGlobalSettings();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`数据库初始化失败: ${(error as Error).message}`);
|
throw new Error(`数据库初始化失败: ${(error as Error).message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async initializeGlobalSettings(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const settings = await GlobalSetting.findOne();
|
||||||
|
if (!settings) {
|
||||||
|
await GlobalSetting.create(DEFAULT_GLOBAL_SETTINGS);
|
||||||
|
console.log("✅ Global settings initialized with default values.");
|
||||||
|
}
|
||||||
|
await Searcher.updateAxiosInstance();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Failed to initialize global settings:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async cleanupBackupTables(): Promise<void> {
|
private async cleanupBackupTables(): Promise<void> {
|
||||||
const backupTables = await this.sequelize.query<{ name: string }>(
|
const backupTables = await this.sequelize.query<{ name: string }>(
|
||||||
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%\\_backup%' ESCAPE '\\'",
|
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%\\_backup%' ESCAPE '\\'",
|
||||||
|
|||||||
@@ -9,34 +9,60 @@ export class ImageService {
|
|||||||
private axiosInstance: AxiosInstance | null = null;
|
private axiosInstance: AxiosInstance | null = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.initializeAxiosInstance();
|
// 移除构造函数中的初始化,改为懒加载
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initializeAxiosInstance(): Promise<void> {
|
private async ensureAxiosInstance(): Promise<AxiosInstance> {
|
||||||
const settings = await GlobalSetting.findOne();
|
if (!this.axiosInstance) {
|
||||||
const globalSetting = settings?.dataValues || ({} as GlobalSettingAttributes);
|
const settings = await GlobalSetting.findOne();
|
||||||
|
const globalSetting = settings?.dataValues || ({} as GlobalSettingAttributes);
|
||||||
|
|
||||||
this.axiosInstance = axios.create({
|
this.axiosInstance = axios.create({
|
||||||
timeout: 3000,
|
timeout: 30000,
|
||||||
httpsAgent: globalSetting.isProxyEnabled
|
headers: {
|
||||||
? tunnel.httpsOverHttp({
|
Accept: "image/*, */*",
|
||||||
proxy: {
|
"User-Agent":
|
||||||
host: globalSetting.httpProxyHost,
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
||||||
port: globalSetting.httpProxyPort,
|
},
|
||||||
headers: {
|
withCredentials: false,
|
||||||
"Proxy-Authorization": "",
|
maxRedirects: 5,
|
||||||
|
httpsAgent: globalSetting.isProxyEnabled
|
||||||
|
? tunnel.httpsOverHttp({
|
||||||
|
proxy: {
|
||||||
|
host: globalSetting.httpProxyHost,
|
||||||
|
port: globalSetting.httpProxyPort,
|
||||||
|
headers: {
|
||||||
|
"Proxy-Authorization": "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
})
|
: undefined,
|
||||||
: undefined,
|
});
|
||||||
withCredentials: true,
|
|
||||||
});
|
this.axiosInstance.interceptors.response.use(
|
||||||
|
(response) => response,
|
||||||
|
(error) => {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.axiosInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateAxiosInstance(): Promise<void> {
|
||||||
|
this.axiosInstance = null;
|
||||||
|
await this.ensureAxiosInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getImages(url: string): Promise<any> {
|
async getImages(url: string): Promise<any> {
|
||||||
if (!this.axiosInstance) {
|
const axiosInstance = await this.ensureAxiosInstance();
|
||||||
throw new Error("Axios instance not initialized");
|
|
||||||
}
|
return await axiosInstance.get(url, {
|
||||||
return await this.axiosInstance.get(url, { responseType: "stream" });
|
responseType: "stream",
|
||||||
|
validateStatus: (status) => status >= 200 && status < 300,
|
||||||
|
headers: {
|
||||||
|
Referer: new URL(url).origin,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import { createAxiosInstance } from "../utils/axiosInstance";
|
|||||||
import { injectable } from "inversify";
|
import { injectable } from "inversify";
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
|
import {
|
||||||
|
ShareInfoResponse,
|
||||||
|
FolderListResponse,
|
||||||
|
QuarkFolderItem,
|
||||||
|
SaveFileParams,
|
||||||
|
} from "../types/cloud";
|
||||||
|
import { ICloudStorageService } from "@/types/services";
|
||||||
|
|
||||||
interface QuarkShareInfo {
|
interface QuarkShareInfo {
|
||||||
stoken?: string;
|
stoken?: string;
|
||||||
@@ -17,14 +24,8 @@ interface QuarkShareInfo {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QuarkFolderItem {
|
|
||||||
fid: string;
|
|
||||||
file_name: string;
|
|
||||||
file_type: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class QuarkService {
|
export class QuarkService implements ICloudStorageService {
|
||||||
private api: AxiosInstance;
|
private api: AxiosInstance;
|
||||||
private cookie: string = "";
|
private cookie: string = "";
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ export class QuarkService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getShareInfo(pwdId: string, passcode = ""): Promise<{ data: QuarkShareInfo }> {
|
async getShareInfo(pwdId: string, passcode = ""): Promise<ShareInfoResponse> {
|
||||||
const response = await this.api.post(
|
const response = await this.api.post(
|
||||||
`/1/clouddrive/share/sharepage/token?pr=ucpro&fr=pc&uc_param_str=&__dt=994&__t=${Date.now()}`,
|
`/1/clouddrive/share/sharepage/token?pr=ucpro&fr=pc&uc_param_str=&__dt=994&__t=${Date.now()}`,
|
||||||
{
|
{
|
||||||
@@ -84,7 +85,7 @@ export class QuarkService {
|
|||||||
throw new Error("获取夸克分享信息失败");
|
throw new Error("获取夸克分享信息失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getShareList(pwdId: string, stoken: string): Promise<QuarkShareInfo> {
|
async getShareList(pwdId: string, stoken: string): Promise<ShareInfoResponse["data"]> {
|
||||||
const response = await this.api.get("/1/clouddrive/share/sharepage/detail", {
|
const response = await this.api.get("/1/clouddrive/share/sharepage/detail", {
|
||||||
params: {
|
params: {
|
||||||
pr: "ucpro",
|
pr: "ucpro",
|
||||||
@@ -125,9 +126,7 @@ export class QuarkService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFolderList(
|
async getFolderList(parentCid = "0"): Promise<FolderListResponse> {
|
||||||
parentCid = "0"
|
|
||||||
): Promise<{ data: { cid: string; name: string; path: [] }[] }> {
|
|
||||||
const response = await this.api.get("/1/clouddrive/file/sort", {
|
const response = await this.api.get("/1/clouddrive/file/sort", {
|
||||||
params: {
|
params: {
|
||||||
pr: "ucpro",
|
pr: "ucpro",
|
||||||
@@ -161,19 +160,20 @@ export class QuarkService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSharedFile(params: {
|
async saveSharedFile(params: SaveFileParams): Promise<{ message: string; data: unknown }> {
|
||||||
fid_list: string[];
|
const quarkParams = {
|
||||||
fid_token_list: string[];
|
fid_list: params.fids,
|
||||||
to_pdir_fid: string;
|
fid_token_list: params.fidTokens,
|
||||||
pwd_id: string;
|
to_pdir_fid: params.folderId,
|
||||||
stoken: string;
|
pwd_id: params.shareCode,
|
||||||
pdir_fid: string;
|
stoken: params.receiveCode,
|
||||||
scene: string;
|
pdir_fid: "0",
|
||||||
}): Promise<{ message: string; data: unknown }> {
|
scene: "link",
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
const response = await this.api.post(
|
const response = await this.api.post(
|
||||||
`/1/clouddrive/share/sharepage/save?pr=ucpro&fr=pc&uc_param_str=&__dt=208097&__t=${Date.now()}`,
|
`/1/clouddrive/share/sharepage/save?pr=ucpro&fr=pc&uc_param_str=&__dt=208097&__t=${Date.now()}`,
|
||||||
params
|
quarkParams
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -31,9 +31,12 @@ export class Searcher {
|
|||||||
Searcher.instance = this;
|
Searcher.instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initAxiosInstance() {
|
private async initAxiosInstance(isUpdate: boolean = false) {
|
||||||
const settings = await GlobalSetting.findOne();
|
let globalSetting = {} as GlobalSettingAttributes;
|
||||||
const globalSetting = settings?.dataValues || ({} as GlobalSettingAttributes);
|
if (isUpdate) {
|
||||||
|
const settings = await GlobalSetting.findOne();
|
||||||
|
globalSetting = settings?.dataValues || ({} as GlobalSettingAttributes);
|
||||||
|
}
|
||||||
this.api = createAxiosInstance(
|
this.api = createAxiosInstance(
|
||||||
config.telegram.baseUrl,
|
config.telegram.baseUrl,
|
||||||
AxiosHeaders.from({
|
AxiosHeaders.from({
|
||||||
@@ -59,9 +62,7 @@ export class Searcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async updateAxiosInstance(): Promise<void> {
|
public static async updateAxiosInstance(): Promise<void> {
|
||||||
if (Searcher.instance) {
|
await Searcher.instance.initAxiosInstance(true);
|
||||||
await Searcher.instance.initAxiosInstance();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private extractCloudLinks(text: string): { links: string[]; cloudType: string } {
|
private extractCloudLinks(text: string): { links: string[]; cloudType: string } {
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { injectable } from "inversify";
|
import { injectable, inject } from "inversify";
|
||||||
|
import { TYPES } from "../core/types";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
import GlobalSetting from "../models/GlobalSetting";
|
import GlobalSetting from "../models/GlobalSetting";
|
||||||
import { Searcher } from "./Searcher";
|
import { Searcher } from "./Searcher";
|
||||||
|
import { ImageService } from "./ImageService";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class SettingService {
|
export class SettingService {
|
||||||
|
constructor(@inject(TYPES.ImageService) private imageService: ImageService) {}
|
||||||
|
|
||||||
async getSettings(userId: string | undefined, role: number | undefined) {
|
async getSettings(userId: string | undefined, role: number | undefined) {
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
throw new Error("用户ID无效");
|
throw new Error("用户ID无效");
|
||||||
@@ -39,8 +43,17 @@ export class SettingService {
|
|||||||
if (role === 1 && globalSetting) {
|
if (role === 1 && globalSetting) {
|
||||||
await GlobalSetting.update(globalSetting, { where: {} });
|
await GlobalSetting.update(globalSetting, { where: {} });
|
||||||
}
|
}
|
||||||
|
await this.updateSettings();
|
||||||
await Searcher.updateAxiosInstance();
|
|
||||||
return { message: "保存成功" };
|
return { message: "保存成功" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateSettings(/* 参数 */): Promise<void> {
|
||||||
|
// ... 其他代码 ...
|
||||||
|
|
||||||
|
// 修改这一行,使用注入的实例方法而不是静态方法
|
||||||
|
await this.imageService.updateAxiosInstance();
|
||||||
|
await Searcher.updateAxiosInstance();
|
||||||
|
|
||||||
|
// ... 其他代码 ...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
export interface ShareInfoResponse {
|
export interface ShareInfoResponse {
|
||||||
data: {
|
data: {
|
||||||
fileId: string;
|
list: ShareInfoItem[];
|
||||||
fileName: string;
|
fileSize?: number;
|
||||||
fileSize: number;
|
pwdId?: string;
|
||||||
}[];
|
stoken?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetShareInfoParams {
|
||||||
|
shareCode: string;
|
||||||
|
receiveCode?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShareInfoItem {
|
||||||
|
fileId: string;
|
||||||
|
fileName: string;
|
||||||
|
fileSize?: number;
|
||||||
|
fileIdToken?: string;
|
||||||
|
}
|
||||||
export interface FolderListResponse {
|
export interface FolderListResponse {
|
||||||
data: {
|
data: {
|
||||||
cid: string;
|
cid: string;
|
||||||
@@ -15,13 +27,57 @@ export interface FolderListResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveFileParams {
|
export interface SaveFileParams {
|
||||||
shareCode: string;
|
shareCode: string; // 分享code
|
||||||
receiveCode?: string;
|
receiveCode?: string; // 分享文件的密码
|
||||||
fileId: string;
|
folderId?: string; // 文件夹id
|
||||||
cid?: string;
|
fids?: string[]; // 存储文件id
|
||||||
|
fidTokens?: string[]; // 存储文件token
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveFileResponse {
|
export interface SaveFileResponse {
|
||||||
message: string;
|
message: string;
|
||||||
data: unknown;
|
data: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShareFileInfo {
|
||||||
|
shareCode: string;
|
||||||
|
receiveCode?: string;
|
||||||
|
fileId: string;
|
||||||
|
cid?: string;
|
||||||
|
fid_list?: string[];
|
||||||
|
fid_token_list?: string[];
|
||||||
|
to_pdir_fid?: string;
|
||||||
|
pwd_id?: string;
|
||||||
|
stoken?: string;
|
||||||
|
pdir_fid?: string;
|
||||||
|
scene?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuarkShareFileInfo {
|
||||||
|
fid_list: string[];
|
||||||
|
fid_token_list: string[];
|
||||||
|
to_pdir_fid: string;
|
||||||
|
pwd_id: string;
|
||||||
|
stoken: string;
|
||||||
|
pdir_fid: string;
|
||||||
|
scene: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuarkShareInfo {
|
||||||
|
stoken?: string;
|
||||||
|
pwdId?: string;
|
||||||
|
fileSize?: number;
|
||||||
|
list: {
|
||||||
|
fid: string;
|
||||||
|
file_name: string;
|
||||||
|
file_type: number;
|
||||||
|
share_fid_token: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuarkFolderItem {
|
||||||
|
fid: string;
|
||||||
|
file_name: string;
|
||||||
|
file_type: number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
import { ShareInfoResponse } from "./cloud115";
|
import { ShareInfoResponse, FolderListResponse, SaveFileParams } from "./cloud";
|
||||||
|
|
||||||
export interface ICloudService {
|
export interface ICloudStorageService {
|
||||||
setCookie(req: Request): Promise<void>;
|
setCookie(req: Request): Promise<void>;
|
||||||
getShareInfo(shareCode: string, receiveCode?: string): Promise<ShareInfoResponse>;
|
getShareInfo(shareCode: string, receiveCode?: string): Promise<ShareInfoResponse>;
|
||||||
getFolderList(parentCid?: string): Promise<any>;
|
getFolderList(parentCid?: string): Promise<FolderListResponse>;
|
||||||
saveSharedFile(params: any): Promise<any>;
|
saveSharedFile(params: SaveFileParams): Promise<any>;
|
||||||
}
|
}
|
||||||
|
|||||||
21
frontend/components.d.ts
vendored
21
frontend/components.d.ts
vendored
@@ -43,27 +43,6 @@ declare module 'vue' {
|
|||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SearchBar: typeof import('./src/components/SearchBar.vue')['default']
|
SearchBar: typeof import('./src/components/SearchBar.vue')['default']
|
||||||
VanBackTop: typeof import('vant/es')['BackTop']
|
|
||||||
VanButton: typeof import('vant/es')['Button']
|
|
||||||
VanCell: typeof import('vant/es')['Cell']
|
|
||||||
VanCellGroup: typeof import('vant/es')['CellGroup']
|
|
||||||
VanCheckbox: typeof import('vant/es')['Checkbox']
|
|
||||||
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
|
|
||||||
VanEmpty: typeof import('vant/es')['Empty']
|
|
||||||
VanField: typeof import('vant/es')['Field']
|
|
||||||
VanForm: typeof import('vant/es')['Form']
|
|
||||||
VanIcon: typeof import('vant/es')['Icon']
|
|
||||||
VanImage: typeof import('vant/es')['Image']
|
|
||||||
VanLoading: typeof import('vant/es')['Loading']
|
|
||||||
VanOverlay: typeof import('vant/es')['Overlay']
|
|
||||||
VanPopup: typeof import('vant/es')['Popup']
|
|
||||||
VanSearch: typeof import('vant/es')['Search']
|
|
||||||
VanSwitch: typeof import('vant/es')['Switch']
|
|
||||||
VanTab: typeof import('vant/es')['Tab']
|
|
||||||
VanTabbar: typeof import('vant/es')['Tabbar']
|
|
||||||
VanTabbarItem: typeof import('vant/es')['TabbarItem']
|
|
||||||
VanTabs: typeof import('vant/es')['Tabs']
|
|
||||||
VanTag: typeof import('vant/es')['Tag']
|
|
||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
export interface ComponentCustomProperties {
|
||||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import type { ShareInfoResponse, Folder, Save115FileParams } from "@/types";
|
import type { ShareInfoResponse, Folder, SaveFileParams, GetShareInfoParams } from "@/types";
|
||||||
|
|
||||||
export const cloud115Api = {
|
export const cloud115Api = {
|
||||||
async getShareInfo(shareCode: string, receiveCode = "") {
|
async getShareInfo(params: GetShareInfoParams) {
|
||||||
const { data } = await request.get<ShareInfoResponse>("/api/cloud115/share-info", {
|
const { data } = await request.get<ShareInfoResponse>("/api/cloud115/share-info", {
|
||||||
params: { shareCode, receiveCode },
|
params,
|
||||||
});
|
});
|
||||||
return data as ShareInfoResponse;
|
return data as ShareInfoResponse;
|
||||||
},
|
},
|
||||||
@@ -16,7 +16,7 @@ export const cloud115Api = {
|
|||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveFile(params: Save115FileParams) {
|
async saveFile(params: SaveFileParams) {
|
||||||
const res = await request.post("/api/cloud115/save", params);
|
const res = await request.post("/api/cloud115/save", params);
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import type { ShareInfoResponse, Folder, SaveQuarkFileParams } from "@/types";
|
import type { ShareInfoResponse, Folder, SaveFileParams, GetShareInfoParams } from "@/types";
|
||||||
|
|
||||||
export const quarkApi = {
|
export const quarkApi = {
|
||||||
async getShareInfo(shareCode: string, receiveCode = "") {
|
async getShareInfo(params: GetShareInfoParams) {
|
||||||
const { data } = await request.get<ShareInfoResponse>("/api/quark/share-info", {
|
const { data } = await request.get<ShareInfoResponse>("/api/quark/share-info", {
|
||||||
params: { shareCode, receiveCode },
|
params,
|
||||||
});
|
});
|
||||||
return data as ShareInfoResponse;
|
return data as ShareInfoResponse;
|
||||||
},
|
},
|
||||||
@@ -16,7 +16,7 @@ export const quarkApi = {
|
|||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveFile(params: SaveQuarkFileParams) {
|
async saveFile(params: SaveFileParams) {
|
||||||
return await request.post("/api/quark/save", params);
|
return await request.post("/api/quark/save", params);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import { quarkApi } from "@/api/quark";
|
|||||||
import type {
|
import type {
|
||||||
Resource,
|
Resource,
|
||||||
ShareInfoResponse,
|
ShareInfoResponse,
|
||||||
Save115FileParams,
|
|
||||||
SaveQuarkFileParams,
|
|
||||||
ShareInfo,
|
ShareInfo,
|
||||||
ResourceItem,
|
ResourceItem,
|
||||||
|
GetShareInfoParams,
|
||||||
|
SaveFileParams,
|
||||||
|
ShareFileInfoAndFolder,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
@@ -24,46 +25,40 @@ const lastResource = (
|
|||||||
) as StorageListObject;
|
) as StorageListObject;
|
||||||
|
|
||||||
// 定义云盘驱动配置类型
|
// 定义云盘驱动配置类型
|
||||||
interface CloudDriveConfig<
|
interface CloudDriveConfig {
|
||||||
T extends Record<string, string>,
|
|
||||||
P extends Save115FileParams | SaveQuarkFileParams,
|
|
||||||
> {
|
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
regex: RegExp;
|
regex: RegExp;
|
||||||
api: {
|
api: {
|
||||||
getShareInfo: (parsedCode: T) => Promise<ShareInfoResponse>;
|
getShareInfo: (params: GetShareInfoParams) => Promise<ShareInfoResponse>;
|
||||||
saveFile: (params: P) => Promise<{ code: number; message?: string }>;
|
saveFile: (params: SaveFileParams) => Promise<{ code: number; message?: string }>;
|
||||||
};
|
};
|
||||||
parseShareCode: (match: RegExpMatchArray) => T;
|
parseShareCode: (match: RegExpMatchArray) => GetShareInfoParams;
|
||||||
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => P;
|
getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => SaveFileParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 云盘类型配置
|
// 云盘类型配置
|
||||||
export const CLOUD_DRIVES: [
|
export const CLOUD_DRIVES: CloudDriveConfig[] = [
|
||||||
CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams>,
|
|
||||||
CloudDriveConfig<{ shareCode: string }, SaveQuarkFileParams>,
|
|
||||||
] = [
|
|
||||||
{
|
{
|
||||||
name: "115网盘",
|
name: "115网盘",
|
||||||
type: "pan115",
|
type: "pan115",
|
||||||
regex: /(?:115|anxia|115cdn)\.com\/s\/([^?]+)(?:\?password=([^&#]+))?/,
|
regex: /(?:115|anxia|115cdn)\.com\/s\/([^?]+)(?:\?password=([^&#]+))?/,
|
||||||
api: {
|
api: {
|
||||||
getShareInfo: (parsedCode: { shareCode: string; receiveCode: string }) =>
|
getShareInfo: (params: GetShareInfoParams) => cloud115Api.getShareInfo(params),
|
||||||
cloud115Api.getShareInfo(parsedCode.shareCode, parsedCode.receiveCode),
|
saveFile: async (params: SaveFileParams) => {
|
||||||
saveFile: async (params: Save115FileParams) => {
|
return await cloud115Api.saveFile(params);
|
||||||
return await cloud115Api.saveFile(params as Save115FileParams);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
parseShareCode: (match: RegExpMatchArray) => ({
|
parseShareCode: (match: RegExpMatchArray) => ({
|
||||||
shareCode: match[1],
|
shareCode: match[1],
|
||||||
receiveCode: match[2] || "",
|
receiveCode: match[2] || "",
|
||||||
}),
|
}),
|
||||||
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => ({
|
getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => ({
|
||||||
shareCode: shareInfo.shareCode || "",
|
shareCode: shareInfoAndFolder.shareCode || "",
|
||||||
receiveCode: shareInfo.receiveCode || "",
|
receiveCode: shareInfoAndFolder.receiveCode || "",
|
||||||
fileId: shareInfo.list[0].fileId,
|
fileId: shareInfoAndFolder.shareInfo.list[0].fileId,
|
||||||
folderId,
|
folderId: shareInfoAndFolder.folderId,
|
||||||
|
fids: shareInfoAndFolder.shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -71,23 +66,20 @@ export const CLOUD_DRIVES: [
|
|||||||
type: "quark",
|
type: "quark",
|
||||||
regex: /pan\.quark\.cn\/s\/([a-zA-Z0-9]+)/,
|
regex: /pan\.quark\.cn\/s\/([a-zA-Z0-9]+)/,
|
||||||
api: {
|
api: {
|
||||||
getShareInfo: (parsedCode: { shareCode: string }) =>
|
getShareInfo: (params) => quarkApi.getShareInfo(params),
|
||||||
quarkApi.getShareInfo(parsedCode.shareCode),
|
saveFile: async (params: SaveFileParams) => {
|
||||||
saveFile: async (params: SaveQuarkFileParams) => {
|
return await quarkApi.saveFile(params);
|
||||||
return await quarkApi.saveFile(params as SaveQuarkFileParams);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
parseShareCode: (match: RegExpMatchArray) => ({ shareCode: match[1] }),
|
parseShareCode: (match: RegExpMatchArray) => ({ shareCode: match[1] }),
|
||||||
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => ({
|
getSaveParams: (shareInfoAndFolder: ShareFileInfoAndFolder) => ({
|
||||||
fid_list: shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""),
|
fids: shareInfoAndFolder.shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""),
|
||||||
fid_token_list: shareInfo.list.map(
|
fidTokens: shareInfoAndFolder.shareInfo.list.map(
|
||||||
(item: { fileIdToken?: string }) => item.fileIdToken || ""
|
(item: { fileIdToken?: string }) => item.fileIdToken || ""
|
||||||
),
|
),
|
||||||
to_pdir_fid: folderId,
|
folderId: shareInfoAndFolder.folderId,
|
||||||
pwd_id: shareInfo.shareCode || "",
|
shareCode: shareInfoAndFolder.shareInfo.pwdId || "",
|
||||||
stoken: shareInfo.stoken || "",
|
receiveCode: shareInfoAndFolder.shareInfo.stoken || "",
|
||||||
pdir_fid: "0",
|
|
||||||
scene: "link",
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -189,39 +181,32 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
async saveResourceToDrive(
|
async saveResourceToDrive(
|
||||||
resource: ResourceItem,
|
resource: ResourceItem,
|
||||||
folderId: string,
|
folderId: string,
|
||||||
drive:
|
drive: CloudDriveConfig
|
||||||
| CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams>
|
|
||||||
| CloudDriveConfig<{ shareCode: string }, SaveQuarkFileParams>
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const link = resource.cloudLinks.find((link) => drive.regex.test(link));
|
const link = resource.cloudLinks.find((link) => drive.regex.test(link));
|
||||||
if (!link) return;
|
if (!link) return;
|
||||||
|
|
||||||
const match = link.match(drive.regex);
|
const match = link.match(drive.regex);
|
||||||
if (!match) throw new Error("链接解析失败");
|
if (!match) throw new Error("链接解析失败");
|
||||||
|
const parsedCode = drive.parseShareCode(match);
|
||||||
|
|
||||||
const shareInfo = {
|
const shareInfo = {
|
||||||
...this.shareInfo,
|
...this.shareInfo,
|
||||||
list: this.resourceSelect.filter((x) => x.isChecked),
|
list: this.resourceSelect.filter((x) => x.isChecked),
|
||||||
};
|
};
|
||||||
|
console.log(shareInfo);
|
||||||
|
|
||||||
if (this.is115Drive(drive)) {
|
const params = drive.getSaveParams({
|
||||||
const params = drive.getSaveParams(shareInfo, folderId);
|
shareInfo,
|
||||||
const result = await drive.api.saveFile(params);
|
...parsedCode,
|
||||||
|
folderId,
|
||||||
|
});
|
||||||
|
const result = await drive.api.saveFile(params);
|
||||||
|
|
||||||
if (result.code === 0) {
|
if (result.code === 0) {
|
||||||
ElMessage.success(`${drive.name} 转存成功`);
|
ElMessage.success(`${drive.name} 转存成功`);
|
||||||
} else {
|
|
||||||
ElMessage.error(result.message);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const params = drive.getSaveParams(shareInfo, folderId);
|
ElMessage.error(result.message);
|
||||||
const result = await drive.api.saveFile(params);
|
|
||||||
|
|
||||||
if (result.code === 0) {
|
|
||||||
ElMessage.success(`${drive.name} 转存成功`);
|
|
||||||
} else {
|
|
||||||
ElMessage.error(result.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -237,18 +222,7 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
if (!match) throw new Error("链接解析失败");
|
if (!match) throw new Error("链接解析失败");
|
||||||
|
|
||||||
const parsedCode = matchedDrive.parseShareCode(match);
|
const parsedCode = matchedDrive.parseShareCode(match);
|
||||||
let shareInfo = this.is115Drive(matchedDrive)
|
const shareInfo = await matchedDrive.api.getShareInfo(parsedCode);
|
||||||
? await matchedDrive.api.getShareInfo(
|
|
||||||
parsedCode as { shareCode: string; receiveCode: string }
|
|
||||||
)
|
|
||||||
: await matchedDrive.api.getShareInfo(parsedCode as { shareCode: string });
|
|
||||||
|
|
||||||
if (Array.isArray(shareInfo)) {
|
|
||||||
shareInfo = {
|
|
||||||
list: shareInfo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shareInfo?.list?.length) {
|
if (shareInfo?.list?.length) {
|
||||||
this.resources = [
|
this.resources = [
|
||||||
{
|
{
|
||||||
@@ -296,30 +270,14 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
if (!match) throw new Error("链接解析失败");
|
if (!match) throw new Error("链接解析失败");
|
||||||
|
|
||||||
const parsedCode = drive.parseShareCode(match);
|
const parsedCode = drive.parseShareCode(match);
|
||||||
let shareInfo = {} as ShareInfoResponse;
|
|
||||||
this.setLoadTree(true);
|
this.setLoadTree(true);
|
||||||
if (this.is115Drive(drive)) {
|
let shareInfo = await drive.api.getShareInfo(parsedCode);
|
||||||
shareInfo = await drive.api.getShareInfo(
|
|
||||||
parsedCode as { shareCode: string; receiveCode: string }
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
shareInfo = this.is115Drive(drive)
|
|
||||||
? await drive.api.getShareInfo(parsedCode as { shareCode: string; receiveCode: string })
|
|
||||||
: await drive.api.getShareInfo(parsedCode as { shareCode: string });
|
|
||||||
}
|
|
||||||
this.setLoadTree(false);
|
this.setLoadTree(false);
|
||||||
if (shareInfo) {
|
if (shareInfo) {
|
||||||
if (Array.isArray(shareInfo)) {
|
shareInfo = {
|
||||||
shareInfo = {
|
...shareInfo,
|
||||||
list: shareInfo,
|
...parsedCode,
|
||||||
...parsedCode,
|
};
|
||||||
};
|
|
||||||
} else {
|
|
||||||
shareInfo = {
|
|
||||||
...shareInfo,
|
|
||||||
...parsedCode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.shareInfo = shareInfo;
|
this.shareInfo = shareInfo;
|
||||||
this.setSelectedResource(this.shareInfo.list.map((x) => ({ ...x, isChecked: true })));
|
this.setSelectedResource(this.shareInfo.list.map((x) => ({ ...x, isChecked: true })));
|
||||||
return true;
|
return true;
|
||||||
@@ -334,13 +292,5 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
console.error(message, error);
|
console.error(message, error);
|
||||||
ElMessage.error(error instanceof Error ? error.message : message);
|
ElMessage.error(error instanceof Error ? error.message : message);
|
||||||
},
|
},
|
||||||
|
|
||||||
is115Drive(
|
|
||||||
drive:
|
|
||||||
| CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams>
|
|
||||||
| CloudDriveConfig<{ shareCode: string }, SaveQuarkFileParams>
|
|
||||||
): drive is CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams> {
|
|
||||||
return drive.type === "pan115";
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,13 +33,25 @@ export interface ShareInfo {
|
|||||||
isChecked?: boolean;
|
isChecked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShareInfoItem {
|
||||||
|
fileId: string;
|
||||||
|
fileName: string;
|
||||||
|
fileSize?: number;
|
||||||
|
fileIdToken?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ShareInfoResponse {
|
export interface ShareInfoResponse {
|
||||||
list: ShareInfo[];
|
list: ShareInfoItem[];
|
||||||
|
fileSize?: number;
|
||||||
pwdId?: string;
|
pwdId?: string;
|
||||||
stoken?: string;
|
stoken?: string;
|
||||||
shareCode?: string;
|
}
|
||||||
|
|
||||||
|
export interface ShareFileInfoAndFolder {
|
||||||
|
shareInfo: ShareInfoResponse;
|
||||||
|
folderId: string;
|
||||||
|
shareCode: string;
|
||||||
receiveCode?: string;
|
receiveCode?: string;
|
||||||
fileSize?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Folder {
|
export interface Folder {
|
||||||
@@ -49,10 +61,16 @@ export interface Folder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SaveFileParams {
|
export interface SaveFileParams {
|
||||||
|
shareCode: string; // 分享code
|
||||||
|
receiveCode?: string; // 分享文件的密码
|
||||||
|
folderId: string; // 文件夹id
|
||||||
|
fids: string[]; // 存储文件id
|
||||||
|
fidTokens?: string[]; // 存储文件token
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetShareInfoParams {
|
||||||
shareCode: string;
|
shareCode: string;
|
||||||
receiveCode: string;
|
receiveCode?: string;
|
||||||
fileId: string;
|
|
||||||
folderId: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiResponse<T = unknown> {
|
export interface ApiResponse<T = unknown> {
|
||||||
|
|||||||
Reference in New Issue
Block a user