qiushang 4 月之前
父节点
当前提交
00898c860d
共有 5 个文件被更改,包括 118 次插入18 次删除
  1. 1 0
      package.json
  2. 二进制
      src/renderer/assets/image/file.png
  3. 二进制
      src/renderer/assets/image/folder.png
  4. 106 18
      src/renderer/components/home.vue
  5. 11 0
      yarn.lock

+ 1 - 0
package.json

@@ -39,6 +39,7 @@
     "element-ui": "^2.15.14",
     "fast-glob": "^3.3.2",
     "fs-extra": "10.1.0",
+    "node-xlsx": "^0.24.0",
     "request": "^2.88.2",
     "uuid": "9.0.1",
     "vue": "^2.5.2",

二进制
src/renderer/assets/image/file.png


二进制
src/renderer/assets/image/folder.png


+ 106 - 18
src/renderer/components/home.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
-		<el-container style="user-select: none; height: 100vh;">	
-			<el-header height="45px" style="background-color: #fafafa; padding: 0 10px;">
+		<el-container style="height: 100vh;">	
+			<el-header height="45px" style="user-select: none; background-color: #fafafa; padding: 0 10px;">
 				<soft-header ref="headerRef" @update-soft="updateSoft()" @export-file="exportFile"></soft-header>
 			</el-header>
 			<el-main ref="el-main" style="background-color: #fafafa; position: relative;">
@@ -21,14 +21,38 @@
 				<div class="soft-content">
 					<!-- 设置区域 -->
 					<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 class="handle-item">
+							<b>检索方式:</b>
+							<el-select size="mini" style="width: 160px;" v-model="findType" placeholder="请选择检索方式">
+								<el-option value="1" label="按文件名检索"></el-option>
+								<el-option value="2" label="按创建时间检索"></el-option>
+								<el-option value="3" label="按修改时间检索"></el-option>
+							</el-select>
 						</div>
-						<el-input class="find-textarea" type="textarea" placeholder="查找文件名清单,多个请换行显示:
-						名称1
-						名称2
-						名称3" v-model="handleData.findText"></el-input>
-						<!-- 特殊字符匹配问题!!!! -->
+						
+						<template v-if="findType == '1'">
+							<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>
+						</template>
+						<template v-else>
+							<div class="handle-item">
+								<b>开始时间:</b>
+								<el-date-picker type="datetime" v-model="handleData.startTime" placeholder="开始时间" style="width:160px;" size="mini"></el-date-picker>
+							</div>
+							<div class="handle-item">
+								<b>结束时间:</b>
+								<el-date-picker type="datetime" v-model="handleData.endTime" placeholder="结束时间" style="width:160px;" size="mini"></el-date-picker>
+							</div>
+							<div class="find-textarea" style="height: calc(100% - 258px);">
+								
+							</div>
+						</template>
 						
 						<div style="position: relative; margin: 10px 0;">
 							<el-button type="danger" size="mini" style="position: absolute; right: 0; top: 0;" :loading="searchLoading" @click="search()">搜索</el-button>
@@ -42,11 +66,13 @@
 					</div>
 					
 					<div class="content-left" v-loading="searchLoading">
-						<div class="handle-item" style="margin-bottom: 5px;">
+						<div class="handle-item" style="margin-bottom: 5px; display: flex; flex-wrap: nowrap; justify-content: space-between;">
 							<p>
 								<b>文件名检索结果:</b>
 								<span style="color: #F56C6C; font-size: 12px;" >共有 {{fileList.length}} 个文件,搜索耗时 {{times / 1000}} 秒</span>
 							</p>
+							
+							<el-button size="mini" :disabled="fileList.length == 0" title="检索结果导出到excel表格中" :loading="xlsxLoading" @click="exportXlsx()">导出检索结果</el-button>
 						</div>
 						<div class="table-scroll">
 							<vxe-table ref="xTable" :column-config="{resizable: true}" size="mini"
@@ -55,7 +81,13 @@
 								:edit-config="{trigger: 'click', mode: 'cell'}" :data="fileList" :scroll-y="{enabled: true}">
 								<vxe-column type="seq" width="60" title="编号" align="center"></vxe-column>
 								<vxe-column field="match" title="匹配词" width="150" min-width="120" align="center"></vxe-column>
-								<vxe-column field="path" title="文件位置/名称"></vxe-column>
+								<vxe-column field="path" title="文件位置/名称">
+									<template #default="{ row }">
+										<img v-if="row.isDirectory" src="../assets/image/folder.png" style="width: 20px; vertical-align: middle;"/>
+										<img v-else src="../assets/image/file.png" style="width: 20px; vertical-align: middle;"/>
+										<span>{{row.path}}</span>
+									</template>
+								</vxe-column>
 								<vxe-column field="status" title="操作" width="50" min-width="50" max-width="50" align="center">
 									<template #default="{ rowIndex }">
 										<el-link type="warning" @click="delFile(rowIndex)" style="font-size: 12px;">忽略</el-link>
@@ -154,6 +186,7 @@ import softHeader from './header.vue';
 import pjson from '/package.json';
 import fse from 'fs-extra';
 const fg = require('fast-glob');
+import xlsx from 'node-xlsx';
 import { v4 as uuidv4 } from 'uuid';
 
 let separator = '';
@@ -181,7 +214,10 @@ export default {
 				type: '1',
 				rule: '1',
 				findText: '',
+				startTime: '',
+				endTime: '',
 			},
+			findType: '1',
 			exportLoading: false,
 			searchLoading: false,
 			tabLoading: false,
@@ -194,11 +230,19 @@ export default {
 			loadingModal: false,
 			
 			execlimit: 5,
+			xlsxLoading: false,
 	    };
 	},
 	mounted() {
 		this.$refs.updateRef.updateSoft(true);
 		
+		let __dirname = os.userInfo().homedir;
+		if(fs.existsSync(__dirname + separator + "Desktop")){
+			this.handleData.newPath = __dirname + separator + "Desktop"
+		} else{
+			this.handleData.newPath = __dirname + separator + "Downloads"
+		}
+		
 	    // 打开浏览器
 	    const { shell } = require('electron');
 	    const links = document.querySelectorAll('a[href]');
@@ -287,10 +331,15 @@ export default {
 				this.$message({message: '请先选择搜索目录' , type: 'error'});
 				return false;
 			}
-			if(!this.handleData.findText){
+			if(!this.handleData.findText && this.findType == '1'){
 				this.$message({message: '请输入要查找的文件搜索清单' , type: 'error'});
 				return false;
 			}
+			if(this.findType != '1' && !this.handleData.startTime && !this.handleData.endTime){ // 根据时间搜索
+				this.$message({message: '请选择搜索的时间范围' , type: 'error'});
+				return false;
+			}
+			
 			(async () => {
 				let startTime = new Date().getTime();
 				this.searchLoading = true;
@@ -300,7 +349,7 @@ export default {
 				let findText = this.handleData.findText.split('\n');
 				let searchDir = this.searchDir.replace(/\\/g, '/');
 				let paramArr = []; // 匹配规则1
-				let paramArr2 = []; // 匹配规则2 - 带后缀名的文件,带.
+				let paramArr2 = []; // 匹配规则2 - 文件名称中带.
 				for(let i=0; i< findText.length; i++){
 					if(findText[i].trim()){
 						if(findText[i].indexOf('.') > -1){
@@ -350,12 +399,13 @@ export default {
 				}
 				console.log('----验证规则----', ruleStr);
 				try{
-					const files = await fg(ruleStr, { dot: true });
+					const files = await fg(ruleStr, { dot: true, onlyFiles:true, objectMode: true,markDirectories: true});
 					let regExp = new RegExp(paramArr.join('|'));
 					let regExp2 = new RegExp(paramArr2.join('|'));
 					this.fileList = [];
 					files.map(item => {
-						let filename = item.substr(item.lastIndexOf('/')+1);
+						let isDirectory = item.dirent.isDirectory();
+						let filename = item.name;//item.substr(item.lastIndexOf('/')+1);
 						let title = filename.substr(0, filename.lastIndexOf('.'));
 						let suffix = filename.substr(filename.lastIndexOf('.'));
 						if(filename.indexOf('.') < 0){
@@ -363,15 +413,16 @@ export default {
 							suffix = '';
 						}
 						let res = regExp.exec(filename);
-						if(!res[0]){
+						if(!res){
 							res = regExp2.exec(filename);
 						}
 						this.fileList.push({
 							title: title,
+							isDirectory: isDirectory,
 							suffix: suffix, // 带.
 							name: filename,
 							match: res,
-							path: item,
+							path: item.path,
 							status: '1'
 						});
 					});
@@ -386,6 +437,43 @@ export default {
 			})();
 			
 		},
+		// 导出检索结果
+		exportXlsx(){
+			this.xlsxLoading = true;
+			let filename = '文件检索结果' + new Date().getTime() +'.xlsx';
+			let sheet1 = [['编号','匹配词','文件位置/名称','类型']];
+			let sheet2 = [];
+			
+			let findText = this.handleData.findText.split('\n');
+			for(let i = 0; i < this.fileList.length; i++){
+				let item = this.fileList[i];
+				let info = [i+1, item.match, item.path, item.isDirectory ? '文件夹' : '文件'];
+				sheet1.push(info);
+				
+				if(findText.indexOf(item.match[0]) > -1){ // 匹配到了
+					let removeIndex = findText.indexOf(item.match[0]);
+					findText.splice(removeIndex, 1);
+				}
+			}
+			findText.map(fitem => {
+				sheet2.push([fitem]);
+			})
+			
+			let buffer = xlsx.build([
+				{
+					name: '检索成功',
+					data: sheet1
+				},
+				{
+					name: '未检索',
+					data: sheet2
+				}
+			]);
+			fs.writeFileSync(this.handleData.newPath + separator + filename, buffer, {'flag':'w'});
+			this.xlsxLoading = false;
+			this.$message({message: '文件导出成功!', type: 'success'});
+			electronApi.call('showItemInfolder',[this.handleData.newPath + separator + filename])
+		},
 		// 导出
 	    exportFile(flag) {
 			let authority = this.$refs.headerRef.authority;
@@ -793,7 +881,7 @@ export default {
 	}
 	
 	.find-textarea{
-		height: calc(100% - 187px);
+		height: calc(100% - 216px);
 		
 		textarea{
 			height: 100%;

+ 11 - 0
yarn.lock

@@ -6582,6 +6582,13 @@ node-sass@^4.14.1:
     stdout-stream "^1.4.0"
     "true-case-path" "^1.0.2"
 
+node-xlsx@^0.24.0:
+  version "0.24.0"
+  resolved "https://registry.npmmirror.com/node-xlsx/-/node-xlsx-0.24.0.tgz#a6a365acb18ad37c66c2b254b6ebe0c22dc9dc6f"
+  integrity sha512-1olwK48XK9nXZsyH/FCltvGrQYvXXZuxVitxXXv2GIuRm51aBi1+5KwR4rWM4KeO61sFU+00913WLZTD+AcXEg==
+  dependencies:
+    xlsx "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
+
 "nopt@2 || 3":
   version "3.0.6"
   resolved "https://registry.npmmirror.com/nopt/-/nopt-3.0.6.tgz"
@@ -9894,6 +9901,10 @@ xe-utils@^3.5.19, xe-utils@^3.5.26:
   resolved "https://registry.npmmirror.com/xe-utils/-/xe-utils-3.5.26.tgz"
   integrity sha512-u9R7RqWDumamToEelrCv2nVA2PBJSPPUubvmiMcuHeFxwbYeBsouoi/opejmr7AdPlSj92FifF7IKFzFrczU7w==
 
+"xlsx@https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz":
+  version "0.20.2"
+  resolved "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz#0f64eeed3f1a46e64724620c3553f2dbd3cd2d7d"
+
 xml-char-classes@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz"