feat:temp

This commit is contained in:
fanxb 2021-06-27 21:00:24 +08:00
parent 8e518a614d
commit 670f0258a3
34 changed files with 1301 additions and 28351 deletions

View File

@ -1,18 +1,28 @@
import { Context } from "koa"; import { Context } from "koa";
import FileService from "../service/FileService"; import FileService from "../service/FileService";
import config from "../config";
const router = {};
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) { router["GET /file/query"] = async function (ctx: Context) {
ctx.body = "asdfasdf"; ctx.body = await FileService.readPath(ctx.query.path as string, ctx.query.showHidden === '1');
}; };
router["DELETE /plan/:planId"] = async function (ctx: Context) { /**
ctx.body = ""; *windows
} */
router['GET /file/isWindows'] = async function (ctx:Context) {
export default router; 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;

View File

@ -1,17 +1,17 @@
import { Context } from "koa"; import { Context } from "koa";
const router = {}; const router = {};
router["GET /plan"] = async function (ctx: Context) { router["GET /plan"] = async function (ctx: Context) {
ctx.body = "asdfasd"; ctx.body = "asdfasd";
}; };
router["PUT /plan"] = async function (ctx: Context) { router["PUT /plan"] = async function (ctx: Context) {
ctx.body = "asdfasdf"; ctx.body = "asdfasdf";
}; };
router["DELETE /plan/:planId"] = async function (ctx: Context) { router["DELETE /plan/:planId"] = async function (ctx: Context) {
ctx.body = ""; ctx.body = "";
} }
export default router; export default router;

View File

@ -1,13 +1,13 @@
{ "name": "nas_backup", "script": "./dist/index.js", { "name": "nas_backup", "script": "./dist/index.js",
"cwd": "./", "cwd": "./",
"env": { "env": {
"PORT": 8082, "PORT": 8082,
"MYSQL_HOST":"localhost", "MYSQL_HOST":"localhost",
"MYSQL_PORT":3306, "MYSQL_PORT":3306,
"MYSQL_USER":"root", "MYSQL_USER":"root",
"MYSQL_PASS":"123456" "MYSQL_PASS":"123456"
}, },
"log_file": "./log/combined.log", "log_file": "./log/combined.log",
"out_file": "./log/out.log", "out_file": "./log/out.log",
"error_file": "./error.log" "error_file": "./error.log"
} }

View File

@ -1,35 +1,24 @@
import * as path from 'path'; import * as path from 'path';
//后台所在绝对路径 //后台所在绝对路径
const rootPath = path.resolve(__dirname, '..'); const rootPath = path.resolve(__dirname, '..');
let config = { let config = {
rootPath, rootPath,
port: process.env.PORT ? parseInt(process.env.PORT) : 8089, port: process.env.PORT ? parseInt(process.env.PORT) : 8089,
urlPrefix: '/backup/api', urlPrefix: '/openRenamer/api',
//是否为windows平台 //是否为windows平台
isWindows: process.platform.toLocaleLowerCase().includes("win"), isWindows: process.platform.toLocaleLowerCase().includes("win"),
//需要监控的磁盘列表 bodyLimit: {
disKCheckList: ["/dev/nvme0n1", "/dev/nvme1n1"], formLimit: '2mb',
mysqlConfig: { urlencoded: true,
host: process.env.MYSQL_HOST || "localhost", multipart: true,
database: "nas_backup", formidable: {
port: process.env.MYSQL_PORT ? parseInt(process.env.MYSQL_PORT) : 3306, uploadDir: path.join(rootPath, 'files', 'temp', 'uploads'),
user: process.env.MYSQL_USER || "root", keepExtenstions: true,
password: process.env.MYSQL_PASS || "123456", maxFieldsSize: 1024 * 1024
supportBigNumbers: true, }
multipleStatements: false }
}, };
bodyLimit: {
formLimit: '2mb', export default config;
urlencoded: true,
multipart: true,
formidable: {
uploadDir: path.join(rootPath, 'files', 'temp', 'uploads'),
keepExtenstions: true,
maxFieldsSize: 1024 * 1024
}
}
};
export default config;

View File

@ -1,32 +1,32 @@
import { MysqlUtil } from '../util/MysqlHelper'; import { MysqlUtil } from '../util/MysqlHelper';
import History from '../entity/History'; import History from '../entity/History';
import { OkPacket } from 'mysql2'; import { OkPacket } from 'mysql2';
import Plan from 'entity/Plan'; import Plan from 'entity/Plan';
export default class HistoryDao { export default class HistoryDao {
/** /**
* *
* @param history history * @param history history
*/ */
static async addOne(history: History): Promise<number> { static async addOne(history: History): Promise<number> {
let sql = `insert into history(createdDate,updatedDate,planId,fileNum,fileSize,speed,startTime,endTime,comment) values(?,?,?,?,?,?,?,?,?)`; 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]); 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; return (res[0] as unknown as OkPacket).insertId;
} }
/** /**
* plan下所有的历史记录 * plan下所有的历史记录
* @param planId planId * @param planId planId
*/ */
static async deleteByPlanId(planId: number) { static async deleteByPlanId(planId: number) {
await MysqlUtil.pool.execute("delete from history where planId=?", [planId]); await MysqlUtil.pool.execute("delete from history where planId=?", [planId]);
} }
/** /**
* *
* @param planId planId * @param planId planId
*/ */
static async getByPlanId(planId: number): Promise<Array<Plan>> { 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>; return (await MysqlUtil.pool.query("select * from history where planId=?", planId))[0] as unknown as Array<Plan>;
} }
} }

View File

@ -1,40 +1,40 @@
import { MysqlUtil } from '../util/MysqlHelper'; import { MysqlUtil } from '../util/MysqlHelper';
import Plan from '../entity/Plan'; import Plan from '../entity/Plan';
import { OkPacket } from 'mysql2'; import { OkPacket } from 'mysql2';
export default class PlanDao { export default class PlanDao {
/** /**
* *
* @param plan plan * @param plan plan
*/ */
static async addOne(plan: Plan): Promise<number> { 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(?,?,?,?,?,?,?,?,?,?,?)" 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]); , [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; return (res[0] as unknown as OkPacket).insertId;
} }
/** /**
* plan * plan
*/ */
static async getNeedActionPlan(): Promise<Array<Plan>> { static async getNeedActionPlan(): Promise<Array<Plan>> {
let sql = `select * from plan where nextLaunchTime < ${Date.now()} order by nextLaunchTime`; let sql = `select * from plan where nextLaunchTime < ${Date.now()} order by nextLaunchTime`;
return (await MysqlUtil.pool.query(sql))[0] as unknown as Array<Plan>; return (await MysqlUtil.pool.query(sql))[0] as unknown as Array<Plan>;
} }
/** /**
* *
* @param id planId * @param id planId
*/ */
static async updateNextlaunchTimeAndLatestHistoryId(planId: number, historyId: number) { static async updateNextlaunchTimeAndLatestHistoryId(planId: number, historyId: number) {
await MysqlUtil.pool.execute(`update plan set nextLaunchTime = nextLaunchTime+launchInterval,latestHistoryId=? where planId=?` await MysqlUtil.pool.execute(`update plan set nextLaunchTime = nextLaunchTime+launchInterval,latestHistoryId=? where planId=?`
, [historyId, planId]); , [historyId, planId]);
} }
static async deleteByPlanId(planId: number) { static async deleteByPlanId(planId: number) {
await MysqlUtil.pool.execute(`delete from plan where planid=?`, [planId]); await MysqlUtil.pool.execute(`delete from plan where planid=?`, [planId]);
} }
static async getAll(): Promise<Array<Plan>> { static async getAll(): Promise<Array<Plan>> {
return (await MysqlUtil.pool.query("select * from plan"))[0] as unknown as Array<Plan>; return (await MysqlUtil.pool.query("select * from plan"))[0] as unknown as Array<Plan>;
} }
} }

View File

@ -1,10 +1,10 @@
export default class History { export default class History {
historyId: number = 0; historyId: number = 0;
planId: number = 0; planId: number = 0;
fileNum: number = 0; fileNum: number = 0;
fileSize: number = 0; fileSize: number = 0;
speed: number = 0; speed: number = 0;
startTime: number = 0; startTime: number = 0;
endTime: number = 0; endTime: number = 0;
comment: string = ""; comment: string = "";
} }

View File

@ -1,22 +1,22 @@
export default class Plan { export default class Plan {
/** /**
*/ */
createdDate: number; createdDate: number;
/** /**
*/ */
updateDate: number; updateDate: number;
planId: number = 0; planId: number = 0;
planName: string = ""; planName: string = "";
description: string = ""; description: string = "";
//保留的历史份数,最小1 //保留的历史份数,最小1
holdHistory: number = 1; holdHistory: number = 1;
sourcePath: string = ""; sourcePath: string = "";
targetPath: string = ""; targetPath: string = "";
nextLaunchTime: number = 0; nextLaunchTime: number = 0;
lanuchInterval: number = 0; lanuchInterval: number = 0;
latestHistoryId: number = 0; latestHistoryId: number = 0;
ignoreList: Array<String> = []; ignoreList: Array<String> = [];
latestHistoryDetail: Object | null = null; latestHistoryDetail: Object | null = null;
} }

View File

@ -29,8 +29,11 @@ app.use(handleError);
app.use(RouterMW(router, path.join(config.rootPath, "dist/api"))); app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
(async () => { (async () => {
await SqliteUtil.createPool(config.mysqlConfig); await SqliteUtil.createPool();
app.listen(config.port); app.listen(config.port);
log.info(`server listened `, config.port); log.info(`server listened `, config.port);
})(); })();
app.on("error", (error) => {
console.error(error);
})

View File

@ -1,45 +1,58 @@
import config from '../config'; import config from '../config';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs-extra'; import * as fs from 'fs-extra';
import ProcessHelper from '../util/ProcesHelper'; import ProcessHelper from '../util/ProcesHelper';
import FileObj from '../vo/FileObj'; import FileObj from '../vo/FileObj';
class FileService { class FileService {
static async readPath(pathStr: string, showHidden: boolean): Promise<Array<FileObj>> {
static async readPath(pathStr: string): Promise<Array<FileObj>> { pathStr = decodeURIComponent(pathStr);
let fileList = new Array(); let fileList = new Array();
if (pathStr.trim().length == 0) { if (pathStr.trim().length == 0) {
//获取根目录路径 //获取根目录路径
if (config.isWindows) { if (config.isWindows) {
//windows下 //windows下
let std: string = (await ProcessHelper.exec("wmic logicaldisk get caption") as Object)['stdout'].replace("Caption", ""); 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()); fileList = std
} else { .split('\r\n')
//linux下 .filter((item) => item.trim().length > 0)
pathStr = "/"; .map((item) => item.trim());
fileList = await fs.readdir(pathStr); } else {
} //linux下
} else { pathStr = '/';
fileList = await fs.readdir(pathStr); fileList = await fs.readdir(pathStr);
} }
let resList = new Array(); } else {
for (let index in fileList) { fileList = await fs.readdir(pathStr);
try { }
let stat = await fs.stat(path.join(pathStr, fileList[index])); let folderList: Array<FileObj> = new Array();
resList.push(new FileObj(fileList[index], stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime())); let files: Array<FileObj> = new Array();
} catch (e) { for (let index in fileList) {
console.error(e); try {
} let stat = await fs.stat(path.join(pathStr, fileList[index]));
} if (fileList[index].startsWith('.')) {
return resList; if (showHidden) {
} (stat.isDirectory() ? folderList : files).push(
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
static async createPath(pathStr: string) { );
await fs.ensureDir(pathStr); }
} } else {
(stat.isDirectory() ? folderList : files).push(
} new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
);
}
export default FileService; } 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;

View File

@ -1,15 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2017", "target": "ES2017",
"noImplicitAny": false, "noImplicitAny": false,
"module": "commonjs", "module": "commonjs",
"sourceMap": true, "sourceMap": true,
"outDir": "./dist", "outDir": "./dist",
"baseUrl":".", "baseUrl":".",
"rootDir": "./", "rootDir": "./",
"watch": false, "watch": false,
"strict": true, "strict": true,
"strictNullChecks": false, "strictNullChecks": false,
"esModuleInterop": true "esModuleInterop": true
} }
} }

View File

@ -1,108 +1,108 @@
import mysql from "mysql2/promise"; import mysql from "mysql2/promise";
import config from '../config'; import config from '../config';
import * as fs from "fs-extra"; import * as fs from "fs-extra";
import * as path from 'path'; import * as path from 'path';
import log from '../util/LogUtil'; import log from '../util/LogUtil';
const HISTORY_NAME = "history.json"; const HISTORY_NAME = "history.json";
interface Res { interface Res {
rows: any; rows: any;
fields: mysql.FieldPacket; fields: mysql.FieldPacket;
} }
class MysqlUtil { class MysqlUtil {
public static pool: mysql.Pool = null; public static pool: mysql.Pool = null;
static async createPool(mysqlConfig: any) { static async createPool(mysqlConfig: any) {
MysqlUtil.pool = await mysql.createPool(mysqlConfig); MysqlUtil.pool = await mysql.createPool(mysqlConfig);
let basePath = path.join(config.rootPath, "sqls"); let basePath = path.join(config.rootPath, "sqls");
let hisPath = path.join(basePath, HISTORY_NAME); let hisPath = path.join(basePath, HISTORY_NAME);
let history: Array<string>; let history: Array<string>;
if (fs.existsSync(hisPath)) { if (fs.existsSync(hisPath)) {
history = JSON.parse(await fs.readFile(hisPath, "utf-8")); history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
} else { } else {
history = new Array(); history = new Array();
} }
//执行数据库 //执行数据库
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME)); let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
let error = null; let error = null;
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
if (history.indexOf(files[i]) > -1) { if (history.indexOf(files[i]) > -1) {
log.info("sql无需重复执行:", files[i]); log.info("sql无需重复执行:", files[i]);
continue; continue;
} }
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g); let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
try { try {
let sql = ""; let sql = "";
for (let j = 0; j < sqlLines.length; j++) { for (let j = 0; j < sqlLines.length; j++) {
sql = sql + sqlLines[j]; sql = sql + sqlLines[j];
if (sqlLines[j].endsWith(";")) { if (sqlLines[j].endsWith(";")) {
await MysqlUtil.pool.execute(sql); await MysqlUtil.pool.execute(sql);
sql = ""; sql = "";
} }
} }
log.info("sql执行成功:", files[i]); log.info("sql执行成功:", files[i]);
history.push(files[i]); history.push(files[i]);
} catch (err) { } catch (err) {
error = err; error = err;
break; break;
} }
} }
await fs.writeFile(hisPath, JSON.stringify(history)); await fs.writeFile(hisPath, JSON.stringify(history));
if (error != null) { if (error != null) {
throw error; throw error;
} }
} }
static async getRows(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Array<any>> { static async getRows(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Array<any>> {
return (await MysqlUtil.execute(sql, params, connection)).rows; return (await MysqlUtil.execute(sql, params, connection)).rows;
} }
static async getRow(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> { static async getRow(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
let rows = (await MysqlUtil.execute(sql, params, connection)).rows; let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
return rows.length > 0 ? rows[0] : null; return rows.length > 0 ? rows[0] : null;
} }
static async getSingle(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> { static async getSingle(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<any> {
let rows = (await MysqlUtil.execute(sql, params, connection)).rows; let rows = (await MysqlUtil.execute(sql, params, connection)).rows;
if (rows.length == 0) { if (rows.length == 0) {
return null; return null;
} }
let row = rows[0]; let row = rows[0];
return row[Object.keys(row)[0]]; return row[Object.keys(row)[0]];
} }
static async execute(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Res> { static async execute(sql: string, params: Array<any>, connection: mysql.PoolConnection = null): Promise<Res> {
let res: any = {}; let res: any = {};
if (connection == null) { if (connection == null) {
let [rows, fields] = await MysqlUtil.pool.query(sql, params); let [rows, fields] = await MysqlUtil.pool.query(sql, params);
res['rows'] = fields === undefined ? null : rows; res['rows'] = fields === undefined ? null : rows;
res['fields'] = fields === undefined ? rows : fields; res['fields'] = fields === undefined ? rows : fields;
} else { } else {
let [rows, fields] = await connection.query(sql, params); let [rows, fields] = await connection.query(sql, params);
res['rows'] = rows; res['rows'] = rows;
res['fields'] = fields; res['fields'] = fields;
} }
return res; return res;
} }
static async test() { static async test() {
let connection = await MysqlUtil.pool.getConnection(); let connection = await MysqlUtil.pool.getConnection();
connection.beginTransaction(); connection.beginTransaction();
connection.query(`insert into url value(6,"GET","asd","public")`); connection.query(`insert into url value(6,"GET","asd","public")`);
connection.query(`insert into url value(7,"GET","asd","public")`); connection.query(`insert into url value(7,"GET","asd","public")`);
await connection.commit(); await connection.commit();
connection.release(); connection.release();
} }
} }
export { export {
MysqlUtil, MysqlUtil,
Res, Res,
mysql mysql
} }

View File

@ -1,8 +1,8 @@
class NumberUtil { class NumberUtil {
static getRandom(min: number, max: number): number { static getRandom(min: number, max: number): number {
return Math.floor((Math.random() * (max - min + 1) + min)); return Math.floor((Math.random() * (max - min + 1) + min));
} }
} }
export default NumberUtil; export default NumberUtil;

View File

@ -1,24 +1,24 @@
import * as childPrecess from 'child_process'; import * as childPrecess from 'child_process';
class ProcessHelper { class ProcessHelper {
static exec(cmd): Promise<string> { static exec(cmd): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
childPrecess.exec(cmd, (error, stdout, stderr) => { childPrecess.exec(cmd, (error, stdout, stderr) => {
if (error) { if (error) {
reject(error); reject(error);
} if (stderr) { } if (stderr) {
reject(stderr); reject(stderr);
} else { } else {
resolve(stdout) resolve(stdout)
} }
}) })
}) })
} }
} }
// (async()=>{ // (async()=>{
// let res= await ProcessHelper.exec('cd /d e://workspace&&dir'); // let res= await ProcessHelper.exec('cd /d e://workspace&&dir');
// console.log(res); // console.log(res);
// })() // })()
export default ProcessHelper export default ProcessHelper

View File

@ -1,59 +1,59 @@
import sqlite3 from 'sqlite3'; import sqlite3 from 'sqlite3';
import { open, Database } from 'sqlite'; import { open, Database } from 'sqlite';
import config from '../config'; import config from '../config';
import * as fs from "fs-extra"; import * as fs from "fs-extra";
import * as path from 'path'; import * as path from 'path';
import log from './LogUtil'; import log from './LogUtil';
const HISTORY_NAME = "history.json"; const HISTORY_NAME = "history.json";
class MysqlUtil { class MysqlUtil {
public static pool: Database = null; public static pool: Database = null;
static async createPool(mysqlConfig: any) { static async createPool() {
MysqlUtil.pool = await open({ MysqlUtil.pool = await open({
filename: path.join(config.rootPath, "database.db"), filename: path.join(config.rootPath, "database.db"),
driver: sqlite3.Database driver: sqlite3.Database
}); });
let basePath = path.join(config.rootPath, "sqls"); let basePath = path.join(config.rootPath, "sqls");
let hisPath = path.join(basePath, HISTORY_NAME); let hisPath = path.join(basePath, HISTORY_NAME);
let history: Array<string>; let history: Array<string>;
if (fs.existsSync(hisPath)) { if (fs.existsSync(hisPath)) {
history = JSON.parse(await fs.readFile(hisPath, "utf-8")); history = JSON.parse(await fs.readFile(hisPath, "utf-8"));
} else { } else {
history = new Array(); history = new Array();
} }
//执行数据库 //执行数据库
let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME)); let files = (await fs.readdir(basePath)).sort((a, b) => a.localeCompare(b)).filter(item => !(item === HISTORY_NAME));
let error = null; let error = null;
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
if (history.indexOf(files[i]) > -1) { if (history.indexOf(files[i]) > -1) {
log.info("sql无需重复执行:", files[i]); log.info("sql无需重复执行:", files[i]);
continue; continue;
} }
let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g); let sqlLines = (await fs.readFile(path.join(basePath, files[i]), 'utf-8')).split(/[\r\n]/g);
try { try {
let sql = ""; let sql = "";
for (let j = 0; j < sqlLines.length; j++) { for (let j = 0; j < sqlLines.length; j++) {
sql = sql + sqlLines[j]; sql = sql + sqlLines[j];
if (sqlLines[j].endsWith(";")) { if (sqlLines[j].endsWith(";")) {
await MysqlUtil.pool.exec(sql); await MysqlUtil.pool.exec(sql);
sql = ""; sql = "";
} }
} }
log.info("sql执行成功:", files[i]); log.info("sql执行成功:", files[i]);
history.push(files[i]); history.push(files[i]);
} catch (err) { } catch (err) {
error = err; error = err;
break; break;
} }
} }
await fs.writeFile(hisPath, JSON.stringify(history)); await fs.writeFile(hisPath, JSON.stringify(history));
if (error != null) { if (error != null) {
throw error; throw error;
} }
} }
} }
export default MysqlUtil; export default MysqlUtil;

View File

@ -1,22 +1,22 @@
import moment from 'moment'; import moment from 'moment';
class TimeUtil { class TimeUtil {
/** /**
* *
*/ */
static getZeroTime(): Date { static getZeroTime(): Date {
return moment() return moment()
.millisecond(0) .millisecond(0)
.second(0) .second(0)
.minute(0) .minute(0)
.hour(0) .hour(0)
.toDate(); .toDate();
} }
static async sleep(duration: number): Promise<void> { static async sleep(duration: number): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration); setTimeout(() => resolve(), duration);
}); });
} }
} }
export default TimeUtil; export default TimeUtil;

View File

@ -1,14 +1,14 @@
import path, { dirname } from 'path' import path, { dirname } from 'path'
class pathUtil { class pathUtil {
static getPath(pathStr) { static getPath(pathStr) {
return path.resolve(pathUtil.getRootPath(), pathStr); return path.resolve(pathUtil.getRootPath(), pathStr);
} }
static getRootPath() { static getRootPath() {
return path.resolve(__dirname, '..'); return path.resolve(__dirname, '..');
} }
} }
export default pathUtil export default pathUtil

View File

@ -3,6 +3,10 @@ export default class FileObj {
* *
*/ */
name: string; name: string;
/**
*
*/
path: string;
/** /**
* *
*/ */
@ -17,8 +21,9 @@ export default class FileObj {
updatedTime: number; updatedTime: number;
constructor(name, isFolder, createdTime, updatedTime) { constructor(name, path, isFolder, createdTime, updatedTime) {
this.name = name; this.name = name;
this.path = path;
this.isFolder = isFolder; this.isFolder = isFolder;
this.createdTime = createdTime; this.createdTime = createdTime;
this.updatedTime = updatedTime; this.updatedTime = updatedTime;

View File

@ -1,6 +1,7 @@
.DS_Store .DS_Store
node_modules node_modules
/dist /dist
package-lock.json
# local env files # local env files

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"element-plus": "^1.0.2-beta.48",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-router": "^4.0.0-0" "vue-router": "^4.0.0-0"
}, },

View File

@ -1,11 +1,27 @@
<template> <template>
<div id="nav"> <el-menu
<router-link to="/">Home</router-link> | :default-active="activeIndex"
<router-link to="/about">About</router-link> class="el-menu-demo"
</div> mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="dealCenter">处理中心</el-menu-item>
<el-menu-item index="history">历史记录</el-menu-item>
</el-menu>
<router-view /> <router-view />
</template> </template>
<script>
export default {
name: "Home",
data() {
return {
activeIndex: "dealCenter",
};
},
};
</script>
<style lang="less"> <style lang="less">
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; font-family: Avenir, Helvetica, Arial, sans-serif;

View 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>

View File

@ -1,97 +1,5 @@
<template> <template>
<div class="hello"> <div class="hello">hello World!</div>
<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>
</template> </template>
<script> <script>

View 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>

View 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>

View 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" />
&nbsp;&nbsp;
<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>

View 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>

View File

@ -1,5 +1,9 @@
import { createApp } from "vue"; import { createApp } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; 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;

View File

@ -1,5 +1,5 @@
import { createRouter, createWebHistory } from "vue-router"; import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/Home.vue"; import Home from "../views/home/Home.vue";
const routes = [ const routes = [
{ {

View File

@ -1,5 +1,4 @@
import * as http from "axios"; import * as http from "axios";
import router from "../router/index";
/** /**
* 请求 * 请求
@ -11,10 +10,10 @@ import router from "../router/index";
* @param {*} redirect 接口返回未认证是否跳转到登陆 * @param {*} redirect 接口返回未认证是否跳转到登陆
* @returns 数据 * @returns 数据
*/ */
async function request(url, method, params, body, isForm, redirect) { async function request(url, method, params, body, isForm) {
let options = { let options = {
url, url,
baseURL: "/bookmark/api", baseURL: "/openRenamer/api",
method, method,
params, params,
// headers: { // headers: {
@ -35,30 +34,7 @@ async function request(url, method, params, body, isForm, redirect) {
console.error(err); console.error(err);
return; return;
} }
const { code, data, message } = res.data; return 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);
}
} }
/** /**
@ -67,8 +43,8 @@ async function request(url, method, params, body, isForm, redirect) {
* @param {*} params url参数 * @param {*} params url参数
* @param {*} redirect 未登陆是否跳转到登陆页 * @param {*} redirect 未登陆是否跳转到登陆页
*/ */
async function get(url, params = null, redirect = true) { async function get(url, params = null) {
return request(url, "get", params, null, false, redirect); return request(url, "get", params, null, false);
} }
/** /**
@ -79,8 +55,8 @@ async function get(url, params = null, redirect = true) {
* @param {*} isForm 是否表单数据 * @param {*} isForm 是否表单数据
* @param {*} redirect 是否重定向 * @param {*} redirect 是否重定向
*/ */
async function post(url, params, body, isForm = false, redirect = true) { async function post(url, params, body, isForm = false) {
return request(url, "post", params, body, isForm, redirect); return request(url, "post", params, body, isForm);
} }
/** /**
@ -91,8 +67,8 @@ async function post(url, params, body, isForm = false, redirect = true) {
* @param {*} isForm 是否表单数据 * @param {*} isForm 是否表单数据
* @param {*} redirect 是否重定向 * @param {*} redirect 是否重定向
*/ */
async function put(url, params, body, isForm = false, redirect = true) { async function put(url, params, body, isForm = false) {
return request(url, "put", params, body, isForm, redirect); 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 {*} params url参数
* @param {*} redirect 是否重定向 * @param {*} redirect 是否重定向
*/ */
async function deletes(url, params = null, redirect = true) { async function deletes(url, params = null) {
return request(url, "delete", params, null, redirect); return request(url, "delete", params, null);
} }
export default { export default {

View File

@ -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>

View 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>

View File

@ -0,0 +1,5 @@
module.exports = {
devServer: {
proxy: "http://localhost:8089",
},
};