mirror of
https://github.com/jiangrui1994/CloudSaver.git
synced 2026-01-10 07:08:46 +08:00
format:format and fix code
This commit is contained in:
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
coverage
|
||||||
57
.eslintrc.js
Normal file
57
.eslintrc.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
ignorePatterns: ["node_modules", "dist", "build", "coverage"],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
},
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
plugins: ["@typescript-eslint"],
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
|
||||||
|
"@typescript-eslint/explicit-function-return-type": 0,
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["frontend/**/*.{js,ts,vue}"],
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
},
|
||||||
|
parser: "vue-eslint-parser",
|
||||||
|
parserOptions: {
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:vue/vue3-recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
],
|
||||||
|
plugins: ["@typescript-eslint", "vue"],
|
||||||
|
rules: {
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
"vue/require-default-prop": "off",
|
||||||
|
"vue/no-v-html": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["backend/**/*.{js,ts}"],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/explicit-function-return-type": 0,
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -25,3 +25,6 @@ node_modules
|
|||||||
# 系统文件
|
# 系统文件
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
# 版本控制
|
||||||
|
.git
|
||||||
14
.prettierrc.js
Normal file
14
.prettierrc.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
module.exports = {
|
||||||
|
semi: true,
|
||||||
|
trailingComma: "es5",
|
||||||
|
singleQuote: false,
|
||||||
|
printWidth: 100,
|
||||||
|
tabWidth: 2,
|
||||||
|
useTabs: false,
|
||||||
|
endOfLine: "auto",
|
||||||
|
arrowParens: "always",
|
||||||
|
bracketSpacing: true,
|
||||||
|
embeddedLanguageFormatting: "auto",
|
||||||
|
htmlWhitespaceSensitivity: "css",
|
||||||
|
vueIndentScriptAndStyle: false,
|
||||||
|
};
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": false,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"printWidth": 100,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"arrowParens": "always",
|
|
||||||
"vueIndentScriptAndStyle": true
|
|
||||||
}
|
|
||||||
@@ -38,7 +38,7 @@ app.use((req, res, next) => {
|
|||||||
|
|
||||||
app.use("/", routes);
|
app.use("/", routes);
|
||||||
|
|
||||||
const initializeGlobalSettings = async () => {
|
const initializeGlobalSettings = async (): Promise<void> => {
|
||||||
const settings = await GlobalSetting.findOne();
|
const settings = await GlobalSetting.findOne();
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
await GlobalSetting.create({
|
await GlobalSetting.create({
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
import { Cloud115Service } from "../services/Cloud115Service";
|
import { Cloud115Service } from "../services/Cloud115Service";
|
||||||
import { sendSuccess, sendError } from "../utils/response";
|
import { sendSuccess, sendError } from "../utils/response";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
|
|
||||||
const cloud115 = new Cloud115Service();
|
const cloud115 = new Cloud115Service();
|
||||||
const setCookie = async (req: Request) => {
|
const setCookie = async (req: Request): Promise<void> => {
|
||||||
const userId = req.user?.userId;
|
const userId = req.user?.userId;
|
||||||
const userSetting = await UserSetting.findOne({
|
const userSetting = await UserSetting.findOne({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
});
|
});
|
||||||
console.log(userSetting?.dataValues.cloud115Cookie);
|
|
||||||
if (userSetting && userSetting.dataValues.cloud115Cookie) {
|
if (userSetting && userSetting.dataValues.cloud115Cookie) {
|
||||||
cloud115.setCookie(userSetting.dataValues.cloud115Cookie);
|
cloud115.setCookie(userSetting.dataValues.cloud115Cookie);
|
||||||
} else {
|
} else {
|
||||||
@@ -18,7 +17,7 @@ const setCookie = async (req: Request) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const cloud115Controller = {
|
export const cloud115Controller = {
|
||||||
async getShareInfo(req: Request, res: Response, next: NextFunction) {
|
async getShareInfo(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { shareCode, receiveCode } = req.query;
|
const { shareCode, receiveCode } = req.query;
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
@@ -30,7 +29,7 @@ export const cloud115Controller = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async getFolderList(req: Request, res: Response, next: NextFunction) {
|
async getFolderList(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { parentCid } = req.query;
|
const { parentCid } = req.query;
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
@@ -41,7 +40,7 @@ export const cloud115Controller = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveFile(req: Request, res: Response, next: NextFunction) {
|
async saveFile(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { shareCode, receiveCode, fileId, folderId } = req.body;
|
const { shareCode, receiveCode, fileId, folderId } = req.body;
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
import DoubanService from "../services/DoubanService";
|
import DoubanService from "../services/DoubanService";
|
||||||
import { sendSuccess, sendError } from "../utils/response";
|
import { sendSuccess, sendError } from "../utils/response";
|
||||||
|
|
||||||
const doubanService = new DoubanService();
|
const doubanService = new DoubanService();
|
||||||
|
|
||||||
export const doubanController = {
|
export const doubanController = {
|
||||||
async getDoubanHotList(req: Request, res: Response, next: NextFunction) {
|
async getDoubanHotList(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { type = "movie", tag = "热门", page_limit = "50", page_start = "0" } = req.query;
|
const { type = "movie", tag = "热门", page_limit = "50", page_start = "0" } = req.query;
|
||||||
const result = await doubanService.getHotList({
|
const result = await doubanService.getHotList({
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
import { QuarkService } from "../services/QuarkService";
|
import { QuarkService } from "../services/QuarkService";
|
||||||
import { sendSuccess, sendError } from "../utils/response";
|
import { sendSuccess, sendError } from "../utils/response";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
|
|
||||||
const quark = new QuarkService();
|
const quark = new QuarkService();
|
||||||
|
|
||||||
const setCookie = async (req: Request) => {
|
const setCookie = async (req: Request): Promise<void> => {
|
||||||
const userId = req.user?.userId;
|
const userId = req.user?.userId;
|
||||||
const userSetting = await UserSetting.findOne({
|
const userSetting = await UserSetting.findOne({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
@@ -18,7 +18,7 @@ const setCookie = async (req: Request) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const quarkController = {
|
export const quarkController = {
|
||||||
async getShareInfo(req: Request, res: Response, next: NextFunction) {
|
async getShareInfo(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { pwdId, passcode } = req.query;
|
const { pwdId, passcode } = req.query;
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
@@ -29,7 +29,7 @@ export const quarkController = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async getFolderList(req: Request, res: Response, next: NextFunction) {
|
async getFolderList(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { parentCid } = req.query;
|
const { parentCid } = req.query;
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
@@ -40,7 +40,7 @@ export const quarkController = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveFile(req: Request, res: Response, next: NextFunction) {
|
async saveFile(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await setCookie(req);
|
await setCookie(req);
|
||||||
const result = await quark.saveSharedFile(req.body);
|
const result = await quark.saveSharedFile(req.body);
|
||||||
|
|||||||
@@ -1,22 +1,9 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
import { RSSSearcher } from "../services/RSSSearcher";
|
|
||||||
import Searcher from "../services/Searcher";
|
import Searcher from "../services/Searcher";
|
||||||
import { sendSuccess, sendError } from "../utils/response";
|
import { sendSuccess, sendError } from "../utils/response";
|
||||||
|
|
||||||
export const resourceController = {
|
export const resourceController = {
|
||||||
async rssSearch(req: Request, res: Response, next: NextFunction) {
|
async search(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
|
||||||
const { keyword } = req.query;
|
|
||||||
const searcher = new RSSSearcher();
|
|
||||||
const result = await searcher.searchAll(keyword as string);
|
|
||||||
sendSuccess(res, result);
|
|
||||||
} catch (error) {
|
|
||||||
sendError(res, {
|
|
||||||
message: (error as Error).message || "RSS 搜索失败",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async search(req: Request, res: Response, next: NextFunction) {
|
|
||||||
try {
|
try {
|
||||||
const { keyword, channelId = "", lastMessageId = "" } = req.query; // Remove `: string` from here
|
const { keyword, channelId = "", lastMessageId = "" } = req.query; // Remove `: string` from here
|
||||||
const result = await Searcher.searchAll(
|
const result = await Searcher.searchAll(
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
import { sendSuccess, sendError } from "../utils/response";
|
import { sendSuccess, sendError } from "../utils/response";
|
||||||
import Searcher from "../services/Searcher";
|
import Searcher from "../services/Searcher";
|
||||||
import UserSetting from "../models/UserSetting";
|
import UserSetting from "../models/UserSetting";
|
||||||
import GlobalSetting from "../models/GlobalSetting";
|
import GlobalSetting from "../models/GlobalSetting";
|
||||||
|
|
||||||
export const settingController = {
|
export const settingController = {
|
||||||
async get(req: Request, res: Response) {
|
async get(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const userId = req.user?.userId;
|
const userId = req.user?.userId;
|
||||||
const role = req.user?.role;
|
const role = req.user?.role;
|
||||||
@@ -36,7 +36,7 @@ export const settingController = {
|
|||||||
sendError(res, { message: (error as Error).message || "获取设置失败" });
|
sendError(res, { message: (error as Error).message || "获取设置失败" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async save(req: Request, res: Response) {
|
async save(req: Request, res: Response): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const userId = req.user?.userId;
|
const userId = req.user?.userId;
|
||||||
const role = req.user?.role;
|
const role = req.user?.role;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export class ImageControll {
|
|||||||
this.initializeAxiosInstance();
|
this.initializeAxiosInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initializeAxiosInstance(isUpdate = false) {
|
private async initializeAxiosInstance(isUpdate = false): Promise<void> {
|
||||||
let settings = null;
|
let settings = null;
|
||||||
if (isUpdate) {
|
if (isUpdate) {
|
||||||
settings = await GlobalSetting.findOne();
|
settings = await GlobalSetting.findOne();
|
||||||
@@ -35,7 +35,7 @@ export class ImageControll {
|
|||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async getImages(req: Request, res: Response, url: string) {
|
async getImages(req: Request, res: Response, url: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (!this.isUpdate) await this.initializeAxiosInstance(true);
|
if (!this.isUpdate) await this.initializeAxiosInstance(true);
|
||||||
const response = await this.axiosInstance?.get(url, { responseType: "stream" });
|
const response = await this.axiosInstance?.get(url, { responseType: "stream" });
|
||||||
@@ -50,7 +50,7 @@ export class ImageControll {
|
|||||||
const iamgesInstance = new ImageControll();
|
const iamgesInstance = new ImageControll();
|
||||||
|
|
||||||
export const imageControll = {
|
export const imageControll = {
|
||||||
getImages: async (req: Request, res: Response) => {
|
getImages: async (req: Request, res: Response): Promise<void> => {
|
||||||
const url = req.query.url as string;
|
const url = req.query.url as string;
|
||||||
iamgesInstance.getImages(req, res, url);
|
iamgesInstance.getImages(req, res, url);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const isValidInput = (input: string): boolean => {
|
|||||||
return regex.test(input);
|
return regex.test(input);
|
||||||
};
|
};
|
||||||
export const userController = {
|
export const userController = {
|
||||||
async register(req: Request, res: Response) {
|
async register(req: Request, res: Response): Promise<void> {
|
||||||
const { username, password, registerCode } = req.body;
|
const { username, password, registerCode } = req.body;
|
||||||
const globalSetting = await GlobalSetting.findOne();
|
const globalSetting = await GlobalSetting.findOne();
|
||||||
const registerCodeList = [
|
const registerCodeList = [
|
||||||
@@ -39,12 +39,12 @@ export const userController = {
|
|||||||
data: user,
|
data: user,
|
||||||
message: "用户注册成功",
|
message: "用户注册成功",
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error) {
|
||||||
sendError(res, { message: error.message || "用户注册失败" });
|
sendError(res, { message: (error as Error).message || "用户注册失败" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async login(req: Request, res: Response) {
|
async login(req: Request, res: Response): Promise<void> {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
const user = await User.findOne({ where: { username } });
|
const user = await User.findOne({ where: { username } });
|
||||||
if (!user || !(await bcrypt.compare(password, user.password))) {
|
if (!user || !(await bcrypt.compare(password, user.password))) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const authMiddleware = async (
|
|||||||
req: AuthenticatedRequest,
|
req: AuthenticatedRequest,
|
||||||
res: Response,
|
res: Response,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
) => {
|
): Promise<void | Response> => {
|
||||||
if (req.path === "/user/login" || req.path === "/user/register") {
|
if (req.path === "/user/login" || req.path === "/user/register") {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
|
interface CustomError extends Error {
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const errorHandler = (err: CustomError, req: Request, res: Response): void => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
res.status(err.status || 500).json({
|
res.status(err.status || 500).json({
|
||||||
success: false,
|
success: false,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
|
|
||||||
export const validateRequest = (requiredParams: string[]) => {
|
export const validateRequest = (
|
||||||
|
requiredParams: string[]
|
||||||
|
): ((req: Request, res: Response, next: NextFunction) => Response | void) => {
|
||||||
return (req: Request, res: Response, next: NextFunction) => {
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
const missingParams = requiredParams.filter((param) => !req.query[param] && !req.body[param]);
|
const missingParams = requiredParams.filter((param) => !req.query[param] && !req.body[param]);
|
||||||
if (missingParams.length > 0) {
|
if (missingParams.length > 0) {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ router.use("/setting", settingRoutes);
|
|||||||
|
|
||||||
// 资源搜索
|
// 资源搜索
|
||||||
router.get("/search", resourceController.search);
|
router.get("/search", resourceController.search);
|
||||||
router.get("/rssSearch", resourceController.rssSearch);
|
|
||||||
|
|
||||||
// 115网盘相关
|
// 115网盘相关
|
||||||
router.get("/cloud115/share-info", cloud115Controller.getShareInfo);
|
router.get("/cloud115/share-info", cloud115Controller.getShareInfo);
|
||||||
|
|||||||
@@ -4,6 +4,23 @@ import { Logger } from "../utils/logger";
|
|||||||
import { config } from "../config/index";
|
import { config } from "../config/index";
|
||||||
import { ShareInfoResponse } from "../types/cloud115";
|
import { ShareInfoResponse } from "../types/cloud115";
|
||||||
|
|
||||||
|
interface Cloud115ListItem {
|
||||||
|
cid: string;
|
||||||
|
n: string;
|
||||||
|
s: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cloud115FolderItem {
|
||||||
|
cid: string;
|
||||||
|
n: string;
|
||||||
|
ns: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Cloud115PathItem {
|
||||||
|
cid: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class Cloud115Service {
|
export class Cloud115Service {
|
||||||
private api: AxiosInstance;
|
private api: AxiosInstance;
|
||||||
private cookie: string = "";
|
private cookie: string = "";
|
||||||
@@ -39,7 +56,7 @@ export class Cloud115Service {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCookie(cookie: string) {
|
public setCookie(cookie: string): void {
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +73,7 @@ export class Cloud115Service {
|
|||||||
|
|
||||||
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: any) => ({
|
data: response.data.data.list.map((item: Cloud115ListItem) => ({
|
||||||
fileId: item.cid,
|
fileId: item.cid,
|
||||||
fileName: item.n,
|
fileName: item.n,
|
||||||
fileSize: item.s,
|
fileSize: item.s,
|
||||||
@@ -66,7 +83,9 @@ export class Cloud115Service {
|
|||||||
throw new Error("未找到文件信息");
|
throw new Error("未找到文件信息");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFolderList(parentCid = "0") {
|
async getFolderList(
|
||||||
|
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,
|
||||||
@@ -87,8 +106,8 @@ export class Cloud115Service {
|
|||||||
if (response.data?.state) {
|
if (response.data?.state) {
|
||||||
return {
|
return {
|
||||||
data: response.data.data
|
data: response.data.data
|
||||||
.filter((item: any) => item.cid && !!item.ns)
|
.filter((item: Cloud115FolderItem) => item.cid && !!item.ns)
|
||||||
.map((folder: any) => ({
|
.map((folder: Cloud115FolderItem) => ({
|
||||||
cid: folder.cid,
|
cid: folder.cid,
|
||||||
name: folder.n,
|
name: folder.n,
|
||||||
path: response.data.path,
|
path: response.data.path,
|
||||||
@@ -105,7 +124,7 @@ export class Cloud115Service {
|
|||||||
shareCode: string;
|
shareCode: string;
|
||||||
receiveCode: string;
|
receiveCode: string;
|
||||||
fileId: string;
|
fileId: string;
|
||||||
}) {
|
}): Promise<{ message: string; data: unknown }> {
|
||||||
const param = new URLSearchParams({
|
const param = new URLSearchParams({
|
||||||
cid: params.cid,
|
cid: params.cid,
|
||||||
user_id: config.cloud115.userId,
|
user_id: config.cloud115.userId,
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import { AxiosHeaders, AxiosInstance } from "axios";
|
import { AxiosHeaders, AxiosInstance } from "axios";
|
||||||
import { createAxiosInstance } from "../utils/axiosInstance";
|
import { createAxiosInstance } from "../utils/axiosInstance";
|
||||||
|
|
||||||
|
interface DoubanSubject {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
rate: string;
|
||||||
|
cover: string;
|
||||||
|
url: string;
|
||||||
|
is_new: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
class DoubanService {
|
class DoubanService {
|
||||||
private baseUrl: string;
|
private baseUrl: string;
|
||||||
private api: AxiosInstance;
|
private api: AxiosInstance;
|
||||||
@@ -28,7 +37,12 @@ class DoubanService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHotList(params: { type: string; tag: string; page_limit: string; page_start: string }) {
|
async getHotList(params: {
|
||||||
|
type: string;
|
||||||
|
tag: string;
|
||||||
|
page_limit: string;
|
||||||
|
page_start: string;
|
||||||
|
}): Promise<{ data: DoubanSubject[] }> {
|
||||||
try {
|
try {
|
||||||
const response = await this.api.get("/search_subjects", {
|
const response = await this.api.get("/search_subjects", {
|
||||||
params: params,
|
params: params,
|
||||||
|
|||||||
@@ -2,6 +2,23 @@ import { AxiosInstance, AxiosHeaders } from "axios";
|
|||||||
import { Logger } from "../utils/logger";
|
import { Logger } from "../utils/logger";
|
||||||
import { createAxiosInstance } from "../utils/axiosInstance";
|
import { createAxiosInstance } from "../utils/axiosInstance";
|
||||||
|
|
||||||
|
interface QuarkShareInfo {
|
||||||
|
stoken?: string;
|
||||||
|
pwdId?: string;
|
||||||
|
list: {
|
||||||
|
fid: string;
|
||||||
|
file_name: string;
|
||||||
|
file_type: number;
|
||||||
|
share_fid_token: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuarkFolderItem {
|
||||||
|
fid: string;
|
||||||
|
file_name: string;
|
||||||
|
file_type: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class QuarkService {
|
export class QuarkService {
|
||||||
private api: AxiosInstance;
|
private api: AxiosInstance;
|
||||||
private cookie: string = "";
|
private cookie: string = "";
|
||||||
@@ -34,11 +51,11 @@ export class QuarkService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCookie(cookie: string) {
|
public setCookie(cookie: string): void {
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getShareInfo(pwdId: string, passcode = "") {
|
async getShareInfo(pwdId: string, passcode = ""): Promise<{ data: QuarkShareInfo }> {
|
||||||
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()}`,
|
||||||
{
|
{
|
||||||
@@ -49,7 +66,7 @@ export class QuarkService {
|
|||||||
if (response.data?.status === 200 && response.data.data) {
|
if (response.data?.status === 200 && response.data.data) {
|
||||||
const fileInfo = response.data.data;
|
const fileInfo = response.data.data;
|
||||||
if (fileInfo.stoken) {
|
if (fileInfo.stoken) {
|
||||||
let res = await this.getShareList(pwdId, fileInfo.stoken);
|
const res = await this.getShareList(pwdId, fileInfo.stoken);
|
||||||
return {
|
return {
|
||||||
data: res,
|
data: res,
|
||||||
};
|
};
|
||||||
@@ -58,7 +75,7 @@ export class QuarkService {
|
|||||||
throw new Error("获取夸克分享信息失败");
|
throw new Error("获取夸克分享信息失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getShareList(pwdId: string, stoken: string) {
|
async getShareList(pwdId: string, stoken: string): Promise<QuarkShareInfo> {
|
||||||
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",
|
||||||
@@ -80,8 +97,8 @@ export class QuarkService {
|
|||||||
});
|
});
|
||||||
if (response.data?.data) {
|
if (response.data?.data) {
|
||||||
const list = response.data.data.list
|
const list = response.data.data.list
|
||||||
.filter((item: any) => item.fid)
|
.filter((item: QuarkShareInfo["list"][0]) => item.fid)
|
||||||
.map((folder: any) => ({
|
.map((folder: QuarkShareInfo["list"][0]) => ({
|
||||||
fileId: folder.fid,
|
fileId: folder.fid,
|
||||||
fileName: folder.file_name,
|
fileName: folder.file_name,
|
||||||
fileIdToken: folder.share_fid_token,
|
fileIdToken: folder.share_fid_token,
|
||||||
@@ -89,7 +106,7 @@ export class QuarkService {
|
|||||||
return {
|
return {
|
||||||
list,
|
list,
|
||||||
pwdId,
|
pwdId,
|
||||||
stoken: stoken,
|
stoken,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@@ -98,7 +115,9 @@ export class QuarkService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFolderList(parentCid = "0") {
|
async getFolderList(
|
||||||
|
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",
|
||||||
@@ -116,8 +135,8 @@ export class QuarkService {
|
|||||||
});
|
});
|
||||||
if (response.data?.data && response.data.data.list) {
|
if (response.data?.data && response.data.data.list) {
|
||||||
const data = response.data.data.list
|
const data = response.data.data.list
|
||||||
.filter((item: any) => item.fid && item.file_type === 0)
|
.filter((item: QuarkFolderItem) => item.fid && item.file_type === 0)
|
||||||
.map((folder: any) => ({
|
.map((folder: QuarkFolderItem) => ({
|
||||||
cid: folder.fid,
|
cid: folder.fid,
|
||||||
name: folder.file_name,
|
name: folder.file_name,
|
||||||
path: [],
|
path: [],
|
||||||
@@ -140,7 +159,7 @@ export class QuarkService {
|
|||||||
stoken: string;
|
stoken: string;
|
||||||
pdir_fid: string;
|
pdir_fid: string;
|
||||||
scene: string;
|
scene: string;
|
||||||
}) {
|
}): Promise<{ message: string; data: unknown }> {
|
||||||
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()}`,
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
import RSSParser from "rss-parser";
|
|
||||||
import { AxiosInstance, AxiosHeaders } from "axios";
|
|
||||||
import { config } from "../config";
|
|
||||||
import { Logger } from "../utils/logger";
|
|
||||||
import { createAxiosInstance } from "../utils/axiosInstance";
|
|
||||||
import { data } from "cheerio/dist/commonjs/api/attributes";
|
|
||||||
|
|
||||||
interface RSSItem {
|
|
||||||
title?: string;
|
|
||||||
link?: string;
|
|
||||||
pubDate?: string;
|
|
||||||
content?: string;
|
|
||||||
description?: string;
|
|
||||||
image?: string;
|
|
||||||
cloudLinks?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RSSSearcher {
|
|
||||||
private parser: RSSParser;
|
|
||||||
private axiosInstance: AxiosInstance;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.parser = new RSSParser({
|
|
||||||
customFields: {
|
|
||||||
item: [
|
|
||||||
["content:encoded", "content"],
|
|
||||||
["description", "description"],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.axiosInstance = createAxiosInstance(
|
|
||||||
config.rss.baseUrl,
|
|
||||||
AxiosHeaders.from({
|
|
||||||
"User-Agent":
|
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
||||||
Accept: "application/xml,application/xhtml+xml,text/html,application/rss+xml",
|
|
||||||
}),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extractCloudLinks(text: string): { links: string[]; cloudType: string } {
|
|
||||||
const links: string[] = [];
|
|
||||||
let cloudType = "";
|
|
||||||
Object.values(config.cloudPatterns).forEach((pattern, index) => {
|
|
||||||
const matches = text.match(pattern);
|
|
||||||
if (matches) {
|
|
||||||
links.push(...matches);
|
|
||||||
cloudType = Object.keys(config.cloudPatterns)[index];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
links: [...new Set(links)],
|
|
||||||
cloudType,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchAll(keyword: string) {
|
|
||||||
const allResults = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < config.rss.channels.length; i++) {
|
|
||||||
const channel = config.rss.channels[i];
|
|
||||||
try {
|
|
||||||
const rssUrl = `${config.rss.baseUrl}/${
|
|
||||||
channel.id
|
|
||||||
}${keyword ? `/searchQuery=${encodeURIComponent(keyword)}` : ""}`;
|
|
||||||
|
|
||||||
const results = await this.searchInRSSFeed(rssUrl);
|
|
||||||
if (results.items.length > 0) {
|
|
||||||
const channelResults = results.items
|
|
||||||
.filter((item: RSSItem) => item.cloudLinks && item.cloudLinks.length > 0)
|
|
||||||
.map((item: RSSItem) => ({
|
|
||||||
...item,
|
|
||||||
channel: channel.name + "(" + channel.id + ")",
|
|
||||||
}));
|
|
||||||
|
|
||||||
allResults.push(...channelResults);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(`搜索频道 ${channel.name} 失败:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: allResults,
|
|
||||||
message: "搜索成功",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchInRSSFeed(rssUrl: string) {
|
|
||||||
try {
|
|
||||||
const response = await this.axiosInstance.get(rssUrl);
|
|
||||||
const feed = await this.parser.parseString(response.data);
|
|
||||||
|
|
||||||
return {
|
|
||||||
items: feed.items.map((item: RSSItem) => {
|
|
||||||
const linkInfo = this.extractCloudLinks(item.content || item.description || "");
|
|
||||||
return {
|
|
||||||
title: item.title || "",
|
|
||||||
link: item.link || "",
|
|
||||||
pubDate: item.pubDate || "",
|
|
||||||
image: item.image || "",
|
|
||||||
cloudLinks: linkInfo.links,
|
|
||||||
cloudType: linkInfo.cloudType,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(`RSS源解析错误: ${rssUrl}`, error);
|
|
||||||
return {
|
|
||||||
items: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,7 @@ export class Searcher {
|
|||||||
this.initializeAxiosInstance();
|
this.initializeAxiosInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initializeAxiosInstance(isUpdate = false) {
|
private async initializeAxiosInstance(isUpdate = false): Promise<void> {
|
||||||
let settings = null;
|
let settings = null;
|
||||||
if (isUpdate) {
|
if (isUpdate) {
|
||||||
settings = await GlobalSetting.findOne();
|
settings = await GlobalSetting.findOne();
|
||||||
@@ -78,7 +78,6 @@ export class Searcher {
|
|||||||
|
|
||||||
async searchAll(keyword: string, channelId?: string, messageId?: string) {
|
async searchAll(keyword: string, channelId?: string, messageId?: string) {
|
||||||
const allResults = [];
|
const allResults = [];
|
||||||
const totalChannels = config.rss.channels.length;
|
|
||||||
|
|
||||||
const channelList = channelId
|
const channelList = channelId
|
||||||
? config.rss.channels.filter((channel) => channel.id === channelId)
|
? config.rss.channels.filter((channel) => channel.id === channelId)
|
||||||
@@ -90,7 +89,7 @@ export class Searcher {
|
|||||||
const messageIdparams = messageId ? `before=${messageId}` : "";
|
const messageIdparams = messageId ? `before=${messageId}` : "";
|
||||||
const url = `/${channel.id}${keyword ? `?q=${encodeURIComponent(keyword)}&${messageIdparams}` : `?${messageIdparams}`}`;
|
const url = `/${channel.id}${keyword ? `?q=${encodeURIComponent(keyword)}&${messageIdparams}` : `?${messageIdparams}`}`;
|
||||||
console.log(`Searching in channel ${channel.name} with URL: ${url}`);
|
console.log(`Searching in channel ${channel.name} with URL: ${url}`);
|
||||||
const results = await this.searchInWeb(url, channel.id);
|
const results = await this.searchInWeb(url);
|
||||||
console.log(`Found ${results.items.length} items in channel ${channel.name}`);
|
console.log(`Found ${results.items.length} items in channel ${channel.name}`);
|
||||||
if (results.items.length > 0) {
|
if (results.items.length > 0) {
|
||||||
const channelResults = results.items
|
const channelResults = results.items
|
||||||
@@ -120,7 +119,7 @@ export class Searcher {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchInWeb(url: string, channelId: string) {
|
async searchInWeb(url: string) {
|
||||||
try {
|
try {
|
||||||
if (!this.axiosInstance) {
|
if (!this.axiosInstance) {
|
||||||
throw new Error("Axios instance is not initialized");
|
throw new Error("Axios instance is not initialized");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
|
|
||||||
declare module "express" {
|
declare module "express" {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import axios, { AxiosInstance, AxiosRequestHeaders } from "axios";
|
import axios, { AxiosInstance, AxiosRequestHeaders } from "axios";
|
||||||
import tunnel from "tunnel";
|
import tunnel from "tunnel";
|
||||||
import { config } from "../config";
|
|
||||||
import GlobalSetting from "../models/GlobalSetting";
|
|
||||||
|
|
||||||
interface ProxyConfig {
|
interface ProxyConfig {
|
||||||
host: string;
|
host: string;
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
import { Response, NextFunction } from "express";
|
import { Response, NextFunction } from "express";
|
||||||
import { Logger } from "../utils/logger";
|
import { Logger } from "../utils/logger";
|
||||||
|
|
||||||
|
interface CustomError {
|
||||||
|
name?: string;
|
||||||
|
message: string;
|
||||||
|
success?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default function handleError(
|
export default function handleError(
|
||||||
res: Response,
|
res: Response,
|
||||||
error: any,
|
error: CustomError | unknown,
|
||||||
message: string,
|
message: string,
|
||||||
next: NextFunction
|
next: NextFunction
|
||||||
) {
|
) {
|
||||||
|
|||||||
2
frontend/auto-imports.d.ts
vendored
2
frontend/auto-imports.d.ts
vendored
@@ -5,5 +5,5 @@
|
|||||||
// Generated by unplugin-auto-import
|
// Generated by unplugin-auto-import
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
const ElMessage: (typeof import("element-plus/es"))["ElMessage"]
|
||||||
}
|
}
|
||||||
|
|||||||
5
frontend/components.d.ts
vendored
5
frontend/components.d.ts
vendored
@@ -13,8 +13,6 @@ declare module 'vue' {
|
|||||||
ElBacktop: typeof import('element-plus/es')['ElBacktop']
|
ElBacktop: typeof import('element-plus/es')['ElBacktop']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCheckbox: (typeof import("element-plus/es"))["ElCheckbox"]
|
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
|
||||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
@@ -30,8 +28,6 @@ declare module 'vue' {
|
|||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
|
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
|
||||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
@@ -43,7 +39,6 @@ declare module 'vue' {
|
|||||||
ElTree: typeof import('element-plus/es')['ElTree']
|
ElTree: typeof import('element-plus/es')['ElTree']
|
||||||
FolderSelect: typeof import('./src/components/Home/FolderSelect.vue')['default']
|
FolderSelect: typeof import('./src/components/Home/FolderSelect.vue')['default']
|
||||||
ResourceCard: typeof import('./src/components/Home/ResourceCard.vue')['default']
|
ResourceCard: typeof import('./src/components/Home/ResourceCard.vue')['default']
|
||||||
ResourceList: typeof import('./src/components/Home/ResourceList.vue')['default']
|
|
||||||
ResourceTable: typeof import('./src/components/Home/ResourceTable.vue')['default']
|
ResourceTable: typeof import('./src/components/Home/ResourceTable.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
>
|
>
|
||||||
<template v-for="menu in menuList">
|
<template v-for="menu in menuList">
|
||||||
<el-sub-menu :index="menu.index" v-if="menu.children">
|
<el-sub-menu v-if="menu.children" :key="menu.index" :index="menu.index">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon><component :is="menu.icon" /></el-icon>
|
<el-icon><component :is="menu.icon" /></el-icon>
|
||||||
<span>{{ menu.title }}</span>
|
<span>{{ menu.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-for="child in menu.children"
|
v-for="child in menu.children"
|
||||||
:index="child.index"
|
|
||||||
:key="child.index"
|
:key="child.index"
|
||||||
|
:index="child.index"
|
||||||
@click="handleMenuClick(child)"
|
@click="handleMenuClick(child)"
|
||||||
>
|
>
|
||||||
{{ child.title }}
|
{{ child.title }}
|
||||||
@@ -28,9 +28,10 @@
|
|||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-else
|
v-else
|
||||||
|
:key="menu.router"
|
||||||
:index="menu.index"
|
:index="menu.index"
|
||||||
@click="handleMenuClick(menu)"
|
|
||||||
:disabled="menu.disabled"
|
:disabled="menu.disabled"
|
||||||
|
@click="handleMenuClick(menu)"
|
||||||
>
|
>
|
||||||
<el-icon><component :is="menu.icon" /></el-icon>
|
<el-icon><component :is="menu.icon" /></el-icon>
|
||||||
<span>{{ menu.title }}</span>
|
<span>{{ menu.title }}</span>
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
interface MenuItem {
|
interface MenuItem {
|
||||||
index: string;
|
index: string;
|
||||||
title: string;
|
title: string;
|
||||||
icon?: any;
|
icon?: typeof Search | typeof Film | typeof Setting;
|
||||||
router?: string;
|
router?: string;
|
||||||
children?: MenuItem[];
|
children?: MenuItem[];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@@ -100,7 +101,6 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
const currentMenu = computed(() => {
|
const currentMenu = computed(() => {
|
||||||
console.log("route", decodeURIComponent(route.fullPath));
|
|
||||||
return menuList
|
return menuList
|
||||||
.reduce((pre: MenuItem[], cur: MenuItem) => {
|
.reduce((pre: MenuItem[], cur: MenuItem) => {
|
||||||
if (!cur.children) {
|
if (!cur.children) {
|
||||||
@@ -114,20 +114,14 @@
|
|||||||
});
|
});
|
||||||
const currentMenuOpen = computed(() => {
|
const currentMenuOpen = computed(() => {
|
||||||
if (currentMenu.value && currentMenu.value.index.length > 1) {
|
if (currentMenu.value && currentMenu.value.index.length > 1) {
|
||||||
console.log([currentMenu.value.index.split("-")[0]]);
|
|
||||||
return [currentMenu.value.index.split("-")[0]];
|
return [currentMenu.value.index.split("-")[0]];
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const handleOpen = (key: string, keyPath: string[]) => {
|
const handleOpen = (_key: string, _keyPath: string[]): void => {};
|
||||||
console.log(key, keyPath);
|
const handleClose = (_key: string, _keyPath: string[]): void => {};
|
||||||
};
|
const handleMenuClick = (menu: MenuItem): void => {
|
||||||
const handleClose = (key: string, keyPath: string[]) => {
|
|
||||||
console.log(key, keyPath);
|
|
||||||
};
|
|
||||||
const handleMenuClick = (menu: any) => {
|
|
||||||
console.log(menu);
|
|
||||||
if (menu.router) {
|
if (menu.router) {
|
||||||
router.push(menu.router);
|
router.push(menu.router);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
node-key="cid"
|
node-key="cid"
|
||||||
:load="loadNode"
|
:load="loadNode"
|
||||||
lazy
|
lazy
|
||||||
@node-click="handleNodeClick"
|
|
||||||
highlight-current
|
highlight-current
|
||||||
|
@node-click="handleNodeClick"
|
||||||
>
|
>
|
||||||
<template #default="{ node }">
|
<template #default="{ node }">
|
||||||
<span class="folder-node">
|
<span class="folder-node">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
><ArrowDown
|
><ArrowDown
|
||||||
/></el-icon>
|
/></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-item-list" v-show="group.displayList">
|
<div v-show="group.displayList" class="card-item-list">
|
||||||
<div v-for="resource in group.list" :key="resource.messageId" class="card-item-content">
|
<div v-for="resource in group.list" :key="resource.messageId" class="card-item-content">
|
||||||
<el-card class="card-item">
|
<el-card class="card-item">
|
||||||
<el-image
|
<el-image
|
||||||
@@ -28,12 +28,12 @@
|
|||||||
><div class="item-name">{{ resource.title }}</div></el-link
|
><div class="item-name">{{ resource.title }}</div></el-link
|
||||||
>
|
>
|
||||||
<div class="item-description" v-html="resource.content"></div>
|
<div class="item-description" v-html="resource.content"></div>
|
||||||
<div class="tags-list" v-if="resource.tags && resource.tags.length">
|
<div v-if="resource.tags && resource.tags.length" class="tags-list">
|
||||||
<span>标签:</span>
|
<span>标签:</span>
|
||||||
<el-tag
|
<el-tag
|
||||||
v-for="item in resource.tags"
|
v-for="item in resource.tags"
|
||||||
class="resource_tag"
|
|
||||||
:key="item"
|
:key="item"
|
||||||
|
class="resource_tag"
|
||||||
@click="searchMovieforTag(item)"
|
@click="searchMovieforTag(item)"
|
||||||
>
|
>
|
||||||
{{ item }}
|
{{ item }}
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="load-more" v-show="group.displayList">
|
<div v-show="group.displayList" class="load-more">
|
||||||
<el-button @click="handleLoadMore(group.id)"> 加载更多 </el-button>
|
<el-button @click="handleLoadMore(group.id)"> 加载更多 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
<el-table-column label="图片" width="180">
|
<el-table-column label="图片" width="180">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-image
|
<el-image
|
||||||
class="table-item-image"
|
|
||||||
v-if="row.image"
|
v-if="row.image"
|
||||||
|
class="table-item-image"
|
||||||
:src="`/tele-images/?url=${encodeURIComponent(row.image as string)}`"
|
:src="`/tele-images/?url=${encodeURIComponent(row.image as string)}`"
|
||||||
hide-on-click-modal
|
hide-on-click-modal
|
||||||
:preview-src-list="[
|
:preview-src-list="[
|
||||||
@@ -42,17 +42,17 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="title" label="描述">
|
<el-table-column prop="title" label="描述">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div v-html="row.content" class="item-description"></div>
|
<div class="item-description" v-html="row.content"></div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="tags" label="标签">
|
<el-table-column prop="tags" label="标签">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="tags-list" v-if="row.tags.length > 0">
|
<div v-if="row.tags.length > 0" class="tags-list">
|
||||||
<span>标签:</span>
|
<span>标签:</span>
|
||||||
<el-tag
|
<el-tag
|
||||||
v-for="item in row.tags"
|
v-for="item in row.tags"
|
||||||
class="resource_tag"
|
|
||||||
:key="item"
|
:key="item"
|
||||||
|
class="resource_tag"
|
||||||
@click="searchMovieforTag(item)"
|
@click="searchMovieforTag(item)"
|
||||||
>
|
>
|
||||||
{{ item }}
|
{{ item }}
|
||||||
@@ -170,6 +170,7 @@
|
|||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
line-clamp: 4;
|
||||||
-webkit-line-clamp: 4;
|
-webkit-line-clamp: 4;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: all;
|
white-space: all;
|
||||||
|
|||||||
2
frontend/src/env.d.ts
vendored
2
frontend/src/env.d.ts
vendored
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare module "*.vue" {
|
declare module "*.vue" {
|
||||||
import type { DefineComponent } from "vue";
|
import type { DefineComponent } from "vue";
|
||||||
const component: DefineComponent<{}, {}, any>;
|
const component: DefineComponent<Record<string, never>, Record<string, never>, unknown>;
|
||||||
export default component;
|
export default component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import { createApp } from "vue";
|
|||||||
import { createPinia } from "pinia";
|
import { createPinia } from "pinia";
|
||||||
import ElementPlus from "element-plus";
|
import ElementPlus from "element-plus";
|
||||||
import "element-plus/dist/index.css";
|
import "element-plus/dist/index.css";
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router/index";
|
import router from "./router/index";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
app.component(key, component)
|
app.component(key, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(createPinia());
|
app.use(createPinia());
|
||||||
|
|||||||
@@ -23,20 +23,26 @@ 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: any) => Promise<ShareInfoResponse>;
|
getShareInfo: (parsedCode: T) => Promise<ShareInfoResponse>;
|
||||||
saveFile: (params: Record<string, any>) => Promise<any>;
|
saveFile: (params: P) => Promise<{ code: number; message?: string }>;
|
||||||
};
|
};
|
||||||
parseShareCode: (match: RegExpMatchArray) => Record<string, string>;
|
parseShareCode: (match: RegExpMatchArray) => T;
|
||||||
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => Record<string, any>;
|
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => P;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 云盘类型配置
|
// 云盘类型配置
|
||||||
export const CLOUD_DRIVES: CloudDriveConfig[] = [
|
export const CLOUD_DRIVES: [
|
||||||
|
CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams>,
|
||||||
|
CloudDriveConfig<{ pwdId: string }, SaveQuarkFileParams>,
|
||||||
|
] = [
|
||||||
{
|
{
|
||||||
name: "115网盘",
|
name: "115网盘",
|
||||||
type: "pan115",
|
type: "pan115",
|
||||||
@@ -44,15 +50,17 @@ export const CLOUD_DRIVES: CloudDriveConfig[] = [
|
|||||||
api: {
|
api: {
|
||||||
getShareInfo: (parsedCode: { shareCode: string; receiveCode: string }) =>
|
getShareInfo: (parsedCode: { shareCode: string; receiveCode: string }) =>
|
||||||
cloud115Api.getShareInfo(parsedCode.shareCode, parsedCode.receiveCode),
|
cloud115Api.getShareInfo(parsedCode.shareCode, parsedCode.receiveCode),
|
||||||
saveFile: async (params) => await cloud115Api.saveFile(params as Save115FileParams),
|
saveFile: async (params: Save115FileParams) => {
|
||||||
|
return await cloud115Api.saveFile(params as Save115FileParams);
|
||||||
},
|
},
|
||||||
parseShareCode: (match) => ({
|
},
|
||||||
|
parseShareCode: (match: RegExpMatchArray) => ({
|
||||||
shareCode: match[1],
|
shareCode: match[1],
|
||||||
receiveCode: match[2] || "",
|
receiveCode: match[2] || "",
|
||||||
}),
|
}),
|
||||||
getSaveParams: (shareInfo, folderId) => ({
|
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => ({
|
||||||
shareCode: shareInfo.shareCode,
|
shareCode: shareInfo.shareCode || "",
|
||||||
receiveCode: shareInfo.receiveCode,
|
receiveCode: shareInfo.receiveCode || "",
|
||||||
fileId: shareInfo.list[0].fileId,
|
fileId: shareInfo.list[0].fileId,
|
||||||
folderId,
|
folderId,
|
||||||
}),
|
}),
|
||||||
@@ -63,12 +71,16 @@ export const CLOUD_DRIVES: CloudDriveConfig[] = [
|
|||||||
regex: /pan\.quark\.cn\/s\/([a-zA-Z0-9]+)/,
|
regex: /pan\.quark\.cn\/s\/([a-zA-Z0-9]+)/,
|
||||||
api: {
|
api: {
|
||||||
getShareInfo: (parsedCode: { pwdId: string }) => quarkApi.getShareInfo(parsedCode.pwdId),
|
getShareInfo: (parsedCode: { pwdId: string }) => quarkApi.getShareInfo(parsedCode.pwdId),
|
||||||
saveFile: async (params) => await quarkApi.saveFile(params as SaveQuarkFileParams),
|
saveFile: async (params: SaveQuarkFileParams) => {
|
||||||
|
return await quarkApi.saveFile(params as SaveQuarkFileParams);
|
||||||
},
|
},
|
||||||
parseShareCode: (match) => ({ pwdId: match[1] }),
|
},
|
||||||
getSaveParams: (shareInfo, folderId) => ({
|
parseShareCode: (match: RegExpMatchArray) => ({ pwdId: match[1] }),
|
||||||
fid_list: shareInfo.list.map((item) => item.fileId || ""),
|
getSaveParams: (shareInfo: ShareInfoResponse, folderId: string) => ({
|
||||||
fid_token_list: shareInfo.list.map((item) => item.fileIdToken || ""),
|
fid_list: shareInfo.list.map((item: { fileId?: string }) => item.fileId || ""),
|
||||||
|
fid_token_list: shareInfo.list.map(
|
||||||
|
(item: { fileIdToken?: string }) => item.fileIdToken || ""
|
||||||
|
),
|
||||||
to_pdir_fid: folderId,
|
to_pdir_fid: folderId,
|
||||||
pwd_id: shareInfo.pwdId || "",
|
pwd_id: shareInfo.pwdId || "",
|
||||||
stoken: shareInfo.stoken || "",
|
stoken: shareInfo.stoken || "",
|
||||||
@@ -156,7 +168,9 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
async saveResourceToDrive(
|
async saveResourceToDrive(
|
||||||
resource: ResourceItem,
|
resource: ResourceItem,
|
||||||
folderId: string,
|
folderId: string,
|
||||||
drive: CloudDriveConfig
|
drive:
|
||||||
|
| CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams>
|
||||||
|
| CloudDriveConfig<{ pwdId: 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;
|
||||||
@@ -166,7 +180,10 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
|
|
||||||
const parsedCode = drive.parseShareCode(match);
|
const parsedCode = drive.parseShareCode(match);
|
||||||
|
|
||||||
let shareInfo = await drive.api.getShareInfo(parsedCode);
|
if (this.is115Drive(drive)) {
|
||||||
|
let shareInfo = await drive.api.getShareInfo(
|
||||||
|
parsedCode as { shareCode: string; receiveCode: string }
|
||||||
|
);
|
||||||
if (shareInfo) {
|
if (shareInfo) {
|
||||||
if (Array.isArray(shareInfo)) {
|
if (Array.isArray(shareInfo)) {
|
||||||
shareInfo = {
|
shareInfo = {
|
||||||
@@ -188,6 +205,26 @@ export const useResourceStore = defineStore("resource", {
|
|||||||
} else {
|
} else {
|
||||||
ElMessage.error(result.message);
|
ElMessage.error(result.message);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let shareInfo = this.is115Drive(drive)
|
||||||
|
? await drive.api.getShareInfo(parsedCode as { shareCode: string; receiveCode: string })
|
||||||
|
: await drive.api.getShareInfo(parsedCode as { pwdId: string });
|
||||||
|
if (shareInfo) {
|
||||||
|
if (Array.isArray(shareInfo)) {
|
||||||
|
shareInfo = {
|
||||||
|
list: shareInfo,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const params = drive.getSaveParams(shareInfo, folderId);
|
||||||
|
const result = await drive.api.saveFile(params);
|
||||||
|
|
||||||
|
if (result.code === 0) {
|
||||||
|
ElMessage.success(`${drive.name} 转存成功`);
|
||||||
|
} else {
|
||||||
|
ElMessage.error(result.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 解析云盘链接
|
// 解析云盘链接
|
||||||
@@ -202,7 +239,12 @@ 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 = await matchedDrive.api.getShareInfo(parsedCode);
|
let shareInfo = this.is115Drive(matchedDrive)
|
||||||
|
? await matchedDrive.api.getShareInfo(
|
||||||
|
parsedCode as { shareCode: string; receiveCode: string }
|
||||||
|
)
|
||||||
|
: await matchedDrive.api.getShareInfo(parsedCode as { pwdId: string });
|
||||||
|
|
||||||
if (Array.isArray(shareInfo)) {
|
if (Array.isArray(shareInfo)) {
|
||||||
shareInfo = {
|
shareInfo = {
|
||||||
list: shareInfo,
|
list: shareInfo,
|
||||||
@@ -246,5 +288,13 @@ 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<{ pwdId: string }, SaveQuarkFileParams>
|
||||||
|
): drive is CloudDriveConfig<{ shareCode: string; receiveCode: string }, Save115FileParams> {
|
||||||
|
return drive.type === "pan115";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export interface SaveFileParams {
|
|||||||
folderId: string;
|
folderId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiResponse<T = any> {
|
export interface ApiResponse<T = unknown> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data?: T;
|
data?: T;
|
||||||
error?: string;
|
error?: string;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import axios, { AxiosResponse } from "axios";
|
import axios, { AxiosResponse, AxiosRequestConfig } from "axios";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { RequestResult } from "../types/response";
|
import { RequestResult } from "../types/response";
|
||||||
|
|
||||||
@@ -49,13 +49,17 @@ axiosInstance.interceptors.response.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
get: <T>(
|
get: <T>(url: string, config?: AxiosRequestConfig): Promise<RequestResult<T>> => {
|
||||||
url: string,
|
|
||||||
config?: Record<string, any>
|
|
||||||
): Promise<RequestResult<T>> => {
|
|
||||||
return axiosInstance.get(url, { ...config });
|
return axiosInstance.get(url, { ...config });
|
||||||
},
|
},
|
||||||
post: axiosInstance.post,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
post: <T, D = any>(
|
||||||
|
url: string,
|
||||||
|
data: D,
|
||||||
|
config?: AxiosRequestConfig
|
||||||
|
): Promise<RequestResult<T>> => {
|
||||||
|
return axiosInstance.post(url, data, { ...config });
|
||||||
|
},
|
||||||
put: axiosInstance.put,
|
put: axiosInstance.put,
|
||||||
delete: axiosInstance.delete,
|
delete: axiosInstance.delete,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,9 +40,7 @@
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const routeParams = computed(
|
const routeParams = computed((): CurrentParams => ({ ...route.query }) as unknown as CurrentParams);
|
||||||
(): CurrentParams => ({ ...route.query }) as unknown as CurrentParams
|
|
||||||
);
|
|
||||||
const doubanStore = useDoubanStore();
|
const doubanStore = useDoubanStore();
|
||||||
if (routeParams.value) {
|
if (routeParams.value) {
|
||||||
doubanStore.setCurrentParams(routeParams.value);
|
doubanStore.setCurrentParams(routeParams.value);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home" v-loading="resourcStore.loading" element-loading-background="rgba(0,0,0,0.6)">
|
<div v-loading="resourcStore.loading" class="home" element-loading-background="rgba(0,0,0,0.6)">
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-aside width="200px"><aside-menu /></el-aside>
|
<el-aside width="200px"><aside-menu /></el-aside>
|
||||||
<el-container class="home-main">
|
<el-container class="home-main">
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
<!-- 登录表单 -->
|
<!-- 登录表单 -->
|
||||||
<el-form
|
<el-form
|
||||||
v-if="activeTab === 'login'"
|
v-if="activeTab === 'login'"
|
||||||
|
ref="loginFormRef"
|
||||||
:model="loginForm"
|
:model="loginForm"
|
||||||
:rules="loginRules"
|
:rules="loginRules"
|
||||||
ref="loginFormRef"
|
|
||||||
label-position="top"
|
label-position="top"
|
||||||
>
|
>
|
||||||
<el-form-item prop="username" class="form-item">
|
<el-form-item prop="username" class="form-item">
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
<!-- 注册表单 -->
|
<!-- 注册表单 -->
|
||||||
<el-form
|
<el-form
|
||||||
v-if="activeTab === 'register'"
|
v-if="activeTab === 'register'"
|
||||||
|
ref="registerFormRef"
|
||||||
:model="registerForm"
|
:model="registerForm"
|
||||||
:rules="registerRules"
|
:rules="registerRules"
|
||||||
ref="registerFormRef"
|
|
||||||
label-position="top"
|
label-position="top"
|
||||||
><el-form-item prop="username" class="form-item">
|
><el-form-item prop="username" class="form-item">
|
||||||
<el-input v-model="registerForm.username" placeholder="用户名" class="form-input" />
|
<el-input v-model="registerForm.username" placeholder="用户名" class="form-input" />
|
||||||
@@ -83,6 +83,7 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { userApi } from "@/api/user";
|
import { userApi } from "@/api/user";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
const activeTab = ref("login"); // 默认显示登录表单
|
const activeTab = ref("login"); // 默认显示登录表单
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="header_right">
|
<div class="header_right">
|
||||||
<el-icon
|
<el-icon
|
||||||
class="type_icon"
|
|
||||||
v-if="userStore.displayStyle === 'card'"
|
v-if="userStore.displayStyle === 'card'"
|
||||||
|
class="type_icon"
|
||||||
@click="setDisplayStyle('table')"
|
@click="setDisplayStyle('table')"
|
||||||
><Menu
|
><Menu
|
||||||
/></el-icon>
|
/></el-icon>
|
||||||
@@ -20,19 +20,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ResourceTable
|
<ResourceTable
|
||||||
@loadMore="handleLoadMore"
|
|
||||||
@searchMovieforTag="searchMovieforTag"
|
|
||||||
@save="handleSave"
|
|
||||||
v-if="userStore.displayStyle === 'table'"
|
v-if="userStore.displayStyle === 'table'"
|
||||||
|
@load-more="handleLoadMore"
|
||||||
|
@search-moviefor-tag="searchMovieforTag"
|
||||||
|
@save="handleSave"
|
||||||
></ResourceTable>
|
></ResourceTable>
|
||||||
<ResourceCard
|
<ResourceCard
|
||||||
@loadMore="handleLoadMore"
|
|
||||||
@searchMovieforTag="searchMovieforTag"
|
|
||||||
@save="handleSave"
|
|
||||||
v-else
|
v-else
|
||||||
|
@load-more="handleLoadMore"
|
||||||
|
@search-moviefor-tag="searchMovieforTag"
|
||||||
|
@save="handleSave"
|
||||||
></ResourceCard>
|
></ResourceCard>
|
||||||
<el-empty v-if="resourceStore.resources.length === 0" :image-size="200" />
|
<el-empty v-if="resourceStore.resources.length === 0" :image-size="200" />
|
||||||
<el-dialog v-model="folderDialogVisible" title="选择保存目录" v-if="currentResource">
|
<el-dialog v-if="currentResource" v-model="folderDialogVisible" title="选择保存目录">
|
||||||
<template #header="{ titleId }">
|
<template #header="{ titleId }">
|
||||||
<div class="my-header">
|
<div class="my-header">
|
||||||
<div :id="titleId">
|
<div :id="titleId">
|
||||||
@@ -49,9 +49,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<folder-select
|
<folder-select
|
||||||
v-if="folderDialogVisible"
|
v-if="folderDialogVisible"
|
||||||
|
:cloud-type="currentResource.cloudType"
|
||||||
@select="handleFolderSelect"
|
@select="handleFolderSelect"
|
||||||
@close="folderDialogVisible = false"
|
@close="folderDialogVisible = false"
|
||||||
:cloudType="currentResource.cloudType"
|
|
||||||
/>
|
/>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="folderDialogVisible = false">取消</el-button>
|
<el-button @click="folderDialogVisible = false">取消</el-button>
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
<el-card class="setting-card" v-if="settingStore.globalSetting">
|
<el-card v-if="settingStore.globalSetting" class="setting-card">
|
||||||
<h2>网络配置</h2>
|
<h2>网络配置</h2>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proxyDomain">代理域名:</label>
|
<label for="proxyDomain">代理域名:</label>
|
||||||
<el-input
|
<el-input
|
||||||
|
id="proxyDomain"
|
||||||
|
v-model="settingStore.globalSetting.httpProxyHost"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
id="proxyDomain"
|
|
||||||
placeholder="127.0.0.1"
|
placeholder="127.0.0.1"
|
||||||
v-model="settingStore.globalSetting.httpProxyHost"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="proxyPort">代理端口:</label>
|
<label for="proxyPort">代理端口:</label>
|
||||||
<el-input
|
<el-input
|
||||||
|
id="proxyPort"
|
||||||
|
v-model="settingStore.globalSetting.httpProxyPort"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
id="proxyPort"
|
|
||||||
placeholder="7890"
|
placeholder="7890"
|
||||||
v-model="settingStore.globalSetting.httpProxyPort"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="AdminUserCode">管理员注册码:</label>
|
<label for="AdminUserCode">管理员注册码:</label>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
|
id="AdminUserCode"
|
||||||
|
v-model="settingStore.globalSetting.AdminUserCode"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
id="AdminUserCode"
|
|
||||||
:controls="false"
|
:controls="false"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
placeholder="设置管理员注册码"
|
placeholder="设置管理员注册码"
|
||||||
v-model="settingStore.globalSetting.AdminUserCode"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="CommonUserCode">普通用户注册码:</label>
|
<label for="CommonUserCode">普通用户注册码:</label>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
|
id="CommonUserCode"
|
||||||
|
v-model="settingStore.globalSetting.CommonUserCode"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
type="text"
|
type="text"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
:controls="false"
|
:controls="false"
|
||||||
id="CommonUserCode"
|
|
||||||
placeholder="设置普通用户注册码"
|
placeholder="设置普通用户注册码"
|
||||||
v-model="settingStore.globalSetting.CommonUserCode"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -61,19 +61,19 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cookie115">115网盘Cookie:</label>
|
<label for="cookie115">115网盘Cookie:</label>
|
||||||
<el-input
|
<el-input
|
||||||
class="form-input"
|
|
||||||
type="text"
|
|
||||||
id="cookie115"
|
id="cookie115"
|
||||||
v-model="settingStore.userSettings.cloud115Cookie"
|
v-model="settingStore.userSettings.cloud115Cookie"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cookieQuark">夸克网盘Cookie:</label>
|
<label for="cookieQuark">夸克网盘Cookie:</label>
|
||||||
<el-input
|
<el-input
|
||||||
class="form-input"
|
|
||||||
type="text"
|
|
||||||
id="cookieQuark"
|
id="cookieQuark"
|
||||||
v-model="settingStore.userSettings.quarkCookie"
|
v-model="settingStore.userSettings.quarkCookie"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -17,13 +17,23 @@
|
|||||||
"build:frontend": "cd frontend && npm run build",
|
"build:frontend": "cd frontend && npm run build",
|
||||||
"build:backend": "cd backend && npm run build",
|
"build:backend": "cd backend && npm run build",
|
||||||
"clean": "rimraf **/node_modules **/dist",
|
"clean": "rimraf **/node_modules **/dist",
|
||||||
"format": "prettier --write \"**/*.{js,ts,vue,json,md}\"",
|
"format": "prettier --write \"**/*.{js,ts,vue,json,css,scss}\"",
|
||||||
"format:check": "prettier --check \"**/*.{js,ts,vue,json,md}\""
|
"format:check": "prettier --check \"**/*.{js,ts,vue,json,css,scss}\"",
|
||||||
|
"format:all": "npm run format && npm run lint:fix",
|
||||||
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||||
|
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||||
|
"@typescript-eslint/parser": "^7.1.0",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-config-prettier": "^10.0.1",
|
||||||
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
|
"eslint-plugin-vue": "^9.32.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.4.2",
|
||||||
"rimraf": "^5.0.5"
|
"rimraf": "^5.0.5",
|
||||||
|
"vue-eslint-parser": "^9.4.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"pnpm": ">=6.0.0"
|
"pnpm": ">=6.0.0"
|
||||||
|
|||||||
837
pnpm-lock.yaml
generated
837
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user