فهرست منبع

feat(ChapterTools): 增强批量文本处理功能,支持正则表达式替换

- 在章节工具中新增正则表达式处理选项,允许用户启用正则表达式进行文本替换
- 添加正则表达式输入框和替换内容输入框,提供示例以帮助用户理解
- 扩展batchProcessForm数据结构,包含正则表达式相关字段
- 更新文本处理逻辑,支持正则表达式匹配和替换功能
moyanxiaoyi 1 هفته پیش
والد
کامیت
899c4c8993
3فایلهای تغییر یافته به همراه119 افزوده شده و 14 حذف شده
  1. 80 11
      package-lock.json
  2. 1 0
      package.json
  3. 38 3
      src/components/ChapterTools.vue

+ 80 - 11
package-lock.json

@@ -14,6 +14,7 @@
         "epubjs": "^0.3.93",
         "file-saver": "^2.0.5",
         "jszip": "^3.10.1",
+        "pnpm": "^10.14.0",
         "quill": "^2.0.3",
         "stream-browserify": "^3.0.0",
         "util": "^0.12.5",
@@ -2105,7 +2106,14 @@
       }
     },
     "node_modules/@types/body-parser": {
-      "dev": true
+      "version": "1.19.6",
+      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+      "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+      "dev": true,
+      "dependencies": {
+        "@types/connect": "*",
+        "@types/node": "*"
+      }
     },
     "node_modules/@types/bonjour": {
       "version": "3.5.13",
@@ -2117,6 +2125,15 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@types/connect": {
+      "version": "3.4.38",
+      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+      "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/connect-history-api-fallback": {
       "version": "1.5.4",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz",
@@ -2129,7 +2146,14 @@
       }
     },
     "node_modules/@types/eslint": {
-      "dev": true
+      "version": "9.6.1",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+      "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
     },
     "node_modules/@types/eslint-scope": {
       "version": "3.7.7",
@@ -2143,6 +2167,9 @@
       }
     },
     "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
       "dev": true
     },
     "node_modules/@types/express": {
@@ -2192,6 +2219,9 @@
       "license": "MIT"
     },
     "node_modules/@types/http-errors": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+      "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
       "dev": true
     },
     "node_modules/@types/http-proxy": {
@@ -2236,6 +2266,12 @@
         "@types/lodash": "*"
       }
     },
+    "node_modules/@types/mime": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+      "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+      "dev": true
+    },
     "node_modules/@types/minimist": {
       "version": "1.2.5",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/minimist/-/minimist-1.2.5.tgz",
@@ -2244,7 +2280,13 @@
       "license": "MIT"
     },
     "node_modules/@types/node": {
-      "dev": true
+      "version": "24.2.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.0.tgz",
+      "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==",
+      "dev": true,
+      "dependencies": {
+        "undici-types": "~7.10.0"
+      }
     },
     "node_modules/@types/node-forge": {
       "version": "1.3.13",
@@ -2271,9 +2313,15 @@
       "license": "MIT"
     },
     "node_modules/@types/qs": {
+      "version": "6.14.0",
+      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+      "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
       "dev": true
     },
     "node_modules/@types/range-parser": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+      "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
       "dev": true
     },
     "node_modules/@types/retry": {
@@ -2284,7 +2332,14 @@
       "license": "MIT"
     },
     "node_modules/@types/send": {
-      "dev": true
+      "version": "0.17.5",
+      "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
+      "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
+      "dev": true,
+      "dependencies": {
+        "@types/mime": "^1",
+        "@types/node": "*"
+      }
     },
     "node_modules/@types/serve-index": {
       "version": "1.9.4",
@@ -9387,6 +9442,21 @@
         "node": ">=8"
       }
     },
+    "node_modules/pnpm": {
+      "version": "10.14.0",
+      "resolved": "https://registry.npmjs.org/pnpm/-/pnpm-10.14.0.tgz",
+      "integrity": "sha512-rSenlkG0nD5IGhaoBbqnGBegS74Go40X5g4urug/ahRsamiBJfV5LkjdW6MOfaUqXNpMOZK5zPMz+c4iOvhHSA==",
+      "bin": {
+        "pnpm": "bin/pnpm.cjs",
+        "pnpx": "bin/pnpx.cjs"
+      },
+      "engines": {
+        "node": ">=18.12"
+      },
+      "funding": {
+        "url": "https://opencollective.com/pnpm"
+      }
+    },
     "node_modules/portfinder": {
       "version": "1.0.37",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/portfinder/-/portfinder-1.0.37.tgz",
@@ -11832,6 +11902,12 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/undici-types": {
+      "version": "7.10.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
+      "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
+      "dev": true
+    },
     "node_modules/unicode-canonical-property-names-ecmascript": {
       "version": "2.0.1",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
@@ -12584,13 +12660,6 @@
       "dev": true,
       "license": "MIT"
     },
-    "node_modules/webpack/node_modules/@types/estree": {
-      "version": "1.0.8",
-      "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/estree/-/estree-1.0.8.tgz",
-      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/webpack/node_modules/ajv": {
       "version": "8.17.1",
       "resolved": "https://mirrors.huaweicloud.com/repository/npm/ajv/-/ajv-8.17.1.tgz",

+ 1 - 0
package.json

@@ -14,6 +14,7 @@
     "epubjs": "^0.3.93",
     "file-saver": "^2.0.5",
     "jszip": "^3.10.1",
+    "pnpm": "^10.14.0",
     "quill": "^2.0.3",
     "stream-browserify": "^3.0.0",
     "util": "^0.12.5",

+ 38 - 3
src/components/ChapterTools.vue

@@ -210,6 +210,21 @@
                      <el-checkbox v-model="batchProcessForm.replaceText">替换指定文本</el-checkbox>
                    </el-form-item>
                    
+                   <el-form-item label="正则处理">
+                     <el-checkbox v-model="batchProcessForm.useRegex">启用正则表达式处理</el-checkbox>
+                   </el-form-item>
+                   <el-form-item v-if="batchProcessForm.useRegex" label="正则表达式">
+                     <el-input v-model="batchProcessForm.regexPattern" placeholder="请输入正则表达式,如:分卷阅读\\d+" />
+                   </el-form-item>
+                   <el-form-item v-if="batchProcessForm.useRegex" label="替换内容">
+                     <el-input v-model="batchProcessForm.regexReplace" placeholder="留空则为去除,填写内容则为替换" />
+                     <div class="regex-examples" style="margin-top: 5px; color: #888; font-size: 12px;">
+                       例如:<br />
+                       <span class="example-item">分卷阅读\\d+</span> 匹配“分卷阅读1、分卷阅读2”等<br />
+                       <span class="example-item">(第[0-9]+章)</span> 匹配“第12章”等
+                     </div>
+                   </el-form-item>
+                   
                    <el-form-item v-if="batchProcessForm.removeText" label="去除的文本">
                      <el-input
                        v-model="batchProcessForm.removeTextList"
@@ -301,6 +316,7 @@ const textProcessResult = ref('');
 
 const textProcessActiveTab = ref('single');
 
+// 1. 扩展 batchProcessForm 数据结构
 const batchProcessForm = ref({
   selectedChapters: [],
   removeSpaces: false,
@@ -308,7 +324,10 @@ const batchProcessForm = ref({
   removeHtml: false,
   removeTextList: '',
   replaceText: false,
-  replaceRules: ''
+  replaceRules: '',
+  useRegex: false, // 新增:是否启用正则
+  regexPattern: '', // 新增:正则表达式
+  regexReplace: ''  // 新增:正则替换内容
 });
 
 const batchProcessResult = ref([]);
@@ -379,6 +398,16 @@ function processContent(content, options) {
   if (options.removeSpaces) {
     processedContent = processedContent.replace(/\s+/g, '');
   }
+
+  if (options.useRegex && options.regexPattern) {
+    try {
+      const reg = new RegExp(options.regexPattern, 'g');
+      processedContent = processedContent.replace(reg, options.regexReplace ?? '');
+    } catch (e) {
+      // 正则错误直接抛出
+      throw new Error('正则表达式错误: ' + e.message);
+    }
+  }
   
   return processedContent;
 }
@@ -641,7 +670,10 @@ function processBatchChapters() {
         removeHtml: batchProcessForm.value.removeHtml,
         removeTextList: batchProcessForm.value.removeTextList,
         replaceText: batchProcessForm.value.replaceText,
-        replaceRules: batchProcessForm.value.replaceRules
+        replaceRules: batchProcessForm.value.replaceRules,
+        useRegex: batchProcessForm.value.useRegex,
+        regexPattern: batchProcessForm.value.regexPattern,
+        regexReplace: batchProcessForm.value.regexReplace
       });
       
       // 更新章节内容
@@ -694,7 +726,10 @@ function clearBatchProcess() {
     removeHtml: false,
     removeTextList: '',
     replaceText: false,
-    replaceRules: ''
+    replaceRules: '',
+    useRegex: false,
+    regexPattern: '',
+    regexReplace: ''
   };
   batchProcessResult.value = [];
 }