Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
6e983f8949
@ -25,7 +25,7 @@ renamer 的开源实现版本,BS 应用,支持全平台部署使用
|
||||
|
||||
```bash
|
||||
# 管理/mnt/vdisk目录中的文件,通过8089端口访问服务
|
||||
docker run -itd --name openRenamer -v /mnt/vdisk:/data -p 8089:8089 fleyx/open-renamer
|
||||
docker run -itd --name openRenamer -v /mnt/vdisk:/data -p 8089:8089 -e PORT="8089" -e TOKEN="123456" fleyx/open-renamer
|
||||
```
|
||||
|
||||
- docker-compose 运行:
|
||||
@ -40,6 +40,8 @@ version: "3.6"
|
||||
environment:
|
||||
# 指定启动端口
|
||||
- PORT=11004
|
||||
# 指定认证token,不设置此项无需认证
|
||||
- TOKEN=123456
|
||||
volumes:
|
||||
# 关键,把想要管理的文件夹映射到容器的data目录中,即可在程序中选择data目录进行重命名操作
|
||||
- /mnt/vdisk:/data
|
||||
|
@ -25,4 +25,25 @@ router["GET /file/path/exist"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.checkExist(ctx.query.path as string);
|
||||
};
|
||||
|
||||
/**
|
||||
* 收藏路径
|
||||
*/
|
||||
router["POST /file/path/save"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.savePath(ctx.request.body);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取收藏路径
|
||||
*/
|
||||
router["GET /file/path"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.getSaveList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取收藏路径
|
||||
*/
|
||||
router["DELETE /file/path/delete"] = async function (ctx: Context) {
|
||||
ctx.body = await FileService.deleteOne(ctx.query.id);
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
42
openRenamerBackend/dao/SavePathDao.ts
Normal file
42
openRenamerBackend/dao/SavePathDao.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import ErrorHelper from "../util/ErrorHelper";
|
||||
import SavePath from "../entity/dto/SavePath";
|
||||
import SqliteHelper from "../util/SqliteHelper";
|
||||
|
||||
export default class SavePathDao {
|
||||
/**
|
||||
* 查询所有
|
||||
* @param obj
|
||||
* @returns
|
||||
*/
|
||||
static async getAll(): Promise<Array<SavePath>> {
|
||||
let res = await SqliteHelper.pool.all('select id,name,content from path_save');
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param obj
|
||||
* @returns
|
||||
*/
|
||||
static async addOne(obj: SavePath): Promise<number> {
|
||||
let res = await SqliteHelper.pool.run('insert into path_save(name,content) values(?,?)'
|
||||
, obj.name, obj.content);
|
||||
obj.id = res.lastID;
|
||||
return res.lastID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
*/
|
||||
static async delete(id: number): Promise<void> {
|
||||
let res = await SqliteHelper.pool.run('delete from path_save where id=?', id);
|
||||
if (res.changes == 0) {
|
||||
throw ErrorHelper.Error404("数据不存在");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
12
openRenamerBackend/entity/dto/SavePath.ts
Normal file
12
openRenamerBackend/entity/dto/SavePath.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export default class SavePath {
|
||||
id: number;
|
||||
/**
|
||||
名称
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
规则内容,json序列化后
|
||||
*/
|
||||
content: string;
|
||||
}
|
@ -4,6 +4,8 @@ import * as fs from 'fs-extra';
|
||||
|
||||
import ProcessHelper from '../util/ProcesHelper';
|
||||
import FileObj from '../vo/FileObj';
|
||||
import SavePathDao from '../dao/SavePathDao';
|
||||
import SavePath from '../entity/dto/SavePath';
|
||||
|
||||
let numberSet = new Set(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
||||
|
||||
@ -56,6 +58,33 @@ class FileService {
|
||||
return await fs.pathExists(pathStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏路径
|
||||
* @param saveObj
|
||||
* @returns
|
||||
*/
|
||||
static async savePath(saveObj: SavePath) {
|
||||
await SavePathDao.addOne(saveObj);
|
||||
return saveObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保存列表
|
||||
* @returns
|
||||
*/
|
||||
static async getSaveList() {
|
||||
return await SavePathDao.getAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
static async deleteOne(id) {
|
||||
return await SavePathDao.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字字母混合排序
|
||||
* @param a str
|
||||
|
7
openRenamerBackend/sqls/v002__init.sql
Normal file
7
openRenamerBackend/sqls/v002__init.sql
Normal file
@ -0,0 +1,7 @@
|
||||
-- 路径收藏表
|
||||
CREATE TABLE path_save (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
-- 路径内容
|
||||
content TEXT NOT NULL DEFAULT ''
|
||||
);
|
@ -43,27 +43,29 @@ export default class InsertRule implements RuleInterface {
|
||||
|
||||
deal(file: FileObj): void {
|
||||
let str = this.ignorePostfix ? file.realName : file.name;
|
||||
let season = '';
|
||||
if (this.autoSeason) {
|
||||
let patternRes = path.basename(file.path).replace(/[ ]+/, "").toLocaleLowerCase().match(pattern);
|
||||
if (patternRes && patternRes[2]) {
|
||||
season = patternRes[2];
|
||||
}
|
||||
}
|
||||
switch (this.type) {
|
||||
case "front":
|
||||
str = this.insertContent + str;
|
||||
str = this.insertContent + season + str;
|
||||
break;
|
||||
case "backend":
|
||||
str = str + this.insertContent;
|
||||
str = str + this.insertContent + season;
|
||||
break;
|
||||
case "at":
|
||||
let index = this.atIsRightToleft ? str.length - this.atInput + 1 : this.atInput - 1;
|
||||
str = str.substring(0, index) + this.insertContent + str.substring(index);
|
||||
str = str.substring(0, index) + this.insertContent + season + str.substring(index);
|
||||
break;
|
||||
case "replace":
|
||||
str = this.insertContent;
|
||||
str = this.insertContent + season;
|
||||
break;
|
||||
}
|
||||
if (this.autoSeason) {
|
||||
let patternRes = path.basename(file.path).replace(/[ ]+/, "").toLocaleLowerCase().match(pattern);
|
||||
if (patternRes[2]) {
|
||||
str += patternRes[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.ignorePostfix) {
|
||||
file.realName = str;
|
||||
|
@ -12,7 +12,7 @@
|
||||
"axios": "^0.21.1",
|
||||
"core-js": "^3.6.5",
|
||||
"dayjs": "^1.10.7",
|
||||
"element-plus": "^1.2.0-beta.5",
|
||||
"element-plus": "^2.2.5",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
},
|
||||
|
@ -14,7 +14,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
activeIndex: "dealCenter",
|
||||
version: "0.6",
|
||||
version: "0.8",
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
|
@ -11,9 +11,11 @@
|
||||
<div class="fileList">
|
||||
<div>
|
||||
<el-input style="display: inline-block; width: 150px" type="text" size="small" placeholder="关键词过滤" v-model="filterText" clearable />
|
||||
<el-button type="primary" @click="selectAll(true)" size="mini">全选</el-button>
|
||||
<el-button type="primary" @click="selectAll(false)" size="mini">全不选</el-button>
|
||||
<el-button type="primary" @click="refresh" size="mini">刷新</el-button>
|
||||
<el-button type="primary" @click="selectAll(true)" size="small">全选</el-button>
|
||||
<el-button type="primary" @click="selectAll(false)" size="small">全不选</el-button>
|
||||
<el-button type="primary" @click="refresh" size="small">刷新</el-button>
|
||||
<el-button v-if="curSavePathId" type="warning" @click="cancelSavePath" size="small">取消收藏</el-button>
|
||||
<el-button v-else type="primary" @click="showSave = true" size="small">收藏路径</el-button>
|
||||
</div>
|
||||
<div v-for="(item, index) in filterFileList" :key="index">
|
||||
<span class="folder" v-if="item.isFolder" @click="fileClick(item)">{{ item.name }}</span>
|
||||
@ -24,6 +26,11 @@
|
||||
<div>
|
||||
<el-button type="primary" @click="submit">确定</el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog title="保存路径" v-model="showSave" width="40em">
|
||||
<el-input type="text" v-model="saveName" placeholder="输入名称" />
|
||||
<el-button type="primary" @click="savePath" style="padding-top: 1em">提交</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -38,6 +45,9 @@ export default {
|
||||
pathList: [], //选择的路径
|
||||
loading: false, //加载
|
||||
filterText: "", //关键字过滤
|
||||
showSave: false, //保存路径
|
||||
saveName: "",
|
||||
savePathList: [], //保存的路径
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -45,16 +55,25 @@ export default {
|
||||
let text = this.filterText.trim();
|
||||
return text === "" ? this.fileList : this.fileList.filter((item) => item.name.indexOf(text) > -1);
|
||||
},
|
||||
curSavePathId() {
|
||||
let curPath = JSON.stringify(this.pathList);
|
||||
let targetList = this.savePathList.filter((item) => item.content == curPath);
|
||||
return targetList.length > 0 ? targetList[0].id : null;
|
||||
},
|
||||
async mounted() {
|
||||
this.isWindows = await HttpUtil.get("/file/isWindows");
|
||||
await this.breadcrumbClick(-1);
|
||||
},
|
||||
async created() {
|
||||
await this.breadcrumbClick(this.pathList.length - 1);
|
||||
await this.refreshSavePathList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
async refresh() {
|
||||
await this.breadcrumbClick(this.pathList.length - 1);
|
||||
},
|
||||
//刷新保存的路径
|
||||
async refreshSavePathList() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
},
|
||||
//点击面包蟹
|
||||
async breadcrumbClick(index) {
|
||||
this.loading = true;
|
||||
@ -84,15 +103,17 @@ export default {
|
||||
},
|
||||
//根据index构建路径
|
||||
createPath(index) {
|
||||
console.log("当前路径为:", this.pathList);
|
||||
let path;
|
||||
if (index == -1) {
|
||||
path = "";
|
||||
this.pathList = [];
|
||||
} else {
|
||||
this.pathList = this.pathList.slice(0, index + 1);
|
||||
let str = this.pathList.join(this.isWindows ? "\\" : "/") + (this.isWindows ? "\\" : "/");
|
||||
path = this.isWindows ? str : "/" + str;
|
||||
let str = this.pathList.join(window.isWindows ? "\\" : "/") + (window.isWindows ? "\\" : "/");
|
||||
path = window.isWindows ? str : "/" + str;
|
||||
}
|
||||
console.log("构建出的路径为:", path);
|
||||
return path;
|
||||
},
|
||||
//点击确定
|
||||
@ -102,11 +123,30 @@ export default {
|
||||
this.$message({ message: "未选择文件", type: "warning" });
|
||||
return;
|
||||
}
|
||||
this.$emit("addData", chosedFiles);
|
||||
this.$emit("addData", JSON.parse(JSON.stringify(chosedFiles)));
|
||||
this.fileList.forEach((item) => (item.checked = false));
|
||||
this.fileList = [...this.fileList];
|
||||
this.filterText = "";
|
||||
},
|
||||
//收藏路径
|
||||
async savePath() {
|
||||
let res = await HttpUtil.post("/file/path/save", null, { name: this.saveName, content: JSON.stringify(this.pathList) });
|
||||
this.$emit("refreshSavePathList");
|
||||
this.refreshSavePathList();
|
||||
this.saveName = "";
|
||||
this.showSave = false;
|
||||
this.$message.success("操作成功");
|
||||
},
|
||||
async cancelSavePath() {
|
||||
await HttpUtil.delete("/file/path/delete", { id: this.curSavePathId });
|
||||
this.refreshSavePathList();
|
||||
this.$emit("refreshSavePathList");
|
||||
this.$message.success("操作成功");
|
||||
},
|
||||
changePath(item) {
|
||||
this.pathList = JSON.parse(item.content);
|
||||
this.breadcrumbClick(this.pathList.length - 1);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<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 :disabled="editRule != null" index="insert">插入</el-menu-item>
|
||||
<el-menu-item :disabled="editRule != null" 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-item :disabled="editRule != null" index="serialization">序列化</el-menu-item>
|
||||
</el-menu>
|
||||
<div class="rule">
|
||||
<insert-rule ref="rule" :editRule="editRule" v-if="currentIndex == 'insert'" />
|
||||
|
@ -9,7 +9,7 @@
|
||||
<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-input-number size="small" v-model="ruleObj.data.atInput" />
|
||||
|
||||
<el-switch v-model="ruleObj.data.atIsRightToleft" :min="1" active-text="从右到左" inactive-text="从左到右" />
|
||||
</el-radio>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<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-input-number size="small" :min="1" :disabled="ruleObj.data.insertType !== 'at'" v-model="ruleObj.data.insertValue" />
|
||||
</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,9 +9,10 @@
|
||||
<div class="fileList">
|
||||
<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="danger" size="mini" @click="deleteCheckedFiles">删除</el-button>
|
||||
<el-button type="primary" @click="showFileAdd" size="small">新增</el-button>
|
||||
<el-button type="primary" size="small" @click="selectAllFiles">反选</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteCheckedFiles">删除</el-button>
|
||||
收藏路径:<el-button v-for="item in savePathList" :key="item.id" @click="clickSavePath(item)" type="primary" text>{{ item.name }}</el-button>
|
||||
</div>
|
||||
<div class="fileBlock">
|
||||
<!-- 左侧原始文件名 -->
|
||||
@ -44,7 +45,7 @@
|
||||
<!-- 新增文件弹窗 -->
|
||||
|
||||
<el-dialog title="新增文件" v-model="dialogVisible" width="70%">
|
||||
<file-chose @addData="addData" />
|
||||
<file-chose ref="fileChose" :curSavePath="curSavePath" @addData="addData" @refreshSavePathList="refreshSavePathList" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@ -75,9 +76,14 @@ export default {
|
||||
changedFileList: [], //执行修改后的文件
|
||||
needPreview: false, //需要点击预览
|
||||
applicationRule: null, //当前应用的应用规则模板
|
||||
savePathList: [], //收藏的路径列表
|
||||
curSavePath: null, //当前选择的收藏路径
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
window.isWindows = await HttpUtil.get("/file/isWindows");
|
||||
},
|
||||
methods: {
|
||||
//新增文件
|
||||
async addData(data) {
|
||||
@ -160,6 +166,20 @@ export default {
|
||||
this.needPreview = true;
|
||||
await this.showResult();
|
||||
},
|
||||
showFileAdd() {
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
//点击收藏路径
|
||||
clickSavePath(item) {
|
||||
this.dialogVisible = true;
|
||||
console.log(item);
|
||||
this.$nextTick(() => {
|
||||
this.$refs["fileChose"].changePath(item);
|
||||
});
|
||||
},
|
||||
async refreshSavePathList() {
|
||||
this.savePathList = await HttpUtil.get("/file/path");
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
<el-table-column prop="createdDate" label="创建时间" width="180" />
|
||||
<el-table-column prop="name" label="名称" width="180" />
|
||||
<el-table-column prop="comment" label="备注" />
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<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>
|
||||
<el-button text type="primary" size="small" @click="ruleTemplateAction('chose', scope.row)">选择</el-button>
|
||||
<el-button text type="warning" size="small" @click="ruleTemplateAction('delete', scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -2,12 +2,12 @@
|
||||
<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 type="primary" size="small" @click="addRuleDialogShow = true">新增</el-button>
|
||||
<el-button type="primary" size="small" v-if="checkedRules.length == 1" @click="editClick">编辑</el-button>
|
||||
<el-button type="warning" size="small" @click="block">禁用/启用</el-button>
|
||||
<el-button type="danger" size="small" @click="deleteRule">删除</el-button>
|
||||
<el-button type="primary" size="small" v-if="chosedTemplate" @click="templateSubmit">保存规则</el-button>
|
||||
<el-button type="primary" size="small" v-if="chosedTemplate == null && ruleList.length > 0" @click="saveTemplateDilalogShow = true"
|
||||
>存为模板</el-button
|
||||
>
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
<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>
|
||||
<el-button type="primary" size="small" @click="ruleTemplateShow = true">选择模板</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 弹窗 -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user