From f5023487867ae3aed71e7ff1365489990e538da7 Mon Sep 17 00:00:00 2001
From: fanxb <fanxb.tl@gmail.com>
Date: Wed, 10 May 2023 20:24:29 +0800
Subject: [PATCH 1/2] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E6=9B=BF=E6=8D=A2?=
 =?UTF-8?q?=E8=A7=84=E5=88=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../.idea/openRenamerBackend.iml              |  1 +
 .../entity/bo/rules/ReplaceRule.ts            | 54 +++++++++++
 openRenamerBackend/entity/vo/RuleObj.ts       | 56 ++++++-----
 openRenamerBackend/service/RenamerService.ts  |  2 +-
 openRenamerFront/src/App.vue                  |  2 +-
 openRenamerFront/src/components/Rule.vue      | 25 ++---
 .../src/components/rules/ReplaceRule.vue      | 94 +++++++++++++++++++
 7 files changed, 195 insertions(+), 39 deletions(-)
 create mode 100644 openRenamerBackend/entity/bo/rules/ReplaceRule.ts
 create mode 100644 openRenamerFront/src/components/rules/ReplaceRule.vue

diff --git a/openRenamerBackend/.idea/openRenamerBackend.iml b/openRenamerBackend/.idea/openRenamerBackend.iml
index c0d38ce..9582cd4 100644
--- a/openRenamerBackend/.idea/openRenamerBackend.iml
+++ b/openRenamerBackend/.idea/openRenamerBackend.iml
@@ -4,6 +4,7 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <excludeFolder url="file://$MODULE_DIR$/dist" />
+      <excludeFolder url="file://$MODULE_DIR$/.vscode" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
diff --git a/openRenamerBackend/entity/bo/rules/ReplaceRule.ts b/openRenamerBackend/entity/bo/rules/ReplaceRule.ts
new file mode 100644
index 0000000..a710aa6
--- /dev/null
+++ b/openRenamerBackend/entity/bo/rules/ReplaceRule.ts
@@ -0,0 +1,54 @@
+import RuleInterface from "./RuleInterface";
+import FileObj from "../../vo/FileObj";
+import path from 'path';
+
+
+export default class ReplaceRule implements RuleInterface {
+
+    /**
+     * 1:替换第一个,2:替换最后一个,3:全部替换
+     */
+    type: number;
+    /**
+     * 前面追加
+     */
+    source: string;
+    /**
+     * 后面追加
+     */
+    target: string;
+
+    constructor(data: any) {
+        this.type = data.type;
+        this.source = data.source;
+        this.target = data.target;
+    }
+
+
+    deal(file: FileObj): void {
+        let start = 0;
+        let changed = false;
+        for (; ;) {
+            let index = this.type == 1 || this.type == 3 ? file.name.indexOf(this.source, start) : file.name.lastIndexOf(this.source);
+            if (index > -1) {
+                file.name = file.name.substring(0, index) + this.target + file.name.substring(index + this.source.length);
+                start = index + this.target.length;
+                changed = true;
+                if (this.type != 3) {
+                    break;
+                }
+            } else {
+                break;
+            }
+        }
+        if (changed) {
+            file.originName = file.name;
+            file.expandName = path.extname(file.name);
+            if (file.expandName && file.expandName.length > 0) {
+                file.realName = file.name.substring(0, file.name.lastIndexOf("."));
+            } else {
+                file.realName = file.name;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/openRenamerBackend/entity/vo/RuleObj.ts b/openRenamerBackend/entity/vo/RuleObj.ts
index 5444998..d4bfc96 100644
--- a/openRenamerBackend/entity/vo/RuleObj.ts
+++ b/openRenamerBackend/entity/vo/RuleObj.ts
@@ -2,34 +2,38 @@ import DeleteRule from "../bo/rules/DeleteRule";
 import InsertRule from "../bo/rules/InsertRule";
 import SerializationRule from "../bo/rules/SerializationRule";
 import AutoRule from "../bo/rules/AutoRule";
+import ReplaceRule from "../bo/rules/ReplaceRule";
 
 export default class RuleObj {
-	type: string;
-	message: string;
-	/**
-	 * 具体参数
-	 */
-	data: any;
+    type: string;
+    message: string;
+    /**
+     * 具体参数
+     */
+    data: any;
 
-	constructor(data: any) {
-		this.type = data.type;
-		this.message = data.message;
-		switch (this.type) {
-			case "delete":
-				this.data = new DeleteRule(data.data);
-				break;
-			case "insert":
-				this.data = new InsertRule(data.data);
-				break;
-			case "serialization":
-				this.data = new SerializationRule(data.data);
-				break;
-			case "auto":
-				this.data = new AutoRule(data.data);
-				break;
-			default:
-				throw new Error("不支持的规则:" + this.type);
+    constructor(data: any) {
+        this.type = data.type;
+        this.message = data.message;
+        switch (this.type) {
+            case "delete":
+                this.data = new DeleteRule(data.data);
+                break;
+            case "insert":
+                this.data = new InsertRule(data.data);
+                break;
+            case "serialization":
+                this.data = new SerializationRule(data.data);
+                break;
+            case "auto":
+                this.data = new AutoRule(data.data);
+                break;
+            case "replace":
+                this.data = new ReplaceRule(data.data);
+                break;
+            default:
+                throw new Error("不支持的规则:" + this.type);
 
-		}
-	}
+        }
+    }
 }
\ No newline at end of file
diff --git a/openRenamerBackend/service/RenamerService.ts b/openRenamerBackend/service/RenamerService.ts
index dfdf363..e665ce8 100644
--- a/openRenamerBackend/service/RenamerService.ts
+++ b/openRenamerBackend/service/RenamerService.ts
@@ -17,7 +17,7 @@ class RenamerService {
             if (newNameSet.has(obj.name)) {
                 obj.errorMessage = "重名";
             }
-            newNameSet.add(obj.name);
+            newNameSet.add(obj.path + obj.name);
         }
         return fileList;
     }
diff --git a/openRenamerFront/src/App.vue b/openRenamerFront/src/App.vue
index 631f7f2..b31ca64 100644
--- a/openRenamerFront/src/App.vue
+++ b/openRenamerFront/src/App.vue
@@ -42,7 +42,7 @@ export default {
   name: "Home",
   data() {
     return {
-      version: "1.5",
+      version: "1.6",
       latestVersion: null,
       activeIndex: location.pathname,
       showNewVersion: false
diff --git a/openRenamerFront/src/components/Rule.vue b/openRenamerFront/src/components/Rule.vue
index 6382d5f..dfaa6e5 100644
--- a/openRenamerFront/src/components/Rule.vue
+++ b/openRenamerFront/src/components/Rule.vue
@@ -3,15 +3,16 @@
     <el-menu style="width: 8em" mode="vertical" :default-active="currentIndex" @select="menuChange">
       <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 != null" index="replace">替换</el-menu-item>
       <el-menu-item :disabled="editRule != null || isAutoPlan" index="serialization">序列化</el-menu-item>
       <el-menu-item :disabled="editRule != null" index="auto">自动识别</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'" />
-      <auto-rule ref="rule" :editRule="editRule" v-else-if="currentIndex == 'auto'" />
+      <insert-rule ref="rule" :editRule="editRule" v-if="currentIndex === 'insert'"/>
+      <delete-rule ref="rule" :editRule="editRule" v-else-if="currentIndex === 'delete'"/>
+      <replace-rule ref="rule" :editRule="editRule" v-else-if="currentIndex === 'replace'"/>
+      <serialization-rule ref="rule" :editRule="editRule" v-else-if="currentIndex === 'serialization'"/>
+      <auto-rule ref="rule" :editRule="editRule" v-else-if="currentIndex === 'auto'"/>
     </div>
   </div>
   <div style="text-align: center">
@@ -24,27 +25,29 @@ import InsertRule from "./rules/InsertRule.vue";
 import DeleteRule from "./rules/DeleteRule.vue";
 import SerializationRule from "./rules/SerializationRule.vue";
 import AutoRule from "./rules/AutoRule";
+import ReplaceRule from "@/components/rules/ReplaceRule";
+
 export default {
-  components: { InsertRule, DeleteRule, SerializationRule, AutoRule },
+  components: {InsertRule, DeleteRule, SerializationRule, AutoRule, ReplaceRule},
   props: ["editRule", "isAutoPlan"],
   emits: ["ruleAdd"],
   name: "Rule",
-  data () {
+  data() {
     return {
       currentIndex: "insert",
-      options: [{ label: "插入", value: "insert" }],
+      options: [{label: "插入", value: "insert"}],
     };
   },
-  created () {
+  created() {
     if (this.editRule) {
       this.currentIndex = this.editRule.type;
     }
   },
   methods: {
-    menuChange (index) {
+    menuChange(index) {
       this.currentIndex = index;
     },
-    submit () {
+    submit() {
       let data = this.$refs["rule"].exportObj();
       if (data != null) {
         this.$emit("ruleAdd", data);
diff --git a/openRenamerFront/src/components/rules/ReplaceRule.vue b/openRenamerFront/src/components/rules/ReplaceRule.vue
new file mode 100644
index 0000000..3a4bae0
--- /dev/null
+++ b/openRenamerFront/src/components/rules/ReplaceRule.vue
@@ -0,0 +1,94 @@
+<template>
+  <div class="flex">
+    <span class="left">源:</span>
+    <el-input style="width:20em" v-model="ruleObj.data.source"/>
+  </div>
+  <div class="flex">
+    <span class="left">目标:</span>
+    <el-input style="width:20em" v-model="ruleObj.data.target"/>
+  </div>
+  <div class="flex">
+    <span class="left">替换选项:</span>
+    <div class="location">
+      <el-radio v-for="item in radioList" :key="item.code" v-model="ruleObj.data.type" :label="item.code"
+      >{{ item.label }}
+      </el-radio>
+
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "ReplaceRule",
+  props: ["editRule"],
+  data() {
+    return {
+      radioList: [
+        {
+          label: "替换第一个",
+          code: 1,
+        },
+        {
+          label: "替换最后一个",
+          code: 2,
+        },
+        {
+          label: "全部替换",
+          code: 3,
+        },
+      ],
+      ruleObj: {
+        type: "replace",
+        message: "",
+        data: {
+          source: "",
+          target: "",
+          type: 1, //1:替换第一个,2:替换最后一个,3:全部替换
+        },
+      },
+    };
+  },
+  created() {
+    if (this.editRule) {
+      console.log(this.editRule);
+      this.ruleObj = JSON.parse(JSON.stringify(this.editRule));
+    }
+  },
+  methods: {
+    exportObj() {
+      if (!this.ruleObj.data.source) {
+        this.$message({message: "源不能为空", type: "warning"});
+        return null;
+      }
+      if (!this.ruleObj.data.type) {
+        this.$message({message: "请选择替换选项", type: "warning"});
+        return null;
+      }
+      this.ruleObj.message = `替换:将${this.ruleObj.data.source}替换为${this.ruleObj.data.target};`
+          + this.radioList.filter(item => item.code === this.ruleObj.data.type)[0].label;
+      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>

From faedc09771783a1a5548ba93b872b011635462c5 Mon Sep 17 00:00:00 2001
From: fanxb <fanxb.tl@gmail.com>
Date: Wed, 10 May 2023 20:30:42 +0800
Subject: [PATCH 2/2] =?UTF-8?q?deploy:=E4=BF=AE=E6=94=B9=E9=83=A8=E7=BD=B2?=
 =?UTF-8?q?=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Dockerfile | 4 +++-
 build.sh   | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 8d9f636..a57c355 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,9 @@
 FROM node:lts-buster-slim
 WORKDIR /app
 COPY ./openRenamerBackend /app
-RUN chmod 777 -R /app && npm install -g pnpm typescript --registry https://registry.npmmirror.com
+# RUN chmod 777 -R /app && npm install -g pnpm typescript --registry https://registry.npmmirror.com
+# 注意此处未添加npm代理
+RUN chmod 777 -R /app && npm install -g pnpm typescript 
 ENV PORT 80
 CMD ["bash", "start.sh"]
 
diff --git a/build.sh b/build.sh
index 88ac01e..973cff6 100644
--- a/build.sh
+++ b/build.sh
@@ -2,7 +2,9 @@
 base=$(cd "$(dirname "$0")";pwd)
 cd $base
 rm -rf openRenamerBackend/dist
-docker run -it --rm --name buildOpenRenamer --user ${UID} -v $base/openRenamerFront:/opt/front node:lts-slim  bash -c "cd /opt/front &&   npm install -g pnpm --registry https://registry.npmmirror.com && pnpm install --registry https://registry.npmmirror.com && pnpm run build"
+# 注意此处未添加npm代理
+# docker run -it --rm --name buildOpenRenamer --user ${UID} -v $base/openRenamerFront:/opt/front node:lts-slim  bash -c "cd /opt/front &&   npm install -g pnpm --registry https://registry.npmmirror.com && pnpm install --registry https://registry.npmmirror.com && pnpm run build"
+docker run -it --rm --name buildOpenRenamer --user ${UID} -v $base/openRenamerFront:/opt/front node:lts-slim  bash -c "cd /opt/front &&   npm install -g pnpm  && pnpm install  && pnpm run build"
 
 rm -rf openRenamerBackend/static/*
 touch openRenamerBackend/static/.gitkeep