feat:temp
This commit is contained in:
parent
8e518a614d
commit
670f0258a3
@ -1,18 +1,28 @@
|
||||
import { Context } from "koa";
|
||||
import FileService from "../service/FileService";
|
||||
|
||||
const router = {};
|
||||
|
||||
router["GET /file/query"] = async function (ctx: Context) {
|
||||
ctx.body = FileService.readPath(ctx.query.path as string);
|
||||
};
|
||||
|
||||
router["PUT /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasdf";
|
||||
};
|
||||
|
||||
router["DELETE /plan/:planId"] = async function (ctx: Context) {
|
||||
ctx.body = "";
|
||||
}
|
||||
|
||||
export default router;
|
||||
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);
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { Context } from "koa";
|
||||
|
||||
const router = {};
|
||||
|
||||
router["GET /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasd";
|
||||
};
|
||||
|
||||
router["PUT /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasdf";
|
||||
};
|
||||
|
||||
router["DELETE /plan/:planId"] = async function (ctx: Context) {
|
||||
ctx.body = "";
|
||||
}
|
||||
|
||||
export default router;
|
||||
import { Context } from "koa";
|
||||
|
||||
const router = {};
|
||||
|
||||
router["GET /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasd";
|
||||
};
|
||||
|
||||
router["PUT /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasdf";
|
||||
};
|
||||
|
||||
router["DELETE /plan/:planId"] = async function (ctx: Context) {
|
||||
ctx.body = "";
|
||||
}
|
||||
|
||||
export default router;
|
||||
|
@ -1,13 +1,13 @@
|
||||
{ "name": "nas_backup", "script": "./dist/index.js",
|
||||
"cwd": "./",
|
||||
"env": {
|
||||
"PORT": 8082,
|
||||
"MYSQL_HOST":"localhost",
|
||||
"MYSQL_PORT":3306,
|
||||
"MYSQL_USER":"root",
|
||||
"MYSQL_PASS":"123456"
|
||||
},
|
||||
"log_file": "./log/combined.log",
|
||||
"out_file": "./log/out.log",
|
||||
"error_file": "./error.log"
|
||||
}
|
||||
{ "name": "nas_backup", "script": "./dist/index.js",
|
||||
"cwd": "./",
|
||||
"env": {
|
||||
"PORT": 8082,
|
||||
"MYSQL_HOST":"localhost",
|
||||
"MYSQL_PORT":3306,
|
||||
"MYSQL_USER":"root",
|
||||
"MYSQL_PASS":"123456"
|
||||
},
|
||||
"log_file": "./log/combined.log",
|
||||
"out_file": "./log/out.log",
|
||||
"error_file": "./error.log"
|
||||
}
|
||||
|
@ -1,35 +1,24 @@
|
||||
import * as path from 'path';
|
||||
|
||||
//后台所在绝对路径
|
||||
const rootPath = path.resolve(__dirname, '..');
|
||||
|
||||
let config = {
|
||||
rootPath,
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 8089,
|
||||
urlPrefix: '/backup/api',
|
||||
//是否为windows平台
|
||||
isWindows: process.platform.toLocaleLowerCase().includes("win"),
|
||||
//需要监控的磁盘列表
|
||||
disKCheckList: ["/dev/nvme0n1", "/dev/nvme1n1"],
|
||||
mysqlConfig: {
|
||||
host: process.env.MYSQL_HOST || "localhost",
|
||||
database: "nas_backup",
|
||||
port: process.env.MYSQL_PORT ? parseInt(process.env.MYSQL_PORT) : 3306,
|
||||
user: process.env.MYSQL_USER || "root",
|
||||
password: process.env.MYSQL_PASS || "123456",
|
||||
supportBigNumbers: true,
|
||||
multipleStatements: false
|
||||
},
|
||||
bodyLimit: {
|
||||
formLimit: '2mb',
|
||||
urlencoded: true,
|
||||
multipart: true,
|
||||
formidable: {
|
||||
uploadDir: path.join(rootPath, 'files', 'temp', 'uploads'),
|
||||
keepExtenstions: true,
|
||||
maxFieldsSize: 1024 * 1024
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
import * as path from 'path';
|
||||
|
||||
//后台所在绝对路径
|
||||
const rootPath = path.resolve(__dirname, '..');
|
||||
|
||||
let config = {
|
||||
rootPath,
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 8089,
|
||||
urlPrefix: '/openRenamer/api',
|
||||
//是否为windows平台
|
||||
isWindows: process.platform.toLocaleLowerCase().includes("win"),
|
||||
bodyLimit: {
|
||||
formLimit: '2mb',
|
||||
urlencoded: true,
|
||||
multipart: true,
|
||||
formidable: {
|
||||
uploadDir: path.join(rootPath, 'files', 'temp', 'uploads'),
|
||||
keepExtenstions: true,
|
||||
maxFieldsSize: 1024 * 1024
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
@ -1,32 +1,32 @@
|
||||
import { MysqlUtil } from '../util/MysqlHelper';
|
||||
import History from '../entity/History';
|
||||
import { OkPacket } from 'mysql2';
|
||||
import Plan from 'entity/Plan';
|
||||
|
||||
export default class HistoryDao {
|
||||
/**
|
||||
* 增加一个
|
||||
* @param history history
|
||||
*/
|
||||
static async addOne(history: History): Promise<number> {
|
||||
let sql = `insert into history(createdDate,updatedDate,planId,fileNum,fileSize,speed,startTime,endTime,comment) values(?,?,?,?,?,?,?,?,?)`;
|
||||
let res = await MysqlUtil.pool.execute(sql, [Date.now(), Date.now(), history.planId, history.fileNum, history.fileSize, history.speed, history.startTime, history.endTime, history.comment]);
|
||||
return (res[0] as unknown as OkPacket).insertId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某个plan下所有的历史记录
|
||||
* @param planId planId
|
||||
*/
|
||||
static async deleteByPlanId(planId: number) {
|
||||
await MysqlUtil.pool.execute("delete from history where planId=?", [planId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个备份计划下的备份历史
|
||||
* @param planId planId
|
||||
*/
|
||||
static async getByPlanId(planId: number): Promise<Array<Plan>> {
|
||||
return (await MysqlUtil.pool.query("select * from history where planId=?", planId))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
import { MysqlUtil } from '../util/MysqlHelper';
|
||||
import History from '../entity/History';
|
||||
import { OkPacket } from 'mysql2';
|
||||
import Plan from 'entity/Plan';
|
||||
|
||||
export default class HistoryDao {
|
||||
/**
|
||||
* 增加一个
|
||||
* @param history history
|
||||
*/
|
||||
static async addOne(history: History): Promise<number> {
|
||||
let sql = `insert into history(createdDate,updatedDate,planId,fileNum,fileSize,speed,startTime,endTime,comment) values(?,?,?,?,?,?,?,?,?)`;
|
||||
let res = await MysqlUtil.pool.execute(sql, [Date.now(), Date.now(), history.planId, history.fileNum, history.fileSize, history.speed, history.startTime, history.endTime, history.comment]);
|
||||
return (res[0] as unknown as OkPacket).insertId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某个plan下所有的历史记录
|
||||
* @param planId planId
|
||||
*/
|
||||
static async deleteByPlanId(planId: number) {
|
||||
await MysqlUtil.pool.execute("delete from history where planId=?", [planId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个备份计划下的备份历史
|
||||
* @param planId planId
|
||||
*/
|
||||
static async getByPlanId(planId: number): Promise<Array<Plan>> {
|
||||
return (await MysqlUtil.pool.query("select * from history where planId=?", planId))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
}
|
@ -1,40 +1,40 @@
|
||||
import { MysqlUtil } from '../util/MysqlHelper';
|
||||
import Plan from '../entity/Plan';
|
||||
import { OkPacket } from 'mysql2';
|
||||
|
||||
export default class PlanDao {
|
||||
/**
|
||||
* 新增一个备份计划
|
||||
* @param plan plan
|
||||
*/
|
||||
static async addOne(plan: Plan): Promise<number> {
|
||||
let res = await MysqlUtil.pool.execute("insert into plan(createdDate,updatedDate,planName,description,sourcePath,targetPath,nextLaunchTime,launchInterval,latestHistoryId,ignoreList,holdHistory) values(?,?,?,?,?,?,?,?,?,?,?)"
|
||||
, [Date.now(), Date.now(), plan.planName, plan.description, plan.sourcePath, plan.targetPath, plan.nextLaunchTime, plan.lanuchInterval, plan.latestHistoryId, JSON.stringify(plan.ignoreList), plan.holdHistory]);
|
||||
return (res[0] as unknown as OkPacket).insertId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有待执行的plan
|
||||
*/
|
||||
static async getNeedActionPlan(): Promise<Array<Plan>> {
|
||||
let sql = `select * from plan where nextLaunchTime < ${Date.now()} order by nextLaunchTime`;
|
||||
return (await MysqlUtil.pool.query(sql))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新某个计划的下次执行时间
|
||||
* @param id planId
|
||||
*/
|
||||
static async updateNextlaunchTimeAndLatestHistoryId(planId: number, historyId: number) {
|
||||
await MysqlUtil.pool.execute(`update plan set nextLaunchTime = nextLaunchTime+launchInterval,latestHistoryId=? where planId=?`
|
||||
, [historyId, planId]);
|
||||
}
|
||||
|
||||
static async deleteByPlanId(planId: number) {
|
||||
await MysqlUtil.pool.execute(`delete from plan where planid=?`, [planId]);
|
||||
}
|
||||
|
||||
static async getAll(): Promise<Array<Plan>> {
|
||||
return (await MysqlUtil.pool.query("select * from plan"))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
import { MysqlUtil } from '../util/MysqlHelper';
|
||||
import Plan from '../entity/Plan';
|
||||
import { OkPacket } from 'mysql2';
|
||||
|
||||
export default class PlanDao {
|
||||
/**
|
||||
* 新增一个备份计划
|
||||
* @param plan plan
|
||||
*/
|
||||
static async addOne(plan: Plan): Promise<number> {
|
||||
let res = await MysqlUtil.pool.execute("insert into plan(createdDate,updatedDate,planName,description,sourcePath,targetPath,nextLaunchTime,launchInterval,latestHistoryId,ignoreList,holdHistory) values(?,?,?,?,?,?,?,?,?,?,?)"
|
||||
, [Date.now(), Date.now(), plan.planName, plan.description, plan.sourcePath, plan.targetPath, plan.nextLaunchTime, plan.lanuchInterval, plan.latestHistoryId, JSON.stringify(plan.ignoreList), plan.holdHistory]);
|
||||
return (res[0] as unknown as OkPacket).insertId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有待执行的plan
|
||||
*/
|
||||
static async getNeedActionPlan(): Promise<Array<Plan>> {
|
||||
let sql = `select * from plan where nextLaunchTime < ${Date.now()} order by nextLaunchTime`;
|
||||
return (await MysqlUtil.pool.query(sql))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新某个计划的下次执行时间
|
||||
* @param id planId
|
||||
*/
|
||||
static async updateNextlaunchTimeAndLatestHistoryId(planId: number, historyId: number) {
|
||||
await MysqlUtil.pool.execute(`update plan set nextLaunchTime = nextLaunchTime+launchInterval,latestHistoryId=? where planId=?`
|
||||
, [historyId, planId]);
|
||||
}
|
||||
|
||||
static async deleteByPlanId(planId: number) {
|
||||
await MysqlUtil.pool.execute(`delete from plan where planid=?`, [planId]);
|
||||
}
|
||||
|
||||
static async getAll(): Promise<Array<Plan>> {
|
||||
return (await MysqlUtil.pool.query("select * from plan"))[0] as unknown as Array<Plan>;
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
export default class History {
|
||||
historyId: number = 0;
|
||||
planId: number = 0;
|
||||
fileNum: number = 0;
|
||||
fileSize: number = 0;
|
||||
speed: number = 0;
|
||||
startTime: number = 0;
|
||||
endTime: number = 0;
|
||||
comment: string = "";
|
||||
export default class History {
|
||||
historyId: number = 0;
|
||||
planId: number = 0;
|
||||
fileNum: number = 0;
|
||||
fileSize: number = 0;
|
||||
speed: number = 0;
|
||||
startTime: number = 0;
|
||||
endTime: number = 0;
|
||||
comment: string = "";
|
||||
}
|
@ -1,22 +1,22 @@
|
||||
export default class Plan {
|
||||
/**
|
||||
创建时间
|
||||
*/
|
||||
createdDate: number;
|
||||
/**
|
||||
更新时间
|
||||
*/
|
||||
updateDate: number;
|
||||
planId: number = 0;
|
||||
planName: string = "";
|
||||
description: string = "";
|
||||
//保留的历史份数,最小1
|
||||
holdHistory: number = 1;
|
||||
sourcePath: string = "";
|
||||
targetPath: string = "";
|
||||
nextLaunchTime: number = 0;
|
||||
lanuchInterval: number = 0;
|
||||
latestHistoryId: number = 0;
|
||||
ignoreList: Array<String> = [];
|
||||
latestHistoryDetail: Object | null = null;
|
||||
export default class Plan {
|
||||
/**
|
||||
创建时间
|
||||
*/
|
||||
createdDate: number;
|
||||
/**
|
||||
更新时间
|
||||
*/
|
||||
updateDate: number;
|
||||
planId: number = 0;
|
||||
planName: string = "";
|
||||
description: string = "";
|
||||
//保留的历史份数,最小1
|
||||
holdHistory: number = 1;
|
||||
sourcePath: string = "";
|
||||
targetPath: string = "";
|
||||
nextLaunchTime: number = 0;
|
||||
lanuchInterval: number = 0;
|
||||
latestHistoryId: number = 0;
|
||||
ignoreList: Array<String> = [];
|
||||
latestHistoryDetail: Object | null = null;
|
||||
}
|
@ -29,8 +29,11 @@ app.use(handleError);
|
||||
|
||||
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
|
||||
(async () => {
|
||||
await SqliteUtil.createPool(config.mysqlConfig);
|
||||
await SqliteUtil.createPool();
|
||||
app.listen(config.port);
|
||||
log.info(`server listened `, config.port);
|
||||
})();
|
||||
|
||||
app.on("error", (error) => {
|
||||
console.error(error);
|
||||
})
|
||||
|
@ -1,45 +1,58 @@
|
||||
import config from '../config';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
import ProcessHelper from '../util/ProcesHelper';
|
||||
import FileObj from '../vo/FileObj';
|
||||
|
||||
class FileService {
|
||||
|
||||
static async readPath(pathStr: string): Promise<Array<FileObj>> {
|
||||
let fileList = new Array();
|
||||
if (pathStr.trim().length == 0) {
|
||||
//获取根目录路径
|
||||
if (config.isWindows) {
|
||||
//windows下
|
||||
let std: string = (await ProcessHelper.exec("wmic logicaldisk get caption") as Object)['stdout'].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 {
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
let resList = new Array();
|
||||
for (let index in fileList) {
|
||||
try {
|
||||
let stat = await fs.stat(path.join(pathStr, fileList[index]));
|
||||
resList.push(new FileObj(fileList[index], stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
return resList;
|
||||
}
|
||||
|
||||
static async createPath(pathStr: string) {
|
||||
await fs.ensureDir(pathStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default FileService;
|
||||
import config from '../config';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
import ProcessHelper from '../util/ProcesHelper';
|
||||
import FileObj from '../vo/FileObj';
|
||||
|
||||
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')) as Object)['stdout'].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 {
|
||||
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) => a.name.localeCompare(b.name)).push(...files.sort((a, b) => a.name.localeCompare(b.name)));
|
||||
return folderList;
|
||||
}
|
||||
|
||||
static async checkExist(pathStr: string) {
|
||||
return await fs.pathExists(pathStr);
|
||||
}
|
||||
}
|
||||
|
||||
export default FileService;
|
||||
|
@ -1,15 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"noImplicitAny": false,
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl":".",
|
||||
"rootDir": "./",
|
||||
"watch": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": false,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"noImplicitAny": false,
|
||||
"module": "commonjs",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl":".",
|
||||
"rootDir": "./",
|
||||
"watch": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": false,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
@ -1,108 +1,108 @@
|
||||
import mysql from "mysql2/promise";
|
||||
import config from '../config';
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from 'path';
|
||||
import log from '../util/LogUtil';
|
||||
|
||||
const HISTORY_NAME = "history.json";
|
||||
|
||||
interface Res {
|
||||
rows: any;
|
||||
fields: mysql.FieldPacket;
|
||||
}
|
||||
|
||||
class MysqlUtil {
|
||||
public static pool: mysql.Pool = null;
|
||||
|
||||
static async createPool(mysqlConfig: any) {
|
||||
MysqlUtil.pool = await mysql.createPool(mysqlConfig);
|
||||
let basePath = path.join(config.rootPath, "sqls");
|
||||
let hisPath = path.join(basePath, HISTORY_NAME);
|
||||
let history: Array<string>;
|
||||
if (fs.existsSync(hisPath)) {
|
||||
history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
|
||||
} else {
|
||||
history = new Array();
|
||||
}
|
||||
//执行数据库
|
||||
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
|
||||
let error = null;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (history.indexOf(files[i]) > -1) {
|
||||
log.info("sql无需重复执行:", files[i]);
|
||||
continue;
|
||||
}
|
||||
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
|
||||
try {
|
||||
let sql = "";
|
||||
for (let j = 0; j < sqlLines.length; j++) {
|
||||
sql = sql + sqlLines[j];
|
||||
if (sqlLines[j].endsWith(";")) {
|
||||
await MysqlUtil.pool.execute(sql);
|
||||
sql = "";
|
||||
}
|
||||
}
|
||||
log.info("sql执行成功:", files[i]);
|
||||
history.push(files[i]);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await fs.writeFile(hisPath, JSON.stringify(history));
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async getRows(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Array<any>> {
|
||||
return (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
}
|
||||
|
||||
|
||||
static async getRow(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
|
||||
let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
return rows.length > 0 ? rows[0] : null;
|
||||
}
|
||||
|
||||
static async getSingle(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
|
||||
let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
if (rows.length == 0) {
|
||||
return null;
|
||||
}
|
||||
let row = rows[0];
|
||||
return row[Object.keys(row)[0]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static async execute(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Res> {
|
||||
let res: any = {};
|
||||
if (connection == null) {
|
||||
let [rows, fields] = await MysqlUtil.pool.query(sql, params);
|
||||
res['rows'] = fields === undefined ? null : rows;
|
||||
res['fields'] = fields === undefined ? rows : fields;
|
||||
} else {
|
||||
let [rows, fields] = await connection.query(sql, params);
|
||||
res['rows'] = rows;
|
||||
res['fields'] = fields;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static async test() {
|
||||
let connection = await MysqlUtil.pool.getConnection();
|
||||
connection.beginTransaction();
|
||||
connection.query(`insert into url value(6,"GET","asd","public")`);
|
||||
connection.query(`insert into url value(7,"GET","asd","public")`);
|
||||
await connection.commit();
|
||||
connection.release();
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
MysqlUtil,
|
||||
Res,
|
||||
mysql
|
||||
import mysql from "mysql2/promise";
|
||||
import config from '../config';
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from 'path';
|
||||
import log from '../util/LogUtil';
|
||||
|
||||
const HISTORY_NAME = "history.json";
|
||||
|
||||
interface Res {
|
||||
rows: any;
|
||||
fields: mysql.FieldPacket;
|
||||
}
|
||||
|
||||
class MysqlUtil {
|
||||
public static pool: mysql.Pool = null;
|
||||
|
||||
static async createPool(mysqlConfig: any) {
|
||||
MysqlUtil.pool = await mysql.createPool(mysqlConfig);
|
||||
let basePath = path.join(config.rootPath, "sqls");
|
||||
let hisPath = path.join(basePath, HISTORY_NAME);
|
||||
let history: Array<string>;
|
||||
if (fs.existsSync(hisPath)) {
|
||||
history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
|
||||
} else {
|
||||
history = new Array();
|
||||
}
|
||||
//执行数据库
|
||||
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
|
||||
let error = null;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (history.indexOf(files[i]) > -1) {
|
||||
log.info("sql无需重复执行:", files[i]);
|
||||
continue;
|
||||
}
|
||||
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
|
||||
try {
|
||||
let sql = "";
|
||||
for (let j = 0; j < sqlLines.length; j++) {
|
||||
sql = sql + sqlLines[j];
|
||||
if (sqlLines[j].endsWith(";")) {
|
||||
await MysqlUtil.pool.execute(sql);
|
||||
sql = "";
|
||||
}
|
||||
}
|
||||
log.info("sql执行成功:", files[i]);
|
||||
history.push(files[i]);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await fs.writeFile(hisPath, JSON.stringify(history));
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async getRows(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Array<any>> {
|
||||
return (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
}
|
||||
|
||||
|
||||
static async getRow(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
|
||||
let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
return rows.length > 0 ? rows[0] : null;
|
||||
}
|
||||
|
||||
static async getSingle(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
|
||||
let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
|
||||
if (rows.length == 0) {
|
||||
return null;
|
||||
}
|
||||
let row = rows[0];
|
||||
return row[Object.keys(row)[0]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static async execute(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Res> {
|
||||
let res: any = {};
|
||||
if (connection == null) {
|
||||
let [rows, fields] = await MysqlUtil.pool.query(sql, params);
|
||||
res['rows'] = fields === undefined ? null : rows;
|
||||
res['fields'] = fields === undefined ? rows : fields;
|
||||
} else {
|
||||
let [rows, fields] = await connection.query(sql, params);
|
||||
res['rows'] = rows;
|
||||
res['fields'] = fields;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static async test() {
|
||||
let connection = await MysqlUtil.pool.getConnection();
|
||||
connection.beginTransaction();
|
||||
connection.query(`insert into url value(6,"GET","asd","public")`);
|
||||
connection.query(`insert into url value(7,"GET","asd","public")`);
|
||||
await connection.commit();
|
||||
connection.release();
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
MysqlUtil,
|
||||
Res,
|
||||
mysql
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
|
||||
class NumberUtil {
|
||||
static getRandom(min: number, max: number): number {
|
||||
return Math.floor((Math.random() * (max - min + 1) + min));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NumberUtil {
|
||||
static getRandom(min: number, max: number): number {
|
||||
return Math.floor((Math.random() * (max - min + 1) + min));
|
||||
}
|
||||
}
|
||||
|
||||
export default NumberUtil;
|
@ -1,24 +1,24 @@
|
||||
import * as childPrecess from 'child_process';
|
||||
|
||||
class ProcessHelper {
|
||||
static exec(cmd): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
childPrecess.exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} if (stderr) {
|
||||
reject(stderr);
|
||||
} else {
|
||||
resolve(stdout)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// (async()=>{
|
||||
// let res= await ProcessHelper.exec('cd /d e://workspace&&dir');
|
||||
// console.log(res);
|
||||
// })()
|
||||
|
||||
import * as childPrecess from 'child_process';
|
||||
|
||||
class ProcessHelper {
|
||||
static exec(cmd): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
childPrecess.exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} if (stderr) {
|
||||
reject(stderr);
|
||||
} else {
|
||||
resolve(stdout)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// (async()=>{
|
||||
// let res= await ProcessHelper.exec('cd /d e://workspace&&dir');
|
||||
// console.log(res);
|
||||
// })()
|
||||
|
||||
export default ProcessHelper
|
@ -1,59 +1,59 @@
|
||||
import sqlite3 from 'sqlite3';
|
||||
import { open, Database } from 'sqlite';
|
||||
import config from '../config';
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from 'path';
|
||||
import log from './LogUtil';
|
||||
|
||||
const HISTORY_NAME = "history.json";
|
||||
|
||||
|
||||
class MysqlUtil {
|
||||
public static pool: Database = null;
|
||||
|
||||
static async createPool(mysqlConfig: any) {
|
||||
MysqlUtil.pool = await open({
|
||||
filename: path.join(config.rootPath, "database.db"),
|
||||
driver: sqlite3.Database
|
||||
});
|
||||
let basePath = path.join(config.rootPath, "sqls");
|
||||
let hisPath = path.join(basePath, HISTORY_NAME);
|
||||
let history: Array<string>;
|
||||
if (fs.existsSync(hisPath)) {
|
||||
history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
|
||||
} else {
|
||||
history = new Array();
|
||||
}
|
||||
//执行数据库
|
||||
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
|
||||
let error = null;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (history.indexOf(files[i]) > -1) {
|
||||
log.info("sql无需重复执行:", files[i]);
|
||||
continue;
|
||||
}
|
||||
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
|
||||
try {
|
||||
let sql = "";
|
||||
for (let j = 0; j < sqlLines.length; j++) {
|
||||
sql = sql + sqlLines[j];
|
||||
if (sqlLines[j].endsWith(";")) {
|
||||
await MysqlUtil.pool.exec(sql);
|
||||
sql = "";
|
||||
}
|
||||
}
|
||||
log.info("sql执行成功:", files[i]);
|
||||
history.push(files[i]);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await fs.writeFile(hisPath, JSON.stringify(history));
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MysqlUtil;
|
||||
import sqlite3 from 'sqlite3';
|
||||
import { open, Database } from 'sqlite';
|
||||
import config from '../config';
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from 'path';
|
||||
import log from './LogUtil';
|
||||
|
||||
const HISTORY_NAME = "history.json";
|
||||
|
||||
|
||||
class MysqlUtil {
|
||||
public static pool: Database = null;
|
||||
|
||||
static async createPool() {
|
||||
MysqlUtil.pool = await open({
|
||||
filename: path.join(config.rootPath, "database.db"),
|
||||
driver: sqlite3.Database
|
||||
});
|
||||
let basePath = path.join(config.rootPath, "sqls");
|
||||
let hisPath = path.join(basePath, HISTORY_NAME);
|
||||
let history: Array<string>;
|
||||
if (fs.existsSync(hisPath)) {
|
||||
history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
|
||||
} else {
|
||||
history = new Array();
|
||||
}
|
||||
//执行数据库
|
||||
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
|
||||
let error = null;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
if (history.indexOf(files[i]) > -1) {
|
||||
log.info("sql无需重复执行:", files[i]);
|
||||
continue;
|
||||
}
|
||||
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
|
||||
try {
|
||||
let sql = "";
|
||||
for (let j = 0; j < sqlLines.length; j++) {
|
||||
sql = sql + sqlLines[j];
|
||||
if (sqlLines[j].endsWith(";")) {
|
||||
await MysqlUtil.pool.exec(sql);
|
||||
sql = "";
|
||||
}
|
||||
}
|
||||
log.info("sql执行成功:", files[i]);
|
||||
history.push(files[i]);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await fs.writeFile(hisPath, JSON.stringify(history));
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MysqlUtil;
|
||||
|
@ -1,22 +1,22 @@
|
||||
import moment from 'moment';
|
||||
class TimeUtil {
|
||||
/**
|
||||
* 获取今天的零点
|
||||
*/
|
||||
static getZeroTime(): Date {
|
||||
return moment()
|
||||
.millisecond(0)
|
||||
.second(0)
|
||||
.minute(0)
|
||||
.hour(0)
|
||||
.toDate();
|
||||
}
|
||||
|
||||
static async sleep(duration: number): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => resolve(), duration);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default TimeUtil;
|
||||
import moment from 'moment';
|
||||
class TimeUtil {
|
||||
/**
|
||||
* 获取今天的零点
|
||||
*/
|
||||
static getZeroTime(): Date {
|
||||
return moment()
|
||||
.millisecond(0)
|
||||
.second(0)
|
||||
.minute(0)
|
||||
.hour(0)
|
||||
.toDate();
|
||||
}
|
||||
|
||||
static async sleep(duration: number): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => resolve(), duration);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default TimeUtil;
|
||||
|
@ -1,14 +1,14 @@
|
||||
import path, { dirname } from 'path'
|
||||
|
||||
class pathUtil {
|
||||
static getPath(pathStr) {
|
||||
return path.resolve(pathUtil.getRootPath(), pathStr);
|
||||
}
|
||||
|
||||
static getRootPath() {
|
||||
return path.resolve(__dirname, '..');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import path, { dirname } from 'path'
|
||||
|
||||
class pathUtil {
|
||||
static getPath(pathStr) {
|
||||
return path.resolve(pathUtil.getRootPath(), pathStr);
|
||||
}
|
||||
|
||||
static getRootPath() {
|
||||
return path.resolve(__dirname, '..');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default pathUtil
|
@ -3,6 +3,10 @@ export default class FileObj {
|
||||
* 文件名
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 所属路径
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* 是否文件夹
|
||||
*/
|
||||
@ -17,8 +21,9 @@ export default class FileObj {
|
||||
updatedTime: number;
|
||||
|
||||
|
||||
constructor(name, isFolder, createdTime, updatedTime) {
|
||||
constructor(name, path, isFolder, createdTime, updatedTime) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.isFolder = isFolder;
|
||||
this.createdTime = createdTime;
|
||||
this.updatedTime = updatedTime;
|
||||
|
1
openRenamerFront/.gitignore
vendored
1
openRenamerFront/.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
package-lock.json
|
||||
|
||||
|
||||
# local env files
|
||||
|
27724
openRenamerFront/package-lock.json
generated
27724
openRenamerFront/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"core-js": "^3.6.5",
|
||||
"element-plus": "^1.0.2-beta.48",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
},
|
||||
|
@ -1,11 +1,27 @@
|
||||
<template>
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</div>
|
||||
<el-menu
|
||||
:default-active="activeIndex"
|
||||
class="el-menu-demo"
|
||||
mode="horizontal"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item index="dealCenter">处理中心</el-menu-item>
|
||||
<el-menu-item index="history">历史记录</el-menu-item>
|
||||
</el-menu>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Home",
|
||||
data() {
|
||||
return {
|
||||
activeIndex: "dealCenter",
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
|
129
openRenamerFront/src/components/FileChose.vue
Normal file
129
openRenamerFront/src/components/FileChose.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="main">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item
|
||||
><a @click.prevent="breadcrumbClick(-1)">根</a></el-breadcrumb-item
|
||||
>
|
||||
<el-breadcrumb-item v-for="(item, index) in pathList" :key="index">
|
||||
<a
|
||||
v-if="index < pathList.length - 1"
|
||||
@click.prevent="breadcrumbClick(index)"
|
||||
>{{ item }}</a
|
||||
>
|
||||
<span v-else>{{ item }}</span>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
|
||||
<div class="fileList">
|
||||
<div>
|
||||
<el-button type="primary" @click="selectAll(true)" size="mini"
|
||||
>全选</el-button
|
||||
>
|
||||
<el-button type="primary" @click="selectAll(false)" size="mini"
|
||||
>全不选</el-button
|
||||
>
|
||||
</div>
|
||||
<div v-for="(item, index) in fileList" :key="index">
|
||||
<span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{
|
||||
item.name
|
||||
}}</span>
|
||||
<el-checkbox v-model="item.checked" v-else>{{ item.name }}</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<el-button type="primary" @click="submit">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HttpUtil from "../utils/HttpUtil";
|
||||
export default {
|
||||
name: "FileChose",
|
||||
data() {
|
||||
return {
|
||||
isWindows: false,
|
||||
fileList: [], //路径下的文件节点
|
||||
chosedFileList: [], //选中的文件节点
|
||||
pathList: [], //选择的路径
|
||||
loading: false, //加载
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.isWindows = await HttpUtil.get("/file/isWindows");
|
||||
await this.breadcrumbClick(-1);
|
||||
},
|
||||
methods: {
|
||||
//点击面包蟹
|
||||
async breadcrumbClick(index) {
|
||||
this.loading = true;
|
||||
let path = this.createPath(index);
|
||||
let fileList = await HttpUtil.get("/file/query", {
|
||||
path: encodeURIComponent(path),
|
||||
showHidden: false,
|
||||
});
|
||||
fileList.forEach((item) => (item.checked = false));
|
||||
this.fileList = fileList;
|
||||
this.loading = false;
|
||||
return false;
|
||||
},
|
||||
//文件列表点击
|
||||
fileClick(item) {
|
||||
if (item.isFolder) {
|
||||
this.pathList.push(item.name);
|
||||
this.breadcrumbClick(this.pathList.length);
|
||||
} else {
|
||||
item.checked = !item.checked;
|
||||
}
|
||||
},
|
||||
//全选
|
||||
selectAll(status) {
|
||||
this.fileList
|
||||
.filter((item) => !item.isFolder)
|
||||
.forEach((item) => (item.checked = status));
|
||||
},
|
||||
//根据index构建路径
|
||||
createPath(index) {
|
||||
let path;
|
||||
if (index == -1) {
|
||||
path = "/";
|
||||
this.pathList = [];
|
||||
} else {
|
||||
this.pathList = this.pathList.slice(0, index + 1);
|
||||
let str = this.pathList.join(this.isWindows ? "\\" : "/");
|
||||
path = this.isWindows ? str : "/" + str;
|
||||
}
|
||||
return path;
|
||||
},
|
||||
//点击确定
|
||||
submit() {
|
||||
let chosedFiles = this.fileList.filter((item) => item.checked);
|
||||
if (chosedFiles.length == 0) {
|
||||
this.$message({ message: "未选择文件", type: "warning" });
|
||||
return;
|
||||
}
|
||||
this.$emit("addData", chosedFiles);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
height: 65vh;
|
||||
}
|
||||
.fileList {
|
||||
padding: 1em;
|
||||
text-align: left;
|
||||
height: 80%;
|
||||
overflow: hidden auto;
|
||||
|
||||
.folder {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
display: inline-block;
|
||||
min-width: 3em;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,97 +1,5 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="hello">hello World!</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
82
openRenamerFront/src/components/Rule.vue
Normal file
82
openRenamerFront/src/components/Rule.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<el-menu
|
||||
style="width: 8em"
|
||||
mode="vertical"
|
||||
:default-active="currentIndex"
|
||||
@select="menuChange"
|
||||
>
|
||||
<el-menu-item :disabled="editRule" index="insert">插入</el-menu-item>
|
||||
<el-menu-item :disabled="editRule" index="delete">删除</el-menu-item>
|
||||
<!-- <el-menu-item index="replace">替换</el-menu-item> -->
|
||||
<el-menu-item :disabled="editRule" index="serialization"
|
||||
>序列化</el-menu-item
|
||||
>
|
||||
</el-menu>
|
||||
<div class="rule">
|
||||
<insert-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-if="currentIndex == 'insert'"
|
||||
/>
|
||||
<delete-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-else-if="currentIndex == 'delete'"
|
||||
/>
|
||||
<serialization-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-else-if="currentIndex == 'serialization'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button type="primary" @click="submit">确定</el-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InsertRule from "./rules/InsertRule.vue";
|
||||
import DeleteRule from "./rules/DeleteRule.vue";
|
||||
import SerializationRule from "./rules/SerializationRule.vue";
|
||||
export default {
|
||||
components: { InsertRule, DeleteRule, SerializationRule },
|
||||
props: ["editRule"],
|
||||
name: "Rule",
|
||||
data() {
|
||||
return {
|
||||
currentIndex: "insert",
|
||||
options: [{ label: "插入", value: "insert" }],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.currentIndex = this.editRule.type;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
menuChange(index) {
|
||||
this.currentIndex = index;
|
||||
},
|
||||
submit() {
|
||||
let data = this.$refs["rule"].exportObj();
|
||||
if (data != null) {
|
||||
this.$emit("ruleAdd", data);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
display: flex;
|
||||
height: 65vh;
|
||||
text-align: left;
|
||||
|
||||
.rule {
|
||||
padding: 5px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
197
openRenamerFront/src/components/rules/DeleteRule.vue
Normal file
197
openRenamerFront/src/components/rules/DeleteRule.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">部分删除:</span>
|
||||
<div class="location">
|
||||
<div>
|
||||
<div>开始</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.start.type"
|
||||
label="location"
|
||||
:disabled="deleteAll"
|
||||
>位置:</el-radio
|
||||
>
|
||||
<el-input-number
|
||||
:min="1"
|
||||
size="small"
|
||||
:disabled="deleteAll"
|
||||
v-model="startIndex"
|
||||
/>
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.start.type"
|
||||
label="text"
|
||||
:disabled="deleteAll"
|
||||
>文本:</el-radio
|
||||
>
|
||||
<el-input v-model="startText" size="small" :disabled="deleteAll" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 4em">
|
||||
<div>结束</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="location"
|
||||
:disabled="deleteAll"
|
||||
>位置:</el-radio
|
||||
>
|
||||
<el-input-number
|
||||
size="small"
|
||||
:disabled="deleteAll"
|
||||
v-model="endIndex"
|
||||
/>
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="text"
|
||||
:disabled="deleteAll"
|
||||
>文本:</el-radio
|
||||
>
|
||||
<el-input v-model="endText" size="small" :disabled="deleteAll" />
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="end"
|
||||
:disabled="untilEnd"
|
||||
>直到末尾</el-radio
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="left">全部删除:</div>
|
||||
<el-switch v-model="deleteAll" @change="allDeleteChange" />
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DeleteRule",
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "delete",
|
||||
message: "",
|
||||
data: {
|
||||
type: "deletePart",
|
||||
start: {
|
||||
type: "location",
|
||||
value: "",
|
||||
},
|
||||
end: {
|
||||
type: "location",
|
||||
value: "",
|
||||
},
|
||||
ignorePostfix: false,
|
||||
},
|
||||
},
|
||||
startIndex: 1,
|
||||
endIndex: 1,
|
||||
startText: "",
|
||||
endText: "",
|
||||
deleteAll: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
if (this.ruleObj.data.type == "deletePart") {
|
||||
if (this.ruleObj.data.start.type == "location") {
|
||||
this.startIndex = parseInt(this.ruleObj.data.start.value);
|
||||
} else {
|
||||
this.startText = this.ruleObj.data.start.value;
|
||||
}
|
||||
if (this.ruleObj.data.end.type == "location") {
|
||||
this.endIndex = parseInt(this.ruleObj.data.end.value);
|
||||
} else {
|
||||
this.endText = this.ruleObj.data.end.value;
|
||||
}
|
||||
} else {
|
||||
this.deleteAll = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
if (this.ruleObj.data.type.length == 0) {
|
||||
this.$message({ message: "请填写完整", type: "warning" });
|
||||
return null;
|
||||
}
|
||||
if (this.ruleObj.data.type == "deletePart") {
|
||||
if (
|
||||
(this.ruleObj.data.start.type == "text" &&
|
||||
this.startText.length == 0) ||
|
||||
(this.ruleObj.data.start.type == "text" && this.startText.length == 0)
|
||||
) {
|
||||
this.$message({
|
||||
message: "开始或者结束文本不能为空",
|
||||
type: "warning",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
this.ruleObj.data.start.value =
|
||||
this.ruleObj.data.start.type == "location"
|
||||
? this.startIndex.toString()
|
||||
: this.startText;
|
||||
this.ruleObj.data.end.value =
|
||||
this.ruleObj.data.end.type == "location"
|
||||
? this.endIndex.toString()
|
||||
: this.endText;
|
||||
let message = `删除:`;
|
||||
if (this.deleteAll) {
|
||||
message += "全部删除";
|
||||
} else {
|
||||
message += `从"${this.ruleObj.data.start.value}"到"${
|
||||
this.ruleObj.data.end.type == "untilEnd"
|
||||
? "末尾"
|
||||
: this.ruleObj.data.end.value
|
||||
}"`;
|
||||
}
|
||||
this.ruleObj.message = message;
|
||||
return this.ruleObj;
|
||||
},
|
||||
allDeleteChange(val) {
|
||||
console.log(val);
|
||||
this.deleteAll = val;
|
||||
this.ruleObj.data.type = val ? "deleteAll" : "deletePart";
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
103
openRenamerFront/src/components/rules/InsertRule.vue
Normal file
103
openRenamerFront/src/components/rules/InsertRule.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">插入:</span>
|
||||
<el-input style="flex: 1" v-model="ruleObj.data.insertContent" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">位置:</span>
|
||||
<div class="location">
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="front"
|
||||
>前缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="backend"
|
||||
>后缀</el-radio
|
||||
>
|
||||
<el-radio style="margin-top: 1em" v-model="ruleObj.data.type" label="at"
|
||||
>位置:<el-input-number size="mini" v-model="ruleObj.data.atInput" />
|
||||
|
||||
<el-switch
|
||||
v-model="ruleObj.data.atIsRightToleft"
|
||||
:min="1"
|
||||
active-text="从右到左"
|
||||
inactive-text="从左到右"
|
||||
/>
|
||||
</el-radio>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="replace"
|
||||
>替换当前文件名</el-radio
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "InsertRule",
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "insert",
|
||||
message: "",
|
||||
data: {
|
||||
insertContent: "",
|
||||
type: "",
|
||||
atInput: 0,
|
||||
atIsRightToleft: false,
|
||||
ignorePostfix: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
console.log(this.editRule);
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
if (
|
||||
this.ruleObj.data.insertContent.length == 0 ||
|
||||
this.ruleObj.data.type.length == 0
|
||||
) {
|
||||
this.$message({ message: "请填写完整", type: "warning" });
|
||||
return null;
|
||||
}
|
||||
this.ruleObj.message = `插入:"${this.ruleObj.data.insertContent}"`;
|
||||
return this.ruleObj;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
justify-content: left;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
114
openRenamerFront/src/components/rules/SerializationRule.vue
Normal file
114
openRenamerFront/src/components/rules/SerializationRule.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">起始数:</span>
|
||||
<div class="right">
|
||||
<el-input-number :min="1" size="small" v-model="ruleObj.data.start" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">增量:</span>
|
||||
<div class="right">
|
||||
<el-input-number :min="1" size="small" v-model="ruleObj.data.increment" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">填充0补足:</span>
|
||||
<div class="right">
|
||||
<el-switch v-model="ruleObj.data.addZero" />
|
||||
<el-input-number
|
||||
size="small"
|
||||
:min="1"
|
||||
:disabled="!ruleObj.data.addZero"
|
||||
v-model="ruleObj.data.numLength"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">位置:</span>
|
||||
<div class="location">
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="front"
|
||||
>前缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="backend"
|
||||
>后缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="at"
|
||||
>位置:<el-input-number
|
||||
size="mini"
|
||||
:min="1"
|
||||
:disabled="ruleObj.data.insertType !== 'at'"
|
||||
v-model="ruleObj.data.insertValue"
|
||||
/>
|
||||
</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SerializationRule",
|
||||
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "serialization",
|
||||
message: "",
|
||||
data: {
|
||||
start: 1,
|
||||
increment: 1,
|
||||
addZero: false,
|
||||
numLength: 1,
|
||||
ignorePostfix: false,
|
||||
insertType: "front",
|
||||
insertValue: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
this.ruleObj.message = `序列化:从开始${this.ruleObj.data.start},增量${this.ruleObj.data.increment}`;
|
||||
return this.ruleObj;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
justify-content: left;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,5 +1,9 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/lib/theme-chalk/index.css";
|
||||
|
||||
createApp(App).use(router).mount("#app");
|
||||
const vueInstance = createApp(App);
|
||||
vueInstance.use(router).use(ElementPlus).mount("#app");
|
||||
window.vueInstance = vueInstance;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import Home from "../views/Home.vue";
|
||||
import Home from "../views/home/Home.vue";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as http from "axios";
|
||||
import router from "../router/index";
|
||||
|
||||
/**
|
||||
* 请求
|
||||
@ -11,10 +10,10 @@ import router from "../router/index";
|
||||
* @param {*} redirect 接口返回未认证是否跳转到登陆
|
||||
* @returns 数据
|
||||
*/
|
||||
async function request(url, method, params, body, isForm, redirect) {
|
||||
async function request(url, method, params, body, isForm) {
|
||||
let options = {
|
||||
url,
|
||||
baseURL: "/bookmark/api",
|
||||
baseURL: "/openRenamer/api",
|
||||
method,
|
||||
params,
|
||||
// headers: {
|
||||
@ -35,30 +34,7 @@ async function request(url, method, params, body, isForm, redirect) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const { code, data, message } = res.data;
|
||||
if (code === 1) {
|
||||
return data;
|
||||
} else if (code === -1 && redirect) {
|
||||
// 跳转到登陆页
|
||||
window.vueInstance.$message.error("您尚未登陆,请先登陆");
|
||||
router.replace(
|
||||
`/public/login?redirect=${encodeURIComponent(
|
||||
router.currentRoute.fullPath
|
||||
)}`
|
||||
);
|
||||
throw new Error(message);
|
||||
} else if (code === 0) {
|
||||
//通用异常,使用
|
||||
window.vueInstance.$notification.error({
|
||||
message: "异常",
|
||||
description: message,
|
||||
});
|
||||
throw new Error(message);
|
||||
} else if (code === -2) {
|
||||
//表单异常,使用message提示
|
||||
window.vueInstance.$message.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
return res.data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,8 +43,8 @@ async function request(url, method, params, body, isForm, redirect) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 未登陆是否跳转到登陆页
|
||||
*/
|
||||
async function get(url, params = null, redirect = true) {
|
||||
return request(url, "get", params, null, false, redirect);
|
||||
async function get(url, params = null) {
|
||||
return request(url, "get", params, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,8 +55,8 @@ async function get(url, params = null, redirect = true) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function post(url, params, body, isForm = false, redirect = true) {
|
||||
return request(url, "post", params, body, isForm, redirect);
|
||||
async function post(url, params, body, isForm = false) {
|
||||
return request(url, "post", params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,8 +67,8 @@ async function post(url, params, body, isForm = false, redirect = true) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function put(url, params, body, isForm = false, redirect = true) {
|
||||
return request(url, "put", params, body, isForm, redirect);
|
||||
async function put(url, params, body, isForm = false) {
|
||||
return request(url, "put", params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,8 +77,8 @@ async function put(url, params, body, isForm = false, redirect = true) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function deletes(url, params = null, redirect = true) {
|
||||
return request(url, "delete", params, null, redirect);
|
||||
async function deletes(url, params = null) {
|
||||
return request(url, "delete", params, null);
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {
|
||||
HelloWorld,
|
||||
},
|
||||
};
|
||||
</script>
|
136
openRenamerFront/src/views/home/Home.vue
Normal file
136
openRenamerFront/src/views/home/Home.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button type="primary" @click="dialogVisible = true" size="small"
|
||||
>新增文件</el-button
|
||||
>
|
||||
<el-button type="primary" @click="showResult" size="small">预览</el-button>
|
||||
<!-- 规则列表 -->
|
||||
<div class="ruleList">
|
||||
<div class="menu">
|
||||
<span>应用规则</span>
|
||||
<el-button type="primary" size="mini" @click="ruleDialogShow = true"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="checkedRules.length == 1"
|
||||
@click="editClick"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button type="warning" size="mini" @click="block"
|
||||
>禁用/启用</el-button
|
||||
>
|
||||
<el-button type="danger" size="mini" @click="deleteRule"
|
||||
>删除</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="ruleBlock">
|
||||
<el-checkbox
|
||||
v-model="item.checked"
|
||||
v-for="(item, index) in ruleList"
|
||||
:key="index"
|
||||
>
|
||||
<s v-if="item.blocked">{{ item.message }}</s>
|
||||
<span v-else>{{ item.message }}</span>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 文件预览列表 -->
|
||||
<div class="fileList">
|
||||
<div>文件列表</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog
|
||||
title="新增文件"
|
||||
v-model="dialogVisible"
|
||||
width="70%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<file-chose v-if="dialogVisible" @addData="addData" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="新增规则"
|
||||
v-model="ruleDialogShow"
|
||||
width="70%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<rule :editRule="editRule" v-if="ruleDialogShow" @ruleAdd="ruleAdd" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import FileChose from "@/components/FileChose";
|
||||
import Rule from "@/components/Rule";
|
||||
export default {
|
||||
name: "Home",
|
||||
components: { FileChose, Rule },
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
ruleDialogShow: true, //规则弹床
|
||||
fileList: [],
|
||||
ruleList: [],
|
||||
editRule: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
checkedRules() {
|
||||
return this.ruleList.filter((item) => item.checked);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addData(data) {
|
||||
console.log(data);
|
||||
this.fileList.push(...data);
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
ruleAdd(data) {
|
||||
data.checked = false;
|
||||
data.blocked = false;
|
||||
if (this.editRule != null) {
|
||||
let index = this.ruleList.indexOf(this.editRule);
|
||||
this.ruleList.splice(index, 1, data);
|
||||
this.editRule = null;
|
||||
} else {
|
||||
this.ruleList.push(data);
|
||||
}
|
||||
this.ruleDialogShow = false;
|
||||
},
|
||||
//禁用/启用
|
||||
block() {
|
||||
this.ruleList
|
||||
.filter((item) => item.checked)
|
||||
.forEach((item) => (item.blocked = !item.blocked));
|
||||
},
|
||||
//删除规则
|
||||
deleteRule() {
|
||||
this.ruleList = this.ruleList.filter((item) => !item.checked);
|
||||
},
|
||||
editClick() {
|
||||
this.editRule = this.checkedRules[0];
|
||||
this.ruleDialogShow = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ruleList {
|
||||
border: 1px solid black;
|
||||
padding: 5px;
|
||||
.menu {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
}
|
||||
.ruleBlock {
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
</style>
|
5
openRenamerFront/vue.config.js
Normal file
5
openRenamerFront/vue.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
devServer: {
|
||||
proxy: "http://localhost:8089",
|
||||
},
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user