temp
This commit is contained in:
parent
8d78127e4d
commit
2cf41a9c18
8
openRenamerBackend/.idea/.gitignore
generated
vendored
Normal file
8
openRenamerBackend/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
8
openRenamerBackend/.idea/modules.xml
generated
Normal file
8
openRenamerBackend/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/openRenamerBackend.iml" filepath="$PROJECT_DIR$/.idea/openRenamerBackend.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
11
openRenamerBackend/.idea/openRenamerBackend.iml
generated
Normal file
11
openRenamerBackend/.idea/openRenamerBackend.iml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
openRenamerBackend/.idea/vcs.xml
generated
Normal file
6
openRenamerBackend/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -1,49 +0,0 @@
|
||||
import { Context } from "koa";
|
||||
import FileService from "../service/FileService";
|
||||
import config from "../config";
|
||||
|
||||
const router = {};
|
||||
|
||||
/**
|
||||
* 获取目录下的文件列表
|
||||
*/
|
||||
router["GET /file/query"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.readPath(ctx.query.path as string, ctx.query.showHidden === '1');
|
||||
};
|
||||
|
||||
/**
|
||||
*是否windows
|
||||
*/
|
||||
router['GET /file/isWindows'] = async function (ctx: Context) {
|
||||
ctx.body = config.isWindows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查路径是否存在
|
||||
*/
|
||||
router["GET /file/path/exist"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.checkExist(ctx.query.path as string);
|
||||
};
|
||||
|
||||
/**
|
||||
* 收藏路径
|
||||
*/
|
||||
router["POST /file/path/save"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.savePath(ctx.request.body);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取收藏路径
|
||||
*/
|
||||
router["GET /file/path"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.getSaveList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取收藏路径
|
||||
*/
|
||||
router["DELETE /file/path/delete"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.deleteOne(ctx.query.id);
|
||||
};
|
||||
|
||||
export default router;
|
@ -1,4 +1,4 @@
|
||||
import { Context } from "koa";
|
||||
import {Context} from "koa";
|
||||
import FileService from "../service/FileService";
|
||||
import config from "../config";
|
||||
|
||||
@ -11,6 +11,13 @@ router["GET /file/query"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.readPath(ctx.query.path as string, ctx.query.showHidden === '1');
|
||||
};
|
||||
|
||||
/**
|
||||
* 递归读取文件夹下所有的文件
|
||||
*/
|
||||
router["POST /file/recursionQuery"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.readRecursion(ctx.request.body);
|
||||
};
|
||||
|
||||
/**
|
||||
*是否windows
|
||||
*/
|
||||
@ -46,4 +53,19 @@ router["DELETE /file/path/delete"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.deleteOne(ctx.query.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* delete file batch
|
||||
*/
|
||||
router["POST /file/deleteBatch"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.deleteBatch(ctx.request.body);
|
||||
};
|
||||
|
||||
/**
|
||||
* rename file
|
||||
*/
|
||||
router["POST /file/rename"] = async function (ctx: Context) {
|
||||
await FileService.rename(ctx.request.body.source, ctx.request.body.target);
|
||||
ctx.body = "";
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
@ -4,86 +4,88 @@ import path from 'path';
|
||||
|
||||
|
||||
let pattern = new RegExp(/s(eason)?(\d+)/);
|
||||
let eNumPatternArr = [new RegExp(/e[p]?(\d+)/), new RegExp(/[\(\[(](\d+)[\)\])]/), new RegExp(/[\.-](\d+)/), new RegExp(/(\d+)/)];
|
||||
let eNumPatternArr = [new RegExp(/ep?(\d+)/), new RegExp(/[\(\[(](\d+)[\)\])]/), new RegExp(/[\.-](\d+)/), new RegExp(/(\d+)/)];
|
||||
let resolutionPattern = new RegExp(/(\d{3,}[pP])/);
|
||||
let resolutionArr = ['1k', '1K', '2k', '2K', '4k', '4K', '8k', '8K'];
|
||||
let charSet = new Set([' ', '[', '.', '(', '(']);
|
||||
export default class InsertRule implements RuleInterface {
|
||||
|
||||
/**
|
||||
* 识别类型,season:季号,name:剧名/电影名识别
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
* 前面追加
|
||||
*/
|
||||
frontAdd: string;
|
||||
/**
|
||||
* 后面追加
|
||||
*/
|
||||
endAdd: string;
|
||||
eNumWidth: number;
|
||||
/**
|
||||
* 识别类型,season:季号,name:剧名/电影名识别
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
* 前面追加
|
||||
*/
|
||||
frontAdd: string;
|
||||
/**
|
||||
* 后面追加
|
||||
*/
|
||||
endAdd: string;
|
||||
eNumWidth: number;
|
||||
|
||||
constructor(data: any) {
|
||||
this.type = data.type;
|
||||
this.frontAdd = data.frontAdd;
|
||||
this.endAdd = data.endAdd;
|
||||
}
|
||||
constructor(data: any) {
|
||||
this.type = data.type;
|
||||
this.frontAdd = data.frontAdd;
|
||||
this.endAdd = data.endAdd;
|
||||
}
|
||||
|
||||
|
||||
deal(file: FileObj): void {
|
||||
//识别到的内容
|
||||
let getStr = null;
|
||||
let patternRes = path.basename(file.path).replace(/[ ]+/, "").toLocaleLowerCase().match(pattern);
|
||||
if (this.type === 'season') {
|
||||
if (patternRes && patternRes[2]) {
|
||||
getStr = patternRes[2];
|
||||
}
|
||||
} else if (this.type === 'name') {
|
||||
let originName = null;
|
||||
if (patternRes && patternRes[2]) {
|
||||
//说明是剧集,取父文件夹的父文件夹名称
|
||||
originName = path.basename(path.resolve(file.path, '..'));
|
||||
} else {
|
||||
//说明是电影
|
||||
originName = path.basename(file.path);
|
||||
}
|
||||
getStr = '';
|
||||
for (let i = 0; i < originName.length; i++) {
|
||||
let char = originName.charAt(i);
|
||||
if (charSet.has(char)) {
|
||||
break;
|
||||
}
|
||||
getStr += char;
|
||||
}
|
||||
} else if (this.type === 'eNum') {
|
||||
let lowName = file.originName.toLocaleLowerCase().replace(/ /g, '');
|
||||
for (let i in eNumPatternArr) {
|
||||
let patternRes = lowName.match(eNumPatternArr[i]);
|
||||
if (patternRes && patternRes.length > 1) {
|
||||
getStr = patternRes[1];
|
||||
for (let i = 0; i < this.eNumWidth - getStr.length; i++) {
|
||||
getStr = '0' + getStr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (this.type === 'resolution') {
|
||||
let res = file.originName.match(resolutionPattern);
|
||||
if (res && res.length > 1) {
|
||||
getStr = res[1];
|
||||
} else {
|
||||
for (let i = 0; i < resolutionArr.length; i++) {
|
||||
if (file.originName.indexOf(resolutionArr[i]) > -1) {
|
||||
getStr = resolutionArr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getStr && getStr.length > 0) {
|
||||
file.realName = file.realName + this.frontAdd + getStr + this.endAdd;
|
||||
file.name = file.realName + file.expandName;
|
||||
}
|
||||
}
|
||||
deal(file: FileObj): void {
|
||||
//识别到的内容
|
||||
let getStr = null;
|
||||
let patternRes = path.basename(file.path).replace(/[ ]+/, "").toLocaleLowerCase().match(pattern);
|
||||
if (this.type === 'season') {
|
||||
if (patternRes && patternRes[2]) {
|
||||
getStr = patternRes[2];
|
||||
}
|
||||
} else if (this.type === 'name') {
|
||||
let originName = null;
|
||||
if (patternRes && patternRes[2]) {
|
||||
//说明是剧集,取父文件夹的父文件夹名称
|
||||
originName = path.basename(path.resolve(file.path, '..'));
|
||||
} else {
|
||||
//说明是电影
|
||||
originName = path.basename(file.path);
|
||||
}
|
||||
getStr = '';
|
||||
for (let i = 0; i < originName.length; i++) {
|
||||
let char = originName.charAt(i);
|
||||
if (charSet.has(char)) {
|
||||
break;
|
||||
}
|
||||
getStr += char;
|
||||
}
|
||||
} else if (this.type === 'eNum') {
|
||||
let lowName = file.originName.toLocaleLowerCase().replace(/ /g, '')
|
||||
.replace(/\d+[a-z]/g, '')//去除4k,1080p等
|
||||
.replace(/[xh]\d+/g, '')//去除x264,h264等 ;
|
||||
for (let i in eNumPatternArr) {
|
||||
let patternRes = lowName.match(eNumPatternArr[i]);
|
||||
if (patternRes && patternRes.length > 1) {
|
||||
getStr = patternRes[1];
|
||||
for (let i = 0; i < this.eNumWidth - getStr.length; i++) {
|
||||
getStr = '0' + getStr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (this.type === 'resolution') {
|
||||
let res = file.originName.match(resolutionPattern);
|
||||
if (res && res.length > 1) {
|
||||
getStr = res[1];
|
||||
} else {
|
||||
for (let i = 0; i < resolutionArr.length; i++) {
|
||||
if (file.originName.indexOf(resolutionArr[i]) > -1) {
|
||||
getStr = resolutionArr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getStr && getStr.length > 0) {
|
||||
file.realName = file.realName + this.frontAdd + getStr + this.endAdd;
|
||||
file.name = file.realName + file.expandName;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,14 +9,15 @@ import handleError from "./middleware/handleError";
|
||||
import init from "./middleware/init";
|
||||
import SqliteUtil from './util/SqliteHelper';
|
||||
import log from './util/LogUtil';
|
||||
import { updateQbInfo } from './util/QbApiUtil';
|
||||
import {updateQbInfo} from './util/QbApiUtil';
|
||||
|
||||
|
||||
console.log(config);
|
||||
|
||||
const app = new koa();
|
||||
|
||||
let router = new Router({
|
||||
prefix: config.urlPrefix
|
||||
prefix: config.urlPrefix
|
||||
});
|
||||
|
||||
app.use(require('koa-static')(path.join(config.rootPath, 'static')));
|
||||
@ -30,12 +31,12 @@ app.use(handleError);
|
||||
|
||||
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
|
||||
(async () => {
|
||||
await SqliteUtil.createPool();
|
||||
await updateQbInfo(null, null);
|
||||
app.listen(config.port);
|
||||
log.info(`server listened `, config.port);
|
||||
await SqliteUtil.createPool();
|
||||
await updateQbInfo(null, null);
|
||||
app.listen(config.port);
|
||||
log.info(`server listened `, config.port);
|
||||
})();
|
||||
|
||||
app.on("error", (error) => {
|
||||
console.error(error);
|
||||
console.error(error);
|
||||
})
|
||||
|
@ -6,136 +6,190 @@ import ProcessHelper from '../util/ProcesHelper';
|
||||
import FileObj from '../entity/vo/FileObj';
|
||||
import SavePathDao from '../dao/SavePathDao';
|
||||
import SavePath from '../entity/po/SavePath';
|
||||
import ErrorHelper from "../util/ErrorHelper";
|
||||
|
||||
let numberSet = new Set(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
||||
|
||||
class FileService {
|
||||
static async readPath(pathStr: string, showHidden: boolean): Promise<Array<FileObj>> {
|
||||
pathStr = decodeURIComponent(pathStr);
|
||||
let fileList = new Array();
|
||||
if (pathStr.trim().length == 0) {
|
||||
//获取根目录路径
|
||||
if (config.isWindows) {
|
||||
//windows下
|
||||
let std: string = (await ProcessHelper.exec('wmic logicaldisk get caption')).replace('Caption', '');
|
||||
fileList = std
|
||||
.split('\r\n')
|
||||
.filter((item) => item.trim().length > 0)
|
||||
.map((item) => item.trim());
|
||||
} else {
|
||||
//linux下
|
||||
pathStr = '/';
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
} else {
|
||||
if (!(fs.pathExists(pathStr))) {
|
||||
throw new Error("路径不存在");
|
||||
}
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
let folderList: Array<FileObj> = new Array();
|
||||
let files: Array<FileObj> = new Array();
|
||||
for (let index in fileList) {
|
||||
try {
|
||||
let stat = await fs.stat(path.join(pathStr, fileList[index]));
|
||||
if (fileList[index].startsWith('.')) {
|
||||
if (showHidden) {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
folderList.sort((a, b) => FileService.compareStr(a.name, b.name)).push(...files.sort((a, b) => FileService.compareStr(a.name, b.name)));
|
||||
return folderList;
|
||||
}
|
||||
static async readPath(pathStr: string, showHidden: boolean): Promise<Array<FileObj>> {
|
||||
pathStr = decodeURIComponent(pathStr);
|
||||
let fileList = [];
|
||||
if (pathStr.trim().length == 0) {
|
||||
//获取根目录路径
|
||||
if (config.isWindows) {
|
||||
//windows下
|
||||
let std: string = (await ProcessHelper.exec('wmic logicaldisk get caption')).replace('Caption', '');
|
||||
fileList = std
|
||||
.split('\r\n')
|
||||
.filter((item) => item.trim().length > 0)
|
||||
.map((item) => item.trim());
|
||||
} else {
|
||||
//linux下
|
||||
pathStr = '/';
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
} else {
|
||||
if (!(fs.pathExists(pathStr))) {
|
||||
throw new Error("路径不存在");
|
||||
}
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
let folderList: Array<FileObj> = [];
|
||||
let files: Array<FileObj> = [];
|
||||
for (let index in fileList) {
|
||||
try {
|
||||
let stat = await fs.stat(path.join(pathStr, fileList[index]));
|
||||
if (fileList[index].startsWith('.')) {
|
||||
if (showHidden) {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
folderList.sort((a, b) => FileService.compareStr(a.name, b.name)).push(...files.sort((a, b) => FileService.compareStr(a.name, b.name)));
|
||||
return folderList;
|
||||
}
|
||||
|
||||
static async checkExist(pathStr: string) {
|
||||
return await fs.pathExists(pathStr);
|
||||
}
|
||||
/**
|
||||
* 递归读取文件夹下所有的文件
|
||||
*/
|
||||
static async readRecursion(folders: Array<FileObj>): Promise<Array<FileObj>> {
|
||||
let res = [];
|
||||
await this.readDirRecursion(res, folders, 1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏路径
|
||||
* @param saveObj
|
||||
* @returns
|
||||
*/
|
||||
static async savePath(saveObj: SavePath) {
|
||||
await SavePathDao.addOne(saveObj);
|
||||
return saveObj;
|
||||
}
|
||||
private static async readDirRecursion(res: Array<FileObj>, folders: Array<FileObj>, depth: number): Promise<void> {
|
||||
if (depth > 10) {
|
||||
throw ErrorHelper.Error400("递归读取超过10层,强制结束");
|
||||
}
|
||||
if (folders == null || folders.length == 0) {
|
||||
return;
|
||||
}
|
||||
for (let i in folders) {
|
||||
let file = folders[i];
|
||||
if (!file.isFolder) {
|
||||
res.push(file);
|
||||
} else {
|
||||
let filePath = path.join(file.path, file.name);
|
||||
let temp = (await fs.readdir(filePath)).map(item => {
|
||||
let stat = fs.statSync(path.join(filePath, item));
|
||||
return new FileObj(item, filePath, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime());
|
||||
});
|
||||
await FileService.readDirRecursion(res, temp, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保存列表
|
||||
* @returns
|
||||
*/
|
||||
static async getSaveList() {
|
||||
return await SavePathDao.getAll();
|
||||
}
|
||||
static async checkExist(pathStr: string) {
|
||||
return await fs.pathExists(pathStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
static async deleteOne(id) {
|
||||
return await SavePathDao.delete(id);
|
||||
}
|
||||
/**
|
||||
* 收藏路径
|
||||
* @param saveObj
|
||||
* @returns
|
||||
*/
|
||||
static async savePath(saveObj: SavePath) {
|
||||
await SavePathDao.addOne(saveObj);
|
||||
return saveObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字字母混合排序
|
||||
* @param a str
|
||||
* @param b str
|
||||
*/
|
||||
static compareStr(a: string, b: string) {
|
||||
let an = a.length;
|
||||
let bn = b.length;
|
||||
for (let i = 0; i < an;) {
|
||||
let charA = FileService.readChar(a, i, an);
|
||||
let charB = FileService.readChar(b, i, bn);
|
||||
if (charB.length == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (charA !== charB) {
|
||||
//读取字符串不相等说明可以得到排序结果
|
||||
//如果都为数字,按照数字的比较方法,否则按照字符串比较
|
||||
return numberSet.has(charA.charAt(0)) && numberSet.has(charB.charAt(0)) ? Number(charA) - Number(charB) : charA.localeCompare(charB);
|
||||
}
|
||||
i += charA.length;
|
||||
}
|
||||
//排到最后都没分结果说明相等
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* 获取保存列表
|
||||
* @returns
|
||||
*/
|
||||
static async getSaveList() {
|
||||
return await SavePathDao.getAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取字符,如果字符为数字就读取整个数字
|
||||
* @param a a
|
||||
* @param n 数字长度
|
||||
*/
|
||||
static readChar(a: string, i: number, n: number) {
|
||||
let res = "";
|
||||
for (; i < n; i++) {
|
||||
let char = a.charAt(i);
|
||||
if (numberSet.has(char)) {
|
||||
//如果当前字符是数字,添加到结果中
|
||||
res += char;
|
||||
} else {
|
||||
//如果不为数字,但是为第一个字符,直接返回,否则返回res
|
||||
if (res.length == 0) {
|
||||
return char;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
static async deleteOne(id) {
|
||||
return await SavePathDao.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字字母混合排序
|
||||
* @param a str
|
||||
* @param b str
|
||||
*/
|
||||
static compareStr(a: string, b: string) {
|
||||
let an = a.length;
|
||||
let bn = b.length;
|
||||
for (let i = 0; i < an;) {
|
||||
let charA = FileService.readChar(a, i, an);
|
||||
let charB = FileService.readChar(b, i, bn);
|
||||
if (charB.length == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (charA !== charB) {
|
||||
//读取字符串不相等说明可以得到排序结果
|
||||
//如果都为数字,按照数字的比较方法,否则按照字符串比较
|
||||
return numberSet.has(charA.charAt(0)) && numberSet.has(charB.charAt(0)) ? Number(charA) - Number(charB) : charA.localeCompare(charB);
|
||||
}
|
||||
i += charA.length;
|
||||
}
|
||||
//排到最后都没分结果说明相等
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取字符,如果字符为数字就读取整个数字
|
||||
* @param a a
|
||||
* @param n 数字长度
|
||||
*/
|
||||
static readChar(a: string, i: number, n: number) {
|
||||
let res = "";
|
||||
for (; i < n; i++) {
|
||||
let char = a.charAt(i);
|
||||
if (numberSet.has(char)) {
|
||||
//如果当前字符是数字,添加到结果中
|
||||
res += char;
|
||||
} else {
|
||||
//如果不为数字,但是为第一个字符,直接返回,否则返回res
|
||||
if (res.length == 0) {
|
||||
return char;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete batch
|
||||
* @param files files
|
||||
*/
|
||||
static async deleteBatch(files: Array<FileObj>): Promise<void> {
|
||||
if (files == null || files.length == 0) {
|
||||
return;
|
||||
}
|
||||
for (let i in files) {
|
||||
await fs.remove(path.join(files[i].path, files[i].name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rename file from source to target
|
||||
* @param source sourceFile
|
||||
* @param target targetFile
|
||||
*/
|
||||
static async rename(source: FileObj, target: FileObj): Promise<void> {
|
||||
await fs.rename(path.join(source.path, source.name), path.join(target.path, target.name));
|
||||
}
|
||||
}
|
||||
|
||||
export default FileService;
|
||||
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<el-menu :default-active="activeIndex" mode="horizontal" background-color="#545c64" text-color="#fff"
|
||||
active-text-color="#ffd04b" router>
|
||||
active-text-color="#ffd04b" router>
|
||||
<el-menu-item index="/">重命名</el-menu-item>
|
||||
<el-menu-item index="/auto">自动化</el-menu-item>
|
||||
<!-- <el-menu-item index="/auto">自动化</el-menu-item>-->
|
||||
<!-- <el-sub-menu index="/download">
|
||||
<template #title>bt下载</template>
|
||||
<el-menu-item index="/download/center">下载中心</el-menu-item>
|
||||
@ -11,7 +11,7 @@
|
||||
</el-sub-menu> -->
|
||||
</el-menu>
|
||||
<div class="content">
|
||||
<router-view />
|
||||
<router-view/>
|
||||
</div>
|
||||
<div class="footer">版本:{{ version }} 开源地址:<a
|
||||
href="https://github.com/FleyX/open-renamer">open-renamer</a></div>
|
||||
@ -20,22 +20,23 @@
|
||||
|
||||
<script>
|
||||
import httpUtil from "./utils/HttpUtil";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
version: "1.2",
|
||||
activeIndex: location.pathname,
|
||||
};
|
||||
},
|
||||
async created () {
|
||||
async created() {
|
||||
let token = localStorage.getItem("token");
|
||||
window.token = token;
|
||||
window.isWindows = await httpUtil.get("/file/isWindows");
|
||||
console.log(this.$route);
|
||||
console.log(this.activeIndex);
|
||||
},
|
||||
async mounted () {
|
||||
async mounted() {
|
||||
console.log(this.$route);
|
||||
console.log(location);
|
||||
},
|
||||
|
@ -11,8 +11,8 @@
|
||||
<div class="fileList">
|
||||
<div>
|
||||
<el-input style="display: inline-block; width: 150px" type="text" size="small" placeholder="关键词过滤"
|
||||
v-model="filterText" clearable />
|
||||
<template v-if="type == 'file'">
|
||||
v-model="filterText" clearable/>
|
||||
<template v-if="type === 'file'">
|
||||
<el-button type="primary" @click="selectAll(true)" size="small">全选</el-button>
|
||||
<el-button type="primary" @click="selectAll(false)" size="small">全不选</el-button>
|
||||
<el-button type="primary" @click="refresh" size="small">刷新</el-button>
|
||||
@ -21,9 +21,10 @@
|
||||
</template>
|
||||
</div>
|
||||
<div v-for="(item, index) in filterFileList" :key="index">
|
||||
<span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{ item.name }}</span>
|
||||
<el-checkbox style="height: 1.4em" v-model="item.checked" v-else-if="type == 'file'">{{ item.name
|
||||
}}</el-checkbox>
|
||||
<el-checkbox style="height: 1.4em" v-model="item.checked" :disabled="type==='folder' && !item.isFolder">
|
||||
<a v-if="item.isFolder" @click="fileClick(item)" style="color: #289fff">{{ item.name }}</a>
|
||||
<span v-else>{{ item.name }}</span>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -32,7 +33,7 @@
|
||||
</div>
|
||||
|
||||
<el-dialog title="保存路径" v-model="showSave" width="40em">
|
||||
<el-input type="text" v-model="saveName" placeholder="输入名称" />
|
||||
<el-input type="text" v-model="saveName" placeholder="输入名称"/>
|
||||
<el-button type="primary" @click="savePath" style="padding-top: 1em">提交</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@ -41,10 +42,12 @@
|
||||
<script>
|
||||
import HttpUtil from "../utils/HttpUtil";
|
||||
import Bus from "../utils/Bus";
|
||||
|
||||
export default {
|
||||
name: "FileChose",
|
||||
//type:folder:选择文件夹。file:选择文件
|
||||
props: ["curChoosePath", "type"],
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
isWindows: false,
|
||||
fileList: [], //路径下的文件节点
|
||||
@ -57,24 +60,24 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filterFileList () {
|
||||
filterFileList() {
|
||||
let text = this.filterText.trim();
|
||||
return text === "" ? this.fileList : this.fileList.filter((item) => item.name.indexOf(text) > -1);
|
||||
},
|
||||
curSavePathId () {
|
||||
curSavePathId() {
|
||||
let curPath = JSON.stringify(this.pathList);
|
||||
let targetList = this.savePathList.filter((item) => item.content == curPath);
|
||||
let targetList = this.savePathList.filter((item) => item.content === curPath);
|
||||
return targetList.length > 0 ? targetList[0].id : null;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async curChoosePath (newVal) {
|
||||
async curChoosePath(newVal) {
|
||||
console.log("变更路径:", newVal);
|
||||
this.pathList = newVal;
|
||||
await this.breadcrumbClick(this.pathList.length - 1);
|
||||
},
|
||||
},
|
||||
async created () {
|
||||
async created() {
|
||||
if (this.curChoosePath && this.curChoosePath.length > 0) {
|
||||
this.pathList = this.curChoosePath;
|
||||
}
|
||||
@ -84,15 +87,15 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
async refresh () {
|
||||
async refresh() {
|
||||
await this.breadcrumbClick(this.pathList.length - 1);
|
||||
},
|
||||
//刷新保存的路径
|
||||
async refreshSavePathList () {
|
||||
async refreshSavePathList() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
},
|
||||
//点击面包蟹
|
||||
async breadcrumbClick (index) {
|
||||
async breadcrumbClick(index) {
|
||||
this.loading = true;
|
||||
try {
|
||||
let path = this.createPath(index);
|
||||
@ -109,7 +112,7 @@ export default {
|
||||
return false;
|
||||
},
|
||||
//文件列表点击
|
||||
fileClick (item) {
|
||||
fileClick(item) {
|
||||
if (item.isFolder) {
|
||||
this.pathList.push(item.name);
|
||||
this.breadcrumbClick(this.pathList.length);
|
||||
@ -118,14 +121,14 @@ export default {
|
||||
}
|
||||
},
|
||||
//全选
|
||||
selectAll (status) {
|
||||
selectAll(status) {
|
||||
this.filterFileList.filter((item) => !item.isFolder).forEach((item) => (item.checked = status));
|
||||
},
|
||||
//根据index构建路径
|
||||
createPath (index) {
|
||||
createPath(index) {
|
||||
console.log("当前路径为:", this.pathList);
|
||||
let path;
|
||||
if (index == -1) {
|
||||
if (index === -1) {
|
||||
path = "";
|
||||
this.pathList = [];
|
||||
} else {
|
||||
@ -137,34 +140,35 @@ export default {
|
||||
return path;
|
||||
},
|
||||
//点击确定
|
||||
submit () {
|
||||
async submit() {
|
||||
let chosenFiles = this.fileList.filter((item) => item.checked);
|
||||
if (chosenFiles.length === 0) {
|
||||
this.$message({message: "未选择文件", type: "warning"});
|
||||
return;
|
||||
}
|
||||
if (this.type === 'file') {
|
||||
let chosedFiles = this.fileList.filter((item) => item.checked);
|
||||
if (chosedFiles.length == 0) {
|
||||
this.$message({ message: "未选择文件", type: "warning" });
|
||||
return;
|
||||
}
|
||||
this.$emit("addData", JSON.parse(JSON.stringify(chosedFiles)));
|
||||
let body = await HttpUtil.post("/file/recursionQuery", null, chosenFiles);
|
||||
this.$emit("addData", JSON.parse(JSON.stringify(body)));
|
||||
this.fileList.forEach((item) => (item.checked = false));
|
||||
this.fileList = [...this.fileList];
|
||||
} else if (this.type === 'folder') {
|
||||
//选择文件夹
|
||||
this.$emit("folderChose", this.createPath(this.pathList.length - 1));
|
||||
this.$emit("folderChose", JSON.parse(JSON.stringify(chosenFiles)));
|
||||
}
|
||||
this.filterText = "";
|
||||
|
||||
},
|
||||
//收藏路径
|
||||
async savePath () {
|
||||
await HttpUtil.post("/file/path/save", null, { name: this.saveName, content: JSON.stringify(this.pathList) });
|
||||
async savePath() {
|
||||
await HttpUtil.post("/file/path/save", null, {name: this.saveName, content: JSON.stringify(this.pathList)});
|
||||
Bus.$emit("refreshSavePathList");
|
||||
this.saveName = "";
|
||||
this.showSave = false;
|
||||
this.$message.success("操作成功");
|
||||
},
|
||||
//取消收藏路径
|
||||
async cancelSavePath () {
|
||||
await HttpUtil.delete("/file/path/delete", { id: this.curSavePathId });
|
||||
async cancelSavePath() {
|
||||
await HttpUtil.delete("/file/path/delete", {id: this.curSavePathId});
|
||||
Bus.$emit("refreshSavePathList");
|
||||
this.$message.success("操作成功");
|
||||
},
|
||||
|
@ -11,35 +11,37 @@ import router from '../router/index';
|
||||
* @param {*} redirect 接口返回未认证是否跳转到登陆
|
||||
* @returns 数据
|
||||
*/
|
||||
async function request (url, method, params, body, isForm) {
|
||||
let options = {
|
||||
url,
|
||||
baseURL: '/openRenamer/api',
|
||||
method,
|
||||
params,
|
||||
headers: { token: window.token }
|
||||
};
|
||||
if (isForm) {
|
||||
options.headers['Content-Type'] = 'multipart/form-data';
|
||||
}
|
||||
if (body) {
|
||||
options.data = body;
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = await http.default.request(options);
|
||||
} catch (err) {
|
||||
console.log(Object.keys(err));
|
||||
console.log(err.response);
|
||||
if (err.response.status == 401) {
|
||||
window.vueInstance.config.globalProperties.$message.error('密钥验证错误');
|
||||
router.push("/public/login");
|
||||
} else {
|
||||
window.vueInstance.config.globalProperties.$message.error('发生了某些异常问题');
|
||||
async function request(url, method, params, body, isForm) {
|
||||
let options = {
|
||||
url,
|
||||
baseURL: '/openRenamer/api',
|
||||
method,
|
||||
params,
|
||||
headers: {token: window.token}
|
||||
};
|
||||
if (isForm) {
|
||||
options.headers['Content-Type'] = 'multipart/form-data';
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return res.data;
|
||||
if (body) {
|
||||
options.data = body;
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = await http.default.request(options);
|
||||
} catch (err) {
|
||||
console.log(Object.keys(err));
|
||||
console.log(err.response);
|
||||
if (err.response.status === 401) {
|
||||
window.vueInstance.config.globalProperties.$message.error('密钥验证错误');
|
||||
router.push("/public/login");
|
||||
} else if (err.response.status === 400) {
|
||||
window.vueInstance.config.globalProperties.$message.error(err.response.data);
|
||||
} else {
|
||||
window.vueInstance.config.globalProperties.$message.error('发生了某些异常问题');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return res.data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,8 +50,8 @@ async function request (url, method, params, body, isForm) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 未登陆是否跳转到登陆页
|
||||
*/
|
||||
async function get (url, params = null) {
|
||||
return request(url, 'get', params, null, false);
|
||||
async function get(url, params = null) {
|
||||
return request(url, 'get', params, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,8 +62,8 @@ async function get (url, params = null) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function post (url, params, body, isForm = false) {
|
||||
return request(url, 'post', params, body, isForm);
|
||||
async function post(url, params, body, isForm = false) {
|
||||
return request(url, 'post', params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,8 +74,8 @@ async function post (url, params, body, isForm = false) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function put (url, params, body, isForm = false) {
|
||||
return request(url, 'put', params, body, isForm);
|
||||
async function put(url, params, body, isForm = false) {
|
||||
return request(url, 'put', params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,13 +84,13 @@ async function put (url, params, body, isForm = false) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function deletes (url, params = null) {
|
||||
return request(url, 'delete', params, null);
|
||||
async function deletes(url, params = null) {
|
||||
return request(url, 'delete', params, null);
|
||||
}
|
||||
|
||||
export default {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: deletes,
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: deletes,
|
||||
};
|
||||
|
@ -1,36 +1,60 @@
|
||||
<template>
|
||||
<div v-loading="loading" element-loading-text="后台处理中,请稍候">
|
||||
<br />
|
||||
<br/>
|
||||
<el-button type="success" @click="submit" size="default">开始重命名</el-button>
|
||||
<el-divider content-position="left">
|
||||
<div class="head-text">规则设置</div>
|
||||
</el-divider>
|
||||
<!-- 规则列表 -->
|
||||
<rule-block @ruleUpdate="ruleUpdate" />
|
||||
<rule-block @ruleUpdate="ruleUpdate"/>
|
||||
<el-divider content-position="left">
|
||||
<div class="head-text">文件预览</div>
|
||||
</el-divider>
|
||||
<!-- 文件预览列表 -->
|
||||
<div class="fileList">
|
||||
<div>
|
||||
<el-button type="primary" @click="showFileAdd" size="small">新增</el-button>
|
||||
收藏路径:<el-tag v-for="item in savePathList" :round="true" class="savePath" closable :key="item.id"
|
||||
@click="clickSavePath(item)" @close="deleteSavePath(item)" text>{{ item.name }}</el-tag>
|
||||
<el-tooltip effect="dark" content="添加需要重命名的文件" placement="top">
|
||||
<el-button type="primary" @click="showFileAdd" size="small">添加</el-button>
|
||||
</el-tooltip>
|
||||
收藏路径:
|
||||
<el-tag v-for="item in savePathList" :round="true" class="savePath" closable :key="item.id"
|
||||
@click="clickSavePath(item)" @close="deleteSavePath(item)" text>{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<div style="margin-top: 5px">
|
||||
<el-button type="primary" size="small" @click="selectAllFiles">反选</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteCheckedFiles">删除</el-button>
|
||||
<el-tooltip effect="dark" content="一键选中所有的非视频、字幕文件和小于5MB的视频文件" placement="bottom">
|
||||
<el-button type="success" size="small" @click="">一键选择</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="移除(非删除)需要重命名的文件" placement="bottom">
|
||||
<el-button type="warning" size="small" @click="removeCheckedFiles">移除</el-button>
|
||||
</el-tooltip>
|
||||
<el-popconfirm width="250" confirm-button-text="确认" cancel-button-text="取消"
|
||||
title="确认删除勾选的文件(无法恢复)?" @confirm="deleteCheckedFiles">
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-button type="primary" size="small" @click="moveIndex('top')">
|
||||
<el-tooltip effect="dark" content="上移规则" placement="top">
|
||||
<el-icon>
|
||||
<top />
|
||||
<top/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" @click="moveIndex('bottom')">
|
||||
<el-tooltip effect="dark" content="下移规则" placement="top"><el-icon>
|
||||
<bottom />
|
||||
</el-icon></el-tooltip>
|
||||
<el-tooltip effect="dark" content="下移规则" placement="top">
|
||||
<el-icon>
|
||||
<bottom/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" @click="editFile">
|
||||
<el-tooltip effect="dark" content="修改文件名" placement="top">
|
||||
<el-icon>
|
||||
<Edit/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="fileBlock">
|
||||
@ -53,66 +77,72 @@
|
||||
|
||||
<el-dialog title="新增文件" v-model="dialogVisible" width="70%">
|
||||
<file-chose ref="fileChose" type="file" :curChoosePath="curChoosePath" @addData="addData"
|
||||
@refreshSavePathList="refreshSavePathList" />
|
||||
@refreshSavePathList="refreshSavePathList"/>
|
||||
</el-dialog>
|
||||
<el-dialog title="编辑名称" v-model="showNameEditDialog" width="50%">
|
||||
<el-input type="text" v-model="newName"/>
|
||||
<div>
|
||||
<el-button type="primary" @click="doEditFile">确认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import { Top, Bottom } from "@element-plus/icons-vue";
|
||||
import {Top, Bottom, Edit} from "@element-plus/icons-vue";
|
||||
import HttpUtil from "../../utils/HttpUtil";
|
||||
import FileChose from "@/components/FileChose";
|
||||
import RuleBlock from "@/components/rules/RuleBlock.vue";
|
||||
import Bus from "../../utils/Bus";
|
||||
import Tips from '@/components/Tips';
|
||||
|
||||
let numberSet = new Set(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {
|
||||
FileChose,
|
||||
RuleBlock,
|
||||
Top,
|
||||
Bottom,
|
||||
FileChose, RuleBlock, Top, Bottom, Tips, Edit
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
loading: false, //遮罩
|
||||
dialogVisible: false, //新增文件弹窗
|
||||
ruleList: [], //当前生效的规则
|
||||
fileList: [], //选择的文件
|
||||
changedFileList: [], //执行修改后的文件
|
||||
needPreview: false, //需要点击预览
|
||||
applicationRule: null, //当前应用的应用规则模板
|
||||
savePathList: [], //收藏的路径列表
|
||||
curChoosePath: null, //当前选择的收藏路径
|
||||
timer: null, //修改顺序计时器
|
||||
newName: "", //新的文件名
|
||||
currentEditFile: null,
|
||||
showNameEditDialog: false //显示编辑文件弹窗
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
async created () {
|
||||
async created() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
window.isWindows = await HttpUtil.get("/file/isWindows");
|
||||
Bus.$on("refreshSavePathList", this.refreshSavePathList);
|
||||
},
|
||||
methods: {
|
||||
//新增文件
|
||||
async addData (data) {
|
||||
async addData(data) {
|
||||
let existSet = new Set();
|
||||
data.forEach((item) => (item.checked = false));
|
||||
this.fileList.push(...data);
|
||||
this.fileList.forEach(item => existSet.add(item.path + item.name));
|
||||
this.fileList.push(...data.filter(item => !existSet.has(item.path + item.name)));
|
||||
this.fileList = [...this.fileList.sort((a, b) => compareStr(a.name, b.name))];
|
||||
this.dialogVisible = false;
|
||||
this.needPreview = true;
|
||||
await this.showResult();
|
||||
},
|
||||
async ruleUpdate (rules) {
|
||||
async ruleUpdate(rules) {
|
||||
this.ruleList = rules;
|
||||
this.needPreview = true;
|
||||
await this.showResult();
|
||||
},
|
||||
//预览结果
|
||||
async showResult () {
|
||||
async showResult() {
|
||||
this.changedFileList = [];
|
||||
if (!this.checkRuleAndFile()) {
|
||||
return;
|
||||
@ -124,16 +154,15 @@ export default {
|
||||
};
|
||||
this.changedFileList = await HttpUtil.post("/renamer/preview", null, body);
|
||||
this.fileList = [...this.fileList];
|
||||
this.needPreview = false;
|
||||
this.loading = false;
|
||||
},
|
||||
//提交
|
||||
async submit () {
|
||||
async submit() {
|
||||
if (!this.checkRuleAndFile()) {
|
||||
return;
|
||||
}
|
||||
if (this.changedFileList.filter((item) => item.errorMessage).length > 0) {
|
||||
this.$message({ message: "存在错误,无法执行操作", type: "error" });
|
||||
this.$message({message: "存在错误,无法执行操作", type: "error"});
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
@ -143,48 +172,80 @@ export default {
|
||||
};
|
||||
try {
|
||||
await HttpUtil.post("/renamer/submit", null, body);
|
||||
this.$message({ message: "重命名成功", type: "success" });
|
||||
this.$message({message: "重命名成功", type: "success"});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
//删除选中的文件名
|
||||
async deleteCheckedFiles () {
|
||||
//移除选中的文件名
|
||||
async removeCheckedFiles() {
|
||||
this.fileList = this.fileList.filter((item) => !item.checked);
|
||||
this.needPreview = true;
|
||||
await this.showResult();
|
||||
},
|
||||
//delete checked item
|
||||
async deleteCheckedFiles() {
|
||||
let body = this.fileList.filter((item) => item.checked);
|
||||
await HttpUtil.post("/file/deleteBatch", null, body);
|
||||
this.fileList = this.fileList.filter((item) => !item.checked);
|
||||
await this.showResult();
|
||||
},
|
||||
//edit file
|
||||
async editFile() {
|
||||
let list = this.fileList.filter((item) => item.checked);
|
||||
if (list.length === 0 || list.length > 1) {
|
||||
this.$message({message: "只能选择一个进行编辑", type: "warning"});
|
||||
return;
|
||||
}
|
||||
this.newName = list[0].name;
|
||||
this.currentEditFile = list[0];
|
||||
this.showNameEditDialog = true;
|
||||
await this.showResult();
|
||||
},
|
||||
async doEditFile() {
|
||||
if (!this.newName) {
|
||||
this.$message({message: "文件名不能为空", type: "warning"});
|
||||
return;
|
||||
}
|
||||
let target = JSON.parse(JSON.stringify(this.currentEditFile));
|
||||
target.name = this.newName;
|
||||
await HttpUtil.post("/file/rename", null, {source: this.currentEditFile, target});
|
||||
this.currentEditFile.name = this.newName;
|
||||
this.fileList = [...this.fileList];
|
||||
this.currentEditFile = null;
|
||||
this.showNameEditDialog = false;
|
||||
await this.showResult();
|
||||
},
|
||||
//反选
|
||||
selectAllFiles () {
|
||||
selectAllFiles() {
|
||||
this.fileList.forEach((item) => (item.checked = !item.checked));
|
||||
},
|
||||
//检查规则和文件
|
||||
checkRuleAndFile () {
|
||||
if (this.fileList.length == 0) {
|
||||
this.$message({ message: "请选择文件", type: "warning" });
|
||||
checkRuleAndFile() {
|
||||
if (this.fileList.length === 0) {
|
||||
this.$message({message: "请选择文件", type: "warning"});
|
||||
return false;
|
||||
}
|
||||
if (this.ruleList.filter((item) => !item.blocked).length == 0) {
|
||||
this.$message({ message: "无生效规则", type: "warning" });
|
||||
if (this.ruleList.filter((item) => !item.blocked).length === 0) {
|
||||
this.$message({message: "无生效规则", type: "warning"});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
//移动文件顺序
|
||||
async moveIndex (type) {
|
||||
let temps = this.fileList.filter((item) => item.checked == true);
|
||||
if (temps.length == 0) {
|
||||
this.$message({ type: "warning", message: "未选中文件,无法移动" });
|
||||
async moveIndex(type) {
|
||||
let temps = this.fileList.filter((item) => item.checked === true);
|
||||
if (temps.length === 0) {
|
||||
this.$message({type: "warning", message: "未选中文件,无法移动"});
|
||||
return;
|
||||
}
|
||||
if (type == "top") {
|
||||
if (this.fileList.indexOf(temps[0]) == 0) {
|
||||
this.$message({ type: "warning", message: "无法上移" });
|
||||
this.$message({type: "warning", message: "无法上移"});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (this.fileList.indexOf(temps[temps.length - 1]) == this.fileList.length - 1) {
|
||||
this.$message({ type: "warning", message: "无法下移" });
|
||||
this.$message({type: "warning", message: "无法下移"});
|
||||
return;
|
||||
}
|
||||
temps = temps.reverse();
|
||||
@ -197,7 +258,6 @@ export default {
|
||||
this.fileList[newIndex] = temp;
|
||||
}
|
||||
this.fileList = [...this.fileList];
|
||||
this.needPreview = true;
|
||||
if (this.timer != null) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
@ -206,20 +266,20 @@ export default {
|
||||
this.timer = null;
|
||||
}, 1000);
|
||||
},
|
||||
showFileAdd () {
|
||||
showFileAdd() {
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
//点击收藏路径
|
||||
async clickSavePath (item) {
|
||||
async clickSavePath(item) {
|
||||
this.curChoosePath = JSON.parse(item.content);
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
async deleteSavePath (item) {
|
||||
async deleteSavePath(item) {
|
||||
console.log(item);
|
||||
await HttpUtil.delete("/file/path/delete", { id: item.id });
|
||||
await HttpUtil.delete("/file/path/delete", {id: item.id});
|
||||
Bus.$emit("refreshSavePathList");
|
||||
},
|
||||
async refreshSavePathList () {
|
||||
async refreshSavePathList() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
},
|
||||
},
|
||||
@ -230,13 +290,13 @@ export default {
|
||||
* @param a str
|
||||
* @param b str
|
||||
*/
|
||||
function compareStr (a, b) {
|
||||
function compareStr(a, b) {
|
||||
let an = a.length;
|
||||
let bn = b.length;
|
||||
for (let i = 0; i < an;) {
|
||||
let charA = readChar(a, i, an);
|
||||
let charB = readChar(b, i, bn);
|
||||
if (charB.length == 0) {
|
||||
if (charB.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
if (charA !== charB) {
|
||||
@ -255,7 +315,7 @@ function compareStr (a, b) {
|
||||
* @param a a
|
||||
* @param n 数字长度
|
||||
*/
|
||||
function readChar (a, i, n) {
|
||||
function readChar(a, i, n) {
|
||||
let res = "";
|
||||
for (; i < n; i++) {
|
||||
let char = a.charAt(i);
|
||||
|
Loading…
x
Reference in New Issue
Block a user