feat:temp
This commit is contained in:
parent
8e518a614d
commit
670f0258a3
@ -1,18 +1,28 @@
|
||||
import { Context } from "koa";
|
||||
import FileService from "../service/FileService";
|
||||
import config from "../config";
|
||||
|
||||
const router = {};
|
||||
|
||||
/**
|
||||
* 获取目录下的文件列表
|
||||
*/
|
||||
router["GET /file/query"] = async function (ctx: Context) {
|
||||
ctx.body = FileService.readPath(ctx.query.path as string);
|
||||
ctx.body = await FileService.readPath(ctx.query.path as string, ctx.query.showHidden === '1');
|
||||
};
|
||||
|
||||
router["PUT /plan"] = async function (ctx: Context) {
|
||||
ctx.body = "asdfasdf";
|
||||
};
|
||||
|
||||
router["DELETE /plan/:planId"] = async function (ctx: Context) {
|
||||
ctx.body = "";
|
||||
/**
|
||||
*是否windows
|
||||
*/
|
||||
router['GET /file/isWindows'] = async function (ctx:Context) {
|
||||
ctx.body=config.isWindows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查路径是否存在
|
||||
*/
|
||||
router["GET /file/path/exist"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.checkExist(ctx.query.path as string);
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
@ -6,20 +6,9 @@ const rootPath = path.resolve(__dirname, '..');
|
||||
let config = {
|
||||
rootPath,
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 8089,
|
||||
urlPrefix: '/backup/api',
|
||||
urlPrefix: '/openRenamer/api',
|
||||
//是否为windows平台
|
||||
isWindows: process.platform.toLocaleLowerCase().includes("win"),
|
||||
//需要监控的磁盘列表
|
||||
disKCheckList: ["/dev/nvme0n1", "/dev/nvme1n1"],
|
||||
mysqlConfig: {
|
||||
host: process.env.MYSQL_HOST || "localhost",
|
||||
database: "nas_backup",
|
||||
port: process.env.MYSQL_PORT ? parseInt(process.env.MYSQL_PORT) : 3306,
|
||||
user: process.env.MYSQL_USER || "root",
|
||||
password: process.env.MYSQL_PASS || "123456",
|
||||
supportBigNumbers: true,
|
||||
multipleStatements: false
|
||||
},
|
||||
bodyLimit: {
|
||||
formLimit: '2mb',
|
||||
urlencoded: true,
|
||||
|
@ -29,8 +29,11 @@ app.use(handleError);
|
||||
|
||||
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
|
||||
(async () => {
|
||||
await SqliteUtil.createPool(config.mysqlConfig);
|
||||
await SqliteUtil.createPool();
|
||||
app.listen(config.port);
|
||||
log.info(`server listened `, config.port);
|
||||
})();
|
||||
|
||||
app.on("error", (error) => {
|
||||
console.error(error);
|
||||
})
|
||||
|
@ -6,40 +6,53 @@ import ProcessHelper from '../util/ProcesHelper';
|
||||
import FileObj from '../vo/FileObj';
|
||||
|
||||
class FileService {
|
||||
|
||||
static async readPath(pathStr: string): Promise<Array<FileObj>> {
|
||||
static async readPath(pathStr: string, showHidden: boolean): Promise<Array<FileObj>> {
|
||||
pathStr = decodeURIComponent(pathStr);
|
||||
let fileList = new Array();
|
||||
if (pathStr.trim().length == 0) {
|
||||
//获取根目录路径
|
||||
if (config.isWindows) {
|
||||
//windows下
|
||||
let std: string = (await ProcessHelper.exec("wmic logicaldisk get caption") as Object)['stdout'].replace("Caption", "");
|
||||
fileList = std.split("\r\n").filter(item => item.trim().length > 0).map(item => item.trim());
|
||||
let std: string = ((await ProcessHelper.exec('wmic logicaldisk get caption')) as Object)['stdout'].replace('Caption', '');
|
||||
fileList = std
|
||||
.split('\r\n')
|
||||
.filter((item) => item.trim().length > 0)
|
||||
.map((item) => item.trim());
|
||||
} else {
|
||||
//linux下
|
||||
pathStr = "/";
|
||||
pathStr = '/';
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
} else {
|
||||
fileList = await fs.readdir(pathStr);
|
||||
}
|
||||
let resList = new Array();
|
||||
let folderList: Array<FileObj> = new Array();
|
||||
let files: Array<FileObj> = new Array();
|
||||
for (let index in fileList) {
|
||||
try {
|
||||
let stat = await fs.stat(path.join(pathStr, fileList[index]));
|
||||
resList.push(new FileObj(fileList[index], stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()));
|
||||
if (fileList[index].startsWith('.')) {
|
||||
if (showHidden) {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
(stat.isDirectory() ? folderList : files).push(
|
||||
new FileObj(fileList[index], pathStr, stat.isDirectory(), stat.birthtime.getTime(), stat.mtime.getTime()),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
return resList;
|
||||
folderList.sort((a, b) => a.name.localeCompare(b.name)).push(...files.sort((a, b) => a.name.localeCompare(b.name)));
|
||||
return folderList;
|
||||
}
|
||||
|
||||
static async createPath(pathStr: string) {
|
||||
await fs.ensureDir(pathStr);
|
||||
static async checkExist(pathStr: string) {
|
||||
return await fs.pathExists(pathStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default FileService;
|
||||
|
@ -11,7 +11,7 @@ const HISTORY_NAME = "history.json";
|
||||
class MysqlUtil {
|
||||
public static pool: Database = null;
|
||||
|
||||
static async createPool(mysqlConfig: any) {
|
||||
static async createPool() {
|
||||
MysqlUtil.pool = await open({
|
||||
filename: path.join(config.rootPath, "database.db"),
|
||||
driver: sqlite3.Database
|
||||
|
@ -3,6 +3,10 @@ export default class FileObj {
|
||||
* 文件名
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 所属路径
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* 是否文件夹
|
||||
*/
|
||||
@ -17,8 +21,9 @@ export default class FileObj {
|
||||
updatedTime: number;
|
||||
|
||||
|
||||
constructor(name, isFolder, createdTime, updatedTime) {
|
||||
constructor(name, path, isFolder, createdTime, updatedTime) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.isFolder = isFolder;
|
||||
this.createdTime = createdTime;
|
||||
this.updatedTime = updatedTime;
|
||||
|
1
openRenamerFront/.gitignore
vendored
1
openRenamerFront/.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
package-lock.json
|
||||
|
||||
|
||||
# local env files
|
||||
|
27724
openRenamerFront/package-lock.json
generated
27724
openRenamerFront/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"core-js": "^3.6.5",
|
||||
"element-plus": "^1.0.2-beta.48",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
},
|
||||
|
@ -1,11 +1,27 @@
|
||||
<template>
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</div>
|
||||
<el-menu
|
||||
:default-active="activeIndex"
|
||||
class="el-menu-demo"
|
||||
mode="horizontal"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item index="dealCenter">处理中心</el-menu-item>
|
||||
<el-menu-item index="history">历史记录</el-menu-item>
|
||||
</el-menu>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Home",
|
||||
data() {
|
||||
return {
|
||||
activeIndex: "dealCenter",
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
|
129
openRenamerFront/src/components/FileChose.vue
Normal file
129
openRenamerFront/src/components/FileChose.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="main">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item
|
||||
><a @click.prevent="breadcrumbClick(-1)">根</a></el-breadcrumb-item
|
||||
>
|
||||
<el-breadcrumb-item v-for="(item, index) in pathList" :key="index">
|
||||
<a
|
||||
v-if="index < pathList.length - 1"
|
||||
@click.prevent="breadcrumbClick(index)"
|
||||
>{{ item }}</a
|
||||
>
|
||||
<span v-else>{{ item }}</span>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
|
||||
<div class="fileList">
|
||||
<div>
|
||||
<el-button type="primary" @click="selectAll(true)" size="mini"
|
||||
>全选</el-button
|
||||
>
|
||||
<el-button type="primary" @click="selectAll(false)" size="mini"
|
||||
>全不选</el-button
|
||||
>
|
||||
</div>
|
||||
<div v-for="(item, index) in fileList" :key="index">
|
||||
<span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{
|
||||
item.name
|
||||
}}</span>
|
||||
<el-checkbox v-model="item.checked" v-else>{{ item.name }}</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<el-button type="primary" @click="submit">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HttpUtil from "../utils/HttpUtil";
|
||||
export default {
|
||||
name: "FileChose",
|
||||
data() {
|
||||
return {
|
||||
isWindows: false,
|
||||
fileList: [], //路径下的文件节点
|
||||
chosedFileList: [], //选中的文件节点
|
||||
pathList: [], //选择的路径
|
||||
loading: false, //加载
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.isWindows = await HttpUtil.get("/file/isWindows");
|
||||
await this.breadcrumbClick(-1);
|
||||
},
|
||||
methods: {
|
||||
//点击面包蟹
|
||||
async breadcrumbClick(index) {
|
||||
this.loading = true;
|
||||
let path = this.createPath(index);
|
||||
let fileList = await HttpUtil.get("/file/query", {
|
||||
path: encodeURIComponent(path),
|
||||
showHidden: false,
|
||||
});
|
||||
fileList.forEach((item) => (item.checked = false));
|
||||
this.fileList = fileList;
|
||||
this.loading = false;
|
||||
return false;
|
||||
},
|
||||
//文件列表点击
|
||||
fileClick(item) {
|
||||
if (item.isFolder) {
|
||||
this.pathList.push(item.name);
|
||||
this.breadcrumbClick(this.pathList.length);
|
||||
} else {
|
||||
item.checked = !item.checked;
|
||||
}
|
||||
},
|
||||
//全选
|
||||
selectAll(status) {
|
||||
this.fileList
|
||||
.filter((item) => !item.isFolder)
|
||||
.forEach((item) => (item.checked = status));
|
||||
},
|
||||
//根据index构建路径
|
||||
createPath(index) {
|
||||
let path;
|
||||
if (index == -1) {
|
||||
path = "/";
|
||||
this.pathList = [];
|
||||
} else {
|
||||
this.pathList = this.pathList.slice(0, index + 1);
|
||||
let str = this.pathList.join(this.isWindows ? "\\" : "/");
|
||||
path = this.isWindows ? str : "/" + str;
|
||||
}
|
||||
return path;
|
||||
},
|
||||
//点击确定
|
||||
submit() {
|
||||
let chosedFiles = this.fileList.filter((item) => item.checked);
|
||||
if (chosedFiles.length == 0) {
|
||||
this.$message({ message: "未选择文件", type: "warning" });
|
||||
return;
|
||||
}
|
||||
this.$emit("addData", chosedFiles);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
height: 65vh;
|
||||
}
|
||||
.fileList {
|
||||
padding: 1em;
|
||||
text-align: left;
|
||||
height: 80%;
|
||||
overflow: hidden auto;
|
||||
|
||||
.folder {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
display: inline-block;
|
||||
min-width: 3em;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,97 +1,5 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="hello">hello World!</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
82
openRenamerFront/src/components/Rule.vue
Normal file
82
openRenamerFront/src/components/Rule.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<el-menu
|
||||
style="width: 8em"
|
||||
mode="vertical"
|
||||
:default-active="currentIndex"
|
||||
@select="menuChange"
|
||||
>
|
||||
<el-menu-item :disabled="editRule" index="insert">插入</el-menu-item>
|
||||
<el-menu-item :disabled="editRule" index="delete">删除</el-menu-item>
|
||||
<!-- <el-menu-item index="replace">替换</el-menu-item> -->
|
||||
<el-menu-item :disabled="editRule" index="serialization"
|
||||
>序列化</el-menu-item
|
||||
>
|
||||
</el-menu>
|
||||
<div class="rule">
|
||||
<insert-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-if="currentIndex == 'insert'"
|
||||
/>
|
||||
<delete-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-else-if="currentIndex == 'delete'"
|
||||
/>
|
||||
<serialization-rule
|
||||
ref="rule"
|
||||
:editRule="editRule"
|
||||
v-else-if="currentIndex == 'serialization'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button type="primary" @click="submit">确定</el-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InsertRule from "./rules/InsertRule.vue";
|
||||
import DeleteRule from "./rules/DeleteRule.vue";
|
||||
import SerializationRule from "./rules/SerializationRule.vue";
|
||||
export default {
|
||||
components: { InsertRule, DeleteRule, SerializationRule },
|
||||
props: ["editRule"],
|
||||
name: "Rule",
|
||||
data() {
|
||||
return {
|
||||
currentIndex: "insert",
|
||||
options: [{ label: "插入", value: "insert" }],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.currentIndex = this.editRule.type;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
menuChange(index) {
|
||||
this.currentIndex = index;
|
||||
},
|
||||
submit() {
|
||||
let data = this.$refs["rule"].exportObj();
|
||||
if (data != null) {
|
||||
this.$emit("ruleAdd", data);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
display: flex;
|
||||
height: 65vh;
|
||||
text-align: left;
|
||||
|
||||
.rule {
|
||||
padding: 5px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
197
openRenamerFront/src/components/rules/DeleteRule.vue
Normal file
197
openRenamerFront/src/components/rules/DeleteRule.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">部分删除:</span>
|
||||
<div class="location">
|
||||
<div>
|
||||
<div>开始</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.start.type"
|
||||
label="location"
|
||||
:disabled="deleteAll"
|
||||
>位置:</el-radio
|
||||
>
|
||||
<el-input-number
|
||||
:min="1"
|
||||
size="small"
|
||||
:disabled="deleteAll"
|
||||
v-model="startIndex"
|
||||
/>
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.start.type"
|
||||
label="text"
|
||||
:disabled="deleteAll"
|
||||
>文本:</el-radio
|
||||
>
|
||||
<el-input v-model="startText" size="small" :disabled="deleteAll" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 4em">
|
||||
<div>结束</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="location"
|
||||
:disabled="deleteAll"
|
||||
>位置:</el-radio
|
||||
>
|
||||
<el-input-number
|
||||
size="small"
|
||||
:disabled="deleteAll"
|
||||
v-model="endIndex"
|
||||
/>
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="text"
|
||||
:disabled="deleteAll"
|
||||
>文本:</el-radio
|
||||
>
|
||||
<el-input v-model="endText" size="small" :disabled="deleteAll" />
|
||||
</div>
|
||||
<div class="line">
|
||||
<el-radio
|
||||
v-model="ruleObj.data.end.type"
|
||||
label="end"
|
||||
:disabled="untilEnd"
|
||||
>直到末尾</el-radio
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="left">全部删除:</div>
|
||||
<el-switch v-model="deleteAll" @change="allDeleteChange" />
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DeleteRule",
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "delete",
|
||||
message: "",
|
||||
data: {
|
||||
type: "deletePart",
|
||||
start: {
|
||||
type: "location",
|
||||
value: "",
|
||||
},
|
||||
end: {
|
||||
type: "location",
|
||||
value: "",
|
||||
},
|
||||
ignorePostfix: false,
|
||||
},
|
||||
},
|
||||
startIndex: 1,
|
||||
endIndex: 1,
|
||||
startText: "",
|
||||
endText: "",
|
||||
deleteAll: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
if (this.ruleObj.data.type == "deletePart") {
|
||||
if (this.ruleObj.data.start.type == "location") {
|
||||
this.startIndex = parseInt(this.ruleObj.data.start.value);
|
||||
} else {
|
||||
this.startText = this.ruleObj.data.start.value;
|
||||
}
|
||||
if (this.ruleObj.data.end.type == "location") {
|
||||
this.endIndex = parseInt(this.ruleObj.data.end.value);
|
||||
} else {
|
||||
this.endText = this.ruleObj.data.end.value;
|
||||
}
|
||||
} else {
|
||||
this.deleteAll = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
if (this.ruleObj.data.type.length == 0) {
|
||||
this.$message({ message: "请填写完整", type: "warning" });
|
||||
return null;
|
||||
}
|
||||
if (this.ruleObj.data.type == "deletePart") {
|
||||
if (
|
||||
(this.ruleObj.data.start.type == "text" &&
|
||||
this.startText.length == 0) ||
|
||||
(this.ruleObj.data.start.type == "text" && this.startText.length == 0)
|
||||
) {
|
||||
this.$message({
|
||||
message: "开始或者结束文本不能为空",
|
||||
type: "warning",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
this.ruleObj.data.start.value =
|
||||
this.ruleObj.data.start.type == "location"
|
||||
? this.startIndex.toString()
|
||||
: this.startText;
|
||||
this.ruleObj.data.end.value =
|
||||
this.ruleObj.data.end.type == "location"
|
||||
? this.endIndex.toString()
|
||||
: this.endText;
|
||||
let message = `删除:`;
|
||||
if (this.deleteAll) {
|
||||
message += "全部删除";
|
||||
} else {
|
||||
message += `从"${this.ruleObj.data.start.value}"到"${
|
||||
this.ruleObj.data.end.type == "untilEnd"
|
||||
? "末尾"
|
||||
: this.ruleObj.data.end.value
|
||||
}"`;
|
||||
}
|
||||
this.ruleObj.message = message;
|
||||
return this.ruleObj;
|
||||
},
|
||||
allDeleteChange(val) {
|
||||
console.log(val);
|
||||
this.deleteAll = val;
|
||||
this.ruleObj.data.type = val ? "deleteAll" : "deletePart";
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
103
openRenamerFront/src/components/rules/InsertRule.vue
Normal file
103
openRenamerFront/src/components/rules/InsertRule.vue
Normal file
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">插入:</span>
|
||||
<el-input style="flex: 1" v-model="ruleObj.data.insertContent" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">位置:</span>
|
||||
<div class="location">
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="front"
|
||||
>前缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="backend"
|
||||
>后缀</el-radio
|
||||
>
|
||||
<el-radio style="margin-top: 1em" v-model="ruleObj.data.type" label="at"
|
||||
>位置:<el-input-number size="mini" v-model="ruleObj.data.atInput" />
|
||||
|
||||
<el-switch
|
||||
v-model="ruleObj.data.atIsRightToleft"
|
||||
:min="1"
|
||||
active-text="从右到左"
|
||||
inactive-text="从左到右"
|
||||
/>
|
||||
</el-radio>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.type"
|
||||
label="replace"
|
||||
>替换当前文件名</el-radio
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "InsertRule",
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "insert",
|
||||
message: "",
|
||||
data: {
|
||||
insertContent: "",
|
||||
type: "",
|
||||
atInput: 0,
|
||||
atIsRightToleft: false,
|
||||
ignorePostfix: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
console.log(this.editRule);
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
if (
|
||||
this.ruleObj.data.insertContent.length == 0 ||
|
||||
this.ruleObj.data.type.length == 0
|
||||
) {
|
||||
this.$message({ message: "请填写完整", type: "warning" });
|
||||
return null;
|
||||
}
|
||||
this.ruleObj.message = `插入:"${this.ruleObj.data.insertContent}"`;
|
||||
return this.ruleObj;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
justify-content: left;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
114
openRenamerFront/src/components/rules/SerializationRule.vue
Normal file
114
openRenamerFront/src/components/rules/SerializationRule.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<span class="left">起始数:</span>
|
||||
<div class="right">
|
||||
<el-input-number :min="1" size="small" v-model="ruleObj.data.start" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">增量:</span>
|
||||
<div class="right">
|
||||
<el-input-number :min="1" size="small" v-model="ruleObj.data.increment" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">填充0补足:</span>
|
||||
<div class="right">
|
||||
<el-switch v-model="ruleObj.data.addZero" />
|
||||
<el-input-number
|
||||
size="small"
|
||||
:min="1"
|
||||
:disabled="!ruleObj.data.addZero"
|
||||
v-model="ruleObj.data.numLength"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<span class="left">位置:</span>
|
||||
<div class="location">
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="front"
|
||||
>前缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="backend"
|
||||
>后缀</el-radio
|
||||
>
|
||||
<el-radio
|
||||
style="margin-top: 1em"
|
||||
v-model="ruleObj.data.insertType"
|
||||
label="at"
|
||||
>位置:<el-input-number
|
||||
size="mini"
|
||||
:min="1"
|
||||
:disabled="ruleObj.data.insertType !== 'at'"
|
||||
v-model="ruleObj.data.insertValue"
|
||||
/>
|
||||
</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<div class="left">忽略拓展名:</div>
|
||||
<el-switch v-model="ruleObj.data.ignorePostfix" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SerializationRule",
|
||||
|
||||
props: ["editRule"],
|
||||
data() {
|
||||
return {
|
||||
ruleObj: {
|
||||
type: "serialization",
|
||||
message: "",
|
||||
data: {
|
||||
start: 1,
|
||||
increment: 1,
|
||||
addZero: false,
|
||||
numLength: 1,
|
||||
ignorePostfix: false,
|
||||
insertType: "front",
|
||||
insertValue: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (this.editRule) {
|
||||
this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
exportObj() {
|
||||
this.ruleObj.message = `序列化:从开始${this.ruleObj.data.start},增量${this.ruleObj.data.increment}`;
|
||||
return this.ruleObj;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding-top: 1em;
|
||||
|
||||
.left {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.location {
|
||||
justify-content: left;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,5 +1,9 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/lib/theme-chalk/index.css";
|
||||
|
||||
createApp(App).use(router).mount("#app");
|
||||
const vueInstance = createApp(App);
|
||||
vueInstance.use(router).use(ElementPlus).mount("#app");
|
||||
window.vueInstance = vueInstance;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import Home from "../views/Home.vue";
|
||||
import Home from "../views/home/Home.vue";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as http from "axios";
|
||||
import router from "../router/index";
|
||||
|
||||
/**
|
||||
* 请求
|
||||
@ -11,10 +10,10 @@ import router from "../router/index";
|
||||
* @param {*} redirect 接口返回未认证是否跳转到登陆
|
||||
* @returns 数据
|
||||
*/
|
||||
async function request(url, method, params, body, isForm, redirect) {
|
||||
async function request(url, method, params, body, isForm) {
|
||||
let options = {
|
||||
url,
|
||||
baseURL: "/bookmark/api",
|
||||
baseURL: "/openRenamer/api",
|
||||
method,
|
||||
params,
|
||||
// headers: {
|
||||
@ -35,30 +34,7 @@ async function request(url, method, params, body, isForm, redirect) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const { code, data, message } = res.data;
|
||||
if (code === 1) {
|
||||
return data;
|
||||
} else if (code === -1 && redirect) {
|
||||
// 跳转到登陆页
|
||||
window.vueInstance.$message.error("您尚未登陆,请先登陆");
|
||||
router.replace(
|
||||
`/public/login?redirect=${encodeURIComponent(
|
||||
router.currentRoute.fullPath
|
||||
)}`
|
||||
);
|
||||
throw new Error(message);
|
||||
} else if (code === 0) {
|
||||
//通用异常,使用
|
||||
window.vueInstance.$notification.error({
|
||||
message: "异常",
|
||||
description: message,
|
||||
});
|
||||
throw new Error(message);
|
||||
} else if (code === -2) {
|
||||
//表单异常,使用message提示
|
||||
window.vueInstance.$message.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
return res.data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,8 +43,8 @@ async function request(url, method, params, body, isForm, redirect) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 未登陆是否跳转到登陆页
|
||||
*/
|
||||
async function get(url, params = null, redirect = true) {
|
||||
return request(url, "get", params, null, false, redirect);
|
||||
async function get(url, params = null) {
|
||||
return request(url, "get", params, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,8 +55,8 @@ async function get(url, params = null, redirect = true) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function post(url, params, body, isForm = false, redirect = true) {
|
||||
return request(url, "post", params, body, isForm, redirect);
|
||||
async function post(url, params, body, isForm = false) {
|
||||
return request(url, "post", params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,8 +67,8 @@ async function post(url, params, body, isForm = false, redirect = true) {
|
||||
* @param {*} isForm 是否表单数据
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function put(url, params, body, isForm = false, redirect = true) {
|
||||
return request(url, "put", params, body, isForm, redirect);
|
||||
async function put(url, params, body, isForm = false) {
|
||||
return request(url, "put", params, body, isForm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,8 +77,8 @@ async function put(url, params, body, isForm = false, redirect = true) {
|
||||
* @param {*} params url参数
|
||||
* @param {*} redirect 是否重定向
|
||||
*/
|
||||
async function deletes(url, params = null, redirect = true) {
|
||||
return request(url, "delete", params, null, redirect);
|
||||
async function deletes(url, params = null) {
|
||||
return request(url, "delete", params, null);
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {
|
||||
HelloWorld,
|
||||
},
|
||||
};
|
||||
</script>
|
136
openRenamerFront/src/views/home/Home.vue
Normal file
136
openRenamerFront/src/views/home/Home.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button type="primary" @click="dialogVisible = true" size="small"
|
||||
>新增文件</el-button
|
||||
>
|
||||
<el-button type="primary" @click="showResult" size="small">预览</el-button>
|
||||
<!-- 规则列表 -->
|
||||
<div class="ruleList">
|
||||
<div class="menu">
|
||||
<span>应用规则</span>
|
||||
<el-button type="primary" size="mini" @click="ruleDialogShow = true"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="checkedRules.length == 1"
|
||||
@click="editClick"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button type="warning" size="mini" @click="block"
|
||||
>禁用/启用</el-button
|
||||
>
|
||||
<el-button type="danger" size="mini" @click="deleteRule"
|
||||
>删除</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="ruleBlock">
|
||||
<el-checkbox
|
||||
v-model="item.checked"
|
||||
v-for="(item, index) in ruleList"
|
||||
:key="index"
|
||||
>
|
||||
<s v-if="item.blocked">{{ item.message }}</s>
|
||||
<span v-else>{{ item.message }}</span>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 文件预览列表 -->
|
||||
<div class="fileList">
|
||||
<div>文件列表</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog
|
||||
title="新增文件"
|
||||
v-model="dialogVisible"
|
||||
width="70%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<file-chose v-if="dialogVisible" @addData="addData" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="新增规则"
|
||||
v-model="ruleDialogShow"
|
||||
width="70%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<rule :editRule="editRule" v-if="ruleDialogShow" @ruleAdd="ruleAdd" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import FileChose from "@/components/FileChose";
|
||||
import Rule from "@/components/Rule";
|
||||
export default {
|
||||
name: "Home",
|
||||
components: { FileChose, Rule },
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
ruleDialogShow: true, //规则弹床
|
||||
fileList: [],
|
||||
ruleList: [],
|
||||
editRule: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
checkedRules() {
|
||||
return this.ruleList.filter((item) => item.checked);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addData(data) {
|
||||
console.log(data);
|
||||
this.fileList.push(...data);
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
ruleAdd(data) {
|
||||
data.checked = false;
|
||||
data.blocked = false;
|
||||
if (this.editRule != null) {
|
||||
let index = this.ruleList.indexOf(this.editRule);
|
||||
this.ruleList.splice(index, 1, data);
|
||||
this.editRule = null;
|
||||
} else {
|
||||
this.ruleList.push(data);
|
||||
}
|
||||
this.ruleDialogShow = false;
|
||||
},
|
||||
//禁用/启用
|
||||
block() {
|
||||
this.ruleList
|
||||
.filter((item) => item.checked)
|
||||
.forEach((item) => (item.blocked = !item.blocked));
|
||||
},
|
||||
//删除规则
|
||||
deleteRule() {
|
||||
this.ruleList = this.ruleList.filter((item) => !item.checked);
|
||||
},
|
||||
editClick() {
|
||||
this.editRule = this.checkedRules[0];
|
||||
this.ruleDialogShow = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ruleList {
|
||||
border: 1px solid black;
|
||||
padding: 5px;
|
||||
.menu {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
}
|
||||
.ruleBlock {
|
||||
text-align: left;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
</style>
|
5
openRenamerFront/vue.config.js
Normal file
5
openRenamerFront/vue.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
devServer: {
|
||||
proxy: "http://localhost:8089",
|
||||
},
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user