feat:优化重命名软件

This commit is contained in:
fanxb 2021-12-06 23:20:34 +08:00
parent 4e17b86554
commit 23d9c83593
11 changed files with 572 additions and 483 deletions

4
.gitignore vendored
View File

@ -101,6 +101,4 @@ dist
.dynamodb/ .dynamodb/
# TernJS port file # TernJS port file
.tern-port .tern-port
openRenamerBackend/database.db
openRenamerBackend/database.db

View File

@ -1,15 +1,16 @@
.DS_Store .DS_Store
/.vscode/ /.vscode/
.vscode .vscode
node_modules/ node_modules/
/dist/ /dist/
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
# Editor directories and files # Editor directories and files
yarn.lock yarn.lock
log log
sqls/history.json sqls/history.json
static/* static/*
!static/.gitkeep !static/.gitkeep
database.db

View File

@ -6,53 +6,53 @@ 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, showHidden: boolean): Promise<Array<FileObj>> {
pathStr = decodeURIComponent(pathStr); 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')).replace('Caption', '');
fileList = std fileList = std
.split('\r\n') .split('\r\n')
.filter((item) => item.trim().length > 0) .filter((item) => item.trim().length > 0)
.map((item) => item.trim()); .map((item) => item.trim());
} else { } else {
//linux下 //linux下
pathStr = '/'; pathStr = '/';
fileList = await fs.readdir(pathStr); fileList = await fs.readdir(pathStr);
} }
} else { } else {
fileList = await fs.readdir(pathStr); fileList = await fs.readdir(pathStr);
} }
let folderList: Array<FileObj> = new Array(); let folderList: Array<FileObj> = new Array();
let files: Array<FileObj> = new Array(); let files: Array<FileObj> = new Array();
for (let index in fileList) { for (let index in fileList) {
try { try {
let stat = await fs.stat(path.join(pathStr, fileList[index])); let stat = await fs.stat(path.join(pathStr, fileList[index]));
if (fileList[index].startsWith('.')) { if (fileList[index].startsWith('.')) {
if (showHidden) { if (showHidden) {
(stat.isDirectory() ? folderList : files).push( (stat.isDirectory() ? folderList : files).push(
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()), new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
); );
} }
} else { } else {
(stat.isDirectory() ? folderList : files).push( (stat.isDirectory() ? folderList : files).push(
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()), new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
); );
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
} }
folderList.sort((a, b) => a.name.localeCompare(b.name)).push(...files.sort((a, b) => a.name.localeCompare(b.name))); folderList.sort((a, b) => a.name.localeCompare(b.name)).push(...files.sort((a, b) => a.name.localeCompare(b.name)));
return folderList; return folderList;
} }
static async checkExist(pathStr: string) { static async checkExist(pathStr: string) {
return await fs.pathExists(pathStr); return await fs.pathExists(pathStr);
} }
} }
export default FileService; export default FileService;

View File

@ -11,13 +11,13 @@
"@element-plus/icons": "^0.0.11", "@element-plus/icons": "^0.0.11",
"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", "dayjs": "^1.10.7",
"element-plus": "^1.2.0-beta.5",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-router": "^4.0.0-0" "vue-router": "^4.0.0-0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-service": "~4.5.0", "@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0", "@vue/compiler-sfc": "^3.0.0",

View File

@ -1,46 +1,46 @@
<template> <template>
<el-menu <el-menu
:default-active="activeIndex" :default-active="activeIndex"
class="el-menu-demo" class="el-menu-demo"
mode="horizontal" mode="horizontal"
@select="handleSelect" @select="handleSelect"
> >
<el-menu-item index="dealCenter">处理中心</el-menu-item> <el-menu-item index="dealCenter">处理中心</el-menu-item>
<el-menu-item index="history">历史记录</el-menu-item> <!-- <el-menu-item index="history">历史记录</el-menu-item> -->
</el-menu> </el-menu>
<router-view /> <router-view />
</template> </template>
<script> <script>
export default { export default {
name: "Home", name: "Home",
data() { data() {
return { return {
activeIndex: "dealCenter", activeIndex: "dealCenter",
}; };
}, },
}; };
</script> </script>
<style lang="less"> <style lang="less">
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-align: center; text-align: center;
color: #2c3e50; color: #2c3e50;
} }
#nav { #nav {
padding: 30px; padding: 30px;
a { a {
font-weight: bold; font-weight: bold;
color: #2c3e50; color: #2c3e50;
&.router-link-exact-active { &.router-link-exact-active {
color: #42b983; color: #42b983;
} }
} }
} }
</style> </style>

View File

@ -1,145 +1,124 @@
<template> <template>
<div v-loading="loading" class="main"> <div v-loading="loading" class="main">
<el-breadcrumb separator="/"> <el-breadcrumb separator="/">
<el-breadcrumb-item <el-breadcrumb-item><a @click.prevent="breadcrumbClick(-1)"></a></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>
<el-breadcrumb-item v-for="(item, index) in pathList" :key="index"> <span v-else>{{ item }}</span>
<a </el-breadcrumb-item>
v-if="index < pathList.length - 1" </el-breadcrumb>
@click.prevent="breadcrumbClick(index)"
>{{ item }}</a <div class="fileList">
> <div>
<span v-else>{{ item }}</span> <el-input style="display: inline-block; width: 150px" type="text" size="small" placeholder="关键词过滤" v-model="filterText" />
</el-breadcrumb-item> <el-button type="primary" @click="selectAll(true)" size="mini">全选</el-button>
</el-breadcrumb> <el-button type="primary" @click="selectAll(false)" size="mini">全不选</el-button>
</div>
<div class="fileList"> <div v-for="(item, index) in filterFileList" :key="index">
<div> <span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{ item.name }}</span>
<el-input <el-checkbox style="height: 1.4em" v-model="item.checked" v-else>{{ item.name }}</el-checkbox>
style="display: inline-block; width: 150px" </div>
type="text" </div>
size="small"
placeholder="关键词过滤" <div>
v-model="filterText" <el-button type="primary" @click="submit">确定</el-button>
/> </div>
<el-button type="primary" @click="selectAll(true)" size="mini" </div>
>全选</el-button </template>
>
<el-button type="primary" @click="selectAll(false)" size="mini" <script>
>全不选</el-button import HttpUtil from "../utils/HttpUtil";
> export default {
</div> name: "FileChose",
<div v-for="(item, index) in filterFileList" :key="index"> data() {
<span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{ return {
item.name isWindows: false,
}}</span> fileList: [], //
<el-checkbox v-model="item.checked" v-else>{{ item.name }}</el-checkbox> chosedFileList: [], //
</div> pathList: [], //
</div> loading: false, //
filterText: "", //
<div> };
<el-button type="primary" @click="submit">确定</el-button> },
</div> computed: {
</div> filterFileList() {
</template> let text = this.filterText.trim();
return text === "" ? this.fileList : this.fileList.filter((item) => item.name.indexOf(text) > -1);
<script> },
import HttpUtil from "../utils/HttpUtil"; },
export default { async mounted() {
name: "FileChose", this.isWindows = await HttpUtil.get("/file/isWindows");
data() { await this.breadcrumbClick(-1);
return { },
isWindows: false, methods: {
fileList: [], // //
chosedFileList: [], // async breadcrumbClick(index) {
pathList: [], // this.loading = true;
loading: false, // let path = this.createPath(index);
filterText: "", // let fileList = await HttpUtil.get("/file/query", {
}; path: encodeURIComponent(path),
}, showHidden: false,
computed: { });
filterFileList() { fileList.forEach((item) => (item.checked = false));
let text = this.filterText.trim(); this.fileList = fileList;
return text === "" this.loading = false;
? this.fileList return false;
: this.fileList.filter((item) => item.name.indexOf(text) > -1); },
}, //
}, fileClick(item) {
async mounted() { if (item.isFolder) {
this.isWindows = await HttpUtil.get("/file/isWindows"); this.pathList.push(item.name);
await this.breadcrumbClick(-1); this.breadcrumbClick(this.pathList.length);
}, } else {
methods: { item.checked = !item.checked;
// }
async breadcrumbClick(index) { },
this.loading = true; //
let path = this.createPath(index); selectAll(status) {
let fileList = await HttpUtil.get("/file/query", { this.filterFileList.filter((item) => !item.isFolder).forEach((item) => (item.checked = status));
path: encodeURIComponent(path), },
showHidden: false, //index
}); createPath(index) {
fileList.forEach((item) => (item.checked = false)); let path;
this.fileList = fileList; if (index == -1) {
this.loading = false; path = "";
return false; this.pathList = [];
}, } else {
// this.pathList = this.pathList.slice(0, index + 1);
fileClick(item) { let str = this.pathList.join(this.isWindows ? "\\" : "/") + (this.isWindows ? "\\" : "/");
if (item.isFolder) { path = this.isWindows ? str : "/" + str;
this.pathList.push(item.name); }
this.breadcrumbClick(this.pathList.length); return path;
} else { },
item.checked = !item.checked; //
} submit() {
}, let chosedFiles = this.fileList.filter((item) => item.checked);
// if (chosedFiles.length == 0) {
selectAll(status) { this.$message({ message: "未选择文件", type: "warning" });
this.filterFileList return;
.filter((item) => !item.isFolder) }
.forEach((item) => (item.checked = status)); this.$emit("addData", chosedFiles);
}, },
//index },
createPath(index) { };
let path; </script>
if (index == -1) {
path = "/"; <style lang="less" scoped>
this.pathList = []; .main {
} else { height: 65vh;
this.pathList = this.pathList.slice(0, index + 1); }
let str = this.pathList.join(this.isWindows ? "\\" : "/"); .fileList {
path = this.isWindows ? str : "/" + str; padding: 1em;
} text-align: left;
return path; height: 80%;
}, overflow: hidden auto;
//
submit() { .folder {
let chosedFiles = this.fileList.filter((item) => item.checked); cursor: pointer;
if (chosedFiles.length == 0) { color: blue;
this.$message({ message: "未选择文件", type: "warning" }); display: inline-block;
return; min-width: 3em;
} line-height: 1.4em;
this.$emit("addData", chosedFiles); }
}, }
}, </style>
};
</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,82 +1,64 @@
<template> <template>
<div class="main"> <div class="main">
<el-menu <el-menu style="width: 8em" mode="vertical" :default-active="currentIndex" @select="menuChange">
style="width: 8em" <el-menu-item :disabled="editRule" index="insert">插入</el-menu-item>
mode="vertical" <el-menu-item :disabled="editRule" index="delete">删除</el-menu-item>
:default-active="currentIndex" <!-- <el-menu-item index="replace">替换</el-menu-item> -->
@select="menuChange" <el-menu-item :disabled="editRule" index="serialization">序列化</el-menu-item>
> </el-menu>
<el-menu-item :disabled="editRule" index="insert">插入</el-menu-item> <div class="rule">
<el-menu-item :disabled="editRule" index="delete">删除</el-menu-item> <insert-rule ref="rule" :editRule="editRule" v-if="currentIndex == 'insert'" />
<!-- <el-menu-item index="replace">替换</el-menu-item> --> <delete-rule ref="rule" :editRule="editRule" v-else-if="currentIndex == 'delete'" />
<el-menu-item :disabled="editRule" index="serialization" <serialization-rule ref="rule" :editRule="editRule" v-else-if="currentIndex == 'serialization'" />
>序列化</el-menu-item </div>
> </div>
</el-menu> <div style="text-align: center">
<div class="rule"> <el-button type="primary" @click="submit">确定</el-button>
<insert-rule </div>
ref="rule" </template>
:editRule="editRule"
v-if="currentIndex == 'insert'" <script>
/> import InsertRule from "./rules/InsertRule.vue";
<delete-rule import DeleteRule from "./rules/DeleteRule.vue";
ref="rule" import SerializationRule from "./rules/SerializationRule.vue";
:editRule="editRule" export default {
v-else-if="currentIndex == 'delete'" components: { InsertRule, DeleteRule, SerializationRule },
/> props: ["editRule"],
<serialization-rule name: "Rule",
ref="rule" data() {
:editRule="editRule" return {
v-else-if="currentIndex == 'serialization'" currentIndex: "insert",
/> options: [{ label: "插入", value: "insert" }],
</div> };
</div> },
created() {
<el-button type="primary" @click="submit">确定</el-button> if (this.editRule) {
</template> this.currentIndex = this.editRule.type;
}
<script> },
import InsertRule from "./rules/InsertRule.vue"; methods: {
import DeleteRule from "./rules/DeleteRule.vue"; menuChange(index) {
import SerializationRule from "./rules/SerializationRule.vue"; this.currentIndex = index;
export default { },
components: { InsertRule, DeleteRule, SerializationRule }, submit() {
props: ["editRule"], let data = this.$refs["rule"].exportObj();
name: "Rule", if (data != null) {
data() { this.$emit("ruleAdd", data);
return { }
currentIndex: "insert", },
options: [{ label: "插入", value: "insert" }], },
}; };
}, </script>
created() {
if (this.editRule) { <style lang="less" scoped>
this.currentIndex = this.editRule.type; .main {
} display: flex;
}, height: 65vh;
methods: { text-align: left;
menuChange(index) {
this.currentIndex = index; .rule {
}, padding: 5px;
submit() { flex: 1;
let data = this.$refs["rule"].exportObj(); }
if (data != null) { }
this.$emit("ruleAdd", data); </style>
}
},
},
};
</script>
<style lang="less" scoped>
.main {
display: flex;
height: 65vh;
text-align: left;
.rule {
padding: 5px;
flex: 1;
}
}
</style>

View File

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

View File

@ -1,65 +1,44 @@
<template> <template>
<div v-loading="loading" element-loading-text="后台处理中,请稍候"> <div v-loading="loading" element-loading-text="后台处理中,请稍候">
<el-button type="primary" @click="dialogVisible = true" size="small">1.新增文件</el-button> <br />
<el-button type="primary" @click="showResult" size="small">2.预览</el-button> <el-button type="primary" @click="submit" size="default">重命名</el-button>
<el-button type="primary" @click="submit" size="small">3.重命名</el-button> <br /><br />
<!-- 规则列表 --> <!-- 规则列表 -->
<div class="ruleList"> <rule-block @ruleUpdate="ruleUpdate" />
<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>
<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 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 class="fileList">
<div> <div>
文件列表 文件列表
<el-button type="primary" @click="dialogVisible = true" size="small">新增</el-button>
<el-button type="primary" size="mini" @click="selectAllFiles">反选</el-button> <el-button type="primary" size="mini" @click="selectAllFiles">反选</el-button>
<el-button type="danger" size="mini" @click="deleteCheckedFiles">删除</el-button> <el-button type="danger" size="mini" @click="deleteCheckedFiles">删除</el-button>
</div> </div>
<div class="fileBlock"> <div class="fileBlock">
<!-- 左侧原始文件名 --> <div class="oneLine" v-for="(item, index) in fileList" :key="index">
<el-checkbox style="display: block" v-for="(item, index) in fileList" :key="index" v-model="item.checked"> <!-- 左侧原始文件名 -->
<div class="oneFileName"> <el-checkbox v-model="item.checked" class="left">
{{ item.name }} <div class="oneFileName">
<ArrowDownBold {{ item.name }}
style="width: 20px; padding-left: 10px" <ArrowDownBold
v-if="index < fileList.length - 1" style="width: 20px; padding-left: 10px"
@click.stop.prevent="moveIndex(index + 1, index)" v-if="index < fileList.length - 1"
/> @click.stop.prevent="moveIndex(index + 1, index)"
<ArrowUpBold style="width: 20px; padding-left: 10px" v-if="index > 0" @click.stop.prevent="moveIndex(index - 1, index)" /> />
<ArrowUpBold style="width: 20px; padding-left: 10px" v-if="index > 0" @click.stop.prevent="moveIndex(index - 1, index)" />
</div>
</el-checkbox>
<!-- 修改后的文件名 -->
<div class="right">
{{ changedFileList.length > index ? changedFileList[index].name : "" }}
</div> </div>
</el-checkbox>
</div>
<div class="fileBlock">
<!-- 右侧修改后的文件名-->
<div v-for="(item, index) in changedFileList" :key="index">
{{ item.name }}
</div> </div>
</div> </div>
</div> </div>
<!-- 新增文件弹窗 --> <!-- 新增文件弹窗 -->
<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%"> <el-dialog title="新增文件" v-model="dialogVisible" width="70%">
<file-chose @addData="addData" /> <file-chose @addData="addData" />
</el-dialog> </el-dialog>
<el-dialog title="选择规则模板" v-model="ruleTemplateShow" width="70%">
<application-rule-list />
</el-dialog>
</div> </div>
</template> </template>
@ -68,80 +47,41 @@
import { ArrowDownBold, ArrowUpBold } from "@element-plus/icons"; import { ArrowDownBold, ArrowUpBold } from "@element-plus/icons";
import HttpUtil from "../../utils/HttpUtil"; import HttpUtil from "../../utils/HttpUtil";
import FileChose from "@/components/FileChose"; import FileChose from "@/components/FileChose";
import ApplicationRuleList from "./components/ApplicationRuleList"; import RuleBlock from "./components/RuleBlock.vue";
import Rule from "@/components/Rule";
export default { export default {
name: "Home", name: "Home",
components: { components: {
FileChose, FileChose,
Rule,
ArrowDownBold, ArrowDownBold,
ArrowUpBold, ArrowUpBold,
ApplicationRuleList, RuleBlock,
}, },
data() { data() {
return { return {
loading: false, // loading: false, //
dialogVisible: false, // dialogVisible: false, //
ruleDialogShow: false, // ruleList: [], //
ruleTemplateShow: false, //
fileList: [], fileList: [],
changedFileList: [], changedFileList: [],
ruleList: [],
editRule: null, //
needPreview: false, // needPreview: false, //
applicationRule: null, // applicationRule: null, //
}; };
}, },
computed: {
//
checkedRules() {
return this.ruleList.filter((item) => item.checked);
},
},
methods: { methods: {
// //
async addData(data) { async addData(data) {
data.forEach((item) => (item.checked = false)); data.forEach((item) => (item.checked = false));
this.fileList.push(...data); this.fileList.push(...data);
this.dialogVisible = false; this.dialogVisible = false;
console.log("asdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
this.needPreview = true; this.needPreview = true;
await this.showResult(); await this.showResult();
}, },
// async ruleUpdate(rules) {
async ruleAdd(data) { this.ruleList = rules;
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;
this.needPreview = true; this.needPreview = true;
await this.showResult(); await this.showResult();
}, },
///
async block() {
this.ruleList.filter((item) => item.checked).forEach((item) => (item.blocked = !item.blocked));
this.needPreview = true;
await this.showResult();
},
//
async deleteRule() {
this.ruleList = this.ruleList.filter((item) => !item.checked);
this.needPreview = true;
await this.showResult();
},
//
editClick() {
this.editRule = this.checkedRules[0];
this.ruleDialogShow = true;
},
// //
async showResult() { async showResult() {
if (!this.checkRuleAndFile()) { if (!this.checkRuleAndFile()) {
@ -153,9 +93,11 @@ export default {
ruleList: this.ruleList.filter((item) => !item.blocked), ruleList: this.ruleList.filter((item) => !item.blocked),
}; };
this.changedFileList = await HttpUtil.post("/renamer/preview", null, body); this.changedFileList = await HttpUtil.post("/renamer/preview", null, body);
this.fileList = [...this.fileList];
this.needPreview = false; this.needPreview = false;
this.loading = false; this.loading = false;
}, },
//
async submit() { async submit() {
if (!this.checkRuleAndFile()) { if (!this.checkRuleAndFile()) {
return; return;
@ -212,30 +154,24 @@ export default {
</script> </script>
<style lang="less" scoped> <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;
}
}
.fileList { .fileList {
margin-top: 20px; margin-top: 20px;
text-align: left; text-align: left;
.fileBlock { .fileBlock {
text-align: left; margin-top: 20px;
display: inline-block; .oneLine {
width: 50%; display: flex;
border-top: 1px solid rgb(228, 224, 224);
.left {
flex: 1;
}
.right {
flex: 1;
display: flex;
align-items: center;
}
}
.oneFileName { .oneFileName {
display: flex; display: flex;

View File

@ -1,27 +1,49 @@
<template> <template>
<div> <div>
<el-table :data="applicationRuleList" style="width: 100%"> <el-table :data="applicationRuleList" style="width: 100%">
<el-table-column prop="createdDate" label="创建时间" width="180" /> <el-table-column prop="createdDate" label="创建时间" width="180" />
<el-table-column prop="name" label="名称" width="180" /> <el-table-column prop="name" label="名称" width="180" />
<el-table-column prop="comment" label="备注" /> <el-table-column prop="comment" label="备注" />
</el-table> <el-table-column label="操作" width="120">
</div> <template #default="scope">
</template> <el-button type="text" size="small" @click="ruleTemplateAction('chose', scope.row)">选择</el-button>
<el-button type="text" size="small" @click="ruleTemplateAction('delete', scope.row)">删除</el-button>
<script> </template>
import HttpUtil from "../../../utils/HttpUtil"; </el-table-column>
export default { </el-table>
name: "ApplicationRuleList", </div>
data() { </template>
return {
applicationRuleList: [], <script>
}; import HttpUtil from "../../../utils/HttpUtil";
}, import dayjs from "dayjs";
async mounted() { export default {
this.applicationRuleList = await HttpUtil.get("/applicationRule"); name: "ApplicationRuleList",
}, data() {
}; return {
</script> applicationRuleList: [],
};
<style> },
</style> async created() {
this.init();
},
methods: {
async init() {
this.applicationRuleList = await HttpUtil.get("/applicationRule");
this.applicationRuleList.forEach((item) => (item.createdDate = dayjs(item.createdDate).format("YYYY-MM-DD")));
},
//
async ruleTemplateAction(action, rowData) {
if (action === "chose") {
await this.$emit("update:modelValue", rowData);
await this.$emit("close");
} else {
await HttpUtil.delete("/applicationRule/" + rowData.id);
await this.init();
}
},
},
};
</script>
<style></style>

View File

@ -0,0 +1,171 @@
<template>
<div class="main">
<div class="menu">
<span>应用规则</span>
<el-button type="primary" size="mini" @click="addRuleDialogShow = 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>
<el-button type="primary" size="mini" v-if="chosedTemplate" @click="templateSubmit">保存规则</el-button>
<el-button type="primary" size="mini" v-if="chosedTemplate == null && ruleList.length > 0" @click="saveTemplateDilalogShow = true"
>存为模板</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 v-if="ruleList.length == 0 && chosedTemplate == null" class="choseTemplate">
<el-button type="primary" size="mini" @click="ruleTemplateShow = true">选择模板</el-button>
</div>
</div>
<!-- 弹窗 -->
<el-dialog title="新增规则" v-model="addRuleDialogShow" width="70%">
<rule :editRule="editRule" @ruleAdd="ruleAdd" />
</el-dialog>
<el-dialog title="选择规则模板" v-model="ruleTemplateShow" width="70%">
<application-rule-list v-if="ruleTemplateShow" v-model="chosedTemplate" @close="ruleTemplateShow = false" />
</el-dialog>
<el-dialog title="保存模板" v-model="saveTemplateDilalogShow" width="70%">
<el-form-item label="名称">
<el-input v-model="templateForm.name"></el-input>
</el-form-item>
<el-form-item label="描述">
<el-input v-model="templateForm.comment"></el-input>
</el-form-item>
<template #footer>
<span class="dialog-footer">
<el-button @click="saveTemplateDilalogShow = false">取消</el-button>
<el-button type="primary" @click="templateSubmit">提交</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import Rule from "../../../components/Rule";
import ApplicationRuleList from "./ApplicationRuleList";
import HttpUtil from "../../../utils/HttpUtil";
export default {
name: "RuleBlock",
components: {
Rule,
ApplicationRuleList,
},
data() {
return {
addRuleDialogShow: false, //
ruleTemplateShow: false, //
saveTemplateDilalogShow: false, //
ruleList: [],
editRule: null, //
chosedTemplate: null,
templateForm: {
name: "",
comment: "",
},
};
},
computed: {
//
checkedRules() {
return this.ruleList.filter((item) => item.checked);
},
},
watch: {
chosedTemplate(newVal, oldVal) {
this.ruleList = JSON.parse(newVal.content);
this.ruleUpdate();
},
},
methods: {
//
ruleUpdate() {
this.$emit(
"ruleUpdate",
this.ruleList.filter((item) => !item.blocked)
);
},
//
saveOrUpdateTemplate() {
if (this.chosedTemplate != null) {
this.templateSubmit();
} else {
this.saveTemplateDilalogShow = true;
}
},
//
async templateSubmit() {
let body;
if (this.chosedTemplate) {
this.chosedTemplate.content = JSON.stringify(this.ruleList);
body = this.chosedTemplate;
} else {
body = {
name: this.templateForm.name,
comment: this.templateForm.comment,
content: JSON.stringify(this.ruleList),
};
}
this.chosedTemplate = await HttpUtil.post("/applicationRule", null, body);
this.saveTemplateDilalogShow = false;
this.$message.success("操作成功");
},
//
async 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.ruleUpdate();
this.addRuleDialogShow = false;
},
///
async block() {
this.ruleList.filter((item) => item.checked).forEach((item) => (item.blocked = !item.blocked));
this.ruleUpdate();
},
//
async deleteRule() {
this.ruleList = this.ruleList.filter((item) => !item.checked);
this.ruleUpdate();
},
//
editClick() {
this.editRule = this.checkedRules[0];
this.ruleDialogShow = true;
},
},
};
</script>
<style lang="less" scoped>
.main {
text-align: left;
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;
}
.choseTemplate {
text-align: center;
padding-top: 2em;
padding-bottom: 2em;
}
}
</style>