feat:新增模板保存功能

This commit is contained in:
fanxb 2021-11-22 16:59:38 +08:00
parent 9f0ab4da63
commit c8196aa300
23 changed files with 264 additions and 234 deletions

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"editor.tabSize": 2,
"editor.detectIndentation": false
}

View File

@ -0,0 +1,29 @@
import { Context } from "koa";
import ApplicationRuleService from "../service/ApplicationRuleService";
import config from "../config";
const router = {};
/**
*
*/
router["GET /applicationRule"] = async function (ctx: Context) {
ctx.body = await ApplicationRuleService.getAll();
};
/**
*
*/
router['POST /applicationRule'] = async function (ctx: Context) {
ctx.body = await ApplicationRuleService.saveOrAdd(ctx.request.body);
}
/**
*
*/
router["DELETE /applicationRule/:id"] = async function (ctx: Context) {
await ApplicationRuleService.deleteById(ctx.params.id);
ctx.body = "";
};
export default router;

View File

@ -11,7 +11,7 @@ router["POST /renamer/preview"] = async function (ctx: Context) {
};
/**
*
*
*/
router["POST /renamer/submit"] = async function (ctx: Context) {
ctx.body = await RenamerService.rename(ctx.request.body.fileList, ctx.request.body.changedFileList);

View File

@ -1,17 +0,0 @@
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;

View File

@ -0,0 +1,52 @@
import ErrorHelper from "../util/ErrorHelper";
import ApplicationRule from "../entity/dto/ApplicationRule";
import SqliteHelper from "../util/SqliteHelper";
export default class ApplicationRuleDao {
/**
*
* @param obj
* @returns
*/
static async getAll(): Promise<Array<ApplicationRule>> {
let res = await SqliteHelper.pool.all('select id,createdDate,updatedDate,name,comment,content from application_rule');
return res;
}
/**
*
* @param obj
* @returns
*/
static async addOne(obj: ApplicationRule): Promise<number> {
let res = await SqliteHelper.pool.run('insert into application_rule(createdDate,updatedDate,name,comment,content) values(?,?,?,?,?)'
, obj.createdDate, obj.updatedDate, obj.name, obj.comment, obj.content);
return res.lastID;
}
/**
*
* @param obj
*/
static async updateOne(obj: ApplicationRule): Promise<void> {
let res = await SqliteHelper.pool.run('update application_rule set updatedDate=?,name=?,comment=?,content=? where id=?'
, obj.updatedDate, obj.name, obj.comment, obj.content, obj.id);
if (res.changes == 0) {
throw ErrorHelper.Error404("数据不存在");
}
}
/**
*
* @param id
*/
static async delete(id: number): Promise<void> {
let res = await SqliteHelper.pool.run('delete from application_rule where id=?', id);
if (res.changes == 0) {
throw ErrorHelper.Error404("数据不存在");
}
}
}

View File

@ -1,32 +0,0 @@
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>;
}
}

View File

@ -1,40 +0,0 @@
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>;
}
}

View File

@ -1,14 +0,0 @@
export default class DiskInfo{
/**
*
*/
name:string;
/**
*
*/
isOk:boolean;
/**
*
*/
detail:string;
}

View File

@ -1,10 +0,0 @@
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 = "";
}

View File

@ -1,22 +0,0 @@
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;
}

View File

@ -0,0 +1,23 @@
export default class ApplicationRule {
/**
*/
createdDate: number;
/**
*/
updatedDate: number;
id: number;
/**
*/
name: string;
/**
*/
comment: string;
/**
json序列化后
*/
content: string;
}

View File

@ -1,15 +1,17 @@
import log from '../util/LogUtil';
let f = async (ctx, next) => {
try {
await next();
} catch (error: any) {
if (error.status != undefined) {
ctx.status = error.status;
} else {
ctx.status = 500;
}
ctx.body = error.message;
console.error(error);
}
try {
await next();
} catch (error: any) {
if (error.status != undefined) {
ctx.status = error.status;
} else {
ctx.status = 500;
}
ctx.body = error.message;
log.error(error);
}
}
export default f;

View File

@ -0,0 +1,33 @@
import config from '../config';
import * as path from 'path';
import * as fs from 'fs-extra';
import ApplicationRule from '../entity/dto/ApplicationRule';
import ApplicationRuleDao from '../dao/ApplicationRuleDao';
class ApplicationRuleService {
static async saveOrAdd(ruleObj: ApplicationRule): Promise<ApplicationRule> {
ruleObj.updatedDate = Date.now();
if (!ruleObj.id) {
//说明是新增
ruleObj.createdDate = Date.now();
ruleObj.id = await ApplicationRuleDao.addOne(ruleObj);
} else {
//说明是修改
await ApplicationRuleDao.updateOne(ruleObj);
}
return ruleObj;
}
static async getAll(): Promise<Array<ApplicationRule>> {
return await ApplicationRuleDao.getAll();
}
static async deleteById(id: number): Promise<void> {
await ApplicationRuleDao.delete(id);
}
}
export default ApplicationRuleService;

View File

@ -0,0 +1,14 @@
-- 初始化建表
-- 应用规则表
CREATE TABLE application_rule (
-- 创建时间
createdDate INTEGER NOT NULL,
-- 更新时间
updatedDate INTEGER NOT NULL,
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
-- 注释
comment TEXT NOT NULL DEFAULT '',
-- 规则内容json序列化后保存
content TEXT NOT NULL DEFAULT ''
);

View File

@ -10,6 +10,9 @@ class ErrorHelper {
static Error403(message){
return getError(message,403);
}
static Error404(message){
return getError(message,404);
}
static Error406(message){
return getError(message,406);

View File

@ -8,11 +8,11 @@ import log from './LogUtil';
const HISTORY_NAME = "history.json";
class MysqlUtil {
class SqliteHelper {
public static pool: Database = null;
static async createPool() {
MysqlUtil.pool = await open({
SqliteHelper.pool = await open({
filename: path.join(config.rootPath, "database.db"),
driver: sqlite3.Database
});
@ -32,13 +32,13 @@ class MysqlUtil {
log.info("sql无需重复执行:", files[i]);
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).map(item=>item.trim()).filter(item=>!item.startsWith("--"));
try {
let sql = "";
for (let j = 0; j < sqlLines.length; j++) {
sql = sql + sqlLines[j];
if (sqlLines[j].endsWith(";")) {
await MysqlUtil.pool.exec(sql);
await SqliteHelper.pool.run(sql);
sql = "";
}
}
@ -56,4 +56,4 @@ class MysqlUtil {
}
}
export default MysqlUtil;
export default SqliteHelper;

View File

@ -29,7 +29,7 @@ export default class FileObj {
*/
createdTime: number;
/**
*
* ms
*/
updatedTime: number;

View File

@ -1,5 +1,5 @@
{
"name": "front",
"name": "open-renamer",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@ -1,34 +0,0 @@
<template>
<div class="hello">hello World!</div>
</template>
<script>
import HttpUtil from "../utils/HttpUtil";
export default {
name: "HelloWorld",
props: {
msg: String,
},
mounted() {
HttpUtil.get("");
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -1,9 +1,10 @@
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";
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import ElementPlus, { ElMessage } from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
const vueInstance = createApp(App);
vueInstance.use(router).use(ElementPlus).mount("#app");
vueInstance.use(router).use(ElementPlus).mount('#app');
vueInstance.config.globalProperties.$message = ElMessage;
window.vueInstance = vueInstance;

View File

@ -1,4 +1,4 @@
import * as http from "axios";
import * as http from 'axios';
/**
* 请求
@ -13,15 +13,12 @@ import * as http from "axios";
async function request(url, method, params, body, isForm) {
let options = {
url,
baseURL: "/openRenamer/api",
baseURL: '/openRenamer/api',
method,
params,
// headers: {
// "jwt-token": vuex.state.globalConfig.token,
// },
};
if (isForm) {
options.headers["Content-Type"] = "multipart/form-data";
options.headers['Content-Type'] = 'multipart/form-data';
}
if (body) {
options.data = body;
@ -30,9 +27,8 @@ async function request(url, method, params, body, isForm) {
try {
res = await http.default.request(options);
} catch (err) {
window.vueInstance.$message.error("发生了某些异常问题");
console.error(err);
return;
window.vueInstance.config.globalProperties.$message.error('发生了某些异常问题');
throw err;
}
return res.data;
}
@ -44,7 +40,7 @@ async function request(url, method, params, body, isForm) {
* @param {*} redirect 未登陆是否跳转到登陆页
*/
async function get(url, params = null) {
return request(url, "get", params, null, false);
return request(url, 'get', params, null, false);
}
/**
@ -56,7 +52,7 @@ async function get(url, params = null) {
* @param {*} redirect 是否重定向
*/
async function post(url, params, body, isForm = false) {
return request(url, "post", params, body, isForm);
return request(url, 'post', params, body, isForm);
}
/**
@ -68,7 +64,7 @@ async function post(url, params, body, isForm = false) {
* @param {*} redirect 是否重定向
*/
async function put(url, params, body, isForm = false) {
return request(url, "put", params, body, isForm);
return request(url, 'put', params, body, isForm);
}
/**
@ -78,7 +74,7 @@ async function put(url, params, body, isForm = false) {
* @param {*} redirect 是否重定向
*/
async function deletes(url, params = null) {
return request(url, "delete", params, null);
return request(url, 'delete', params, null);
}
export default {

View File

@ -1,10 +1,12 @@
<template>
<div v-loading="loading" element-loading-text="后台处理中,请稍候">
<el-button type="primary" @click="dialogVisible = true" size="small"
>新增文件</el-button
>1.新增文件</el-button
>
<el-button type="primary" @click="showResult" size="small">预览</el-button>
<el-button type="primary" @click="submit" size="small">重命名</el-button>
<el-button type="primary" @click="showResult" size="small"
>2.预览</el-button
>
<el-button type="primary" @click="submit" size="small">3.重命名</el-button>
<!-- 规则列表 -->
<div class="ruleList">
<div class="menu">
@ -25,6 +27,12 @@
<el-button type="danger" size="mini" @click="deleteRule"
>删除</el-button
>
<el-button type="primary" size="mini" @click="saveOrUpdate"
>保存模板</el-button
>
<el-button type="primary" size="mini" @click="ruleTemplateShow = true"
>选择模板</el-button
>
</div>
<div class="ruleBlock">
<el-checkbox
@ -78,24 +86,18 @@
</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%">
<rule :editRule="editRule" v-if="ruleDialogShow" @ruleAdd="ruleAdd" />
</el-dialog>
<el-dialog title="新增文件" v-model="dialogVisible" width="70%">
<file-chose @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>
<el-dialog title="选择规则模板" v-model="ruleTemplateShow" width="70%">
<application-rule-list />
</el-dialog>
</div>
</template>
<script>
@ -103,23 +105,33 @@
import { ArrowDownBold, ArrowUpBold } from "@element-plus/icons";
import HttpUtil from "../../utils/HttpUtil";
import FileChose from "@/components/FileChose";
import ApplicationRuleList from "./components/ApplicationRuleList";
import Rule from "@/components/Rule";
export default {
name: "Home",
components: { FileChose, Rule, ArrowDownBold, ArrowUpBold },
components: {
FileChose,
Rule,
ArrowDownBold,
ArrowUpBold,
ApplicationRuleList,
},
data() {
return {
loading: false, //
dialogVisible: false,
ruleDialogShow: false, //
dialogVisible: false, //
ruleDialogShow: false, //
ruleTemplateShow: false, //
fileList: [],
changedFileList: [],
ruleList: [],
editRule: null, //
needPreview: false, //
applicationRule: null, //
};
},
computed: {
//
checkedRules() {
return this.ruleList.filter((item) => item.checked);
},
@ -176,7 +188,7 @@ export default {
this.loading = true;
let body = {
fileList: this.fileList,
ruleList: this.ruleList,
ruleList: this.ruleList.filter((item) => !item.blocked),
};
this.changedFileList = await HttpUtil.post(
"/renamer/preview",
@ -199,9 +211,12 @@ export default {
fileList: this.fileList,
changedFileList: this.changedFileList,
};
await HttpUtil.post("/renamer/submit", null, body);
this.loading = false;
this.$message({ message: "重命名成功", type: "success" });
try {
await HttpUtil.post("/renamer/submit", null, body);
this.$message({ message: "重命名成功", type: "success" });
} finally {
this.loading = false;
}
},
//
async deleteCheckedFiles() {

View File

@ -0,0 +1,27 @@
<template>
<div>
<el-table :data="applicationRuleList" style="width: 100%">
<el-table-column prop="createdDate" label="创建时间" width="180" />
<el-table-column prop="name" label="名称" width="180" />
<el-table-column prop="comment" label="备注" />
</el-table>
</div>
</template>
<script>
import HttpUtil from "../../../utils/HttpUtil";
export default {
name: "ApplicationRuleList",
data() {
return {
applicationRuleList: [],
};
},
async mounted() {
this.applicationRuleList = await HttpUtil.get("/applicationRule");
},
};
</script>
<style>
</style>