qiushang 10 months ago
parent
commit
9058caf169
4 changed files with 372 additions and 648 deletions
  1. 2 4
      package.json
  2. 5 3
      src/renderer/assets/css/home.scss
  3. 172 290
      src/renderer/components/home.vue
  4. 193 351
      yarn.lock

+ 2 - 4
package.json

@@ -1,5 +1,5 @@
 {
-  "name": "XYRename",
+  "name": "XYFile",
   "version": "2.1.0.0",
   "author": "苏州星优办公软件有限公司",
   "description": "An electron-vue project",
@@ -7,7 +7,7 @@
   "main": "./dist/electron/main.js",
   "softInfo": {
     "description": "这里是软件描述文档",
-    "downloadName": "XYRename",
+    "downloadName": "XYFile",
     "softMid": "4qgNl8jfYlLV",
     "softName": "星优文件名管理器",
     "copyright": "苏州星优办公软件有限公司",
@@ -39,8 +39,6 @@
     "element-ui": "^2.15.14",
     "fast-glob": "^3.3.2",
     "fs-extra": "^11.2.0",
-    "node-xlsx": "^0.24.0",
-    "officegen": "^0.6.5",
     "request": "^2.88.2",
     "vue": "^2.5.2",
     "vue-electron": "^1.0.6",

+ 5 - 3
src/renderer/assets/css/home.scss

@@ -250,7 +250,7 @@ div,p{
   justify-content: space-between;
   width: 100%;
   padding: 10px;
-  height: calc(100% - 101px);
+  height: calc(100% - 54px);
 }
 
 .img-footer-area{
@@ -277,21 +277,23 @@ div,p{
 
 .table-scroll {
   overflow: hidden;
-  height: 100%;
+  height: calc(100% - 188px);
 }
 
 .img-table {
   min-width: 400px;
+  min-height: 100%;
 }
 
 .content-left {
   width: calc(100% - 310px);
   background: #fff;
+  padding: 5px 10px;
 }
 
 .content-right {
   width: 300px;
-  padding: 5px 15px;
+  padding: 5px 10px;
   background-color: #fff;
   overflow: auto;
 }

+ 172 - 290
src/renderer/components/home.vue

@@ -7,74 +7,61 @@
 			<el-main ref="el-main" style="background-color: #fafafa; position: relative;">
 
 				<div class="content-top">
-					<el-button-group>
-						<el-button type="primary" size="mini" icon="el-icon-document" v-if="['1','3','5'].indexOf(menuIndex) > -1" @click="pickFile()">添加文件</el-button>
-						<el-button type="primary" size="mini" icon="el-icon-document" v-if="['1','3','5'].indexOf(menuIndex) > -1" @click="pickDir()">打开文件夹</el-button>
-						<el-button type="primary" size="mini" icon="el-icon-folder" v-if="['2','4','6'].indexOf(menuIndex) > -1" @click="addDir()">添加文件夹</el-button>
-						<el-button type="primary" size="mini" icon="el-icon-delete" @click="clearList()">清空列表</el-button>
-						<el-popover v-if="['1','3','5'].indexOf(menuIndex) > -1" popper-class="popper-open" placement="bottom" trigger="hover" content="添加目录会导入目录以及子目录下所有文件">
-							<i slot="reference" class="el-icon-question" style="font-size: 16px;margin: 6px 15px;"></i>
-						</el-popover>
-					</el-button-group>
+					<el-row>
+						<el-button type="primary" size="small" @click="pickDir()">添加文件路径</el-button>
+						<el-input readonly ref="search-input" size="small" placeholder="搜索目录路径" v-model="searchDir" style="width:400px;" prefix-icon="el-icon-folder"></el-input>
+					</el-row>
 					
 					<el-row type="flex" style="align-items: center;">
-						<div>
-							<span class="set-title">存放目录:</span>
-							<el-input :title="downloadDir" ref="upload-input" size="mini" @focus="pickPath" placeholder="请选择输出目录" v-model="downloadDir" readonly style="width:200px;" prefix-icon="el-icon-folder"></el-input>
-							<el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="打开保存目录">
-								<i class="el-icon-folder-opened" slot="reference" style="padding-left: 5px; cursor: pointer; font-size: 22px; vertical-align: middle;" @click="openFolder()"></i>
-							</el-popover>
-						</div>
-						<el-button type="danger" style="margin-left: 20px;" @click="exportFile()" :loading="exportLoading">开始处理</el-button>
+						<el-button type="info" size="small" style="margin-left: 20px;">重置</el-button>
 					</el-row>
 				</div>
 				
 				<div class="soft-content">
-					<div class="content-left">
-						<div class="handle-item">
-							<label class="handle-label">搜索目录:</label>
-							<el-input readonly ref="search-input" size="mini" placeholder="请选择搜索目录" v-model="searchDir" style="width:300px;" prefix-icon="el-icon-folder"></el-input>
-							<el-button type="primary" size="mini" @click="pickDir()">选择目录</el-button>
-						</div>
-						<div class="handle-item">
-							<label class="handle-label">操作方式:</label>
-							<el-radio-group v-model="handleData.type" size="mini">
-								<el-radio label="1" border>复制</el-radio>
-								<el-radio label="2" border>剪切</el-radio>
-								<el-radio label="3" border>删除</el-radio>
-							</el-radio-group>
+					<!-- 设置区域 -->
+					<div class="content-right">
+						<div class="handle-item" style="margin-bottom: 5px;">
+							<p><b>文件名检索清单:</b><span style="color: #F56C6C; font-size: 12px;">(一行填写一个)</span></p>
 						</div>
+						<el-input class="find-textarea" type="textarea" placeholder="查找文件名清单,多个请换行显示:
+						名称1
+						名称2
+						名称3" v-model="handleData.findText"></el-input>
+						<!-- 特殊字符匹配问题!!!! -->
 						
-						<div class="handle-item">
-							<label class="handle-label">查找规则:</label>
-							<el-radio-group v-model="handleData.rule" size="mini">
-								<el-radio label="1" border>相同文件名</el-radio>
-								<el-radio label="2" border>包含文件名</el-radio>
-								<el-radio label="3" border>文件名且格式相同</el-radio>
+						<div style="position: relative; margin: 10px 0;">
+							<el-button type="danger" size="small" style="position: absolute; right: 0; top: 0;" :loading="searchLoading" @click="search()">搜索</el-button>
+							<div style="padding: 10px; font-weight: 600;">检索方式:</div>
+							<el-radio-group class="line-radio" v-model="handleData.rule" size="small">
+								<el-radio label="1">精确(文件名相同)</el-radio>
+								<el-radio label="2">模糊(包含文件名)</el-radio>
+								<el-radio label="3">精确到格式(文件名和格式头相同)</el-radio>
 							</el-radio-group>
 						</div>
-						
+					</div>
+					
+					<div class="content-left" v-loading="searchLoading">
+						<div class="handle-item" style="margin-bottom: 5px;">
+							<p>
+								<b>文件名检索结果:</b>
+								<span style="color: #F56C6C; font-size: 12px;" >共有 {{fileList.length}} 个文件</span>
+								<span style="color: #F56C6C; font-size: 12px;" >,耗时 {{times / 1000}} 秒</span>
+							</p>
+						</div>
 						<div class="table-scroll">
-							<!-- 1、文件重命名 -->
-							<vxe-table ref="xTable"
-								v-show="['1','5'].indexOf(menuIndex) > -1"
+							<vxe-table ref="xTable" 
 								show-overflow class="img-table" max-height="100%" empty-text="没有更多数据了!" :loading="tabLoading"
 								:loading-config="{icon: 'vxe-icon-indicator roll', text: '文件加载中...'}" :row-config="{isHover: true}"
 								:edit-config="{trigger: 'click', mode: 'cell'}" :data="fileList" :scroll-y="{enabled: true}">
-								<vxe-column field="name" :title="'原文件名'+'(' + fileList.length + ')'"></vxe-column>
-								<vxe-column field="newName" title="新文件名" :edit-render="{}" v-if="menuIndex == '1'">
-									<template #edit="{ row, rowIndex }">
-										<div style="display: flex; justify-content: space-between;">
-											<vxe-input v-model="row.modifyName" type="text" placeholder="请输入新文件名"></vxe-input>
-											<el-popover popper-class="popper-open" placement="bottom" trigger="manual" v-model="visible3" content='文件名不能包含下列任何字符: \ / : * ? " < > |'>
-												<i slot="reference"></i>
-											</el-popover>
-											<div style="word-break: keep-all; line-height: 33px;">{{row.newName.lastIndexOf('.') > -1 ? row.newName.substr(row.newName.lastIndexOf('.')) : ''}}</div>
-										</div>
+								<vxe-column type="seq" width="60" title="编号"></vxe-column>
+								<vxe-column field="match" title="匹配词" width="150"></vxe-column>
+								<vxe-column field="path" title="文件位置"></vxe-column>
+								<vxe-column field="status" title="操作" width="80">
+									<template #default="{ row }">
+										<el-link icon="el-icon-s-release" type="warning">忽略</el-link>
 									</template>
 								</vxe-column>
-								<vxe-column field="path" title="文件位置" width="200"></vxe-column>
-								<vxe-column field="status" title="状态" width="120">
+								<vxe-column field="status" title="状态" width="100">
 									<template #default="{ row }">
 										<template v-if="row.status == '1'">
 											<i class="el-icon-info" style="font-size: 16px; color: #999;"></i>
@@ -98,23 +85,33 @@
 										</template>
 									</template>
 								</vxe-column>
-								<vxe-column title="操作" width="88">
-									<template #default="{ row, rowIndex }">
-										<i class="el-icon-delete cur-pointer" style="font-size: 20px;" @click="delFile(rowIndex, 'file')"></i>
-									</template>
-								</vxe-column>
 							</vxe-table>
+						</div>
+						
+						<div style="position: relative; margin-top: 20px;">
+							<div class="handle-item">
+								<label class="handle-label">存储位置:</label>
+								<el-input :title="downloadDir" ref="upload-input" size="small" @focus="pickPath" placeholder="请选择输出目录" v-model="downloadDir" readonly style="width:300px;" prefix-icon="el-icon-folder"></el-input>
+								<el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="打开保存目录">
+									<i class="el-icon-folder-opened" slot="reference" style="padding-left: 5px; cursor: pointer; font-size: 22px; vertical-align: middle;" @click="openFolder()"></i>
+								</el-popover>
+							</div>
+							<div class="handle-item">
+								<label class="handle-label">操作方式:</label>
+								<el-radio-group v-model="handleData.type" size="small">
+									<el-radio label="1" border>复制</el-radio>
+									<el-radio label="2" border>剪切</el-radio>
+									<el-radio label="3" border>删除</el-radio>
+									<el-radio label="4" border>覆盖</el-radio>
+								</el-radio-group>
+							</div>
 							
+							<el-button type="danger" style="position: absolute; bottom: 20px; right: 10px;" @click="exportFile()" :loading="exportLoading">开始处理</el-button>
 						</div>
+						
 					</div>
 					
-					<!-- 设置区域 -->
-					<div class="content-right">
-						<el-input type="textarea" :rows="20" placeholder="查找文件名清单,多个请换行显示:
-						名称1
-						名称2
-						名称3" v-model="handleData.findText"></el-input>
-					</div>
+					
 				</div>
 				
 			</el-main>
@@ -136,10 +133,7 @@ import electronApi from '@/utils/electronApi';
 import softUpdate from './update.vue';
 import softHeader from './header.vue';
 import pjson from '/package.json'
-import xlsx from 'node-xlsx';
 const fg = require('fast-glob');
-const child = require("child_process");
-const officegen = require('officegen');
 
 let separator = '';
 if (os.platform == 'linux') {
@@ -167,7 +161,9 @@ export default {
 				findText: '',
 			},
 			exportLoading: false,
+			searchLoading: false,
 			tabLoading: false,
+			times: 0,
 			
 	        dowloadModel: false,
 			finishModel: false,
@@ -195,7 +191,7 @@ export default {
 		});
 	},
 	methods: {
-		// 选择导出目录 1、提取和文件生成
+		// 选择导出目录
 		pickPath() {
 			this.$refs['upload-input'].blur();
 			electronApi.call('pickDir', []).then((path) => {
@@ -204,6 +200,18 @@ export default {
 				}
 			});
 		},
+		// 选择搜索目录
+		async pickDir(){
+			const spinLoad = this.$loading();
+			await electronApi.call('pickDir', []).then((path) =>{
+				if(path){
+					this.searchDir = path;
+				}
+				spinLoad.close();
+			}).catch(err => {
+				spinLoad.close();
+			});
+		},
 		// 打开自定义目录
 		openFolder(str){
 			let path = this.downloadDir;
@@ -221,217 +229,95 @@ export default {
 			const spinLoad = this.$loading();
 			await electronApi.call('pickFile', ['*',true]).then(async(files) =>{
 				if(files.length > 0){
-					this.pushFileToList(files);
+					
 				}
 				spinLoad.close();
 			}).catch(err => {
 				spinLoad.close();
 			});
 		},
-		// 选择搜索目录
-		async pickDir(){
-			const spinLoad = this.$loading();
-			await electronApi.call('pickDir', []).then((path) =>{
-				if(path){
-					this.searchDir = path;
-				}
-				spinLoad.close();
-			}).catch(err => {
-				spinLoad.close();
-			});
+		
+		// 软件更新
+		updateSoft(){
+			this.$refs.updateRef.updateSoft();
 		},
-		// 处理文件夹中的所有文件
-		dealDir(currentDirPath){
-			let files = fs.readdirSync(currentDirPath);
-			for (let i = 0; i < files.length; i++) {
-				let name = files[i];
-				var filePath = path.join(currentDirPath, name);
-				var stat = fs.statSync(filePath);
-			
-				if (stat.isFile()) {
-					this.pushFileToList([filePath]);
-				} else if (stat.isDirectory()) {
-					this.dealDir(filePath)
-				}
-			}
+		// 开通会员
+		openVip(){
+			this.$refs.headerRef.openVip();
 		},
-		// 添加文件夹
-		async addDir(dirArrs){
-			this.tabLoading = true;
-			if(dirArrs){ // 拖拽添加文件夹
-				this.dropDir(dirArrs);
-				setTimeout(()=>{
-					this.tabLoading = false;
-				}, 500)
-			}else{
-				await electronApi.call('addDir', []).then((dirs) =>{
-					if(dirs){
-						this.dropDir(dirs);
-					}
-					setTimeout(()=>{
-						this.tabLoading = false;
-					}, 500)
-				});
+		// 搜索
+		search(){
+			if(!this.searchDir){
+				this.$message({message: '请选择搜索目录' , type: 'warning'});
+				return false;
 			}
-		},
-		// 添加文件
-		pushFileToList(files) {
-			this.tabLoading = true;
-			for (let i = 0; i < files.length; i++) {
-				let path = files[i];
-				let filename = path.substr(path.lastIndexOf(separator)+1);
-				let lastIndex = path.lastIndexOf(filename);
-				let suffix = filename.lastIndexOf('.') > -1 ? filename.substr(filename.lastIndexOf('.')) : '';
-				let modifyName = filename.lastIndexOf('.') > -1 ? filename.substr(0,filename.lastIndexOf('.')) : filename;
-				
-				let fileInfo = {
-					name: filename,
-					aloneName: modifyName,
-					modifyName: modifyName,
-					newName: filename,
-					path: path.slice(0, lastIndex),
-					status: "1",
-					suffix: suffix,
-					btime: '',
-					mtime: ''
-				};
-				
-				if(this.fileList.length == 0){
-					this.fileList.push(fileInfo);
-					fs.stat(path, (err, stats) => {
-						let timeInfo = {
-							name: filename,
-							path: path.slice(0, lastIndex),
-							btime: stats.birthtime,
-							mtime: stats.mtime
-						}
-						this.fileTimeList[0] = timeInfo;
-					})
-				}
-				
-				let flag = true;
-				this.fileList.map((item, index) => {
-					if(item.name == fileInfo.name && item.path == fileInfo.path){
-						flag = false;
-					}
-				})
-				if(flag){
-					let length = this.fileList.length;
-					if(this.filexlsxPath && this.filexlsxData.length > length){
-						fileInfo.newName = this.filexlsxData[length - 1][0] + fileInfo.suffix;
+			if(!this.handleData.findText){
+				this.$message({message: '请输入要查找的文件搜索清单' , type: 'warning'});
+				return false;
+			}
+			(async () => {
+				let startTime = new Date().getTime();
+				this.searchLoading = true;
+				setTimeout(() => {
+					this.searchLoading = false;
+				}, 2000)
+				let findText = this.handleData.findText.split('\n');
+				let searchDir = this.searchDir.replace(/\\/g, '/');
+				let paramArr = [];
+				for(let i=0; i< findText.length; i++){
+					if(findText[i].trim()){
+						paramArr.push(findText[i].trim());
 					}
-					this.fileList.push(fileInfo);
-					let key = this.fileList.length - 1;
-					fs.stat(path, (err, stats) => {
-						let timeInfo = {
-							name: filename,
-							path: path.slice(0, lastIndex),
-							btime: stats.birthtime,
-							mtime: stats.mtime
-						}
-						this.fileTimeList[key] = timeInfo;
-					})
 				}
-			}
-			setTimeout(()=>{
-				this.tabLoading = false;
-				this.setChange();
-			}, 500)
-		},
-		// 重命名导入自定义名称模板
-		importXlsx(){
-			this.$refs['upload-input'].blur();
-			electronApi.call('pickFile', ['xls,xlsx', false]).then((path) =>{
-				if((this.menuIndex == '1' && this.fileList.length == 0) || (this.menuIndex == '2' && this.dirList.length == 0)){
-					this.$notify({
-						title: '提示',
-						message: '请先选择需要重命名的文件',
-						type: 'warning'
-					});
-				}else{
-					if(path.length > 0){
-						this.$notify({
-							title: '提示',
-							message: '导入成功',
-							type: 'success'
-						});
-						let workSheetsFromBuffer = xlsx.parse(fs.readFileSync(path[0]));
-						if(workSheetsFromBuffer && workSheetsFromBuffer.length > 0){
-							if(this.menuIndex == '1'){
-								this.filexlsxPath = path[0];
-								this.filexlsxData = workSheetsFromBuffer[0].data;
-							}else if(this.menuIndex == '2'){
-								this.dirxlsxPath = path[0];
-								this.dirxlsxData = workSheetsFromBuffer[0].data;
-							}
-							this.handleData.fileMethod = '6';
-							let errMsg = "";
-							workSheetsFromBuffer[0].data.map((item, index) => {
-								if(item[0] == undefined){
-									errMsg += "第" + (index+1) + "行格式有误</br>";
-									item[0] = '';
-								}
-								if(this.menuIndex == '1' && index < this.fileList.length){
-									this.fileList[index].newName = item[0].toString().replace(new RegExp(/[\f\n\r\t\v]+/, 'g'), '') + this.fileList[index].suffix;
-									this.fileList[index].modifyName = item[0].toString().replace(new RegExp(/[\f\n\r\t\v]+/, 'g'), '');
-								}else if(this.menuIndex == '2' && index < this.dirList.length){
-									this.dirList[index].newName = item[0].toString().replace(new RegExp(/[\f\n\r\t\v]+/, 'g'), '');
-								}
-							});
-							if(errMsg){
-								this.$notify({
-									title: '请检查文件以下问题',
-									message: errMsg,
-									type: 'warning'
-								});
-							}
+				let params = paramArr.join(',');
+				let ruleStr = '';
+				switch(this.handleData.rule){
+					case '1': //相同文件名
+						if(paramArr.length > 1){
+							ruleStr = searchDir + '/**/{'+params+'}.*';
 						}else{
-							this.$notify({
-								title: '提示',
-								message: '格式有误,请重新导入',
-								type: 'warning'
-							});
+							ruleStr = searchDir + '/**/'+params+'.*';
 						}
-					}
+						break;
+					case '2': //包含文件名
+						if(paramArr.length > 1){
+							ruleStr = searchDir + '/**/*{'+params+'}*.*';
+						}else{
+							ruleStr = searchDir + '/**/*'+params+'*.*';
+						}
+						break;
+					case '3': //文件名格式相同
+						if(paramArr.length > 1){
+							ruleStr = searchDir + '/**/{'+params+'}';
+						}else{
+							ruleStr = searchDir + '/**/'+params;
+						}
+						break;
 				}
-			});
-		},
-		// 批量创建导入模板
-		async importExample(){
-			this.$refs['upload-example'].blur();
-			let str = '';
-			switch(this.foundData.foundType){
-				case 'docx': // word
-					str = 'doc,docx';
-					break;
-				case 'pptx': // ppt
-					str = 'ppt,pptx';
-					break;
-				case 'xlsx': // excel
-					str = 'xls,xlsx';
-					break;
-				case 'pdf': // pdf
-					str = 'pdf';
-					break;
-				case 'txt': // txt
-					str = 'txt';
-					break;
-			}
-			
-			await electronApi.call('pickFile', [str, false]).then(async(files) =>{
-				if(files.length > 0){
-					this.foundData.sourceFileName = files[0].substr(files[0].lastIndexOf(separator)+1);
-					this.foundData.sourceFilePath = files[0];
+				console.log('----验证规则----', ruleStr);
+				try{
+					const files = await fg([ruleStr], { dot: true });
+					let regExp = new RegExp(paramArr.join('|'));
+					this.fileList = [];
+					files.map(item => {
+						let filename = item.substr(item.lastIndexOf('/')+1);
+						let res = regExp.exec(filename);
+						this.fileList.push({
+							match: res,
+							path: item,
+							status: '1'
+						});
+					});
+					this.searchLoading = false;
+					let endTime = new Date().getTime();
+					this.times = endTime - startTime;
+					// console.log('----查找结果----', files);
+				}catch(e){
+					this.showError(e);
 				}
-			});
-		},
-		// 软件更新
-		updateSoft(){
-			this.$refs.updateRef.updateSoft();
-		},
-		// 开通会员
-		openVip(){
-			this.$refs.headerRef.openVip();
+				
+			})();
+			
 		},
 		// 导出
 	    exportFile(flag) {
@@ -445,32 +331,6 @@ export default {
 					this.$refs.headerRef.memberModel = false;
 				}
 				
-				(async () => {
-					let findText = this.handleData.findText.split('\n');
-					let searchDir = this.searchDir.replace(/\\/g, '/');
-					let paramArr = [];
-					for(let i=0; i< findText.length; i++){
-						if(findText[i].trim()){
-							paramArr.push(findText[i].trim());
-						}
-					}
-					let params = paramArr.join('|');
-					let ruleStr = '';
-					switch(this.handleData.rule){
-						case '1': //相同文件名
-							ruleStr = searchDir + '/**/('+params+').*';
-							break;
-						case '2': //包含文件名
-							ruleStr = searchDir + '/**/*('+params+')*.*';
-							break;
-						case '3': //文件名格式相同
-							ruleStr = searchDir + '/**/('+params+')';
-							break;
-					}
-					console.log(ruleStr);
-					const files = await fg([ruleStr], { dot: true });  
-				    console.log(files);  
-				})();
 				
 				this.exportLoading = true;
 				setTimeout(() => {
@@ -509,6 +369,16 @@ export default {
 			return regStr;
 		},
 		
+		// 错误提示
+		showError(e){
+			let str = e.toString().substr(0, 100);
+			this.loading = false;
+			this.$notify.error({
+				title: '提示',
+				message: str
+			});
+		},
+		
 	}
 	
 };
@@ -736,4 +606,16 @@ export default {
 		color: #777; 
 		text-align: center;
 	}
+	
+	.line-radio .el-radio{
+		line-height: 2;
+	}
+	
+	.find-textarea{
+		height: calc(100% - 187px);
+		
+		textarea{
+			height: 100%;
+		}
+	}
 </style>

File diff suppressed because it is too large
+ 193 - 351
yarn.lock


Some files were not shown because too many files changed in this diff