Browse Source

🌈 style(代码格式化): 配置代码格式化,对所有文件执行格式化操作

对HTML、CSS、Vue、JavaScript等格式的文件进行格式化
liyating 3 years ago
parent
commit
05040b9147
57 changed files with 8579 additions and 6476 deletions
  1. 11 0
      .prettierrc.js
  2. 64 0
      .vscode/settings.json
  3. 1 1
      babel.config.js
  4. 1814 459
      package-lock.json
  5. 12 9
      package.json
  6. 2 2
      public/index.html
  7. 45 39
      src/App.vue
  8. 71 20
      src/assets/styles/css/base.css
  9. 4 4
      src/assets/styles/css/element-cover.css
  10. 32 20
      src/assets/styles/css/mediaScreen.styl
  11. 28 23
      src/assets/styles/mixins.styl
  12. 21 25
      src/assets/styles/varibles.styl
  13. 93 86
      src/components/BreadCrumb.vue
  14. 121 112
      src/components/File/AddFileDialog.vue
  15. 125 118
      src/components/File/AddFolderDialog.vue
  16. 958 866
      src/components/File/FileTable.vue
  17. 119 101
      src/components/File/MoveFileDialog.vue
  18. 70 53
      src/components/Footer.vue
  19. 83 52
      src/components/Header.vue
  20. 240 229
      src/components/common/DragVerify.vue
  21. 379 321
      src/components/common/GlobalUploader.vue
  22. 224 201
      src/components/common/ImgPreview.vue
  23. 128 115
      src/components/common/VideoPreview.vue
  24. 16 11
      src/config/index.js
  25. 115 115
      src/element.js
  26. 19 18
      src/filters/index.js
  27. 201 176
      src/globalFunction.js
  28. 12 12
      src/main.js
  29. 30 28
      src/request/file.js
  30. 3 3
      src/request/onlyoffice.js
  31. 8 8
      src/request/user.js
  32. 2 2
      src/router/before.js
  33. 86 78
      src/router/router.js
  34. 46 42
      src/store/index.js
  35. 41 42
      src/store/module/fileList.js
  36. 24 25
      src/store/module/imgPreview.js
  37. 38 32
      src/store/module/sideMenu.js
  38. 40 41
      src/store/module/user.js
  39. 24 25
      src/store/module/videoPreview.js
  40. 10 10
      src/views/ErrorPage/404.vue
  41. 67 56
      src/views/Home/components/Banner.vue
  42. 53 49
      src/views/Home/components/Function.vue
  43. 14 14
      src/views/Home/index.vue
  44. 161 144
      src/views/Login.vue
  45. 103 103
      src/views/MyShare/index.vue
  46. 171 167
      src/views/OnlyOffice/index.vue
  47. 174 155
      src/views/Register.vue
  48. 290 277
      src/views/Share/index.vue
  49. 17 17
      src/views/file/File.vue
  50. 127 108
      src/views/file/components/AsideMenu/AsideMenu.vue
  51. 735 666
      src/views/file/components/FileList/components/FileGrid.vue
  52. 103 90
      src/views/file/components/FileList/components/FileTimeLine.vue
  53. 452 386
      src/views/file/components/FileList/components/OperationMenu.vue
  54. 74 64
      src/views/file/components/FileList/components/SelectColumn.vue
  55. 177 158
      src/views/file/components/FileList/components/ShareFileDialog.vue
  56. 475 469
      src/views/file/components/FileList/index.vue
  57. 26 29
      vue.config.js

+ 11 - 0
.prettierrc.js

@@ -0,0 +1,11 @@
+module.exports = {
+  printWidth: 80, //  每行最大字符数为 80, 如果超出则换行
+  tabWidth: 2, //  一个制表符等于的空格数
+  useTabs: true, //  使用 tab 缩进
+  singleQuote: true, //  使用单引号
+  semi: false, //  代码结尾不加分号
+  trailingComma: 'none', //  不自动添加逗号
+  bracketSpacing: true, //  控制对象字面量的空格输出
+  jsxBracketSameLine: false, //  将多行jsx的>放到下一行
+  endOfLine: 'auto'
+}

+ 64 - 0
.vscode/settings.json

@@ -0,0 +1,64 @@
+{
+	// 控制是否在打开文件时,基于文件内容自动检测 #editor.tabSize# 和 #editor.insertSpaces#。
+	"editor.detectIndentation": false,
+	// 一个制表符等于的空格数
+	"editor.tabSize": 2,
+	// 每次保存的时候是否自动格式化
+	"editor.formatOnSave": true,
+	// 在保存时运行的代码类型操作
+	"editor.codeActionsOnSave": {
+		// 文件保存时自动修复
+		"source.fixAll": true
+	},
+	// 差异编辑器将不会忽略前后空格中的更改
+	"diffEditor.ignoreTrimWhitespace": false,
+	"[vue]": {
+		"editor.defaultFormatter": "esbenp.prettier-vscode" // 使用 prettier 扩展中的配置
+	},
+	"[javascript]": {
+		"editor.defaultFormatter": "esbenp.prettier-vscode" // 使用 prettier 扩展中的配置
+	},
+	"[html]": {
+		"editor.defaultFormatter": "vscode.html-language-features"
+	},
+	"[json]": {
+		"editor.defaultFormatter": "vscode.json-language-features"
+	},
+	"[css]": {
+		"editor.defaultFormatter": "esbenp.prettier-vscode" // 使用 prettier 扩展中的配置
+	},
+	"[stylus]": {
+		"editor.defaultFormatter": "thisismanta.stylus-supremacy"
+	},
+	// 以下均为 stylus Supremacy 扩展配置
+	"stylusSupremacy.insertColons": true, // 是否插入冒号
+	"stylusSupremacy.insertSemicolons": true, // 是否插入分号
+	"stylusSupremacy.insertBraces": true, // 是否插入大括号
+	"stylusSupremacy.insertNewLineAroundImports": true, // import 之后是否换行
+	"stylusSupremacy.insertNewLineAroundBlocks": false, // 两个选择器中是否换行
+	// HTML 每行最大字符数为 80, 如果超出则换行
+	"html.format.wrapLineLength": 80,
+	// JavaScript 函数(名)和后面的括号不添加空格
+	"javascript.format.insertSpaceBeforeFunctionParenthesis": false,
+	// Vetur 扩展配置
+	"vetur.format.defaultFormatterOptions": {
+		"prettier": {
+			"semi": false, //  代码结尾不加分号
+			"singleQuote": true, //  使用单引号
+			"trailingComma": "none" //  不自动添加逗号
+		}
+	},
+	/*
+    以下均为 prettier 扩展配置
+  */
+	// 指定每行代码最佳长度为 80 如果超出则换行
+	"prettier.printWidth": 80,
+	// 代码结尾不加分号
+	"prettier.semi": false,
+	// 使用单引号
+	"prettier.singleQuote": true,
+	// 不自动添加逗号
+	"prettier.trailingComma": "none",
+	// 当箭头函数仅有一个参数不添加括号
+	"prettier.arrowParens": "avoid"
+}

+ 1 - 1
babel.config.js

@@ -1,5 +1,5 @@
 module.exports = {
   presets: [
-    '@vue/app'
+    '@vue/cli-plugin-babel/preset'
   ]
 }

File diff suppressed because it is too large
+ 1814 - 459
package-lock.json


+ 12 - 9
package.json

@@ -9,7 +9,7 @@
   },
   "dependencies": {
     "canvas-nest.js": "^2.0.4",
-    "core-js": "^2.6.5",
+    "core-js": "^3.6.5",
     "element-ui": "^2.15.5",
     "js-cookie": "^2.2.1",
     "qs": "^6.8.0",
@@ -21,20 +21,21 @@
     "vuex": "^3.0.1"
   },
   "devDependencies": {
-    "@vue/cli-plugin-babel": "^3.11.0",
-    "@vue/cli-plugin-eslint": "^3.11.0",
-    "@vue/cli-service": "^3.11.0",
+    "@vue/cli-plugin-babel": "^4.5.13",
+    "@vue/cli-plugin-eslint": "^4.5.13",
+    "@vue/cli-service": "^4.5.13",
     "axios": "^0.18.1",
-    "babel-eslint": "^10.0.1",
+    "babel-eslint": "^10.1.0",
     "babel-plugin-component": "^1.1.1",
-    "eslint": "^5.16.0",
-    "eslint-plugin-vue": "^5.0.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "prettier": "^2.4.1",
     "style-resources-loader": "^1.2.1",
     "stylus": "^0.54.7",
     "stylus-loader": "^3.0.2",
     "vue-cli-plugin-axios": "0.0.4",
     "vue-cli-plugin-element": "^1.0.1",
-    "vue-cli-plugin-style-resources-loader": "^0.1.3",
+    "vue-cli-plugin-style-resources-loader": "^0.1.5",
     "vue-template-compiler": "^2.6.10"
   },
   "eslintConfig": {
@@ -47,7 +48,9 @@
       "eslint:recommended"
     ],
     "rules": {
-      "no-console": "off"
+      "no-console": "off",
+      "no-debugger": "off",
+      "no-mixed-spaces-and-tabs": "off"
     },
     "parserOptions": {
       "parser": "babel-eslint"

+ 2 - 2
public/index.html

@@ -8,13 +8,13 @@
   <meta name="keywords" content="">
   <meta name="description" content="">
   <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-</script>
   <title>奇文网盘</title>
 </head>
 
 <body>
   <noscript>
-    <strong>We're sorry but webscp doesn't work properly without JavaScript enabled. Please enable it to
+    <strong>We're sorry but webscp doesn't work properly without JavaScript
+      enabled. Please enable it to
       continue.</strong>
   </noscript>
   <div id="app"></div>

+ 45 - 39
src/App.vue

@@ -1,16 +1,16 @@
 <template>
-  <div id="app">
-    <Header v-if="isHeaderShow" id="headWrapper"></Header>
-    <router-view class="mainContent"></router-view>
-    <Footer v-if="isFooterShow"></Footer>
-    <el-backtop class="backtop" target="#app" title="回到顶部"></el-backtop>
-    <!-- 将上传组件全局注册 -->
-    <global-uploader v-if="isFileAboutShow"></global-uploader>
-    <!-- 图片预览 -->
-    <img-preview v-if="isFileAboutShow"></img-preview>
-    <!-- 视频预览 -->
-    <video-preview v-if="isFileAboutShow"></video-preview>
-  </div>
+	<div id="app">
+		<Header v-if="isHeaderShow" id="headWrapper"></Header>
+		<router-view class="mainContent"></router-view>
+		<Footer v-if="isFooterShow"></Footer>
+		<el-backtop class="backtop" target="#app" title="回到顶部"></el-backtop>
+		<!-- 将上传组件全局注册 -->
+		<global-uploader v-if="isFileAboutShow"></global-uploader>
+		<!-- 图片预览 -->
+		<img-preview v-if="isFileAboutShow"></img-preview>
+		<!-- 视频预览 -->
+		<video-preview v-if="isFileAboutShow"></video-preview>
+	</div>
 </template>
 
 <script>
@@ -21,31 +21,39 @@ import ImgPreview from '_c/common/ImgPreview'
 import VideoPreview from '_c/common/VideoPreview'
 
 export default {
-  name: 'App',
-  components: {
-    Header,
-    Footer,
-    globalUploader,
-    ImgPreview,
-    VideoPreview
-  },
-  computed: {
-    //  头部是否显示
-    isHeaderShow() {
-      let routerNameList = ['Onlyoffice','Error_401', 'Error_404', 'Error_500']
-      return routerNameList.includes(this.$route.name) ? false : true
-    },
-    //  底部是否显示
-    isFooterShow() {
-      let routerNameList = ['Onlyoffice','File', 'Share', 'MyShare', 'Error_401', 'Error_404', 'Error_500']
-      return routerNameList.includes(this.$route.name) ? false : true
-    },
-    // 网盘页面文件上传/预览相关组件是否显示
-    isFileAboutShow() {
-      let routerNameList = ['Login', 'Register', 'Onlyoffice',]
-      return routerNameList.includes(this.$route.name) ? false : true
-    }
-  }
+	name: 'App',
+	components: {
+		Header,
+		Footer,
+		globalUploader,
+		ImgPreview,
+		VideoPreview
+	},
+	computed: {
+		//  头部是否显示
+		isHeaderShow() {
+			let routerNameList = ['Onlyoffice', 'Error_401', 'Error_404', 'Error_500']
+			return routerNameList.includes(this.$route.name) ? false : true
+		},
+		//  底部是否显示
+		isFooterShow() {
+			let routerNameList = [
+				'Onlyoffice',
+				'File',
+				'Share',
+				'MyShare',
+				'Error_401',
+				'Error_404',
+				'Error_500'
+			]
+			return routerNameList.includes(this.$route.name) ? false : true
+		},
+		// 网盘页面文件上传/预览相关组件是否显示
+		isFileAboutShow() {
+			let routerNameList = ['Login', 'Register', 'Onlyoffice']
+			return routerNameList.includes(this.$route.name) ? false : true
+		}
+	}
 }
 </script>
 <style lang="stylus" scoped>
@@ -56,13 +64,11 @@ export default {
   overflow-x: hidden;
   -webkit-text-size-adjust: none;
   overflow-y: auto;
-
   >>> .el-backtop {
     background-color: $Success;
     color: #fff;
     z-index: 3;
   }
-
   .mainContent {
     flex: 1;
     width: 90%;

+ 71 - 20
src/assets/styles/css/base.css

@@ -1,23 +1,74 @@
-*{ margin:0; padding:0; box-sizing: border-box; outline: 0;}
-html{ height: 100%; }
-body{ height: 100%;font-size:16px; font-family:微软雅黑;font-style:normal;overflow-x: hidden;}
-a{ text-decoration:none}
-/*a,a:hover{  transition:background 0.5s linear;-webkit-transition:background 0.5s linear;-moz-transition:background 0.5s linear;-o-transition:background 0.5s linear;}*/
-em, i{font-style: normal;}
-ul, ol, li{list-style: none;}
-img{ border:none;vertical-align:middle;}
-input,select,textarea{outline:none;border:none;background:none;}
-textarea{resize:none;}
-p{line-height:22px;}
-.fl{float: left;}
-.fr{float: right;}
-.clear{ clear:both; height:0px; width:100%; overflow:hidden;}
-.position{position:relative;}
- 
+* {
+	margin: 0;
+	padding: 0;
+	box-sizing: border-box;
+	outline: 0;
+}
+html {
+	height: 100%;
+}
+body {
+	height: 100%;
+	font-size: 16px;
+	font-family: 微软雅黑;
+	font-style: normal;
+	overflow-x: hidden;
+}
+a {
+	text-decoration: none;
+}
+em,
+i {
+	font-style: normal;
+}
+ul,
+ol,
+li {
+	list-style: none;
+}
+img {
+	border: none;
+	vertical-align: middle;
+}
+input,
+select,
+textarea {
+	outline: none;
+	border: none;
+	background: none;
+}
+textarea {
+	resize: none;
+}
+p {
+	line-height: 22px;
+}
+.fl {
+	float: left;
+}
+.fr {
+	float: right;
+}
+.clear {
+	clear: both;
+	height: 0px;
+	width: 100%;
+	overflow: hidden;
+}
+.position {
+	position: relative;
+}
+
 /*公共样式*/
-.layout{ width:1100px; display:table; margin:0 auto;}
-.margin-bottom { margin-bottom: 15px; }
+.layout {
+	width: 1100px;
+	display: table;
+	margin: 0 auto;
+}
+.margin-bottom {
+	margin-bottom: 15px;
+}
 
 .el-input__count {
-  line-height: 100%;
-}
+	line-height: 100%;
+}

+ 4 - 4
src/assets/styles/css/element-cover.css

@@ -1,6 +1,6 @@
-.el-avatar>img {
-  width: 100%;
+.el-avatar > img {
+	width: 100%;
 }
 .el-textarea__inner {
-  font-family: inherit;
-}
+	font-family: inherit;
+}

+ 32 - 20
src/assets/styles/css/mediaScreen.styl

@@ -1,20 +1,32 @@
-@media screen and (max-width 980px) 
-  //  顶部导航栏
-  .headerWrapper 
-    .headerItem 
-      padding 0 10px !important
-    .userDisplay
-      width 110px !important
-    .el-menu-demo 
-      .userDisplay 
-        .username-header 
-          display none !important
-  //  底部
-  .footer-wrapper 
-    .footer-top  
-      .info 
-        .logo 
-          height 80px !important
-        .link-wrapper 
-          padding 6px 6px 6px 12px !important
-          line-height 30px !important
+@media screen and (max-width: 980px) {
+  // 顶部导航栏
+  .headerWrapper {
+    .headerItem {
+      padding: 0 10px !important;
+    }
+    .userDisplay {
+      width: 110px !important;
+    }
+    .el-menu-demo {
+      .userDisplay {
+        .username-header {
+          display: none !important;
+        }
+      }
+    }
+  }
+  // 底部
+  .footer-wrapper {
+    .footer-top {
+      .info {
+        .logo {
+          height: 80px !important;
+        }
+        .link-wrapper {
+          padding: 6px 6px 6px 12px !important;
+          line-height: 30px !important;
+        }
+      }
+    }
+  }
+}

+ 28 - 23
src/assets/styles/mixins.styl

@@ -1,23 +1,28 @@
-setScrollbar(scrollbarWidth, trackColor = #EBEEF5, thumbColor = #909399)
-	//  修改滚动条下面的宽度
-	&::-webkit-scrollbar
-		width scrollbarWidth
-	//  修改滚动条的下面的样式
-	&::-webkit-scrollbar-track
-		background-color trackColor
-		-webkit-border-radius 2em
-		-moz-border-radius 2em
-		border-radius 2em
-	//  修改滑块
-	&::-webkit-scrollbar-thumb
-		background-color thumbColor
-		-webkit-border-radius 2em
-		-moz-border-radius 2em
-		border-radius 2em
-setEllipsis(line)
-	display: -webkit-box;
-	overflow: hidden;
-	white-space: wrap;
-	text-overflow: ellipsis;
-	-webkit-box-orient: vertical; /*  -webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式  */
-	-webkit-line-clamp: line; /*  -webkit-line-clamp用来限制在一个块元素显示的文本的行数 */
+setScrollbar(scrollbarWidth, trackColor = #EBEEF5, thumbColor = #909399) {
+  // 修改滚动条下面的宽度
+  &::-webkit-scrollbar {
+    width: scrollbarWidth;
+  }
+  // 修改滚动条的下面的样式
+  &::-webkit-scrollbar-track {
+    background-color: trackColor;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+  // 修改滑块
+  &::-webkit-scrollbar-thumb {
+    background-color: thumbColor;
+    -webkit-border-radius: 2em;
+    -moz-border-radius: 2em;
+    border-radius: 2em;
+  }
+}
+setEllipsis(line) {
+  display: -webkit-box;
+  overflow: hidden;
+  white-space: wrap;
+  text-overflow: ellipsis;
+  -webkit-box-orient: vertical; /* -webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 */
+  -webkit-line-clamp: line; /* -webkit-line-clamp用来限制在一个块元素显示的文本的行数 */
+}

+ 21 - 25
src/assets/styles/varibles.styl

@@ -1,25 +1,21 @@
-$Primary = #409EFF
-$Success = #67C23A
-$Warning = #E6A23C
-$Danger = #F56C6C
-$Info = #909399
-
-$PrimaryHover = #ecf5ff
-$SuccessHover = #f0f9eb
-$WarningHover = #fdf6ec
-$DangerHover = #fdf6ec
-$InfoHover = #fef0f0
-
-$PrimaryText = #303133
-$RegularText = #606266
-$SecondaryText = #909399
-$Placeholder = #C0C4CC
-
-$BorderBase = #DCDFE6
-$BorderLight = #E4E7ED
-$BorderLighter = #EBEEF5
-$BorderExtralight = #F2F6FC
-
-$tabBackColor = #F5F7FA
-$tabBoxShadow = 0 2px 12px 0 rgba(0, 0, 0, 0.1)
-$tabBoxShadowMin = 0 2px 4px 0 rgba(0, 0, 0, 0.1)
+$Primary = #409EFF;
+$Success = #67C23A;
+$Warning = #E6A23C;
+$Danger = #F56C6C;
+$Info = #909399;
+$PrimaryHover = #ecf5ff;
+$SuccessHover = #f0f9eb;
+$WarningHover = #fdf6ec;
+$DangerHover = #fdf6ec;
+$InfoHover = #fef0f0;
+$PrimaryText = #303133;
+$RegularText = #606266;
+$SecondaryText = #909399;
+$Placeholder = #C0C4CC;
+$BorderBase = #DCDFE6;
+$BorderLight = #E4E7ED;
+$BorderLighter = #EBEEF5;
+$BorderExtralight = #F2F6FC;
+$tabBackColor = #F5F7FA;
+$tabBoxShadow = 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+$tabBoxShadowMin = 0 2px 4px 0 rgba(0, 0, 0, 0.1);

+ 93 - 86
src/components/BreadCrumb.vue

@@ -1,94 +1,101 @@
 <template>
-  <div class="breadcrumb-wrapper">
-    <div class="title">当前位置:</div>
-    <el-breadcrumb v-if="fileType && !['Share', 'MyShare'].includes($route.name)" separator="/">
-      <el-breadcrumb-item>{{ fileTypeMap[fileType] }}</el-breadcrumb-item>
-    </el-breadcrumb>
-    <el-breadcrumb v-else separator="/">
-      <el-breadcrumb-item v-for="(item, index) in breadCrumbList" :key="index" :to="getRouteQuery(item)">{{
-        item.name
-      }}</el-breadcrumb-item>
-    </el-breadcrumb>
-  </div>
+	<div class="breadcrumb-wrapper">
+		<div class="title">当前位置:</div>
+		<el-breadcrumb
+			v-if="fileType && !['Share', 'MyShare'].includes($route.name)"
+			separator="/"
+		>
+			<el-breadcrumb-item>{{ fileTypeMap[fileType] }}</el-breadcrumb-item>
+		</el-breadcrumb>
+		<el-breadcrumb v-else separator="/">
+			<el-breadcrumb-item
+				v-for="(item, index) in breadCrumbList"
+				:key="index"
+				:to="getRouteQuery(item)"
+				>{{ item.name }}</el-breadcrumb-item
+			>
+		</el-breadcrumb>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'BreadCrumb',
-  props: {
-    // 文件类型
-    fileType: {
-      required: true,
-      type: Number
-    }
-  },
-  data() {
-    return {
-      fileTypeMap: {
-        1: '全部图片',
-        2: '全部文档',
-        3: '全部视频',
-        4: '全部音乐',
-        5: '其他',
-        6: '回收站'
-      }
-    }
-  },
-  computed: {
-    /**
-     * 面包屑导航栏数组
-     */
-    breadCrumbList: {
-      get() {
-        let filePath = this.$route.query.filePath
-        let filePathList = filePath ? filePath.split('/') : []
-        let res = [] //  返回结果数组
-        let _path = [] //  存放祖先路径
-        for (let i = 0; i < filePathList.length; i++) {
-          if (filePathList[i]) {
-            _path.push(filePathList[i] + '/')
-            res.push({
-              path: _path.join(''),
-              name: filePathList[i]
-            })
-          } else if (i === 0) {
-            //  根目录
-            filePathList[i] = '/'
-            _path.push(filePathList[i])
-            res.push({
-              path: '/',
-              name: this.$route.meta.breadCrumbName
-            })
-          }
-        }
-        return res
-      },
-      set() {
-        return []
-      }
-    }
-  },
-  methods: {
-    // 获取文件参数
-    getRouteQuery(item) {
-      let routeName = this.$route.name
-      if (routeName === 'Share') {
-        // 当前是查看他人分享列表的页面
-        return { query: { filePath: item.path } }
-      } else if (routeName === 'MyShare') {
-        // 当前是我的已分享列表页面
-        return {
-          query: {
-            filePath: item.path,
-            shareBatchNum: item.path === '/' ? undefined : this.$route.query.shareBatchNum  //  当查看的是根目录,批次号置空
-          }
-        }
-      } else {
-        // 网盘页面
-        return { query: { filePath: item.path, fileType: 0 } }
-      }
-    }
-  }
+	name: 'BreadCrumb',
+	props: {
+		// 文件类型
+		fileType: {
+			required: true,
+			type: Number
+		}
+	},
+	data() {
+		return {
+			fileTypeMap: {
+				1: '全部图片',
+				2: '全部文档',
+				3: '全部视频',
+				4: '全部音乐',
+				5: '其他',
+				6: '回收站'
+			}
+		}
+	},
+	computed: {
+		/**
+		 * 面包屑导航栏数组
+		 */
+		breadCrumbList: {
+			get() {
+				let filePath = this.$route.query.filePath
+				let filePathList = filePath ? filePath.split('/') : []
+				let res = [] //  返回结果数组
+				let _path = [] //  存放祖先路径
+				for (let i = 0; i < filePathList.length; i++) {
+					if (filePathList[i]) {
+						_path.push(filePathList[i] + '/')
+						res.push({
+							path: _path.join(''),
+							name: filePathList[i]
+						})
+					} else if (i === 0) {
+						//  根目录
+						filePathList[i] = '/'
+						_path.push(filePathList[i])
+						res.push({
+							path: '/',
+							name: this.$route.meta.breadCrumbName
+						})
+					}
+				}
+				return res
+			},
+			set() {
+				return []
+			}
+		}
+	},
+	methods: {
+		// 获取文件参数
+		getRouteQuery(item) {
+			let routeName = this.$route.name
+			if (routeName === 'Share') {
+				// 当前是查看他人分享列表的页面
+				return { query: { filePath: item.path } }
+			} else if (routeName === 'MyShare') {
+				// 当前是我的已分享列表页面
+				return {
+					query: {
+						filePath: item.path,
+						shareBatchNum:
+							item.path === '/' ? undefined : this.$route.query.shareBatchNum //  当查看的是根目录,批次号置空
+					}
+				}
+			} else {
+				// 网盘页面
+				return { query: { filePath: item.path, fileType: 0 } }
+			}
+		}
+	}
 }
 </script>
 

+ 121 - 112
src/components/File/AddFileDialog.vue

@@ -1,120 +1,129 @@
 <template>
-  <!-- 新建文件对话框 -->
-  <el-dialog
-    title="新建文件"
-    :visible.sync="dialogFileStatus"
-    :close-on-click-modal="false"
-    width="550px"
-  >
-    <el-form
-      class="add-File-form"
-      :model="form"
-      :rules="formRules"
-      ref="addFileForm"
-      label-width="100px"
-      label-position="top"
-    >
-      <el-form-item label="文件名称" prop="fileName">
-        <el-input
-          v-model="form.fileName"
-          placeholder="请输入文件名称"
-          type="textarea"
-          autosize
-          maxlength="255"
-          show-word-limit
-        ></el-input>
-      </el-form-item>
-    </el-form>
-    <div slot="footer" class="dialog-footer">
-      <el-button @click="handleAddFileDialogCancel('addFileForm')">取 消</el-button>
-      <el-button type="primary" :loading="loading" @click="handleAddFileDialogOk('addFileForm')">确 定</el-button>
-    </div>
-  </el-dialog>
+	<!-- 新建文件对话框 -->
+	<el-dialog
+		title="新建文件"
+		:visible.sync="dialogFileStatus"
+		:close-on-click-modal="false"
+		width="550px"
+	>
+		<el-form
+			class="add-File-form"
+			:model="form"
+			:rules="formRules"
+			ref="addFileForm"
+			label-width="100px"
+			label-position="top"
+		>
+			<el-form-item label="文件名称" prop="fileName">
+				<el-input
+					v-model="form.fileName"
+					placeholder="请输入文件名称"
+					type="textarea"
+					autosize
+					maxlength="255"
+					show-word-limit
+				></el-input>
+			</el-form-item>
+		</el-form>
+		<div slot="footer" class="dialog-footer">
+			<el-button @click="handleAddFileDialogCancel('addFileForm')"
+				>取 消</el-button
+			>
+			<el-button
+				type="primary"
+				:loading="loading"
+				@click="handleAddFileDialogOk('addFileForm')"
+				>确 定</el-button
+			>
+		</div>
+	</el-dialog>
 </template>
 
 <script>
 import { createOfficeFile } from '_r/onlyoffice.js'
 
 export default {
-  name: 'AddFileDialog',
-  props: {
-    // 对话框是否可见
-    visible: {
-      type: Boolean,
-      required: true
-    },
-    // 文件路径
-    filePath: {
-      required: true,
-      type: String
-    },
-    // 文件扩展名
-    extendName: {
-      required: true,
-      type: String
-    }
-  },
-  data() {
-    return {
-      form: {
-        fileName: ''
-      },
-      formRules: {
-        fileName: [{ required: true, message: '请输入文件名称', trigger: 'blur' }]
-      },
-      loading: false
-    }
-  },
-  computed: {
-    // 对话框是否可见
-    dialogFileStatus: {
-      get() {
-        return this.visible
-      },
-      set(val) {
-        this.$emit('update:visible', val)
-      }
-    }
-  },
-  methods: {
-    /**
-     * 新建文件对话框 | 取消按钮点击事件
-     * @description 关闭对话框,重置表单
-     * @param {string} formName 表单ref值
-     */
-    handleAddFileDialogCancel(formName) {
-      this.dialogFileStatus = false
-      this.$refs[formName].resetFields()
-    },
-    /**
-     * 新建文件对话框 | 确定按钮点击事件
-     * @description 校验表单,校验通过后调用新建文件接口
-     * @param {string} formName 表单ref值
-     */
-    handleAddFileDialogOk(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          this.loading = true
-          createOfficeFile({
-            fileName: this.form.fileName,
-            filePath: this.filePath,
-            extendName: this.extendName
-          }).then((res) => {
-            this.loading = false
-            if (res.success) {
-              this.$message.success('文件创建成功')
-              this.dialogFileStatus = false
-              this.$refs[formName].resetFields()
-              this.$emit('confirmDialog')
-            } else {
-              this.$message.warning(res.message)
-            }
-          })
-        } else {
-          return false
-        }
-      })
-    }
-  }
+	name: 'AddFileDialog',
+	props: {
+		// 对话框是否可见
+		visible: {
+			type: Boolean,
+			required: true
+		},
+		// 文件路径
+		filePath: {
+			required: true,
+			type: String
+		},
+		// 文件扩展名
+		extendName: {
+			required: true,
+			type: String
+		}
+	},
+	data() {
+		return {
+			form: {
+				fileName: ''
+			},
+			formRules: {
+				fileName: [
+					{ required: true, message: '请输入文件名称', trigger: 'blur' }
+				]
+			},
+			loading: false
+		}
+	},
+	computed: {
+		// 对话框是否可见
+		dialogFileStatus: {
+			get() {
+				return this.visible
+			},
+			set(val) {
+				this.$emit('update:visible', val)
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 新建文件对话框 | 取消按钮点击事件
+		 * @description 关闭对话框,重置表单
+		 * @param {string} formName 表单ref值
+		 */
+		handleAddFileDialogCancel(formName) {
+			this.dialogFileStatus = false
+			this.$refs[formName].resetFields()
+		},
+		/**
+		 * 新建文件对话框 | 确定按钮点击事件
+		 * @description 校验表单,校验通过后调用新建文件接口
+		 * @param {string} formName 表单ref值
+		 */
+		handleAddFileDialogOk(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					this.loading = true
+					createOfficeFile({
+						fileName: this.form.fileName,
+						filePath: this.filePath,
+						extendName: this.extendName
+					}).then((res) => {
+						this.loading = false
+						if (res.success) {
+							this.$message.success('文件创建成功')
+							this.dialogFileStatus = false
+							this.$refs[formName].resetFields()
+							this.$emit('confirmDialog')
+						} else {
+							this.$message.warning(res.message)
+						}
+					})
+				} else {
+					return false
+				}
+			})
+		}
+	}
 }
-</script>
+</script>

+ 125 - 118
src/components/File/AddFolderDialog.vue

@@ -1,126 +1,133 @@
 <template>
-  <!-- 新建文件夹对话框 -->
-  <el-dialog
-    title="新建文件夹"
-    :visible.sync="dialogStatus"
-    :close-on-click-modal="false"
-    width="550px"
-  >
-    <el-form
-      class="add-folder-form"
-      :model="form"
-      :rules="formRules"
-      ref="addFolderForm"
-      label-width="100px"
-      label-position="top"
-    >
-      <el-form-item label="文件夹名称" prop="fileName">
-        <el-input
-          v-model="form.fileName"
-          placeholder="请输入文件夹名称"
-          type="textarea"
-          autosize
-          maxlength="255"
-          show-word-limit
-        ></el-input>
-      </el-form-item>
-    </el-form>
-    <div slot="footer" class="dialog-footer">
-      <el-button @click="handleAddFolderDialogCancel('addFolderForm')">取 消</el-button>
-      <el-button type="primary" :loading="loading" @click="handleAddFolderDialogOk('addFolderForm')">确 定</el-button>
-    </div>
-  </el-dialog>
+	<!-- 新建文件夹对话框 -->
+	<el-dialog
+		title="新建文件夹"
+		:visible.sync="dialogStatus"
+		:close-on-click-modal="false"
+		width="550px"
+	>
+		<el-form
+			class="add-folder-form"
+			:model="form"
+			:rules="formRules"
+			ref="addFolderForm"
+			label-width="100px"
+			label-position="top"
+		>
+			<el-form-item label="文件夹名称" prop="fileName">
+				<el-input
+					v-model="form.fileName"
+					placeholder="请输入文件夹名称"
+					type="textarea"
+					autosize
+					maxlength="255"
+					show-word-limit
+				></el-input>
+			</el-form-item>
+		</el-form>
+		<div slot="footer" class="dialog-footer">
+			<el-button @click="handleAddFolderDialogCancel('addFolderForm')"
+				>取 消</el-button
+			>
+			<el-button
+				type="primary"
+				:loading="loading"
+				@click="handleAddFolderDialogOk('addFolderForm')"
+				>确 定</el-button
+			>
+		</div>
+	</el-dialog>
 </template>
 
 <script>
 import { createFold } from '_r/file.js'
 
 export default {
-  name: 'AddFolderDialog',
-  props: {
-    // 对话框是否可见
-    visible: {
-      type: Boolean,
-      required: true
-    },
-    // 文件路径
-    filePath: {
-      required: true,
-      type: String
-    }
-  },
-  data() {
-    const validateFileName = (rule, value, callback) => {
-      const fileNameReg = new RegExp(`[\\\\/:*?\"<>|]`);
-      if (value && fileNameReg.test(value)) {
-        callback(new Error(`文件夹名称不能包含下列任何字符:\\\/:*?"<>|`));
-      } else {
-        callback();
-      }
-    };
-    return {
-      form: {
-        fileName: ''
-      },
-      formRules: {
-        fileName: [
-          { required: true, message: '请输入文件夹名称', trigger: 'blur' },
-          { validator: validateFileName, trigger: ['blur', 'change'] }
-        ]
-      },
-      loading: false
-    }
-  },
-  computed: {
-    // 对话框是否可见
-    dialogStatus: {
-      get() {
-        return this.visible
-      },
-      set(val) {
-        this.$emit('update:visible', val)
-      }
-    }
-  },
-  methods: {
-    /**
-     * 新建文件夹对话框 | 取消按钮点击事件
-     * @description 关闭对话框,重置表单
-     * @param {string} formName 表单ref值
-     */
-    handleAddFolderDialogCancel(formName) {
-      this.dialogStatus = false
-      this.$refs[formName].resetFields()
-    },
-    /**
-     * 新建文件夹对话框 | 确定按钮点击事件
-     * @description 校验表单,校验通过后调用新建文件夹接口
-     * @param {string} formName 表单ref值
-     */
-    handleAddFolderDialogOk(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          this.loading = true
-          createFold({
-            fileName: this.form.fileName,
-            filePath: this.filePath,
-            isDir: 1
-          }).then((res) => {
-            this.loading = false
-            if (res.success) {
-              this.$message.success('添加成功')
-              this.dialogStatus = false
-              this.$refs[formName].resetFields()
-              this.$emit('confirmDialog')
-            } else {
-              this.$message.warning(res.message)
-            }
-          })
-        } else {
-          return false
-        }
-      })
-    }
-  }
+	name: 'AddFolderDialog',
+	props: {
+		// 对话框是否可见
+		visible: {
+			type: Boolean,
+			required: true
+		},
+		// 文件路径
+		filePath: {
+			required: true,
+			type: String
+		}
+	},
+	data() {
+		const validateFileName = (rule, value, callback) => {
+			const fileNameReg = new RegExp(`[\\\\/:*?"<>|]`)
+			if (value && fileNameReg.test(value)) {
+				callback(new Error(`文件夹名称不能包含下列任何字符:\\/:*?"<>|`))
+			} else {
+				callback()
+			}
+		}
+		return {
+			form: {
+				fileName: ''
+			},
+			formRules: {
+				fileName: [
+					{ required: true, message: '请输入文件夹名称', trigger: 'blur' },
+					{ validator: validateFileName, trigger: ['blur', 'change'] }
+				]
+			},
+			loading: false
+		}
+	},
+	computed: {
+		// 对话框是否可见
+		dialogStatus: {
+			get() {
+				return this.visible
+			},
+			set(val) {
+				this.$emit('update:visible', val)
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 新建文件夹对话框 | 取消按钮点击事件
+		 * @description 关闭对话框,重置表单
+		 * @param {string} formName 表单ref值
+		 */
+		handleAddFolderDialogCancel(formName) {
+			this.dialogStatus = false
+			this.$refs[formName].resetFields()
+		},
+		/**
+		 * 新建文件夹对话框 | 确定按钮点击事件
+		 * @description 校验表单,校验通过后调用新建文件夹接口
+		 * @param {string} formName 表单ref值
+		 */
+		handleAddFolderDialogOk(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					this.loading = true
+					createFold({
+						fileName: this.form.fileName,
+						filePath: this.filePath,
+						isDir: 1
+					}).then((res) => {
+						this.loading = false
+						if (res.success) {
+							this.$message.success('添加成功')
+							this.dialogStatus = false
+							this.$refs[formName].resetFields()
+							this.$emit('confirmDialog')
+						} else {
+							this.$message.warning(res.message)
+						}
+					})
+				} else {
+					return false
+				}
+			})
+		}
+	}
 }
-</script>
+</script>

+ 958 - 866
src/components/File/FileTable.vue

@@ -1,877 +1,969 @@
 <template>
-  <div class="file-table-wrapper">
-    <!-- 文件表格 -->
-    <el-table
-      class="file-table"
-      :class="['file-type-' + fileType, routeName === 'Share' ? 'share' : routeName === 'MyShare' ? 'my-share' : '']"
-      ref="multipleTable"
-      fit
-      v-loading="loading"
-      element-loading-text="文件加载中……"
-      tooltip-effect="dark"
-      :data="fileList"
-      :highlight-current-row="true"
-      @selection-change="handleSelectRow"
-      @sort-change="handleSortChange"
-      @row-contextmenu="handleContextMenu"
-    >
-      <el-table-column type="selection" key="selection" width="55"></el-table-column>
-      <el-table-column label prop="isDir" key="isDir" width="60" align="center">
-        <template slot-scope="scope">
-          <img
-            :src="setFileImg(scope.row)"
-            :title="`${scope.row.isDir ? '' : '点击预览'}`"
-            style="width: 30px; max-height: 30px; cursor: pointer"
-            @click="handleFileNameClick(scope.row, scope.$index, fileList)"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column prop="fileName" key="fileName" :sort-by="['isDir', 'fileName']" sortable show-overflow-tooltip>
-        <template slot="header">
-          <span>文件名</span>
-        </template>
-        <template slot-scope="scope">
-          <div
-            style="cursor: pointer"
-            :title="`${scope.row.isDir ? '' : '点击预览'}`"
-            @click="handleFileNameClick(scope.row, scope.$index, fileList)"
-          >
-            {{ scope.row | fileNameComplete }}
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column
-        :label="fileType === 6 ? '原路径' : '路径'"
-        prop="filePath"
-        key="filePath"
-        show-overflow-tooltip
-        v-if="Number($route.query.fileType)"
-      >
-        <template slot-scope="scope">
-          <span
-            style="cursor: pointer"
-            title="点击跳转"
-            @click="
-              $router.push({
-                query: { filePath: scope.row.filePath, fileType: 0 }
-              })
-            "
-            >{{ scope.row.filePath }}</span
-          >
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="类型"
-        width="80"
-        prop="extendName"
-        key="extendName"
-        :sort-by="['isDir', 'extendName']"
-        sortable
-        show-overflow-tooltip
-        v-if="selectedColumnList.includes('extendName')"
-      >
-        <template slot-scope="scope">
-          <span v-if="scope.row.extendName">{{ scope.row.extendName }}</span>
-          <span v-else>文件夹</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="大小"
-        width="80"
-        prop="fileSize"
-        key="fileSize"
-        :sort-by="['isDir', 'fileSize']"
-        sortable
-        show-overflow-tooltip
-        align="right"
-        v-if="selectedColumnList.includes('fileSize')"
-      >
-        <template slot-scope="scope">
-          <div style="padding: 0 10px">
-            {{ calculateFileSize(scope.row.fileSize) }}
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="修改日期"
-        prop="uploadTime"
-        key="uploadTime"
-        width="180"
-        :sort-by="['isDir', 'uploadTime']"
-        sortable
-        align="center"
-        v-if="selectedColumnList.includes('uploadTime') && ![7, 8].includes(fileType)"
-      ></el-table-column>
-      <el-table-column
-        label="删除日期"
-        prop="deleteTime"
-        key="deleteTime"
-        width="180"
-        :sort-by="['isDir', 'deleteTime']"
-        sortable
-        align="center"
-        v-if="fileType === 6 && selectedColumnList.includes('deleteTime')"
-      ></el-table-column>
-      <el-table-column
-        label="分享类型"
-        prop="shareType"
-        key="shareType"
-        width="100"
-        align="center"
-        v-if="routeName === 'MyShare'"
-      >
-        <template slot-scope="scope">
-          {{ scope.row.shareType === 1 ? '私密' : '公共' }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="分享时间"
-        prop="shareTime"
-        key="shareTime"
-        width="180"
-        :sort-by="['isDir', 'shareTime']"
-        show-overflow-tooltip
-        sortable
-        align="center"
-        v-if="routeName === 'MyShare'"
-      ></el-table-column>
-      <el-table-column
-        label="过期时间"
-        prop="endTime"
-        key="endTime"
-        width="190"
-        :sort-by="['isDir', 'endTime']"
-        show-overflow-tooltip
-        sortable
-        align="center"
-        v-if="routeName === 'MyShare'"
-      >
-        <template slot-scope="scope">
-          <div>
-            <i class="el-icon-warning" v-if="getFileShareStatus(scope.row.endTime)"></i>
-            <i class="el-icon-time" v-else></i>
-            {{ scope.row.endTime }}
-          </div>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 右键列表 -->
-    <transition name="el-fade-in-linear">
-      <ul
-        class="right-menu-list"
-        id="rightMenuList"
-        v-show="rightMenu.isShow"
-        :style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
-      >
-        <li class="right-menu-item" @click="handleFileNameClick(selectedFile, 0)" v-if="seeBtnShow">
-          <i class="el-icon-view"></i> 查看
-        </li>
-        <li class="right-menu-item" @click="handleDeleteFileBtnClick(selectedFile)" v-if="deleteBtnShow">
-          <i class="el-icon-delete"></i> 删除
-        </li>
-        <li class="right-menu-item" @click="handleRestoreFileBtnClick(selectedFile)" v-if="restoreBtnShow">
-          <i class="el-icon-refresh-left"></i> 还原
-        </li>
-        <li class="right-menu-item" @click="handleMoveFileBtnClick(selectedFile)" v-if="moveBtnShow">
-          <i class="el-icon-s-promotion"></i> 移动
-        </li>
-        <li class="right-menu-item" @click="handleRenameFileBtnClick(selectedFile)" v-if="renameBtnShow">
-          <i class="el-icon-edit-outline"></i> 重命名
-        </li>
-        <li class="right-menu-item" @click="handleShareFileBtnClick(selectedFile)" v-if="shareBtnShow">
-          <i class="el-icon-share"></i> 分享
-        </li>
-        <li class="right-menu-item" @click="rightMenu.isShow = false" v-if="downloadBtnShow">
-          <a
-            target="_blank"
-            style="display: block; color: inherit"
-            :href="getDownloadFilePath(selectedFile)"
-            :download="selectedFile.fileName + '.' + selectedFile.extendName"
-          >
-            <i class="el-icon-download"></i> 下载
-          </a>
-        </li>
-        <!-- 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 3-手动选择解压目录 -->
-        <li class="right-menu-item unzip-menu-item" v-if="unzipBtnShow">
-          <i class="el-icon-files"></i> 解压缩 <i class="el-icon-arrow-right"></i>
-          <ul class="unzip-list" :style="`top: ${unzipMenu.top};bottom: ${unzipMenu.bottom};left: ${unzipMenu.left};right: ${unzipMenu.right};`">
-            <li class="unzip-item" @click="handleUnzipFileBtnClick(selectedFile, 0)" v-if="unzipBtnShow">
-              <i class="el-icon-files"></i> 解压到当前文件夹
-            </li>
-            <li class="unzip-item" @click="handleUnzipFileBtnClick(selectedFile, 1)" v-if="unzipBtnShow" :title='`解压到"${selectedFile.fileName}"`'>
-              <i class="el-icon-files"></i> 解压到"{{selectedFile.fileName}}"
-            </li>
-          </ul>
-        </li>
-        <li class="right-menu-item" @click="getFileOnlineEditPathByOffice(selectedFile)" v-if="onlineEditBtnShow">
-          <i class="el-icon-edit"></i> 在线编辑
-        </li>
-        <li
-          class="right-menu-item"
-          @click="copyShareLink(selectedFile.shareBatchNum, selectedFile.extractionCode)"
-          v-if="copyLinkBtnShow"
-        >
-          <i class="el-icon-edit"></i> 复制链接
-        </li>
-      </ul>
-    </transition>
-  </div>
+	<div class="file-table-wrapper">
+		<!-- 文件表格 -->
+		<el-table
+			class="file-table"
+			:class="[
+				'file-type-' + fileType,
+				routeName === 'Share'
+					? 'share'
+					: routeName === 'MyShare'
+					? 'my-share'
+					: ''
+			]"
+			ref="multipleTable"
+			fit
+			v-loading="loading"
+			element-loading-text="文件加载中……"
+			tooltip-effect="dark"
+			:data="fileList"
+			:highlight-current-row="true"
+			@selection-change="handleSelectRow"
+			@sort-change="handleSortChange"
+			@row-contextmenu="handleContextMenu"
+		>
+			<el-table-column
+				type="selection"
+				key="selection"
+				width="55"
+			></el-table-column>
+			<el-table-column label prop="isDir" key="isDir" width="60" align="center">
+				<template slot-scope="scope">
+					<img
+						:src="setFileImg(scope.row)"
+						:title="`${scope.row.isDir ? '' : '点击预览'}`"
+						style="width: 30px; max-height: 30px; cursor: pointer"
+						@click="handleFileNameClick(scope.row, scope.$index, fileList)"
+					/>
+				</template>
+			</el-table-column>
+			<el-table-column
+				prop="fileName"
+				key="fileName"
+				:sort-by="['isDir', 'fileName']"
+				sortable
+				show-overflow-tooltip
+			>
+				<template slot="header">
+					<span>文件名</span>
+				</template>
+				<template slot-scope="scope">
+					<div
+						style="cursor: pointer"
+						:title="`${scope.row.isDir ? '' : '点击预览'}`"
+						@click="handleFileNameClick(scope.row, scope.$index, fileList)"
+					>
+						{{ scope.row | fileNameComplete }}
+					</div>
+				</template>
+			</el-table-column>
+			<el-table-column
+				:label="fileType === 6 ? '原路径' : '路径'"
+				prop="filePath"
+				key="filePath"
+				show-overflow-tooltip
+				v-if="Number($route.query.fileType)"
+			>
+				<template slot-scope="scope">
+					<span
+						style="cursor: pointer"
+						title="点击跳转"
+						@click="
+							$router.push({
+								query: { filePath: scope.row.filePath, fileType: 0 }
+							})
+						"
+						>{{ scope.row.filePath }}</span
+					>
+				</template>
+			</el-table-column>
+			<el-table-column
+				label="类型"
+				width="80"
+				prop="extendName"
+				key="extendName"
+				:sort-by="['isDir', 'extendName']"
+				sortable
+				show-overflow-tooltip
+				v-if="selectedColumnList.includes('extendName')"
+			>
+				<template slot-scope="scope">
+					<span v-if="scope.row.extendName">{{ scope.row.extendName }}</span>
+					<span v-else>文件夹</span>
+				</template>
+			</el-table-column>
+			<el-table-column
+				label="大小"
+				width="80"
+				prop="fileSize"
+				key="fileSize"
+				:sort-by="['isDir', 'fileSize']"
+				sortable
+				show-overflow-tooltip
+				align="right"
+				v-if="selectedColumnList.includes('fileSize')"
+			>
+				<template slot-scope="scope">
+					<div style="padding: 0 10px">
+						{{ calculateFileSize(scope.row.fileSize) }}
+					</div>
+				</template>
+			</el-table-column>
+			<el-table-column
+				label="修改日期"
+				prop="uploadTime"
+				key="uploadTime"
+				width="180"
+				:sort-by="['isDir', 'uploadTime']"
+				sortable
+				align="center"
+				v-if="
+					selectedColumnList.includes('uploadTime') &&
+					![7, 8].includes(fileType)
+				"
+			></el-table-column>
+			<el-table-column
+				label="删除日期"
+				prop="deleteTime"
+				key="deleteTime"
+				width="180"
+				:sort-by="['isDir', 'deleteTime']"
+				sortable
+				align="center"
+				v-if="fileType === 6 && selectedColumnList.includes('deleteTime')"
+			></el-table-column>
+			<el-table-column
+				label="分享类型"
+				prop="shareType"
+				key="shareType"
+				width="100"
+				align="center"
+				v-if="routeName === 'MyShare'"
+			>
+				<template slot-scope="scope">
+					{{ scope.row.shareType === 1 ? '私密' : '公共' }}
+				</template>
+			</el-table-column>
+			<el-table-column
+				label="分享时间"
+				prop="shareTime"
+				key="shareTime"
+				width="180"
+				:sort-by="['isDir', 'shareTime']"
+				show-overflow-tooltip
+				sortable
+				align="center"
+				v-if="routeName === 'MyShare'"
+			></el-table-column>
+			<el-table-column
+				label="过期时间"
+				prop="endTime"
+				key="endTime"
+				width="190"
+				:sort-by="['isDir', 'endTime']"
+				show-overflow-tooltip
+				sortable
+				align="center"
+				v-if="routeName === 'MyShare'"
+			>
+				<template slot-scope="scope">
+					<div>
+						<i
+							class="el-icon-warning"
+							v-if="getFileShareStatus(scope.row.endTime)"
+						></i>
+						<i class="el-icon-time" v-else></i>
+						{{ scope.row.endTime }}
+					</div>
+				</template>
+			</el-table-column>
+		</el-table>
+		<!-- 右键列表 -->
+		<transition name="el-fade-in-linear">
+			<ul
+				class="right-menu-list"
+				id="rightMenuList"
+				v-show="rightMenu.isShow"
+				:style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
+			>
+				<li
+					class="right-menu-item"
+					@click="handleFileNameClick(selectedFile, 0)"
+					v-if="seeBtnShow"
+				>
+					<i class="el-icon-view"></i> 查看
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleDeleteFileBtnClick(selectedFile)"
+					v-if="deleteBtnShow"
+				>
+					<i class="el-icon-delete"></i> 删除
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleRestoreFileBtnClick(selectedFile)"
+					v-if="restoreBtnShow"
+				>
+					<i class="el-icon-refresh-left"></i> 还原
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleMoveFileBtnClick(selectedFile)"
+					v-if="moveBtnShow"
+				>
+					<i class="el-icon-s-promotion"></i> 移动
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleRenameFileBtnClick(selectedFile)"
+					v-if="renameBtnShow"
+				>
+					<i class="el-icon-edit-outline"></i> 重命名
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleShareFileBtnClick(selectedFile)"
+					v-if="shareBtnShow"
+				>
+					<i class="el-icon-share"></i> 分享
+				</li>
+				<li
+					class="right-menu-item"
+					@click="rightMenu.isShow = false"
+					v-if="downloadBtnShow"
+				>
+					<a
+						target="_blank"
+						style="display: block; color: inherit"
+						:href="getDownloadFilePath(selectedFile)"
+						:download="selectedFile.fileName + '.' + selectedFile.extendName"
+					>
+						<i class="el-icon-download"></i> 下载
+					</a>
+				</li>
+				<!-- 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 3-手动选择解压目录 -->
+				<li class="right-menu-item unzip-menu-item" v-if="unzipBtnShow">
+					<i class="el-icon-files"></i> 解压缩
+					<i class="el-icon-arrow-right"></i>
+					<ul
+						class="unzip-list"
+						:style="`top: ${unzipMenu.top};bottom: ${unzipMenu.bottom};left: ${unzipMenu.left};right: ${unzipMenu.right};`"
+					>
+						<li
+							class="unzip-item"
+							@click="handleUnzipFileBtnClick(selectedFile, 0)"
+							v-if="unzipBtnShow"
+						>
+							<i class="el-icon-files"></i> 解压到当前文件夹
+						</li>
+						<li
+							class="unzip-item"
+							@click="handleUnzipFileBtnClick(selectedFile, 1)"
+							v-if="unzipBtnShow"
+							:title="`解压到&quot;${selectedFile.fileName}&quot;`"
+						>
+							<i class="el-icon-files"></i> 解压到"{{ selectedFile.fileName }}"
+						</li>
+					</ul>
+				</li>
+				<li
+					class="right-menu-item"
+					@click="getFileOnlineEditPathByOffice(selectedFile)"
+					v-if="onlineEditBtnShow"
+				>
+					<i class="el-icon-edit"></i> 在线编辑
+				</li>
+				<li
+					class="right-menu-item"
+					@click="
+						copyShareLink(
+							selectedFile.shareBatchNum,
+							selectedFile.extractionCode
+						)
+					"
+					v-if="copyLinkBtnShow"
+				>
+					<i class="el-icon-edit"></i> 复制链接
+				</li>
+			</ul>
+		</transition>
+	</div>
 </template>
 
 <script>
-import { unzipFile, deleteFile, renameFile, deleteRecoveryFile, restoreRecoveryFile } from '_r/file.js'
+import {
+	unzipFile,
+	deleteFile,
+	renameFile,
+	deleteRecoveryFile,
+	restoreRecoveryFile
+} from '_r/file.js'
 import { mapGetters } from 'vuex'
 
 export default {
-  name: 'FileTable',
-  props: {
-    // 文件类型
-    fileType: {
-      required: true,
-      type: Number
-    },
-    // 文件路径
-    filePath: {
-      required: true,
-      type: String
-    },
-    // 文件列表
-    fileList: {
-      required: true,
-      type: Array
-    },
-    // 文件加载状态
-    loading: {
-      required: true,
-      type: Boolean
-    }
-  },
-  data() {
-    return {
-      //  可以识别的文件类型
-      fileImgTypeList: [
-        'png',
-        'jpg',
-        'jpeg',
-        'docx',
-        'doc',
-        'ppt',
-        'pptx',
-        'xls',
-        'xlsx',
-        'avi',
-        'mp4',
-        'css',
-        'csv',
-        'chm',
-        'rar',
-        'zip',
-        'dmg',
-        'mp3',
-        'open',
-        'pdf',
-        'rtf',
-        'txt',
-        'oa',
-        'js',
-        'html',
-        'img',
-        'sql',
-        'jar',
-        'svg',
-        'gif',
-        'json',
-        'exe'
-      ],
-      //  文件图片Map映射
-      fileImgMap: {
-        dir: require('_a/images/file/dir.png'),
-        chm: require('_a/images/file/file_chm.png'),
-        css: require('_a/images/file/file_css.png'),
-        csv: require('_a/images/file/file_csv.png'),
-        png: require('_a/images/file/file_pic.png'),
-        jpg: require('_a/images/file/file_pic.png'),
-        jpeg: require('_a/images/file/file_pic.png'),
-        docx: require('_a/images/file/file_word.png'),
-        doc: require('_a/images/file/file_word.png'),
-        ppt: require('_a/images/file/file_ppt.png'),
-        pptx: require('_a/images/file/file_ppt.png'),
-        xls: require('_a/images/file/file_excel.png'),
-        xlsx: require('_a/images/file/file_excel.png'),
-        mp4: require('_a/images/file/file_video.png'),
-        avi: require('_a/images/file/file_avi.png'),
-        rar: require('_a/images/file/file_rar.png'),
-        zip: require('_a/images/file/file_zip.png'),
-        dmg: require('_a/images/file/file_dmg.png'),
-        mp3: require('_a/images/file/file_music.png'),
-        open: require('_a/images/file/file_open.png'),
-        pdf: require('_a/images/file/file_pdf.png'),
-        rtf: require('_a/images/file/file_rtf.png'),
-        txt: require('_a/images/file/file_txt.png'),
-        oa: require('_a/images/file/file_oa.png'),
-        unknown: require('_a/images/file/file_unknown.png'),
-        js: require('_a/images/file/file_js.png'),
-        html: require('_a/images/file/file_html.png'),
-        img: require('_a/images/file/file_img.png'),
-        sql: require('_a/images/file/file_sql.png'),
-        jar: require('_a/images/file/file_jar.png'),
-        svg: require('_a/images/file/file_svg.png'),
-        gif: require('_a/images/file/file_gif.png'),
-        json: require('_a/images/file/file_json.png'),
-        exe: require('_a/images/file/file_exe.png')
-      },
-      officeFileType: ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx'],
-      downloadFilePath: '',
-      viewFilePath: '',
-      // 音频预览
-      audioObj: {
-        src: ''
-      },
-      sortedFileList: [], //  排序后的表格数据
-      // 右键菜单
-      rightMenu: {
-        isShow: false,
-        top: 0,
-        left: 0,
-        bottom: 'auto',
-        right: 'auto'
-      },
-      // 右键解压缩菜单
-      unzipMenu: {
-        top: 0,
-        bottom: 'auto',
-        left: '138px',
-        right: 'auto'
-      },
-      selectedFile: {} //  右键选中的表格行数据
-    }
-  },
-  computed: {
-    //  selectedColumnList: 判断当前用户设置的左侧栏是否折叠
-    ...mapGetters(['selectedColumnList']),
-    //  判断当前路径下是否有普通文件
-    isIncludeNormalFile() {
-      return this.fileList.map((data) => data.isDir).includes(0)
-    },
-    //  判断当前路径下是否有压缩文件
-    isIncludeZipRarFile() {
-      return (
-        this.fileList.map((data) => data.extendName).includes('zip') ||
-        this.fileList.map((data) => data.extendName).includes('rar')
-      )
-    },
-    // 路由名称
-    routeName() {
-      return this.$route.name
-    },
-    // 查看按钮是否显示
-    seeBtnShow() {
-      return this.fileType !== 6
-    },
-    // 删除按钮是否显示
-    deleteBtnShow() {
-      return !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 还原按钮是否显示
-    restoreBtnShow() {
-      return this.fileType === 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 移动按钮是否显示
-    moveBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 重命名按钮是否显示
-    renameBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 删除按钮是否显示
-    shareBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 下载按钮是否显示
-    downloadBtnShow() {
-      return this.fileType !== 6 && !['MyShare'].includes(this.routeName)
-    },
-    // 解压缩按钮是否显示
-    unzipBtnShow() {
-      return (
-        this.fileType !== 6 &&
-        !['Share', 'MyShare'].includes(this.routeName) &&
-        ['zip', 'rar'].includes(this.selectedFile.extendName)
-      )
-    },
-    // 在线编辑按钮是否显示
-    onlineEditBtnShow() {
-      return (
-        this.fileType !== 6 &&
-        this.officeFileType.includes(this.selectedFile.extendName) &&
-        !['Share', 'MyShare'].includes(this.routeName)
-      )
-    },
-    // 复制链接按钮是否显示
-    copyLinkBtnShow() {
-      return this.routeName === 'MyShare'
-    }
-  },
-  watch: {
-    /**
-     * 文件路径变化时清空表格已选行
-     */
-    filePath() {
-      this.clearSelectedTable()
-      this.$refs.multipleTable.clearSort()
-    },
-    /**
-     * 文件类型变化时清空表格已选行
-     */
-    fileType() {
-      this.clearSelectedTable()
-      this.$refs.multipleTable.clearSort()
-    },
-    /**
-     * 文件列表变化时清空表格已选行
-     */
-    fileList() {
-      this.clearSelectedTable()
-      this.$refs.multipleTable.clearSort()
-      this.sortedFileList = this.fileList
-    },
-    /**
-     * 监听右键列表状态
-     * @description 右键列表打开时,body 添加点击事件的监听
-     */
-    'rightMenu.isShow'(newValue) {
-      if (newValue) {
-        document.body.addEventListener('click', this.closeRightMenu)
-      } else {
-        document.body.removeEventListener('click', this.closeRightMenu)
-      }
-    }
-  },
-  methods: {
-    /**
-     * 当表格的排序条件发生变化的时候会触发该事件
-     */
-    handleSortChange() {
-      this.sortedFileList = this.$refs.multipleTable.tableData
-    },
-    /**
-     * 表格某一行右键事件
-     */
-    handleContextMenu(row, column, event) {
-      event.preventDefault()
-      this.$refs.multipleTable.setCurrentRow(row)
-      this.selectedFile = row
-      // 纵坐标设置
-      if (
-        document.body.clientHeight - event.clientY <
-        document.querySelectorAll('#rightMenuList > .right-menu-item').length * 36 + 10
-      ) {
-        // 如果到底部的距离小于元素总高度
-        this.rightMenu.top = 'auto'
-        this.rightMenu.bottom = `${document.body.clientHeight - event.clientY}px`
-        this.unzipMenu.top = 'auto'
-        this.unzipMenu.bottom = '0px'
-      } else {
-        this.rightMenu.top = `${event.clientY}px`
-        this.rightMenu.bottom = 'auto'
-        this.unzipMenu.top = '0px'
-        this.unzipMenu.bottom = 'auto'
-      }
-      // 横坐标设置
-      if (document.body.clientWidth - event.clientX < 138) {
-        // 如果到右边的距离小于元素总宽度
-        this.rightMenu.left = 'auto'
-        this.rightMenu.right = `${document.body.clientWidth - event.clientX}px`
-        this.unzipMenu.left = '-200px'
-        this.unzipMenu.right = 'auto'
-      } else {
-        this.rightMenu.left = `${event.clientX + 8}px`
-        this.rightMenu.right = 'auto'
-        this.unzipMenu.left = '138px'
-        this.unzipMenu.right = 'auto'
-      }
-      this.rightMenu.isShow = true
-    },
-    /**
-     * 关闭右键列表
-     */
-    closeRightMenu() {
-      this.rightMenu.isShow = false
-      this.$refs.multipleTable.setCurrentRow()
-    },
-    /**
-     * 清空表格已选行
-     * @description 用于父组件调用 | 本组件调用,请勿删除
-     */
-    clearSelectedTable() {
-      this.$refs.multipleTable.clearSelection()
-      this.$emit('setSelectionFile', [])
-    },
-    /**
-     * 根据文件扩展名设置文件图片
-     * @param {object} row 文件信息
-     */
-    setFileImg(row) {
-      if (row.isDir === 1) {
-        //  文件夹
-        return this.fileImgMap.dir
-      } else if (!this.fileImgTypeList.includes(row.extendName)) {
-        //  无法识别文件类型的文件
-        return this.fileImgMap.unknown
-      } else if (this.fileType !== 6 && ['jpg', 'png', 'jpeg', 'gif', 'mp4'].includes(row.extendName)) {
-        // 图片类型,直接显示缩略图
-        return this.getImgMinPath(row)
-      } else {
-        //  可以识别文件类型的文件
-        return this.fileImgMap[row.extendName]
-      }
-    },
-    /**
-     * 获取文件分享过期状态
-     */
-    getFileShareStatus(time) {
-      if (new Date(time).getTime() > new Date().getTime()) {
-        return false
-      } else {
-        return true
-      }
-    },
-    /**
-     * 文件名点击事件
-     * @description 若当前点击的为文件夹,则进入文件夹内部;若是文件,则进行相应的预览。
-     * @param {object} row 文件信息
-     */
-    handleFileNameClick(row, activeIndex) {
-      // 若是目录则进入目录
-      if (row.isDir) {
-        if (this.routeName === 'Share') {
-          // 当前是查看他人分享列表的页面
-          this.$router.push({
-            query: {
-              filePath: row.shareFilePath + row.fileName + '/'
-            }
-          })
-        } else if (this.routeName === 'MyShare') {
-          // 当前是我的已分享列表页面
-          this.$router.push({
-            query: {
-              filePath: row.shareFilePath + row.fileName + '/',
-              shareBatchNum: row.shareBatchNum
-            }
-          })
-        } else {
-          // 网盘页面
-          this.$router.push({
-            query: {
-              filePath: row.filePath + row.fileName + '/',
-              fileType: 0
-            }
-          })
-        }
-      }
-      // 若是文件,则进行相应的预览
-      else {
-        // 若当前点击项是图片
-        const PIC = ['png', 'jpg', 'jpeg', 'gif', 'svg']
-        if (PIC.includes(row.extendName)) {
-          if (this.fileType === 1) {
-            //  图片分类下 - 大图查看
-            let data = {
-              imgPreviewVisible: true,
-              imgPreviewList: this.sortedFileList.map((item) => {
-                return {
-                  fileUrl: this.getViewFilePath(item),
-                  downloadLink: this.getDownloadFilePath(item),
-                  fileName: item.fileName,
-                  extendName: item.extendName
-                }
-              }),
-              activeIndex: activeIndex
-            }
-            this.$store.commit('setImgPreviewData', data)
-          } else {
-            //  非图片分类下 - 大图查看
-            let data = {
-              imgPreviewVisible: true,
-              imgPreviewList: [
-                {
-                  fileUrl: this.getViewFilePath(row),
-                  downloadLink: this.getDownloadFilePath(row),
-                  fileName: row.fileName,
-                  extendName: row.extendName
-                }
-              ],
-              activeIndex: 0
-            }
-            this.$store.commit('setImgPreviewData', data)
-          }
-        }
-        //  若当前点击项是可以使用office在线预览的
-        if ([...this.officeFileType, 'pdf'].includes(row.extendName)) {
-          this.getFileOnlineViewPathByOffice(row)
-        }
-        //  若当前点击项是代码或文本文件
-        const CODE = ['html', 'js', 'css', 'json', 'c', 'java', 'txt']
-        if (CODE.includes(row.extendName)) {
-          window.open(this.getViewFilePath(row), '_blank')
-        }
-        //  若当前点击项是视频mp4格式
-        const VIDEO = ['mp4']
-        if (VIDEO.includes(row.extendName)) {
-          if (this.fileType === 3) {
-            // 视频分类下 加载播放列表
-            let data = {
-              videoPreviewVisible: true,
-              videoPreviewList: this.sortedFileList.map((item) => {
-                return {
-                  ...item,
-                  fileUrl: this.getViewFilePath(item),
-                  downloadLink: this.getDownloadFilePath(item),
-                  fileName: item.fileName,
-                  extendName: item.extendName
-                }
-              }),
-              activeIndex: activeIndex
-            }
-            this.$store.commit('setVideoPreviewData', data)
-          } else {
-            // 非视频分类下 - 单个视频预览
-            let data = {
-              videoPreviewVisible: true,
-              videoPreviewList: [
-                {
-                  ...row,
-                  fileUrl: this.getViewFilePath(row),
-                  downloadLink: this.getDownloadFilePath(row),
-                  fileName: row.fileName,
-                  extendName: row.extendName
-                }
-              ],
-              activeIndex: 0
-            }
-            this.$store.commit('setVideoPreviewData', data)
-          }
-        }
-        //  若当前点击项是音频mp3格式
-        const AUDIO = ['mp3']
-        if (AUDIO.includes(row.extendName)) {
-          if (this.audioObj.src !== this.getViewFilePath(row)) {
-            this.$notify.closeAll()
-            this.audioObj.src = this.getViewFilePath(row)
-            this.$notify({
-              title: `${row.fileName}.${row.extendName}`,
-              dangerouslyUseHTMLString: true,
-              message: `<audio class="audio-preview" src="${
-                this.audioObj.src
-              }" controls autoplay style="padding-right: 16px; margin-top: 16px;"></audio>`,
-              duration: 0, //  不自动关闭
-              offset: 100,
-              onClose: () => {
-                this.audioObj.src = ''
-              }
-            })
-          }
-        }
-      }
-    },
-    /**
-     * 表格选择项发生变化时的回调函数
-     * @param {[]} selection 勾选的行数据
-     */
-    handleSelectRow(selection) {
-      this.$emit('setSelectionFile', selection, selection.length !== 0)
-    },
-    /**
-     * 移动按钮点击事件
-     * @description 向父组件传递当前操作的文件信息,并打开“移动文件对话框”
-     * @param {object} fileInfo 文件信息
-     */
-    handleMoveFileBtnClick(fileInfo) {
-      this.$emit('setOperationFile', fileInfo)
-      //  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件对话框
-      this.$emit('setMoveFileDialogData', false, true)
-    },
-    /**
-     * 解压缩按钮点击事件
-     * @description 调用解压缩文件接口,并展示新的文件列表
-     * @param {object} fileInfo 文件信息
-     * @param {number} unzipMode 解压模式 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 2-手动选择解压目录
-     */
-    handleUnzipFileBtnClick(fileInfo, unzipMode) {
-      if(unzipMode === 0 || unzipMode === 1) {
-        const loading = this.$loading({
-          lock: true,
-          text: '正在解压缩,请稍等片刻...',
-          spinner: 'el-icon-loading',
-          background: 'rgba(0, 0, 0, 0.7)'
-        })
-        unzipFile({
-          unzipMode: unzipMode,
-          userFileId: fileInfo.userFileId
-        }).then((res) => {
-          if (res.success) {
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-            this.$message.success('解压成功')
-            loading.close()
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      } else if(unzipMode === 2) {
-        this.$emit('setOperationFile', fileInfo)
-        //  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件对话框
-        this.$emit('setMoveFileDialogData', false, true)
-      }
-    },
+	name: 'FileTable',
+	props: {
+		// 文件类型
+		fileType: {
+			required: true,
+			type: Number
+		},
+		// 文件路径
+		filePath: {
+			required: true,
+			type: String
+		},
+		// 文件列表
+		fileList: {
+			required: true,
+			type: Array
+		},
+		// 文件加载状态
+		loading: {
+			required: true,
+			type: Boolean
+		}
+	},
+	data() {
+		return {
+			//  可以识别的文件类型
+			fileImgTypeList: [
+				'png',
+				'jpg',
+				'jpeg',
+				'docx',
+				'doc',
+				'ppt',
+				'pptx',
+				'xls',
+				'xlsx',
+				'avi',
+				'mp4',
+				'css',
+				'csv',
+				'chm',
+				'rar',
+				'zip',
+				'dmg',
+				'mp3',
+				'open',
+				'pdf',
+				'rtf',
+				'txt',
+				'oa',
+				'js',
+				'html',
+				'img',
+				'sql',
+				'jar',
+				'svg',
+				'gif',
+				'json',
+				'exe'
+			],
+			//  文件图片Map映射
+			fileImgMap: {
+				dir: require('_a/images/file/dir.png'),
+				chm: require('_a/images/file/file_chm.png'),
+				css: require('_a/images/file/file_css.png'),
+				csv: require('_a/images/file/file_csv.png'),
+				png: require('_a/images/file/file_pic.png'),
+				jpg: require('_a/images/file/file_pic.png'),
+				jpeg: require('_a/images/file/file_pic.png'),
+				docx: require('_a/images/file/file_word.png'),
+				doc: require('_a/images/file/file_word.png'),
+				ppt: require('_a/images/file/file_ppt.png'),
+				pptx: require('_a/images/file/file_ppt.png'),
+				xls: require('_a/images/file/file_excel.png'),
+				xlsx: require('_a/images/file/file_excel.png'),
+				mp4: require('_a/images/file/file_video.png'),
+				avi: require('_a/images/file/file_avi.png'),
+				rar: require('_a/images/file/file_rar.png'),
+				zip: require('_a/images/file/file_zip.png'),
+				dmg: require('_a/images/file/file_dmg.png'),
+				mp3: require('_a/images/file/file_music.png'),
+				open: require('_a/images/file/file_open.png'),
+				pdf: require('_a/images/file/file_pdf.png'),
+				rtf: require('_a/images/file/file_rtf.png'),
+				txt: require('_a/images/file/file_txt.png'),
+				oa: require('_a/images/file/file_oa.png'),
+				unknown: require('_a/images/file/file_unknown.png'),
+				js: require('_a/images/file/file_js.png'),
+				html: require('_a/images/file/file_html.png'),
+				img: require('_a/images/file/file_img.png'),
+				sql: require('_a/images/file/file_sql.png'),
+				jar: require('_a/images/file/file_jar.png'),
+				svg: require('_a/images/file/file_svg.png'),
+				gif: require('_a/images/file/file_gif.png'),
+				json: require('_a/images/file/file_json.png'),
+				exe: require('_a/images/file/file_exe.png')
+			},
+			officeFileType: ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx'],
+			downloadFilePath: '',
+			viewFilePath: '',
+			// 音频预览
+			audioObj: {
+				src: ''
+			},
+			sortedFileList: [], //  排序后的表格数据
+			// 右键菜单
+			rightMenu: {
+				isShow: false,
+				top: 0,
+				left: 0,
+				bottom: 'auto',
+				right: 'auto'
+			},
+			// 右键解压缩菜单
+			unzipMenu: {
+				top: 0,
+				bottom: 'auto',
+				left: '138px',
+				right: 'auto'
+			},
+			selectedFile: {} //  右键选中的表格行数据
+		}
+	},
+	computed: {
+		//  selectedColumnList: 判断当前用户设置的左侧栏是否折叠
+		...mapGetters(['selectedColumnList']),
+		//  判断当前路径下是否有普通文件
+		isIncludeNormalFile() {
+			return this.fileList.map((data) => data.isDir).includes(0)
+		},
+		//  判断当前路径下是否有压缩文件
+		isIncludeZipRarFile() {
+			return (
+				this.fileList.map((data) => data.extendName).includes('zip') ||
+				this.fileList.map((data) => data.extendName).includes('rar')
+			)
+		},
+		// 路由名称
+		routeName() {
+			return this.$route.name
+		},
+		// 查看按钮是否显示
+		seeBtnShow() {
+			return this.fileType !== 6
+		},
+		// 删除按钮是否显示
+		deleteBtnShow() {
+			return !['Share', 'MyShare'].includes(this.routeName)
+		},
+		// 还原按钮是否显示
+		restoreBtnShow() {
+			return (
+				this.fileType === 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 移动按钮是否显示
+		moveBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 重命名按钮是否显示
+		renameBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 删除按钮是否显示
+		shareBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 下载按钮是否显示
+		downloadBtnShow() {
+			return this.fileType !== 6 && !['MyShare'].includes(this.routeName)
+		},
+		// 解压缩按钮是否显示
+		unzipBtnShow() {
+			return (
+				this.fileType !== 6 &&
+				!['Share', 'MyShare'].includes(this.routeName) &&
+				['zip', 'rar'].includes(this.selectedFile.extendName)
+			)
+		},
+		// 在线编辑按钮是否显示
+		onlineEditBtnShow() {
+			return (
+				this.fileType !== 6 &&
+				this.officeFileType.includes(this.selectedFile.extendName) &&
+				!['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 复制链接按钮是否显示
+		copyLinkBtnShow() {
+			return this.routeName === 'MyShare'
+		}
+	},
+	watch: {
+		/**
+		 * 文件路径变化时清空表格已选行
+		 */
+		filePath() {
+			this.clearSelectedTable()
+			this.$refs.multipleTable.clearSort()
+		},
+		/**
+		 * 文件类型变化时清空表格已选行
+		 */
+		fileType() {
+			this.clearSelectedTable()
+			this.$refs.multipleTable.clearSort()
+		},
+		/**
+		 * 文件列表变化时清空表格已选行
+		 */
+		fileList() {
+			this.clearSelectedTable()
+			this.$refs.multipleTable.clearSort()
+			this.sortedFileList = this.fileList
+		},
+		/**
+		 * 监听右键列表状态
+		 * @description 右键列表打开时,body 添加点击事件的监听
+		 */
+		'rightMenu.isShow'(newValue) {
+			if (newValue) {
+				document.body.addEventListener('click', this.closeRightMenu)
+			} else {
+				document.body.removeEventListener('click', this.closeRightMenu)
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 当表格的排序条件发生变化的时候会触发该事件
+		 */
+		handleSortChange() {
+			this.sortedFileList = this.$refs.multipleTable.tableData
+		},
+		/**
+		 * 表格某一行右键事件
+		 */
+		handleContextMenu(row, column, event) {
+			event.preventDefault()
+			this.$refs.multipleTable.setCurrentRow(row)
+			this.selectedFile = row
+			// 纵坐标设置
+			if (
+				document.body.clientHeight - event.clientY <
+				document.querySelectorAll('#rightMenuList > .right-menu-item').length *
+					36 +
+					10
+			) {
+				// 如果到底部的距离小于元素总高度
+				this.rightMenu.top = 'auto'
+				this.rightMenu.bottom = `${
+					document.body.clientHeight - event.clientY
+				}px`
+				this.unzipMenu.top = 'auto'
+				this.unzipMenu.bottom = '0px'
+			} else {
+				this.rightMenu.top = `${event.clientY}px`
+				this.rightMenu.bottom = 'auto'
+				this.unzipMenu.top = '0px'
+				this.unzipMenu.bottom = 'auto'
+			}
+			// 横坐标设置
+			if (document.body.clientWidth - event.clientX < 138) {
+				// 如果到右边的距离小于元素总宽度
+				this.rightMenu.left = 'auto'
+				this.rightMenu.right = `${document.body.clientWidth - event.clientX}px`
+				this.unzipMenu.left = '-200px'
+				this.unzipMenu.right = 'auto'
+			} else {
+				this.rightMenu.left = `${event.clientX + 8}px`
+				this.rightMenu.right = 'auto'
+				this.unzipMenu.left = '138px'
+				this.unzipMenu.right = 'auto'
+			}
+			this.rightMenu.isShow = true
+		},
+		/**
+		 * 关闭右键列表
+		 */
+		closeRightMenu() {
+			this.rightMenu.isShow = false
+			this.$refs.multipleTable.setCurrentRow()
+		},
+		/**
+		 * 清空表格已选行
+		 * @description 用于父组件调用 | 本组件调用,请勿删除
+		 */
+		clearSelectedTable() {
+			this.$refs.multipleTable.clearSelection()
+			this.$emit('setSelectionFile', [])
+		},
+		/**
+		 * 根据文件扩展名设置文件图片
+		 * @param {object} row 文件信息
+		 */
+		setFileImg(row) {
+			if (row.isDir === 1) {
+				//  文件夹
+				return this.fileImgMap.dir
+			} else if (!this.fileImgTypeList.includes(row.extendName)) {
+				//  无法识别文件类型的文件
+				return this.fileImgMap.unknown
+			} else if (
+				this.fileType !== 6 &&
+				['jpg', 'png', 'jpeg', 'gif', 'mp4'].includes(row.extendName)
+			) {
+				// 图片类型,直接显示缩略图
+				return this.getImgMinPath(row)
+			} else {
+				//  可以识别文件类型的文件
+				return this.fileImgMap[row.extendName]
+			}
+		},
+		/**
+		 * 获取文件分享过期状态
+		 */
+		getFileShareStatus(time) {
+			if (new Date(time).getTime() > new Date().getTime()) {
+				return false
+			} else {
+				return true
+			}
+		},
+		/**
+		 * 文件名点击事件
+		 * @description 若当前点击的为文件夹,则进入文件夹内部;若是文件,则进行相应的预览。
+		 * @param {object} row 文件信息
+		 */
+		handleFileNameClick(row, activeIndex) {
+			// 若是目录则进入目录
+			if (row.isDir) {
+				if (this.routeName === 'Share') {
+					// 当前是查看他人分享列表的页面
+					this.$router.push({
+						query: {
+							filePath: row.shareFilePath + row.fileName + '/'
+						}
+					})
+				} else if (this.routeName === 'MyShare') {
+					// 当前是我的已分享列表页面
+					this.$router.push({
+						query: {
+							filePath: row.shareFilePath + row.fileName + '/',
+							shareBatchNum: row.shareBatchNum
+						}
+					})
+				} else {
+					// 网盘页面
+					this.$router.push({
+						query: {
+							filePath: row.filePath + row.fileName + '/',
+							fileType: 0
+						}
+					})
+				}
+			}
+			// 若是文件,则进行相应的预览
+			else {
+				// 若当前点击项是图片
+				const PIC = ['png', 'jpg', 'jpeg', 'gif', 'svg']
+				if (PIC.includes(row.extendName)) {
+					if (this.fileType === 1) {
+						//  图片分类下 - 大图查看
+						let data = {
+							imgPreviewVisible: true,
+							imgPreviewList: this.sortedFileList.map((item) => {
+								return {
+									fileUrl: this.getViewFilePath(item),
+									downloadLink: this.getDownloadFilePath(item),
+									fileName: item.fileName,
+									extendName: item.extendName
+								}
+							}),
+							activeIndex: activeIndex
+						}
+						this.$store.commit('setImgPreviewData', data)
+					} else {
+						//  非图片分类下 - 大图查看
+						let data = {
+							imgPreviewVisible: true,
+							imgPreviewList: [
+								{
+									fileUrl: this.getViewFilePath(row),
+									downloadLink: this.getDownloadFilePath(row),
+									fileName: row.fileName,
+									extendName: row.extendName
+								}
+							],
+							activeIndex: 0
+						}
+						this.$store.commit('setImgPreviewData', data)
+					}
+				}
+				//  若当前点击项是可以使用office在线预览的
+				if ([...this.officeFileType, 'pdf'].includes(row.extendName)) {
+					this.getFileOnlineViewPathByOffice(row)
+				}
+				//  若当前点击项是代码或文本文件
+				const CODE = ['html', 'js', 'css', 'json', 'c', 'java', 'txt']
+				if (CODE.includes(row.extendName)) {
+					window.open(this.getViewFilePath(row), '_blank')
+				}
+				//  若当前点击项是视频mp4格式
+				const VIDEO = ['mp4']
+				if (VIDEO.includes(row.extendName)) {
+					if (this.fileType === 3) {
+						// 视频分类下 加载播放列表
+						let data = {
+							videoPreviewVisible: true,
+							videoPreviewList: this.sortedFileList.map((item) => {
+								return {
+									...item,
+									fileUrl: this.getViewFilePath(item),
+									downloadLink: this.getDownloadFilePath(item),
+									fileName: item.fileName,
+									extendName: item.extendName
+								}
+							}),
+							activeIndex: activeIndex
+						}
+						this.$store.commit('setVideoPreviewData', data)
+					} else {
+						// 非视频分类下 - 单个视频预览
+						let data = {
+							videoPreviewVisible: true,
+							videoPreviewList: [
+								{
+									...row,
+									fileUrl: this.getViewFilePath(row),
+									downloadLink: this.getDownloadFilePath(row),
+									fileName: row.fileName,
+									extendName: row.extendName
+								}
+							],
+							activeIndex: 0
+						}
+						this.$store.commit('setVideoPreviewData', data)
+					}
+				}
+				//  若当前点击项是音频mp3格式
+				const AUDIO = ['mp3']
+				if (AUDIO.includes(row.extendName)) {
+					if (this.audioObj.src !== this.getViewFilePath(row)) {
+						this.$notify.closeAll()
+						this.audioObj.src = this.getViewFilePath(row)
+						this.$notify({
+							title: `${row.fileName}.${row.extendName}`,
+							dangerouslyUseHTMLString: true,
+							message: `<audio class="audio-preview" src="${this.audioObj.src}" controls autoplay style="padding-right: 16px; margin-top: 16px;"></audio>`,
+							duration: 0, //  不自动关闭
+							offset: 100,
+							onClose: () => {
+								this.audioObj.src = ''
+							}
+						})
+					}
+				}
+			}
+		},
+		/**
+		 * 表格选择项发生变化时的回调函数
+		 * @param {[]} selection 勾选的行数据
+		 */
+		handleSelectRow(selection) {
+			this.$emit('setSelectionFile', selection, selection.length !== 0)
+		},
+		/**
+		 * 移动按钮点击事件
+		 * @description 向父组件传递当前操作的文件信息,并打开“移动文件对话框”
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleMoveFileBtnClick(fileInfo) {
+			this.$emit('setOperationFile', fileInfo)
+			//  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件对话框
+			this.$emit('setMoveFileDialogData', false, true)
+		},
+		/**
+		 * 解压缩按钮点击事件
+		 * @description 调用解压缩文件接口,并展示新的文件列表
+		 * @param {object} fileInfo 文件信息
+		 * @param {number} unzipMode 解压模式 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 2-手动选择解压目录
+		 */
+		handleUnzipFileBtnClick(fileInfo, unzipMode) {
+			if (unzipMode === 0 || unzipMode === 1) {
+				const loading = this.$loading({
+					lock: true,
+					text: '正在解压缩,请稍等片刻...',
+					spinner: 'el-icon-loading',
+					background: 'rgba(0, 0, 0, 0.7)'
+				})
+				unzipFile({
+					unzipMode: unzipMode,
+					userFileId: fileInfo.userFileId
+				}).then((res) => {
+					if (res.success) {
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+						this.$message.success('解压成功')
+						loading.close()
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			} else if (unzipMode === 2) {
+				this.$emit('setOperationFile', fileInfo)
+				//  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件对话框
+				this.$emit('setMoveFileDialogData', false, true)
+			}
+		},
 
-    /**
-     * 删除按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
-     * @param {object} fileInfo 文件信息
-     */
-    handleDeleteFileBtnClick(fileInfo) {
-      if (this.fileType === 6) {
-        //  回收站里 - 彻底删除
-        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmDeleteFile(fileInfo, true)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      } else {
-        //  非回收站
-        this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmDeleteFile(fileInfo, false)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      }
-    },
-    /**
-     * 删除文件确认对话框 | 确定按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
-     * @param {object} fileInfo 文件信息
-     * @param {boolean} type 文件类型,true 彻底删除;false 删除到回收站
-     */
-    confirmDeleteFile(fileInfo, type) {
-      if (type) {
-        //  回收站中删除
-        deleteRecoveryFile({
-          recoveryFileId: fileInfo.recoveryFileId
-        }).then((res) => {
-          if (res.success) {
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-            this.$message.success('删除成功')
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      } else {
-        //  非回收站删除
-        deleteFile(fileInfo).then((res) => {
-          if (res.success) {
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-            this.$message.success('删除成功')
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      }
-    },
-    /**
-     * 还原按钮点击事件
-     * @description 调用接口,在回收站中还原文件
-     * @param {object} fileInfo 文件信息
-     */
-    handleRestoreFileBtnClick(fileInfo) {
-      restoreRecoveryFile({
-        deleteBatchNum: fileInfo.deleteBatchNum,
-        filePath: fileInfo.filePath
-      }).then((res) => {
-        if (res.success) {
-          this.$emit('getTableDataByType')
-          this.$store.dispatch('showStorage')
-          this.$message.success('已还原')
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 文件重命名按钮点击事件
-     * @description 打开确认对话框让用户输入新的文件名
-     * @param {object} fileInfo 文件信息
-     */
-    handleRenameFileBtnClick(fileInfo) {
-      var fileName = fileInfo.fileName
-      this.$prompt('请输入文件名', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        inputValue: fileName,
-        inputPattern: /\S/, //  文件名不能为空
-        inputErrorMessage: '请输入文件名',
-        closeOnClickModal: false
-      })
-        .then(({ value }) => {
-          fileInfo.oldFileName = fileInfo.fileName
-          fileInfo.fileName = value
-          this.confirmRenameFile(fileInfo)
-        })
-        .catch(() => {
-          this.$message({
-            type: 'info',
-            message: '取消输入'
-          })
-        })
-    },
-    /**
-     * 文件重命名对话框 | 确定按钮点击事件
-     * @description 调用文件重命名接口
-     * @param {object} fileInfo 文件信息
-     */
-    confirmRenameFile(fileInfo) {
-      renameFile(fileInfo).then((res) => {
-        if (res.success) {
-          this.$emit('getTableDataByType')
-          this.$store.dispatch('showStorage')
-          this.$message.success('重命名成功')
-        } else {
-          fileInfo.fileName = fileInfo.oldFileName
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 文件分享按钮点击事件
-     * @description 打开对话框让用户选择过期时间和提取码
-     * @param {object} fileInfo 文件信息
-     */
-    handleShareFileBtnClick(fileInfo) {
-      this.$emit('setSelectionFile', [fileInfo])
-      this.$emit('setShareFileDialogData')
-    }
-  }
+		/**
+		 * 删除按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleDeleteFileBtnClick(fileInfo) {
+			if (this.fileType === 6) {
+				//  回收站里 - 彻底删除
+				this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmDeleteFile(fileInfo, true)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			} else {
+				//  非回收站
+				this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmDeleteFile(fileInfo, false)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			}
+		},
+		/**
+		 * 删除文件确认对话框 | 确定按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
+		 * @param {object} fileInfo 文件信息
+		 * @param {boolean} type 文件类型,true 彻底删除;false 删除到回收站
+		 */
+		confirmDeleteFile(fileInfo, type) {
+			if (type) {
+				//  回收站中删除
+				deleteRecoveryFile({
+					recoveryFileId: fileInfo.recoveryFileId
+				}).then((res) => {
+					if (res.success) {
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+						this.$message.success('删除成功')
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			} else {
+				//  非回收站删除
+				deleteFile(fileInfo).then((res) => {
+					if (res.success) {
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+						this.$message.success('删除成功')
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			}
+		},
+		/**
+		 * 还原按钮点击事件
+		 * @description 调用接口,在回收站中还原文件
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleRestoreFileBtnClick(fileInfo) {
+			restoreRecoveryFile({
+				deleteBatchNum: fileInfo.deleteBatchNum,
+				filePath: fileInfo.filePath
+			}).then((res) => {
+				if (res.success) {
+					this.$emit('getTableDataByType')
+					this.$store.dispatch('showStorage')
+					this.$message.success('已还原')
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 文件重命名按钮点击事件
+		 * @description 打开确认对话框让用户输入新的文件名
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleRenameFileBtnClick(fileInfo) {
+			var fileName = fileInfo.fileName
+			this.$prompt('请输入文件名', '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputValue: fileName,
+				inputPattern: /\S/, //  文件名不能为空
+				inputErrorMessage: '请输入文件名',
+				closeOnClickModal: false
+			})
+				.then(({ value }) => {
+					fileInfo.oldFileName = fileInfo.fileName
+					fileInfo.fileName = value
+					this.confirmRenameFile(fileInfo)
+				})
+				.catch(() => {
+					this.$message({
+						type: 'info',
+						message: '取消输入'
+					})
+				})
+		},
+		/**
+		 * 文件重命名对话框 | 确定按钮点击事件
+		 * @description 调用文件重命名接口
+		 * @param {object} fileInfo 文件信息
+		 */
+		confirmRenameFile(fileInfo) {
+			renameFile(fileInfo).then((res) => {
+				if (res.success) {
+					this.$emit('getTableDataByType')
+					this.$store.dispatch('showStorage')
+					this.$message.success('重命名成功')
+				} else {
+					fileInfo.fileName = fileInfo.oldFileName
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 文件分享按钮点击事件
+		 * @description 打开对话框让用户选择过期时间和提取码
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleShareFileBtnClick(fileInfo) {
+			this.$emit('setSelectionFile', [fileInfo])
+			this.$emit('setShareFileDialogData')
+		}
+	}
 }
 </script>
 

+ 119 - 101
src/components/File/MoveFileDialog.vue

@@ -1,43 +1,61 @@
 <template>
-  <div class="move-dialog-wrapper">
-    <!-- 移动文件-选择目标路径 -->
-    <el-dialog title="选择目标路径" :visible.sync="dialogData.visible" @open="handleDialogOpen">
-      <div class="el-dialog-div">
-        <!-- 选择的目标路径 -->
-        <div class="target-path">
-          <span class="label">目标路径:</span>
-          <el-input class="content" v-model="targetPath" readonly size="small"></el-input>
-        </div>
-        <!-- 文件目录树 -->
-        <el-tree
-          :data="fileTree"
-          :props="defaultProps"
-          :highlight-current="true"
-          :expand-on-click-node="false"
-          :default-expanded-keys="defaultExpandedKeys"
-          node-key="id"
-          @node-click="handleNodeClick"
-        >
-          <span class="custom-tree-node" slot-scope="{ node, data }">
-            <span class="label">{{ node.label }}</span>
-            <el-button class="add-folder-btn" type="text" size="mini" @click.stop="handleAddFolderBtnClick(data)">
-              新建文件夹
-            </el-button>
-          </span>
-        </el-tree>
-      </div>
-      <div slot="footer" class="dialog-footer">
-        <el-button @click="$emit('setDialogData', null, false)">取 消</el-button>
-        <el-button type="primary" @click="$emit('confirmDialog')">确 定</el-button>
-      </div>
-    </el-dialog>
-    <!-- 新建文件夹对话框 -->
-    <AddFolderDialog
-      :visible.sync="dialogAddFolder.visible"
-      :filePath="dialogAddFolder.filePath"
-      @confirmDialog="initFileTree(dialogAddFolder.id)"
-    ></AddFolderDialog>
-  </div>
+	<div class="move-dialog-wrapper">
+		<!-- 移动文件-选择目标路径 -->
+		<el-dialog
+			title="选择目标路径"
+			:visible.sync="dialogData.visible"
+			@open="handleDialogOpen"
+		>
+			<div class="el-dialog-div">
+				<!-- 选择的目标路径 -->
+				<div class="target-path">
+					<span class="label">目标路径:</span>
+					<el-input
+						class="content"
+						v-model="targetPath"
+						readonly
+						size="small"
+					></el-input>
+				</div>
+				<!-- 文件目录树 -->
+				<el-tree
+					:data="fileTree"
+					:props="defaultProps"
+					:highlight-current="true"
+					:expand-on-click-node="false"
+					:default-expanded-keys="defaultExpandedKeys"
+					node-key="id"
+					@node-click="handleNodeClick"
+				>
+					<span class="custom-tree-node" slot-scope="{ node, data }">
+						<span class="label">{{ node.label }}</span>
+						<el-button
+							class="add-folder-btn"
+							type="text"
+							size="mini"
+							@click.stop="handleAddFolderBtnClick(data)"
+						>
+							新建文件夹
+						</el-button>
+					</span>
+				</el-tree>
+			</div>
+			<div slot="footer" class="dialog-footer">
+				<el-button @click="$emit('setDialogData', null, false)"
+					>取 消</el-button
+				>
+				<el-button type="primary" @click="$emit('confirmDialog')"
+					>确 定</el-button
+				>
+			</div>
+		</el-dialog>
+		<!-- 新建文件夹对话框 -->
+		<AddFolderDialog
+			:visible.sync="dialogAddFolder.visible"
+			:filePath="dialogAddFolder.filePath"
+			@confirmDialog="initFileTree(dialogAddFolder.id)"
+		></AddFolderDialog>
+	</div>
 </template>
 
 <script>
@@ -45,68 +63,68 @@ import AddFolderDialog from '_c/File/AddFolderDialog.vue'
 import { getFoldTree } from '_r/file.js'
 
 export default {
-  name: 'MoveFileDialog',
-  props: {
-    dialogData: Object
-  },
-  components: {
-    AddFolderDialog
-  },
-  data() {
-    return {
-      targetPath: '/', //  目标路径
-      defaultProps: {
-        children: 'children',
-        label: 'label'
-      },
-      fileTree: [], //  文件夹目录树
-      defaultExpandedKeys: [],
-      // 新建文件夹对话框数据
-      dialogAddFolder: {
-        visible: false,
-        filePath: '/', //  新增文件夹的父级路径
-        id: -1
-      }
-    }
-  },
-  methods: {
-    /**
-     * 对话框打开的回调
-     */
-    handleDialogOpen() {
-      this.initFileTree()
-    },
-    /**
-     * 初始化文件目录树
-     */
-    initFileTree(id) {
-      getFoldTree().then((res) => {
-        if (res.success) {
-          this.fileTree = [res.data]
-          this.defaultExpandedKeys = id ? [id] : [this.fileTree[0].id]
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 目录树节点点击回调函数
-     * @description 将当前节点中的文件夹路径传递给父组件
-     * @param {object} data 当前点击的节点信息
-     */
-    handleNodeClick(data) {
-      this.targetPath = data.filePath ? data.filePath : '/'
-      this.$emit('setSelectFilePath', this.targetPath)
-    },
-    /**
-     * 新建文件夹按钮点击事件
-     */
-    handleAddFolderBtnClick(data) {
-      this.dialogAddFolder.filePath = data.filePath ? data.filePath : '/'
-      this.dialogAddFolder.id = data.id
-      this.dialogAddFolder.visible = true
-    }
-  }
+	name: 'MoveFileDialog',
+	props: {
+		dialogData: Object
+	},
+	components: {
+		AddFolderDialog
+	},
+	data() {
+		return {
+			targetPath: '/', //  目标路径
+			defaultProps: {
+				children: 'children',
+				label: 'label'
+			},
+			fileTree: [], //  文件夹目录树
+			defaultExpandedKeys: [],
+			// 新建文件夹对话框数据
+			dialogAddFolder: {
+				visible: false,
+				filePath: '/', //  新增文件夹的父级路径
+				id: -1
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 对话框打开的回调
+		 */
+		handleDialogOpen() {
+			this.initFileTree()
+		},
+		/**
+		 * 初始化文件目录树
+		 */
+		initFileTree(id) {
+			getFoldTree().then((res) => {
+				if (res.success) {
+					this.fileTree = [res.data]
+					this.defaultExpandedKeys = id ? [id] : [this.fileTree[0].id]
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 目录树节点点击回调函数
+		 * @description 将当前节点中的文件夹路径传递给父组件
+		 * @param {object} data 当前点击的节点信息
+		 */
+		handleNodeClick(data) {
+			this.targetPath = data.filePath ? data.filePath : '/'
+			this.$emit('setSelectFilePath', this.targetPath)
+		},
+		/**
+		 * 新建文件夹按钮点击事件
+		 */
+		handleAddFolderBtnClick(data) {
+			this.dialogAddFolder.filePath = data.filePath ? data.filePath : '/'
+			this.dialogAddFolder.id = data.id
+			this.dialogAddFolder.visible = true
+		}
+	}
 }
 </script>
 

+ 70 - 53
src/components/Footer.vue

@@ -1,61 +1,78 @@
 <template>
-  <div class="footer-wrapper">
-    <div class="copy-right-wrapper">
-      <img class="logo" :src="logoUrl" :alt="$store.getters.imgAlt + 'footerLogo'" />
-      <div class="copy-right">
-        <span>奇文共赏 2020 版权所有</span>
-        <span class="split">|</span>
-        <span
-          ><a class="link" style="color: white" href="http://beian.miit.gov.cn/" target="_blank">陕ICP备19020251号</a
-          >&nbsp;</span
-        >
-        <p class="tip-website">
-          为获得最佳浏览体验,建议使用IE11、FireFox50.5、Chrome51.0及以上版本的浏览器
-        </p>
-      </div>
-    </div>
-    <div class="join-us">
-      <div class="desc">如果你也是对技术感兴趣的小伙伴,欢迎加入我们</div>
-      <ul class="join-list">
-        <li class="join-item" v-for="(item, index) in joinList" :key="index">
-          <el-popover placement="top" trigger="hover">
-            <img class="img" :src="item.img" :alt="`${$store.getters.imgAlt} ${item.title}`" style="width: 130px" />
-            <i slot="reference" :class="`iconfont ${item.logo} ${item.class}`"></i>
-          </el-popover>
-        </li>
-      </ul>
-    </div>
-  </div>
+	<div class="footer-wrapper">
+		<div class="copy-right-wrapper">
+			<img
+				class="logo"
+				:src="logoUrl"
+				:alt="$store.getters.imgAlt + 'footerLogo'"
+			/>
+			<div class="copy-right">
+				<span>奇文共赏 2020 版权所有</span>
+				<span class="split">|</span>
+				<span
+					><a
+						class="link"
+						style="color: white"
+						href="http://beian.miit.gov.cn/"
+						target="_blank"
+						>陕ICP备19020251号</a
+					>&nbsp;</span
+				>
+				<p class="tip-website">
+					为获得最佳浏览体验,建议使用IE11、FireFox50.5、Chrome51.0及以上版本的浏览器
+				</p>
+			</div>
+		</div>
+		<div class="join-us">
+			<div class="desc">如果你也是对技术感兴趣的小伙伴,欢迎加入我们</div>
+			<ul class="join-list">
+				<li class="join-item" v-for="(item, index) in joinList" :key="index">
+					<el-popover placement="top" trigger="hover">
+						<img
+							class="img"
+							:src="item.img"
+							:alt="`${$store.getters.imgAlt} ${item.title}`"
+							style="width: 130px"
+						/>
+						<i
+							slot="reference"
+							:class="`iconfont ${item.logo} ${item.class}`"
+						></i>
+					</el-popover>
+				</li>
+			</ul>
+		</div>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'Footer',
-  data() {
-    return {
-      logoUrl: require('_a/images/common/logo_footer.png'),
-      joinList: [
-        {
-          class: 'qq',
-          logo: 'icon-qq',
-          img: require('_a/images/footer/QQImg.png'),
-          title: 'QQ群'
-        },
-        {
-          class: 'wechat',
-          logo: 'icon-weixin-copy',
-          img: require('_a/images/footer/wechatImg.png'),
-          title: '微信公众号'
-        },
-        {
-          class: 'gitee',
-          logo: 'icon-mayun',
-          img: require('_a/images/footer/giteeImg.png'),
-          title: '码云 开源社区'
-        }
-      ]
-    }
-  }
+	name: 'Footer',
+	data() {
+		return {
+			logoUrl: require('_a/images/common/logo_footer.png'),
+			joinList: [
+				{
+					class: 'qq',
+					logo: 'icon-qq',
+					img: require('_a/images/footer/QQImg.png'),
+					title: 'QQ群'
+				},
+				{
+					class: 'wechat',
+					logo: 'icon-weixin-copy',
+					img: require('_a/images/footer/wechatImg.png'),
+					title: '微信公众号'
+				},
+				{
+					class: 'gitee',
+					logo: 'icon-mayun',
+					img: require('_a/images/footer/giteeImg.png'),
+					title: '码云 开源社区'
+				}
+			]
+		}
+	}
 }
 </script>
 

+ 83 - 52
src/components/Header.vue

@@ -1,62 +1,93 @@
 <template>
-  <div class="header-wrapper">
-    <img class="logo" :src="logoUrl" @click="$router.push({ name: 'Home' })" />
-    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" router>
-      <el-menu-item index="Home" :route="{ name: 'Home' }">首页</el-menu-item>
-      <el-menu-item index="File" :route="{ name: 'File', query: { fileType: 0, filePath: '/' } }">网盘</el-menu-item>
-      <el-menu-item index="MyShare" :route="{ name: 'MyShare', query: { filePath: '/' } }" >我的分享</el-menu-item>
-      <li class="el-menu-item external-link"><a href="https://pan.qiwenshare.com/docs/" target="_blank">文档</a></li>
-      <!-- 为了和其他菜单样式保持一致,请一定要添加类名 el-menu-item -->
-      <div class="el-menu-item exit" @click="exitButton()" v-show="isLogin">
-        退出
-      </div>
-      <div class="el-menu-item username" v-show="isLogin"><i class="el-icon-user-solid"></i>{{ username }}</div>
-      <el-menu-item class="login" index="Login" :route="{ name: 'Login' }" v-show="!isLogin">登录</el-menu-item>
-      <!-- 生产环境 -->
-      <el-menu-item class="register" v-if="isProductEnv" v-show="!isLogin">
-        <a href="https://www.qiwenshare.com/register" target="_blank">注册</a>
-      </el-menu-item>
-      <!-- 开发环境 -->
-      <el-menu-item class="register" v-else v-show="!isLogin" index="Register" :route="{ name: 'Register' }"
-        >注册</el-menu-item
-      >
-    </el-menu>
-  </div>
+	<div class="header-wrapper">
+		<img class="logo" :src="logoUrl" @click="$router.push({ name: 'Home' })" />
+		<el-menu
+			:default-active="activeIndex"
+			class="el-menu-demo"
+			mode="horizontal"
+			router
+		>
+			<el-menu-item index="Home" :route="{ name: 'Home' }">首页</el-menu-item>
+			<el-menu-item
+				index="File"
+				:route="{ name: 'File', query: { fileType: 0, filePath: '/' } }"
+				>网盘</el-menu-item
+			>
+			<el-menu-item
+				index="MyShare"
+				:route="{ name: 'MyShare', query: { filePath: '/' } }"
+				>我的分享</el-menu-item
+			>
+			<li class="el-menu-item external-link">
+				<a href="https://pan.qiwenshare.com/docs/" target="_blank">文档</a>
+			</li>
+			<!-- 为了和其他菜单样式保持一致,请一定要添加类名 el-menu-item -->
+			<div class="el-menu-item exit" @click="exitButton()" v-show="isLogin">
+				退出
+			</div>
+			<div class="el-menu-item username" v-show="isLogin">
+				<i class="el-icon-user-solid"></i>{{ username }}
+			</div>
+			<el-menu-item
+				class="login"
+				index="Login"
+				:route="{ name: 'Login' }"
+				v-show="!isLogin"
+				>登录</el-menu-item
+			>
+			<!-- 生产环境 -->
+			<el-menu-item class="register" v-if="isProductEnv" v-show="!isLogin">
+				<a href="https://www.qiwenshare.com/register" target="_blank">注册</a>
+			</el-menu-item>
+			<!-- 开发环境 -->
+			<el-menu-item
+				class="register"
+				v-else
+				v-show="!isLogin"
+				index="Register"
+				:route="{ name: 'Register' }"
+				>注册</el-menu-item
+			>
+		</el-menu>
+	</div>
 </template>
 
 <script>
 import { mapGetters } from 'vuex'
 
 export default {
-  name: 'Header',
-  data() {
-    return {
-      logoUrl: require('_a/images/common/logo_header.png')
-    }
-  },
-  computed: {
-    ...mapGetters(['isLogin', 'username']),
-    // 当前激活菜单的 index
-    activeIndex() {
-      return this.$route.name || 'Home' //  获取当前路由名称
-    },
-    isProductEnv() {
-      return process.env.NODE_ENV !== 'development' && location.origin === 'https://pan.qiwenshare.com'
-    }
-  },
-  methods: {
-    /**
-     * 退出登录
-     * @description 清除 cookie 存放的 token  并跳转到登录页面
-     */
-    exitButton() {
-      this.$message.success('退出登录成功!')
-      this.$store.dispatch('getUserInfo').then(() => {
-        this.removeCookies('token')
-        this.$router.push({ path: '/login' })
-      })
-    }
-  }
+	name: 'Header',
+	data() {
+		return {
+			logoUrl: require('_a/images/common/logo_header.png')
+		}
+	},
+	computed: {
+		...mapGetters(['isLogin', 'username']),
+		// 当前激活菜单的 index
+		activeIndex() {
+			return this.$route.name || 'Home' //  获取当前路由名称
+		},
+		isProductEnv() {
+			return (
+				process.env.NODE_ENV !== 'development' &&
+				location.origin === 'https://pan.qiwenshare.com'
+			)
+		}
+	},
+	methods: {
+		/**
+		 * 退出登录
+		 * @description 清除 cookie 存放的 token  并跳转到登录页面
+		 */
+		exitButton() {
+			this.$message.success('退出登录成功!')
+			this.$store.dispatch('getUserInfo').then(() => {
+				this.removeCookies('token')
+				this.$router.push({ path: '/login' })
+			})
+		}
+	}
 }
 </script>
 

+ 240 - 229
src/components/common/DragVerify.vue

@@ -1,225 +1,236 @@
 <template>
-  <!-- 滑动解锁插件 http://www.jq22.com/jquery-info22779 -->
-  <div
-    ref="dragVerify"
-    class="drag_verify"
-    :style="dragVerifyStyle"
-    @mousemove="dragMoving"
-    @mouseup="dragFinish"
-    @mouseleave="dragFinish"
-    @touchmove="dragMoving"
-    @touchend="dragFinish"
-  >
-    <div class="dv_progress_bar" ref="progressBar" :class="{ goFirst2: isOk }" :style="progressBarStyle"></div>
-    <div class="dv_text" :style="textStyle" ref="message">
-      <slot name="textBefore" v-if="$slots.textBefore"></slot>
-      {{ message }}
-      <slot name="textAfter" v-if="$slots.textAfter"></slot>
-    </div>
+	<!-- 滑动解锁插件 http://www.jq22.com/jquery-info22779 -->
+	<div
+		ref="dragVerify"
+		class="drag_verify"
+		:style="dragVerifyStyle"
+		@mousemove="dragMoving"
+		@mouseup="dragFinish"
+		@mouseleave="dragFinish"
+		@touchmove="dragMoving"
+		@touchend="dragFinish"
+	>
+		<div
+			class="dv_progress_bar"
+			ref="progressBar"
+			:class="{ goFirst2: isOk }"
+			:style="progressBarStyle"
+		></div>
+		<div class="dv_text" :style="textStyle" ref="message">
+			<slot name="textBefore" v-if="$slots.textBefore"></slot>
+			{{ message }}
+			<slot name="textAfter" v-if="$slots.textAfter"></slot>
+		</div>
 
-    <div
-      class="dv_handler dv_handler_bg"
-      :class="{ goFirst: isOk }"
-      @mousedown="dragStart"
-      @touchstart="dragStart"
-      ref="handler"
-      :style="handlerStyle"
-    >
-      <i :class="handlerIcon"></i>
-    </div>
-  </div>
+		<div
+			class="dv_handler dv_handler_bg"
+			:class="{ goFirst: isOk }"
+			@mousedown="dragStart"
+			@touchstart="dragStart"
+			ref="handler"
+			:style="handlerStyle"
+		>
+			<i :class="handlerIcon"></i>
+		</div>
+	</div>
 </template>
 <script>
 export default {
-  name: 'dragVerify',
-  props: {
-    // 是否通过
-    isPassing: {
-      type: Boolean,
-      default: false
-    },
-    // 宽度
-    width: {
-      type: Number,
-      default: 250
-    },
-    // 高度
-    height: {
-      type: Number,
-      default: 40
-    },
-    // 组件文案
-    text: {
-      type: String,
-      default: 'swiping to the right side'
-    },
-    // 成功文案
-    successText: {
-      type: String,
-      default: 'success'
-    },
-    // 背景色
-    background: {
-      type: String,
-      default: '#eee'
-    },
-    // 解锁中背景色
-    progressBarBg: {
-      type: String,
-      default: '#76c61d'
-    },
-    // 解锁成功背景色
-    completedBg: {
-      type: String,
-      default: '#76c61d'
-    },
-    circle: {
-      type: Boolean,
-      default: false
-    },
-    radius: {
-      type: String,
-      default: '4px'
-    },
-    handlerIcon: {
-      type: String
-    },
-    successIcon: {
-      type: String
-    },
-    handlerBg: {
-      type: String,
-      default: '#fff'
-    },
-    textSize: {
-      type: String,
-      default: '14px'
-    },
-    textColor: {
-      type: String,
-      default: '#333'
-    }
-  },
-  mounted() {
-    const dragEl = this.$refs.dragVerify
-    dragEl.style.setProperty('--textColor', this.textColor)
-    dragEl.style.setProperty('--width', Math.floor(this.width / 2) + 'px')
-    dragEl.style.setProperty('--pwidth', -Math.floor(this.width / 2) + 'px')
-  },
-  computed: {
-    handlerStyle() {
-      return {
-        left: '0px',
-        width: this.height + 'px',
-        height: this.height + 'px',
-        background: this.handlerBg
-      }
-    },
-    message() {
-      return this.isPassing ? this.successText : this.text
-    },
-    dragVerifyStyle() {
-      return {
-        width: this.width + 'px',
-        height: this.height + 'px',
-        lineHeight: this.height + 'px',
-        background: this.background,
-        borderRadius: this.circle ? this.height / 2 + 'px' : this.radius
-      }
-    },
-    progressBarStyle() {
-      return {
-        background: this.progressBarBg,
-        height: this.height + 'px',
-        borderRadius: this.circle ? this.height / 2 + 'px 0 0 ' + this.height / 2 + 'px' : this.radius
-      }
-    },
-    textStyle() {
-      return {
-        height: this.height + 'px',
-        width: this.width + 'px',
-        fontSize: this.textSize
-      }
-    }
-  },
-  data() {
-    return {
-      isMoving: false,
-      x: 0,
-      isOk: false
-    }
-  },
-  methods: {
-    dragStart(e) {
-      if (!this.isPassing) {
-        this.isMoving = true
-        var handler = this.$refs.handler
-        this.x = (e.pageX || e.touches[0].pageX) - parseInt(handler.style.left.replace('px', ''), 10)
-      }
-      this.$emit('handlerMove')
-    },
-    dragMoving(e) {
-      if (this.isMoving && !this.isPassing) {
-        var _x = (e.pageX || e.touches[0].pageX) - this.x
-        var handler = this.$refs.handler
-        if (_x > 0 && _x <= this.width - this.height) {
-          handler.style.left = _x + 'px'
-          this.$refs.progressBar.style.width = _x + this.height / 2 + 'px'
-        } else if (_x > this.width - this.height) {
-          handler.style.left = this.width - this.height + 'px'
-          this.$refs.progressBar.style.width = this.width - this.height / 2 + 'px'
-          this.passVerify()
-        }
-      }
-    },
-    dragFinish(e) {
-      if (this.isMoving && !this.isPassing) {
-        var _x = (e.pageX || e.changedTouches[0].pageX) - this.x
-        if (_x < this.width - this.height) {
-          this.isOk = true
-          var that = this
-          setTimeout(function() {
-            that.$refs.handler.style.left = '0'
-            that.$refs.progressBar.style.width = '0'
-            that.isOk = false
-          }, 500)
-        } else {
-          var handler = this.$refs.handler
-          handler.style.left = this.width - this.height + 'px'
-          this.$refs.progressBar.style.width = this.width - this.height / 2 + 'px'
-          this.passVerify()
-        }
-        this.isMoving = false
-      }
-    },
-    passVerify() {
-      this.$emit('update:isPassing', true)
-      this.isMoving = false
-      var handler = this.$refs.handler
-      handler.children[0].className = this.successIcon
-      this.$refs.progressBar.style.background = this.completedBg
-      this.$refs.message.style['-webkit-text-fill-color'] = 'unset'
-      this.$refs.message.style.animation = 'slidetounlock2 3s infinite'
-      this.$refs.message.style.color = '#fff'
-      this.$emit('passcallback')
-    },
-    reset() {
-      const oriData = this.$options.data()
-      for (const key in oriData) {
-        if (oriData.hasOwnProperty(key)) {
-          this.$set(this, key, oriData[key])
-        }
-      }
-      var handler = this.$refs.handler
-      var message = this.$refs.message
-      handler.style.left = '0'
-      this.$refs.progressBar.style.width = '0'
-      handler.children[0].className = this.handlerIcon
-      message.style['-webkit-text-fill-color'] = 'transparent'
-      message.style.animation = 'slidetounlock 3s infinite'
-      message.style.color = this.background
-    }
-  }
+	name: 'dragVerify',
+	props: {
+		// 是否通过
+		isPassing: {
+			type: Boolean,
+			default: false
+		},
+		// 宽度
+		width: {
+			type: Number,
+			default: 250
+		},
+		// 高度
+		height: {
+			type: Number,
+			default: 40
+		},
+		// 组件文案
+		text: {
+			type: String,
+			default: 'swiping to the right side'
+		},
+		// 成功文案
+		successText: {
+			type: String,
+			default: 'success'
+		},
+		// 背景色
+		background: {
+			type: String,
+			default: '#eee'
+		},
+		// 解锁中背景色
+		progressBarBg: {
+			type: String,
+			default: '#76c61d'
+		},
+		// 解锁成功背景色
+		completedBg: {
+			type: String,
+			default: '#76c61d'
+		},
+		circle: {
+			type: Boolean,
+			default: false
+		},
+		radius: {
+			type: String,
+			default: '4px'
+		},
+		handlerIcon: {
+			type: String
+		},
+		successIcon: {
+			type: String
+		},
+		handlerBg: {
+			type: String,
+			default: '#fff'
+		},
+		textSize: {
+			type: String,
+			default: '14px'
+		},
+		textColor: {
+			type: String,
+			default: '#333'
+		}
+	},
+	mounted() {
+		const dragEl = this.$refs.dragVerify
+		dragEl.style.setProperty('--textColor', this.textColor)
+		dragEl.style.setProperty('--width', Math.floor(this.width / 2) + 'px')
+		dragEl.style.setProperty('--pwidth', -Math.floor(this.width / 2) + 'px')
+	},
+	computed: {
+		handlerStyle() {
+			return {
+				left: '0px',
+				width: this.height + 'px',
+				height: this.height + 'px',
+				background: this.handlerBg
+			}
+		},
+		message() {
+			return this.isPassing ? this.successText : this.text
+		},
+		dragVerifyStyle() {
+			return {
+				width: this.width + 'px',
+				height: this.height + 'px',
+				lineHeight: this.height + 'px',
+				background: this.background,
+				borderRadius: this.circle ? this.height / 2 + 'px' : this.radius
+			}
+		},
+		progressBarStyle() {
+			return {
+				background: this.progressBarBg,
+				height: this.height + 'px',
+				borderRadius: this.circle
+					? this.height / 2 + 'px 0 0 ' + this.height / 2 + 'px'
+					: this.radius
+			}
+		},
+		textStyle() {
+			return {
+				height: this.height + 'px',
+				width: this.width + 'px',
+				fontSize: this.textSize
+			}
+		}
+	},
+	data() {
+		return {
+			isMoving: false,
+			x: 0,
+			isOk: false
+		}
+	},
+	methods: {
+		dragStart(e) {
+			if (!this.isPassing) {
+				this.isMoving = true
+				var handler = this.$refs.handler
+				this.x =
+					(e.pageX || e.touches[0].pageX) -
+					parseInt(handler.style.left.replace('px', ''), 10)
+			}
+			this.$emit('handlerMove')
+		},
+		dragMoving(e) {
+			if (this.isMoving && !this.isPassing) {
+				var _x = (e.pageX || e.touches[0].pageX) - this.x
+				var handler = this.$refs.handler
+				if (_x > 0 && _x <= this.width - this.height) {
+					handler.style.left = _x + 'px'
+					this.$refs.progressBar.style.width = _x + this.height / 2 + 'px'
+				} else if (_x > this.width - this.height) {
+					handler.style.left = this.width - this.height + 'px'
+					this.$refs.progressBar.style.width =
+						this.width - this.height / 2 + 'px'
+					this.passVerify()
+				}
+			}
+		},
+		dragFinish(e) {
+			if (this.isMoving && !this.isPassing) {
+				var _x = (e.pageX || e.changedTouches[0].pageX) - this.x
+				if (_x < this.width - this.height) {
+					this.isOk = true
+					var that = this
+					setTimeout(function () {
+						that.$refs.handler.style.left = '0'
+						that.$refs.progressBar.style.width = '0'
+						that.isOk = false
+					}, 500)
+				} else {
+					var handler = this.$refs.handler
+					handler.style.left = this.width - this.height + 'px'
+					this.$refs.progressBar.style.width =
+						this.width - this.height / 2 + 'px'
+					this.passVerify()
+				}
+				this.isMoving = false
+			}
+		},
+		passVerify() {
+			this.$emit('update:isPassing', true)
+			this.isMoving = false
+			var handler = this.$refs.handler
+			handler.children[0].className = this.successIcon
+			this.$refs.progressBar.style.background = this.completedBg
+			this.$refs.message.style['-webkit-text-fill-color'] = 'unset'
+			this.$refs.message.style.animation = 'slidetounlock2 3s infinite'
+			this.$refs.message.style.color = '#fff'
+			this.$emit('passcallback')
+		},
+		reset() {
+			const oriData = this.$options.data()
+			for (const key in oriData) {
+				if (Object.prototype.hasOwnProperty.call(oriData, key)) {
+					this.$set(this, key, oriData[key])
+				}
+			}
+			var handler = this.$refs.handler
+			var message = this.$refs.message
+			handler.style.left = '0'
+			this.$refs.progressBar.style.width = '0'
+			handler.children[0].className = this.handlerIcon
+			message.style['-webkit-text-fill-color'] = 'transparent'
+			message.style.animation = 'slidetounlock 3s infinite'
+			message.style.color = this.background
+		}
+	}
 }
 </script>
 <style lang="stylus" scoped>
@@ -295,19 +306,19 @@ export default {
 </style>
 <style>
 @keyframes slidetounlock {
-  0% {
-    background-position: var(--pwidth) 0;
-  }
-  100% {
-    background-position: var(--width) 0;
-  }
+	0% {
+		background-position: var(--pwidth) 0;
+	}
+	100% {
+		background-position: var(--width) 0;
+	}
 }
 @keyframes slidetounlock2 {
-  0% {
-    background-position: var(--pwidth) 0;
-  }
-  100% {
-    background-position: var(--pwidth) 0;
-  }
+	0% {
+		background-position: var(--pwidth) 0;
+	}
+	100% {
+		background-position: var(--pwidth) 0;
+	}
 }
 </style>

+ 379 - 321
src/components/common/GlobalUploader.vue

@@ -1,331 +1,389 @@
 <template>
-  <div id="global-uploader">
-    <!-- 上传文件组件 -->
-    <uploader
-      class="uploader-app"
-      ref="uploader"
-      :options="options"
-      :autoStart="false"
-      :fileStatusText="fileStatusText"
-      @files-added="handleFilesAdded"
-      @file-success="handleFileSuccess"
-      @file-error="handleFileError"
-    >
-      <uploader-unsupport></uploader-unsupport>
-      <!-- 选择按钮 在这里隐藏 -->
-      <uploader-btn class="select-file-btn" :attrs="attrs" ref="uploadBtn">选择文件</uploader-btn>
-      <uploader-btn class="select-file-btn" :attrs="attrs" :directory="true" ref="uploadDirBtn">选择目录</uploader-btn>
-      <!-- 拖拽上传 -->
-      <uploader-drop
-        class="drop-box"
-        id="dropBox"
-        @paste.native="handlePaste"
-        v-show="dropBoxShow"
-      >
-        <div class="paste-img-wrapper" v-show="pasteImg.src">
-          <div class="paste-name">{{ pasteImg.name }}</div>
-          <img class="paste-img" :src="pasteImg.src" :alt="pasteImg.name" v-if="pasteImg.src" />
-        </div>
-        <span class="text" v-show="!pasteImg.src"> 截图粘贴或将文件拖拽至此区域上传 </span>
-        <i class="upload-icon el-icon-upload" v-show="pasteImg.src" @click="handleUploadPasteImg">上传图片</i>
-        <i class="delete-icon el-icon-delete" v-show="pasteImg.src" @click="handleDeletePasteImg">删除图片</i>
-        <i class="close-icon el-icon-circle-close" @click="dropBoxShow = false">关闭</i>
-      </uploader-drop>
-      <!-- 上传列表 -->
-      <uploader-list v-show="panelShow">
-        <template v-slot:default="props">
-          <div class="file-panel">
-            <div class="file-title">
-              <span class="title-span">
-                上传列表<span class="count">({{ props.fileList.length }})</span>
-              </span>
-              <div class="operate">
-                <el-button
-                  type="text"
-                  :title="collapse ? '展开' : '折叠'"
-                  :icon="collapse ? 'el-icon-full-screen' : 'el-icon-minus'"
-                  @click="collapse ? (collapse = false) : (collapse = true)"
-                >
-                </el-button>
-                <el-button @click="handleClosePanel" type="text" title="关闭" icon="el-icon-close"> </el-button>
-              </div>
-            </div>
-            <!-- 正在上传的文件列表 -->
-            <el-collapse-transition>
-              <ul class="file-list" v-show="!collapse">
-                <li
-                  class="file-item"
-                  :class="{ 'custom-status-item': file.statusStr !== '' }"
-                  v-for="file in props.fileList"
-                  :key="file.id"
-                >
-                  <uploader-file ref="fileItem" :file="file" :list="true"></uploader-file>
-                  <!-- 自定义状态 -->
-                  <span class="custom-status">{{ file.statusStr }}</span>
-                </li>
-                <div class="no-file" v-if="!props.fileList.length"><i class="icon-empty-file"></i> 暂无待上传文件</div>
-              </ul>
-            </el-collapse-transition>
-          </div>
-        </template>
-      </uploader-list>
-    </uploader>
-  </div>
+	<div id="global-uploader">
+		<!-- 上传文件组件 -->
+		<uploader
+			class="uploader-app"
+			ref="uploader"
+			:options="options"
+			:autoStart="false"
+			:fileStatusText="fileStatusText"
+			@files-added="handleFilesAdded"
+			@file-success="handleFileSuccess"
+			@file-error="handleFileError"
+		>
+			<uploader-unsupport></uploader-unsupport>
+			<!-- 选择按钮 在这里隐藏 -->
+			<uploader-btn class="select-file-btn" :attrs="attrs" ref="uploadBtn"
+				>选择文件</uploader-btn
+			>
+			<uploader-btn
+				class="select-file-btn"
+				:attrs="attrs"
+				:directory="true"
+				ref="uploadDirBtn"
+				>选择目录</uploader-btn
+			>
+			<!-- 拖拽上传 -->
+			<uploader-drop
+				class="drop-box"
+				id="dropBox"
+				@paste.native="handlePaste"
+				v-show="dropBoxShow"
+			>
+				<div class="paste-img-wrapper" v-show="pasteImg.src">
+					<div class="paste-name">{{ pasteImg.name }}</div>
+					<img
+						class="paste-img"
+						:src="pasteImg.src"
+						:alt="pasteImg.name"
+						v-if="pasteImg.src"
+					/>
+				</div>
+				<span class="text" v-show="!pasteImg.src">
+					截图粘贴或将文件拖拽至此区域上传
+				</span>
+				<i
+					class="upload-icon el-icon-upload"
+					v-show="pasteImg.src"
+					@click="handleUploadPasteImg"
+					>上传图片</i
+				>
+				<i
+					class="delete-icon el-icon-delete"
+					v-show="pasteImg.src"
+					@click="handleDeletePasteImg"
+					>删除图片</i
+				>
+				<i class="close-icon el-icon-circle-close" @click="dropBoxShow = false"
+					>关闭</i
+				>
+			</uploader-drop>
+			<!-- 上传列表 -->
+			<uploader-list v-show="panelShow">
+				<template v-slot:default="props">
+					<div class="file-panel">
+						<div class="file-title">
+							<span class="title-span">
+								上传列表<span class="count"
+									>({{ props.fileList.length }})</span
+								>
+							</span>
+							<div class="operate">
+								<el-button
+									type="text"
+									:title="collapse ? '展开' : '折叠'"
+									:icon="collapse ? 'el-icon-full-screen' : 'el-icon-minus'"
+									@click="collapse ? (collapse = false) : (collapse = true)"
+								>
+								</el-button>
+								<el-button
+									@click="handleClosePanel"
+									type="text"
+									title="关闭"
+									icon="el-icon-close"
+								>
+								</el-button>
+							</div>
+						</div>
+						<!-- 正在上传的文件列表 -->
+						<el-collapse-transition>
+							<ul class="file-list" v-show="!collapse">
+								<li
+									class="file-item"
+									:class="{ 'custom-status-item': file.statusStr !== '' }"
+									v-for="file in props.fileList"
+									:key="file.id"
+								>
+									<uploader-file
+										ref="fileItem"
+										:file="file"
+										:list="true"
+									></uploader-file>
+									<!-- 自定义状态 -->
+									<span class="custom-status">{{ file.statusStr }}</span>
+								</li>
+								<div class="no-file" v-if="!props.fileList.length">
+									<i class="icon-empty-file"></i> 暂无待上传文件
+								</div>
+							</ul>
+						</el-collapse-transition>
+					</div>
+				</template>
+			</uploader-list>
+		</uploader>
+	</div>
 </template>
 
 <script>
 import SparkMD5 from 'spark-md5'
 
 export default {
-  data() {
-    return {
-      // 上传组件配置项
-      options: {
-        target: '/api/filetransfer/uploadfile', // 上传文件-目标 URL
-        chunkSize: 1024 * 1024, //  每个分片的大小
-        fileParameterName: 'file', //  上传文件时文件的参数名,默认 file
-        maxChunkRetries: 3, //  并发上传数,默认 3
-        testChunks: true, //  是否开启分片已存在于服务器的校验
-        // 服务器分片校验函数,秒传及断点续传基础
-        checkChunkUploadedByResponse: function(chunk, message) {
-          let objMessage = JSON.parse(message)
-          if (objMessage.success) {
-            let data = objMessage.data
-            if (data.skipUpload) {
-              // 分片已存在于服务器中
-              return true
-            }
-            return (data.uploaded || []).indexOf(chunk.offset + 1) >= 0
-          }
-          else {
-            console.log(objMessage.message)
-            return true;
-          }
-        },
-        headers: {
-          token: this.getCookies('token')
-        },
-        query() {}
-      },
-      // 文件状态文案映射
-      fileStatusText: {
-        success: '上传成功',
-        error: 'error',
-        uploading: '上传中',
-        paused: '暂停中',
-        waiting: '等待中'
-      },
-      attrs: {
-        accept: '*'
-      },
-      panelShow: false, //  上传文件面板是否显示
-      collapse: false, //	上传文件面板是否折叠
-      dropBoxShow: false, //  拖拽上传是否显示
-      // 粘贴图片的信息
-      pasteImg: {
-        src: '',
-        name: ''
-      },
-      pasteImgObj: null //  粘贴图片 File 对象
-    }
-  },
-  computed: {
-    // Uploader	上传组件实例
-    uploaderInstance() {
-      return this.$refs.uploader.uploader
-    },
-    // 剩余存储空间
-    remainderStorageValue() {
-      return this.$store.getters.remainderStorageValue
-    }
-  },
-  mounted() {
-    this.$EventBus.$on('openUploader', (query, type) => {
-      this.options.headers.token = this.getCookies('token')
-      this.params = query || {}
-      if (type == 0) {
-        this.$refs.uploadBtn.$el.click()
-      } else if (type == 1) {
-        this.$refs.uploadDirBtn.$el.click()
-      } else {
-        this.pasteImg.src = ''
-        this.pasteImg.name = ''
-        this.pasteImgObj = null
-        this.dropBoxShow = true
-      }
-    })
-  },
-  destroyed() {
-    this.$off('openUploader')
-  },
-  methods: {
-    // 图片粘贴事件
-    handlePaste(event) {
-      let pasteItems = (event.clipboardData || window.clipboardData).items
-      if (pasteItems && pasteItems.length) {
-        // 获取剪切板中最新的对象
-        let imgObj = pasteItems[0].getAsFile()
-        this.pasteImgObj = imgObj !== null ? new File([imgObj], `qiwenshare_${new Date().valueOf()}.${imgObj.name.split('.')[1]}`, {
-          type: imgObj.type
-        }) : null
-      } else {
-        this.$message.error('当前浏览器不支持')
-        return false
-      }
-      if (!this.pasteImgObj) {
-        this.$message.error('粘贴内容非图片')
-        return false
-      }
-      this.pasteImg.name = this.pasteImgObj.name
-      // 此时file就是剪切板中的图片对象
-      // 如果需要预览,可以执行下面代码
-      let reader = new FileReader()
-      let _this = this
-      reader.onload = function(event) {
-        _this.pasteImg.src = event.target.result
-      }
-      reader.readAsDataURL(this.pasteImgObj)
-    },
-    // 上传粘贴的图片
-    handleUploadPasteImg() {
-      this.uploaderInstance.addFile(this.pasteImgObj) //  触发文件添加事件
-    },
-    // 删除粘贴的图片
-    handleDeletePasteImg() {
-      this.pasteImg.src = ''
-      this.pasteImg.name = ''
-      this.pasteImgObj = null
-    },
-    /**
-     * 添加批量文件的回调函数
-     * @description 对单个或批量文件都按此逻辑处理
-     * @param {object} files 批量文件信息
-     */
-    handleFilesAdded(files) {
-      // 批量选择的文件的总体大小
-      const filesTotalSize = files.map(item => item.size).reduce((pre, next) => {
-        return pre + next
-      }, 0)
-      if(this.remainderStorageValue < filesTotalSize) {
-        // 批量选择的文件超出剩余存储空间
-        this.$message.warning(`剩余存储空间不足,请重新选择${files.length > 1 ? '批量' : ''}文件`)
-        // https://github.com/simple-uploader/vue-uploader/blob/master/README_zh-CN.md#%E4%BA%8B%E4%BB%B6
-        files.ignored = true  //  本次选择的文件过滤掉
-      } else {
-        // 批量或单个选择的文件未超出剩余存储空间,正常上传
-        files.forEach(file => {
-          this.dropBoxShow = false
-          this.panelShow = true
-          this.collapse = false
-          this.computeMD5(file)
-        });
-      }
-    },
-    /**
-     * 文件上传成功 回调函数
-     * @param {object} rootFile 成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件
-     * @param {object} file 当前成功的 Uploader.File 对象本身
-     * @param {string} response 服务端响应内容,永远都是字符串
-     */
-    handleFileSuccess(rootFile, file, response) {
-      if (response == '') {
-        file.statusStr = '上传失败'
-        return
-      }
-
-      let result = JSON.parse(response)
-      if (result.success) {
-        this.$message.success(`${file.name} - 上传完毕`)
-        file.statusStr = ''
-        // setTimeout(() => {
-        //   this.collapse = true //  折叠上传列表
-        // }, 1500)
-        this.$EventBus.$emit('refreshList', '')
-        this.$EventBus.$emit('refreshStorage', '')
-      } else {
-        this.$message.error(result.message)
-        file.statusStr = '上传失败'
-      }
-    },
-    /**
-     * 文件上传失败 回调函数
-     * @param {object} rootFile 成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件
-     * @param {object} file 当前成功的 Uploader.File 对象本身
-     * @param {string} response 服务端响应内容,永远都是字符串
-     */
-    handleFileError(rootFile, file, response) {
-      this.$message({
-        message: response,
-        type: 'error'
-      })
-    },
-    /**
-     * 计算md5,实现断点续传及秒传
-     * @param {object} file 文件信息
-     */
-    computeMD5(file) {
-      let fileReader = new FileReader()
-      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
-      let currentChunk = 0
-      const chunkSize = 1 * 1024 * 1024
-      let chunks = Math.ceil(file.size / chunkSize)
-      let spark = new SparkMD5.ArrayBuffer()
-      // 文件状态设为"计算MD5"
-      file.statusStr = '计算MD5'
-      file.pause()
-      loadNext()
-      fileReader.onload = (e) => {
-        spark.append(e.target.result)
-        if (currentChunk < chunks) {
-          currentChunk++
-          loadNext()
-          // 实时展示MD5的计算进度
-          file.statusStr = `校验MD5 ${((currentChunk / chunks) * 100).toFixed(0)}%`
-        } else {
-          let md5 = spark.end()
-          this.calculateFileMD5End(md5, file)
-        }
-      }
-      fileReader.onerror = function() {
-        this.$notify({
-          title: '错误',
-          message: `文件${file.name}读取出错,请检查该文件`,
-          type: 'error',
-          duration: 2000
-        })
-        file.cancel()
-      }
-      function loadNext() {
-        let start = currentChunk * chunkSize
-        let end = start + chunkSize >= file.size ? file.size : start + chunkSize
-        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
-      }
-    },
-    /**
-     * 文件MD5计算结束
-     * @param {string} md5 文件 MD5 值
-     * @param {object} file 文件对象
-     */
-    calculateFileMD5End(md5, file) {
-      // 将自定义参数直接加载uploader实例的opts上
-      Object.assign(this.uploaderInstance.opts, {
-        query: {
-          ...this.params
-        }
-      })
-      file.uniqueIdentifier = md5
-      file.resume()
-      // 移除自定义状态
-      file.statusStr = ''
-    },
-    /**
-     * 关闭上传面板,并停止上传
-     */
-    handleClosePanel() {
-      this.uploaderInstance.cancel()
-      this.panelShow = false
-    }
-  }
+	data() {
+		return {
+			// 上传组件配置项
+			options: {
+				target: '/api/filetransfer/uploadfile', // 上传文件-目标 URL
+				chunkSize: 1024 * 1024, //  每个分片的大小
+				fileParameterName: 'file', //  上传文件时文件的参数名,默认 file
+				maxChunkRetries: 3, //  并发上传数,默认 3
+				testChunks: true, //  是否开启分片已存在于服务器的校验
+				// 服务器分片校验函数,秒传及断点续传基础
+				checkChunkUploadedByResponse: function (chunk, message) {
+					let objMessage = JSON.parse(message)
+					if (objMessage.success) {
+						let data = objMessage.data
+						if (data.skipUpload) {
+							// 分片已存在于服务器中
+							return true
+						}
+						return (data.uploaded || []).indexOf(chunk.offset + 1) >= 0
+					} else {
+						console.log(objMessage.message)
+						return true
+					}
+				},
+				headers: {
+					token: this.getCookies('token')
+				},
+				query() {}
+			},
+			// 文件状态文案映射
+			fileStatusText: {
+				success: '上传成功',
+				error: 'error',
+				uploading: '上传中',
+				paused: '暂停中',
+				waiting: '等待中'
+			},
+			attrs: {
+				accept: '*'
+			},
+			panelShow: false, //  上传文件面板是否显示
+			collapse: false, //	上传文件面板是否折叠
+			dropBoxShow: false, //  拖拽上传是否显示
+			// 粘贴图片的信息
+			pasteImg: {
+				src: '',
+				name: ''
+			},
+			pasteImgObj: null //  粘贴图片 File 对象
+		}
+	},
+	computed: {
+		// Uploader	上传组件实例
+		uploaderInstance() {
+			return this.$refs.uploader.uploader
+		},
+		// 剩余存储空间
+		remainderStorageValue() {
+			return this.$store.getters.remainderStorageValue
+		}
+	},
+	mounted() {
+		this.$EventBus.$on('openUploader', (query, type) => {
+			this.options.headers.token = this.getCookies('token')
+			this.params = query || {}
+			if (type == 0) {
+				this.$refs.uploadBtn.$el.click()
+			} else if (type == 1) {
+				this.$refs.uploadDirBtn.$el.click()
+			} else {
+				this.pasteImg.src = ''
+				this.pasteImg.name = ''
+				this.pasteImgObj = null
+				this.dropBoxShow = true
+			}
+		})
+	},
+	destroyed() {
+		this.$off('openUploader')
+	},
+	methods: {
+		// 图片粘贴事件
+		handlePaste(event) {
+			let pasteItems = (event.clipboardData || window.clipboardData).items
+			if (pasteItems && pasteItems.length) {
+				// 获取剪切板中最新的对象
+				let imgObj = pasteItems[0].getAsFile()
+				this.pasteImgObj =
+					imgObj !== null
+						? new File(
+								[imgObj],
+								`qiwenshare_${new Date().valueOf()}.${
+									imgObj.name.split('.')[1]
+								}`,
+								{
+									type: imgObj.type
+								}
+						  )
+						: null
+			} else {
+				this.$message.error('当前浏览器不支持')
+				return false
+			}
+			if (!this.pasteImgObj) {
+				this.$message.error('粘贴内容非图片')
+				return false
+			}
+			this.pasteImg.name = this.pasteImgObj.name
+			// 此时file就是剪切板中的图片对象
+			// 如果需要预览,可以执行下面代码
+			let reader = new FileReader()
+			let _this = this
+			reader.onload = function (event) {
+				_this.pasteImg.src = event.target.result
+			}
+			reader.readAsDataURL(this.pasteImgObj)
+		},
+		// 上传粘贴的图片
+		handleUploadPasteImg() {
+			this.uploaderInstance.addFile(this.pasteImgObj) //  触发文件添加事件
+		},
+		// 删除粘贴的图片
+		handleDeletePasteImg() {
+			this.pasteImg.src = ''
+			this.pasteImg.name = ''
+			this.pasteImgObj = null
+		},
+		/**
+		 * 添加批量文件的回调函数
+		 * @description 对单个或批量文件都按此逻辑处理
+		 * @param {object} files 批量文件信息
+		 */
+		handleFilesAdded(files) {
+			// 批量选择的文件的总体大小
+			const filesTotalSize = files
+				.map((item) => item.size)
+				.reduce((pre, next) => {
+					return pre + next
+				}, 0)
+			if (this.remainderStorageValue < filesTotalSize) {
+				// 批量选择的文件超出剩余存储空间
+				this.$message.warning(
+					`剩余存储空间不足,请重新选择${files.length > 1 ? '批量' : ''}文件`
+				)
+				// https://github.com/simple-uploader/vue-uploader/blob/master/README_zh-CN.md#%E4%BA%8B%E4%BB%B6
+				files.ignored = true //  本次选择的文件过滤掉
+			} else {
+				// 批量或单个选择的文件未超出剩余存储空间,正常上传
+				files.forEach((file) => {
+					this.dropBoxShow = false
+					this.panelShow = true
+					this.collapse = false
+					this.computeMD5(file)
+				})
+			}
+		},
+		/**
+		 * 文件上传成功 回调函数
+		 * @param {object} rootFile 成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件
+		 * @param {object} file 当前成功的 Uploader.File 对象本身
+		 * @param {string} response 服务端响应内容,永远都是字符串
+		 */
+		handleFileSuccess(rootFile, file, response) {
+			if (response == '') {
+				file.statusStr = '上传失败'
+				return
+			}
+
+			let result = JSON.parse(response)
+			if (result.success) {
+				this.$message.success(`${file.name} - 上传完毕`)
+				file.statusStr = ''
+				// setTimeout(() => {
+				//   this.collapse = true //  折叠上传列表
+				// }, 1500)
+				this.$EventBus.$emit('refreshList', '')
+				this.$EventBus.$emit('refreshStorage', '')
+			} else {
+				this.$message.error(result.message)
+				file.statusStr = '上传失败'
+			}
+		},
+		/**
+		 * 文件上传失败 回调函数
+		 * @param {object} rootFile 成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件
+		 * @param {object} file 当前成功的 Uploader.File 对象本身
+		 * @param {string} response 服务端响应内容,永远都是字符串
+		 */
+		handleFileError(rootFile, file, response) {
+			this.$message({
+				message: response,
+				type: 'error'
+			})
+		},
+		/**
+		 * 计算md5,实现断点续传及秒传
+		 * @param {object} file 文件信息
+		 */
+		computeMD5(file) {
+			let fileReader = new FileReader()
+			let blobSlice =
+				File.prototype.slice ||
+				File.prototype.mozSlice ||
+				File.prototype.webkitSlice
+			let currentChunk = 0
+			const chunkSize = 1 * 1024 * 1024
+			let chunks = Math.ceil(file.size / chunkSize)
+			let spark = new SparkMD5.ArrayBuffer()
+			// 文件状态设为"计算MD5"
+			file.statusStr = '计算MD5'
+			file.pause()
+			loadNext()
+			fileReader.onload = (e) => {
+				spark.append(e.target.result)
+				if (currentChunk < chunks) {
+					currentChunk++
+					loadNext()
+					// 实时展示MD5的计算进度
+					file.statusStr = `校验MD5 ${((currentChunk / chunks) * 100).toFixed(
+						0
+					)}%`
+				} else {
+					let md5 = spark.end()
+					this.calculateFileMD5End(md5, file)
+				}
+			}
+			fileReader.onerror = function () {
+				this.$notify({
+					title: '错误',
+					message: `文件${file.name}读取出错,请检查该文件`,
+					type: 'error',
+					duration: 2000
+				})
+				file.cancel()
+			}
+			function loadNext() {
+				let start = currentChunk * chunkSize
+				let end = start + chunkSize >= file.size ? file.size : start + chunkSize
+				fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end))
+			}
+		},
+		/**
+		 * 文件MD5计算结束
+		 * @param {string} md5 文件 MD5 值
+		 * @param {object} file 文件对象
+		 */
+		calculateFileMD5End(md5, file) {
+			// 将自定义参数直接加载uploader实例的opts上
+			Object.assign(this.uploaderInstance.opts, {
+				query: {
+					...this.params
+				}
+			})
+			file.uniqueIdentifier = md5
+			file.resume()
+			// 移除自定义状态
+			file.statusStr = ''
+		},
+		/**
+		 * 关闭上传面板,并停止上传
+		 */
+		handleClosePanel() {
+			this.uploaderInstance.cancel()
+			this.panelShow = false
+		}
+	}
 }
 </script>
 

+ 224 - 201
src/components/common/ImgPreview.vue

@@ -1,209 +1,232 @@
 <template>
-  <transition name="el-fade-in-linear el-fade-in">
-    <div
-      class="img-preview-wrapper"
-      v-show="imgPreviewVisible"
-      @click.self="closeImgReview"
-      @mousewheel.prevent="rollImg()"
-    >
-      <!-- 顶部信息栏 & 工具栏 -->
-      <div class="tip-wrapper" v-if="imgPreviewVisible">
-        <div class="name" :title="activeFileName + activeExtendName">{{ activeFileName }}.{{ activeExtendName }}</div>
-        <div class="opera-btn-group">
-          <el-input-number v-model="inputActiveIndex" :min="1" :max="imgPreviewList.length" size="mini"></el-input-number>
-          <span class="split-line">/</span>{{ imgPreviewList.length }}
-        </div>
-        <div class="tool-wrapper">
-          <i class="item el-icon-refresh-right" title="向右旋转" @click="rotateImg"></i>
-          <a
-            class="item download-link"
-            target="_blank"
-            :href="activeDownloadLink"
-            :download="activeFileName + '.' + activeExtendName"
-          >
-            <i class="el-icon-download" title="保存到本地"></i>
-          </a>
-          <el-tooltip effect="dark" placement="bottom">
-            <div slot="content">
-              操作提示:<br />
-              点击图片以外的区域可退出查看;<br />
-              按Esc键可退出查看;<br />
-              鼠标滚轮可放大缩小图片
-            </div>
-            <div class="item text-wrapper">
-              <span class="text">操作提示</span>
-              <i class="el-icon-question"></i>
-            </div>
-          </el-tooltip>
-        </div>
-      </div>
-      <!-- 大图查看 -->
-      <img
-        class="img-large"
-        ref="imgLarge"
-        v-for="(item, index) in imgPreviewList"
-        :key="index"
-        :src="item.fileUrl"
-        v-show="index === activeIndex"
-      />
-      <!-- 左右切换图标 -->
-      <i class="pre-icon el-icon-arrow-left" title="上一张" v-show="activeIndex > 0" @click.stop="activeIndex--"></i>
-      <i
-        class="next-icon el-icon-arrow-right"
-        title="下一张"
-        v-show="activeIndex < imgPreviewList.length - 1"
-        @click.stop="activeIndex++"
-      ></i>
-      <!-- 底部显示放大缩小比例 -->
-      <div class="zoom-bar">
-        <el-slider
-          v-model="imgZoom"
-          :min="imgZoomMin"
-          :max="imgZoomMax"
-          :format-tooltip="formatZoom"
-          @input="changeZoom"
-        ></el-slider>
-        <div class="zoom-count">{{ imgZoom }}%</div>
-      </div>
-    </div>
-  </transition>
+	<transition name="el-fade-in-linear el-fade-in">
+		<div
+			class="img-preview-wrapper"
+			v-show="imgPreviewVisible"
+			@click.self="closeImgReview"
+			@mousewheel.prevent="rollImg()"
+		>
+			<!-- 顶部信息栏 & 工具栏 -->
+			<div class="tip-wrapper" v-if="imgPreviewVisible">
+				<div class="name" :title="activeFileName + activeExtendName">
+					{{ activeFileName }}.{{ activeExtendName }}
+				</div>
+				<div class="opera-btn-group">
+					<el-input-number
+						v-model="inputActiveIndex"
+						:min="1"
+						:max="imgPreviewList.length"
+						size="mini"
+					></el-input-number>
+					<span class="split-line">/</span>{{ imgPreviewList.length }}
+				</div>
+				<div class="tool-wrapper">
+					<i
+						class="item el-icon-refresh-right"
+						title="向右旋转"
+						@click="rotateImg"
+					></i>
+					<a
+						class="item download-link"
+						target="_blank"
+						:href="activeDownloadLink"
+						:download="activeFileName + '.' + activeExtendName"
+					>
+						<i class="el-icon-download" title="保存到本地"></i>
+					</a>
+					<el-tooltip effect="dark" placement="bottom">
+						<div slot="content">
+							操作提示:<br />
+							点击图片以外的区域可退出查看;<br />
+							按Esc键可退出查看;<br />
+							鼠标滚轮可放大缩小图片
+						</div>
+						<div class="item text-wrapper">
+							<span class="text">操作提示</span>
+							<i class="el-icon-question"></i>
+						</div>
+					</el-tooltip>
+				</div>
+			</div>
+			<!-- 大图查看 -->
+			<img
+				class="img-large"
+				ref="imgLarge"
+				v-for="(item, index) in imgPreviewList"
+				:key="index"
+				:src="item.fileUrl"
+				v-show="index === activeIndex"
+			/>
+			<!-- 左右切换图标 -->
+			<i
+				class="pre-icon el-icon-arrow-left"
+				title="上一张"
+				v-show="activeIndex > 0"
+				@click.stop="activeIndex--"
+			></i>
+			<i
+				class="next-icon el-icon-arrow-right"
+				title="下一张"
+				v-show="activeIndex < imgPreviewList.length - 1"
+				@click.stop="activeIndex++"
+			></i>
+			<!-- 底部显示放大缩小比例 -->
+			<div class="zoom-bar">
+				<el-slider
+					v-model="imgZoom"
+					:min="imgZoomMin"
+					:max="imgZoomMax"
+					:format-tooltip="formatZoom"
+					@input="changeZoom"
+				></el-slider>
+				<div class="zoom-count">{{ imgZoom }}%</div>
+			</div>
+		</div>
+	</transition>
 </template>
 
 <script>
 export default {
-  name: 'ImgPreview',
-  data() {
-    return {
-      rotate: 0, //  旋转角度
-      activeIndex: 0, //  当前图片索引 从 0 开始
-      imgZoom: 40, //  图片缩放比例
-      imgZoomMin: 1, //  图片缩放最小比例
-      imgZoomMax: 200 //  图片缩放最大比例
-    }
-  },
-  computed: {
-    // 图片查看组件是否显示
-    imgPreviewVisible() {
-      return this.$store.state.imgPreview.imgPreviewVisible
-    },
-    // 图片列表
-    imgPreviewList() {
-      return this.$store.state.imgPreview.imgPreviewList
-    },
-    // 默认显示的图片索引 从 0 开始
-    defaultActiveIndex() {
-      return this.$store.state.imgPreview.defaultActiveIndex
-    },
-    // 当前显示的图片名称
-    activeFileName() {
-      return this.imgPreviewList[this.activeIndex].fileName
-    },
-    // 当前显示的图片扩展名
-    activeExtendName() {
-      return this.imgPreviewList[this.activeIndex].extendName
-    },
-    // 对用户而言 显示的图片索引 从 1 开始 顶部栏输入框控制此值变化
-    inputActiveIndex: {
-      get() {
-        return this.activeIndex + 1
-      },
-      set(value) {
-        this.activeIndex = value - 1
-      }
-    },
-    // 当前显示的图片下载链接
-    activeDownloadLink() {
-      return this.imgPreviewList[this.activeIndex].downloadLink
-    }
-  },
-  watch: {
-    // 监听 图片查看组件 显隐状态变化
-    imgPreviewVisible(val) {
-      let body = document.querySelector('body')
-      if (val) {
-        this.activeIndex = this.defaultActiveIndex
-        // 挂在body下,防止组件元素有样式transform而使position: fixed失效
-        body.appendChild(this.$el)
-        body.style.overflow = 'hidden'
-        // 添加键盘Esc事件
-        this.$nextTick(() => {
-          document.addEventListener('keyup', (e) => {
-            if (e.keyCode === 27) {
-              this.closeImgReview()
-            }
-          })
-        })
-        this.$nextTick(() => {
-          this.$refs.imgLarge[this.activeIndex].style.zoom = '40%'
-        })
-      } else {
-        body.style.overflow = 'auto'
-        document.removeEventListener('keyup', (e) => {
-          if (e.keyCode === 27) {
-            this.closeImgReview()
-          }
-        })
-      }
-    },
-    // 监听 图片索引变化
-    activeIndex(newValue) {
-      this.rotate = 0
-      this.$nextTick(() => {
-        if (this.$refs.imgLarge[newValue].style.zoom) {
-          this.imgZoom = Number(this.$refs.imgLarge[newValue].style.zoom.split('%')[0])
-        } else {
-          this.$refs.imgLarge[newValue].style.zoom = '40%'
-          this.imgZoom = 40
-        }
-      })
-    }
-  },
-  methods: {
-    /**
-     * 关闭图片预览,恢复旋转角度
-     */
-    closeImgReview() {
-      this.$store.commit('setImgPreviewData', { imgPreviewVisible: false })
-      this.rotate = 0
-      this.$refs.imgLarge[this.activeIndex].style.transform = `rotate(${this.rotate}deg)`
-    },
-    /**
-     * 格式化 tooltip message - 显示图片缩放比例
-     * @param {number} value 缩放数字
-     * @returns {string}  图片缩放比例
-     */
-    formatZoom(value) {
-      return value + '%'
-    },
-    /**
-     * 数据改变时触发(使用鼠标拖曳时,活动过程实时触发)
-     * @param {number} value 缩放数字
-     */
-    changeZoom(value) {
-      if (this.$refs.imgLarge) {
-        this.$refs.imgLarge[this.activeIndex].style.zoom = value + '%' //  实时设置图片缩放比例
-      }
-    },
-    /**
-     * 缩放图片
-     */
-    rollImg() {
-      let zoom = parseInt(this.$refs.imgLarge[this.activeIndex].style.zoom) || 100
-      zoom += event.wheelDelta / 12
-      if (zoom >= this.imgZoomMin && zoom < this.imgZoomMax) {
-        this.imgZoom = zoom
-        this.$refs.imgLarge[this.activeIndex].style.zoom = zoom + '%'
-      }
-      return false
-    },
-    /**
-     * 旋转图片
-     */
-    rotateImg() {
-      this.rotate += 90
-      this.$refs.imgLarge[this.activeIndex].style.transform = `rotate(${this.rotate}deg)`
-    }
-  }
+	name: 'ImgPreview',
+	data() {
+		return {
+			rotate: 0, //  旋转角度
+			activeIndex: 0, //  当前图片索引 从 0 开始
+			imgZoom: 40, //  图片缩放比例
+			imgZoomMin: 1, //  图片缩放最小比例
+			imgZoomMax: 200 //  图片缩放最大比例
+		}
+	},
+	computed: {
+		// 图片查看组件是否显示
+		imgPreviewVisible() {
+			return this.$store.state.imgPreview.imgPreviewVisible
+		},
+		// 图片列表
+		imgPreviewList() {
+			return this.$store.state.imgPreview.imgPreviewList
+		},
+		// 默认显示的图片索引 从 0 开始
+		defaultActiveIndex() {
+			return this.$store.state.imgPreview.defaultActiveIndex
+		},
+		// 当前显示的图片名称
+		activeFileName() {
+			return this.imgPreviewList[this.activeIndex].fileName
+		},
+		// 当前显示的图片扩展名
+		activeExtendName() {
+			return this.imgPreviewList[this.activeIndex].extendName
+		},
+		// 对用户而言 显示的图片索引 从 1 开始 顶部栏输入框控制此值变化
+		inputActiveIndex: {
+			get() {
+				return this.activeIndex + 1
+			},
+			set(value) {
+				this.activeIndex = value - 1
+			}
+		},
+		// 当前显示的图片下载链接
+		activeDownloadLink() {
+			return this.imgPreviewList[this.activeIndex].downloadLink
+		}
+	},
+	watch: {
+		// 监听 图片查看组件 显隐状态变化
+		imgPreviewVisible(val) {
+			let body = document.querySelector('body')
+			if (val) {
+				this.activeIndex = this.defaultActiveIndex
+				// 挂在body下,防止组件元素有样式transform而使position: fixed失效
+				body.appendChild(this.$el)
+				body.style.overflow = 'hidden'
+				// 添加键盘Esc事件
+				this.$nextTick(() => {
+					document.addEventListener('keyup', (e) => {
+						if (e.keyCode === 27) {
+							this.closeImgReview()
+						}
+					})
+				})
+				this.$nextTick(() => {
+					this.$refs.imgLarge[this.activeIndex].style.zoom = '40%'
+				})
+			} else {
+				body.style.overflow = 'auto'
+				document.removeEventListener('keyup', (e) => {
+					if (e.keyCode === 27) {
+						this.closeImgReview()
+					}
+				})
+			}
+		},
+		// 监听 图片索引变化
+		activeIndex(newValue) {
+			this.rotate = 0
+			this.$nextTick(() => {
+				if (this.$refs.imgLarge[newValue].style.zoom) {
+					this.imgZoom = Number(
+						this.$refs.imgLarge[newValue].style.zoom.split('%')[0]
+					)
+				} else {
+					this.$refs.imgLarge[newValue].style.zoom = '40%'
+					this.imgZoom = 40
+				}
+			})
+		}
+	},
+	methods: {
+		/**
+		 * 关闭图片预览,恢复旋转角度
+		 */
+		closeImgReview() {
+			this.$store.commit('setImgPreviewData', { imgPreviewVisible: false })
+			this.rotate = 0
+			this.$refs.imgLarge[
+				this.activeIndex
+			].style.transform = `rotate(${this.rotate}deg)`
+		},
+		/**
+		 * 格式化 tooltip message - 显示图片缩放比例
+		 * @param {number} value 缩放数字
+		 * @returns {string}  图片缩放比例
+		 */
+		formatZoom(value) {
+			return value + '%'
+		},
+		/**
+		 * 数据改变时触发(使用鼠标拖曳时,活动过程实时触发)
+		 * @param {number} value 缩放数字
+		 */
+		changeZoom(value) {
+			if (this.$refs.imgLarge) {
+				this.$refs.imgLarge[this.activeIndex].style.zoom = value + '%' //  实时设置图片缩放比例
+			}
+		},
+		/**
+		 * 缩放图片
+		 */
+		rollImg() {
+			let zoom =
+				parseInt(this.$refs.imgLarge[this.activeIndex].style.zoom) || 100
+			zoom += event.wheelDelta / 12
+			if (zoom >= this.imgZoomMin && zoom < this.imgZoomMax) {
+				this.imgZoom = zoom
+				this.$refs.imgLarge[this.activeIndex].style.zoom = zoom + '%'
+			}
+			return false
+		},
+		/**
+		 * 旋转图片
+		 */
+		rotateImg() {
+			this.rotate += 90
+			this.$refs.imgLarge[
+				this.activeIndex
+			].style.transform = `rotate(${this.rotate}deg)`
+		}
+	}
 }
 </script>
 

+ 128 - 115
src/components/common/VideoPreview.vue

@@ -1,50 +1,61 @@
 <template>
-  <transition name="el-zoom-in-top">
-    <div class="video-preview-wrapper" v-show="videoPreviewVisible">
-      <div class="top">
-        <div class="video-name">
-          {{ activeFileObj.fileName }}.{{ activeFileObj.extendName }}
-          <span class="size">{{ calculateFileSize(activeFileObj.fileSize) }}</span>
-        </div>
-        <a class="download-link" :href="getDownloadFilePath(activeFileObj)" target="_blank"
-          ><i class="download-icon el-icon-download" title="下载"></i
-        ></a>
-        <i
-          class="fold-icon"
-          :class="isFoldVideoList ? 'el-icon-s-fold' : 'el-icon-s-unfold'"
-          :title="isFoldVideoList ? '展开播放列表' : '折叠播放列表'"
-          @click="isFoldVideoList = !isFoldVideoList"
-        ></i>
-        <i class="close-icon el-icon-close" title="关闭" @click="handleClosePreview"></i>
-      </div>
-      <div class="bottom">
-        <video-player
-          class="video-player vjs-custom-skin"
-          ref="videoPlayer"
-          :playsinline="true"
-          :options="playerOptions"
-          v-if="videoPreviewVisible"
-        ></video-player>
-        <el-collapse-transition>
-          <div class="video-list-wrapper" v-show="!isFoldVideoList">
-            <div class="list-title">播放列表</div>
-            <ul class="video-list">
-              <li
-                class="video-item"
-                v-for="(item, index) in videoPreviewList"
-                :key="index"
-                :class="[activeIndex === index ? 'active' : '']"
-                @click="activeIndex = index"
-              >
-                <span class="name">{{ item.fileName }}.{{ item.extendName }}</span>
-                <span class="size">{{ calculateFileSize(item.fileSize) }}</span>
-              </li>
-            </ul>
-          </div>
-        </el-collapse-transition>
-      </div>
-    </div>
-  </transition>
+	<transition name="el-zoom-in-top">
+		<div class="video-preview-wrapper" v-show="videoPreviewVisible">
+			<div class="top">
+				<div class="video-name">
+					{{ activeFileObj.fileName }}.{{ activeFileObj.extendName }}
+					<span class="size">{{
+						calculateFileSize(activeFileObj.fileSize)
+					}}</span>
+				</div>
+				<a
+					class="download-link"
+					:href="getDownloadFilePath(activeFileObj)"
+					target="_blank"
+					><i class="download-icon el-icon-download" title="下载"></i
+				></a>
+				<i
+					class="fold-icon"
+					:class="isFoldVideoList ? 'el-icon-s-fold' : 'el-icon-s-unfold'"
+					:title="isFoldVideoList ? '展开播放列表' : '折叠播放列表'"
+					@click="isFoldVideoList = !isFoldVideoList"
+				></i>
+				<i
+					class="close-icon el-icon-close"
+					title="关闭"
+					@click="handleClosePreview"
+				></i>
+			</div>
+			<div class="bottom">
+				<video-player
+					class="video-player vjs-custom-skin"
+					ref="videoPlayer"
+					:playsinline="true"
+					:options="playerOptions"
+					v-if="videoPreviewVisible"
+				></video-player>
+				<el-collapse-transition>
+					<div class="video-list-wrapper" v-show="!isFoldVideoList">
+						<div class="list-title">播放列表</div>
+						<ul class="video-list">
+							<li
+								class="video-item"
+								v-for="(item, index) in videoPreviewList"
+								:key="index"
+								:class="[activeIndex === index ? 'active' : '']"
+								@click="activeIndex = index"
+							>
+								<span class="name"
+									>{{ item.fileName }}.{{ item.extendName }}</span
+								>
+								<span class="size">{{ calculateFileSize(item.fileSize) }}</span>
+							</li>
+						</ul>
+					</div>
+				</el-collapse-transition>
+			</div>
+		</div>
+	</transition>
 </template>
 
 <script>
@@ -57,75 +68,77 @@ import 'video.js/dist/video-js.css'
 import 'vue-video-player/src/custom-theme.css'
 
 export default {
-  name: 'VideoPreview',
-  components: {
-    videoPlayer
-  },
-  data() {
-    return {
-      activeIndex: 0, //  当前打开的视频索引
-      isFoldVideoList: false //  是否折叠右侧视频列表
-    }
-  },
-  computed: {
-    // 视频查看组件是否显示
-    videoPreviewVisible() {
-      return this.$store.state.videoPreview.videoPreviewVisible
-    },
-    // 视频列表
-    videoPreviewList() {
-      return this.$store.state.videoPreview.videoPreviewList
-    },
-    // 默认显示的视频索引 从 0 开始
-    defaultActiveIndex() {
-      return this.$store.state.videoPreview.defaultActiveIndex
-    },
-    // 当前显示的文件信息
-    activeFileObj() {
-      return this.videoPreviewList.length ? this.videoPreviewList[this.activeIndex] : {}
-    },
-    // 播放器配置项
-    playerOptions() {
-      return {
-        playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
-        autoplay: true, //  如果true,浏览器准备好时开始播放。
-        muted: false, // 默认情况下将会消除任何音频。
-        loop: false, // 导致视频一结束就重新开始。
-        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
-        language: 'zh-CN',
-        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
-        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
-        sources: [
-          {
-            type: 'video/mp4', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
-            src: this.videoPreviewList[this.activeIndex].fileUrl // url地址
-          }
-        ],
-        // poster: 'https://p1.music.126.net/5zs7IvmLv7KahY3BFzUmrg==/109951163635241613.jpg?param=600y500', // 你的封面地址
-        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
-        controlBar: {
-          timeDivider: true,
-          durationDisplay: true,
-          remainingTimeDisplay: false,
-          fullscreenToggle: true // 全屏按钮
-        }
-      }
-    }
-  },
-  watch: {
-    // 监听视频预览组件状态
-    videoPreviewVisible(newValue) {
-      if (newValue) {
-        this.activeIndex = this.defaultActiveIndex
-      }
-    }
-  },
-  methods: {
-    // 关闭图片预览
-    handleClosePreview() {
-      this.$store.commit('setVideoPreviewData', { videoPreviewVisible: false })
-    }
-  }
+	name: 'VideoPreview',
+	components: {
+		videoPlayer
+	},
+	data() {
+		return {
+			activeIndex: 0, //  当前打开的视频索引
+			isFoldVideoList: false //  是否折叠右侧视频列表
+		}
+	},
+	computed: {
+		// 视频查看组件是否显示
+		videoPreviewVisible() {
+			return this.$store.state.videoPreview.videoPreviewVisible
+		},
+		// 视频列表
+		videoPreviewList() {
+			return this.$store.state.videoPreview.videoPreviewList
+		},
+		// 默认显示的视频索引 从 0 开始
+		defaultActiveIndex() {
+			return this.$store.state.videoPreview.defaultActiveIndex
+		},
+		// 当前显示的文件信息
+		activeFileObj() {
+			return this.videoPreviewList.length
+				? this.videoPreviewList[this.activeIndex]
+				: {}
+		},
+		// 播放器配置项
+		playerOptions() {
+			return {
+				playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+				autoplay: true, //  如果true,浏览器准备好时开始播放。
+				muted: false, // 默认情况下将会消除任何音频。
+				loop: false, // 导致视频一结束就重新开始。
+				preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+				language: 'zh-CN',
+				aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+				fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+				sources: [
+					{
+						type: 'video/mp4', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
+						src: this.videoPreviewList[this.activeIndex].fileUrl // url地址
+					}
+				],
+				// poster: 'https://p1.music.126.net/5zs7IvmLv7KahY3BFzUmrg==/109951163635241613.jpg?param=600y500', // 你的封面地址
+				notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+				controlBar: {
+					timeDivider: true,
+					durationDisplay: true,
+					remainingTimeDisplay: false,
+					fullscreenToggle: true // 全屏按钮
+				}
+			}
+		}
+	},
+	watch: {
+		// 监听视频预览组件状态
+		videoPreviewVisible(newValue) {
+			if (newValue) {
+				this.activeIndex = this.defaultActiveIndex
+			}
+		}
+	},
+	methods: {
+		// 关闭图片预览
+		handleClosePreview() {
+			this.$store.commit('setVideoPreviewData', { videoPreviewVisible: false })
+		}
+	}
 }
 </script>
 

+ 16 - 11
src/config/index.js

@@ -2,17 +2,22 @@
  * 存放项目配置
  */
 const config = {
-  /**
-   * @description 域名
-   *              区分生产环境和开发环境,用来存放session及一些用户配置信息(左侧菜单栏是否收缩等)
-   *              冒号之前配置生产环境域名
-   *              冒号之后配置开发环境域名,开发环境域名默认使用主机名
-   */
-  domain: process.env.NODE_ENV === 'production' ? location.host.indexOf('.qiwenshare.com')  !== -1 ? '.qiwenshare.com' : '' : location.hostname,
-  /**
-   * @description 文件展示模式选择列表时,所有可供选择的表格列名
-   */
-  allColumnList: ['extendName', 'fileSize', 'uploadTime', 'deleteTime']
+	/**
+	 * @description 域名
+	 *              区分生产环境和开发环境,用来存放session及一些用户配置信息(左侧菜单栏是否收缩等)
+	 *              冒号之前配置生产环境域名
+	 *              冒号之后配置开发环境域名,开发环境域名默认使用主机名
+	 */
+	domain:
+		process.env.NODE_ENV === 'production'
+			? location.host.indexOf('.qiwenshare.com') !== -1
+				? '.qiwenshare.com'
+				: ''
+			: location.hostname,
+	/**
+	 * @description 文件展示模式选择列表时,所有可供选择的表格列名
+	 */
+	allColumnList: ['extendName', 'fileSize', 'uploadTime', 'deleteTime']
 }
 
 export default config

+ 115 - 115
src/element.js

@@ -1,119 +1,119 @@
 // 导入自己需要的组件
 import {
-  Dialog,
-  Dropdown,
-  DropdownMenu,
-  DropdownItem,
-  Menu,
-  Submenu,
-  MenuItem,
-  MenuItemGroup,
-  Input,
-  InputNumber,
-  Radio,
-  RadioGroup,
-  RadioButton,
-  Select,
-  Option,
-  OptionGroup,
-  Button,
-  ButtonGroup,
-  Table,
-  TableColumn,
-  Tooltip,
-  Form,
-  FormItem,
-  Icon,
-  Upload,
-  Image,
-  Backtop,
-  MessageBox,
-  Message,
-  Notification,
-  Avatar,
-  Container,
-  Header,
-  Aside,
-  Main,
-  Footer,
-  Breadcrumb,
-  BreadcrumbItem,
-  Loading,
-  Timeline,
-  TimelineItem,
-  Alert,
-  Tree,
-  Progress,
-  Slider,
-  Divider,
-  Pagination,
-  CheckboxGroup,
-  Checkbox,
-  Popover,
-  Carousel,
-  CarouselItem,
-  DatePicker
-} from "element-ui";
+	Dialog,
+	Dropdown,
+	DropdownMenu,
+	DropdownItem,
+	Menu,
+	Submenu,
+	MenuItem,
+	MenuItemGroup,
+	Input,
+	InputNumber,
+	Radio,
+	RadioGroup,
+	RadioButton,
+	Select,
+	Option,
+	OptionGroup,
+	Button,
+	ButtonGroup,
+	Table,
+	TableColumn,
+	Tooltip,
+	Form,
+	FormItem,
+	Icon,
+	Upload,
+	Image,
+	Backtop,
+	MessageBox,
+	Message,
+	Notification,
+	Avatar,
+	Container,
+	Header,
+	Aside,
+	Main,
+	Footer,
+	Breadcrumb,
+	BreadcrumbItem,
+	Loading,
+	Timeline,
+	TimelineItem,
+	Alert,
+	Tree,
+	Progress,
+	Slider,
+	Divider,
+	Pagination,
+	CheckboxGroup,
+	Checkbox,
+	Popover,
+	Carousel,
+	CarouselItem,
+	DatePicker
+} from 'element-ui'
 
 const element = {
-  install: function (Vue) {
-    Vue.use(Dialog);
-    Vue.use(Dropdown);
-    Vue.use(DropdownMenu);
-    Vue.use(DropdownItem);
-    Vue.use(Menu);
-    Vue.use(Submenu);
-    Vue.use(MenuItem);
-    Vue.use(MenuItemGroup);
-    Vue.use(Input);
-    Vue.use(InputNumber);
-    Vue.use(Radio);
-    Vue.use(RadioGroup);
-    Vue.use(RadioButton);
-    Vue.use(Select);
-    Vue.use(Option);
-    Vue.use(OptionGroup);
-    Vue.use(Button);
-    Vue.use(ButtonGroup);
-    Vue.use(Table);
-    Vue.use(TableColumn);
-    Vue.use(Tooltip);
-    Vue.use(Form);
-    Vue.use(FormItem);
-    Vue.use(Icon);
-    Vue.use(Upload);
-    Vue.use(Image);
-    Vue.use(Backtop);
-    Vue.use(Avatar);
-    Vue.use(Container);
-    Vue.use(Header);
-    Vue.use(Aside);
-    Vue.use(Main);
-    Vue.use(Footer);
-    Vue.use(Breadcrumb);
-    Vue.use(BreadcrumbItem);
-    Vue.use(Loading.directive);
-    Vue.use(Timeline);
-    Vue.use(TimelineItem);
-    Vue.use(Alert);
-    Vue.use(Tree);
-    Vue.use(Progress);
-    Vue.use(Slider);
-    Vue.use(Divider);
-    Vue.use(Pagination);
-    Vue.use(CheckboxGroup);
-    Vue.use(Checkbox);
-    Vue.use(Popover);
-    Vue.use(Carousel);
-    Vue.use(CarouselItem);
-    Vue.use(DatePicker);
-    Vue.prototype.$loading = Loading.service;
-    Vue.prototype.$msgbox = MessageBox;
-    Vue.prototype.$alert = MessageBox.alert;
-    Vue.prototype.$confirm = MessageBox.confirm;
-    Vue.prototype.$prompt = MessageBox.prompt;
-    Vue.prototype.$notify = Notification;
-    Vue.prototype.$message = Message;
-  },
-};
-export default element;
+	install: function (Vue) {
+		Vue.use(Dialog)
+		Vue.use(Dropdown)
+		Vue.use(DropdownMenu)
+		Vue.use(DropdownItem)
+		Vue.use(Menu)
+		Vue.use(Submenu)
+		Vue.use(MenuItem)
+		Vue.use(MenuItemGroup)
+		Vue.use(Input)
+		Vue.use(InputNumber)
+		Vue.use(Radio)
+		Vue.use(RadioGroup)
+		Vue.use(RadioButton)
+		Vue.use(Select)
+		Vue.use(Option)
+		Vue.use(OptionGroup)
+		Vue.use(Button)
+		Vue.use(ButtonGroup)
+		Vue.use(Table)
+		Vue.use(TableColumn)
+		Vue.use(Tooltip)
+		Vue.use(Form)
+		Vue.use(FormItem)
+		Vue.use(Icon)
+		Vue.use(Upload)
+		Vue.use(Image)
+		Vue.use(Backtop)
+		Vue.use(Avatar)
+		Vue.use(Container)
+		Vue.use(Header)
+		Vue.use(Aside)
+		Vue.use(Main)
+		Vue.use(Footer)
+		Vue.use(Breadcrumb)
+		Vue.use(BreadcrumbItem)
+		Vue.use(Loading.directive)
+		Vue.use(Timeline)
+		Vue.use(TimelineItem)
+		Vue.use(Alert)
+		Vue.use(Tree)
+		Vue.use(Progress)
+		Vue.use(Slider)
+		Vue.use(Divider)
+		Vue.use(Pagination)
+		Vue.use(CheckboxGroup)
+		Vue.use(Checkbox)
+		Vue.use(Popover)
+		Vue.use(Carousel)
+		Vue.use(CarouselItem)
+		Vue.use(DatePicker)
+		Vue.prototype.$loading = Loading.service
+		Vue.prototype.$msgbox = MessageBox
+		Vue.prototype.$alert = MessageBox.alert
+		Vue.prototype.$confirm = MessageBox.confirm
+		Vue.prototype.$prompt = MessageBox.prompt
+		Vue.prototype.$notify = Notification
+		Vue.prototype.$message = Message
+	}
+}
+export default element

+ 19 - 18
src/filters/index.js

@@ -1,7 +1,7 @@
 /**
  * 存储值格式化
- * @param {number} size 
- * @param {boolean} status 
+ * @param {number} size
+ * @param {boolean} status
  * @returns {string} 存储值(带单位)
  */
 const storageTrans = (size, status) => {
@@ -9,29 +9,30 @@ const storageTrans = (size, status) => {
 	const KB = Math.pow(1024, 2)
 	const MB = Math.pow(1024, 3)
 	const GB = Math.pow(1024, 4)
-	if(status) {	//	截取整数部分
+	if (status) {
+		//	截取整数部分
 		if (!size) {
-			return  0 + 'KB'
+			return 0 + 'KB'
 		} else if (size < KB) {
-			return  (size / B).toFixed(0) + 'KB'
+			return (size / B).toFixed(0) + 'KB'
 		} else if (size < MB) {
-			return  (size / KB).toFixed(0) + 'MB'
+			return (size / KB).toFixed(0) + 'MB'
 		} else if (size < GB) {
-			return  (size / MB).toFixed(0) + 'GB'
+			return (size / MB).toFixed(0) + 'GB'
 		} else {
-			return  (size / GB).toFixed(0) + 'TB'
+			return (size / GB).toFixed(0) + 'TB'
 		}
 	} else {
 		if (!size) {
-			return  0 + 'KB'
+			return 0 + 'KB'
 		} else if (size < KB) {
-			return  (size / B).toFixed(0) + 'KB'
+			return (size / B).toFixed(0) + 'KB'
 		} else if (size < MB) {
-			return  (size / KB).toFixed(2) + 'MB'
+			return (size / KB).toFixed(2) + 'MB'
 		} else if (size < GB) {
-			return  (size / MB).toFixed(3) + 'GB'
+			return (size / MB).toFixed(3) + 'GB'
 		} else {
-			return  (size / GB).toFixed(4) + 'TB'
+			return (size / GB).toFixed(4) + 'TB'
 		}
 	}
 }
@@ -42,10 +43,10 @@ const storageTrans = (size, status) => {
  * @returns {string} 完整文件名称
  */
 const fileNameComplete = (file) => {
-	return file.fileName + (file.isDir === 0 && file.extendName ? `.${file.extendName}` : '')
+	return (
+		file.fileName +
+		(file.isDir === 0 && file.extendName ? `.${file.extendName}` : '')
+	)
 }
 
-export {
-	storageTrans,
-	fileNameComplete
-}
+export { storageTrans, fileNameComplete }

+ 201 - 176
src/globalFunction.js

@@ -1,186 +1,211 @@
 import Cookies from 'js-cookie'
 import config from '@/config'
-import { Message } from 'element-ui';
+import { Message } from 'element-ui'
 
 // 全局函数
 const globalFunction = {
-  /**
-   * 格式化文件大小
-   * @param {number} size 文件大小
-   * @returns {string} 文件大小(带单位)
-   */
-  calculateFileSize: function (size) {
-    const B = 1024
-    const KB = Math.pow(1024, 2)
-    const MB = Math.pow(1024, 3)
-    const GB = Math.pow(1024, 4)
-    if(size === 0) {
-      return '0KB'
-    } else if (!size) {
-      return '_'
-    } else if (size < KB) {
-      return `${(size / B).toFixed(0)}KB`
-    } else if (size < MB) {
-      return (size / KB).toFixed(1) + 'MB'
-    } else if (size < GB) {
-      return (size / MB).toFixed(2) + 'GB'
-    } else {
-      return (size / GB).toFixed(3) + 'TB'
-    }
-  },
-  /**
-   * 获取图片缩略图路径
-   * @param {object} row 文件信息
-   * @returns {string} 图片缩略图路径
-   */
-  getImgMinPath: function (row) {
-    return `/api/filetransfer/preview?userFileId=${row.userFileId}&isMin=true&shareBatchNum=${row.shareBatchNum}&extractionCode=${row.extractionCode}&token=${globalFunction.getCookies('token')}`
-  },
-  /**
-   * 获取文件查看路径
-   * @param {object} row 文件信息
-   * @returns {string} 文件路径
-   */
-  getViewFilePath: function (row) {
-    return `/api/filetransfer/preview?userFileId=${row.userFileId}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${row.extractionCode}&token=${globalFunction.getCookies('token')}`
-  },
-  /**
-   * 获取文件下载路径
-   * @param {object} row 文件信息
-   * @returns {string}  文件下载路径
-   */
-  getDownloadFilePath: function (row) {
-    return `/api/filetransfer/downloadfile?userFileId=${row.userFileId}&shareBatchNum=${row.shareBatchNum}&extractionCode=${row.extractionCode}&token=${globalFunction.getCookies('token')}`
-  },
-  /**
-   * 获取 Onlyoffice 文件创建路径
-   * @param {object} row 
-   * @returns {string} office 文件创建路径
-   */
-  createFileOnlineByOffice: function (data) {
-    let fileUrl = `${location.protocol}//${location.host}/api`
-    const { href } = this.$router.resolve({
-      name: 'Onlyoffice',
-      query: {
-        fileUrl: fileUrl,
-        fileName: data.fileName,
-        filePath: data.filePath,
-        extendName: data.extendName,
-        ot: 'add'
-      }
-    })
-    window.open(href, '_blank')
-  },
-  /**
-   * 获取 Onlyoffice 文件在线预览路径
-   * @param {object} row 
-   * @returns {string} office 文件在线预览路径
-   */
-  getFileOnlineViewPathByOffice: function (row) {
-    let fileUrl = ''
-    let fileName = row.fileName + "." + row.extendName
-    let filePath = row.fileUrl
-    let fileId = row.fileId
-    let userFileId = row.userFileId
-    let extendName = row.extendName
+	/**
+	 * 格式化文件大小
+	 * @param {number} size 文件大小
+	 * @returns {string} 文件大小(带单位)
+	 */
+	calculateFileSize: function (size) {
+		const B = 1024
+		const KB = Math.pow(1024, 2)
+		const MB = Math.pow(1024, 3)
+		const GB = Math.pow(1024, 4)
+		if (size === 0) {
+			return '0KB'
+		} else if (!size) {
+			return '_'
+		} else if (size < KB) {
+			return `${(size / B).toFixed(0)}KB`
+		} else if (size < MB) {
+			return (size / KB).toFixed(1) + 'MB'
+		} else if (size < GB) {
+			return (size / MB).toFixed(2) + 'GB'
+		} else {
+			return (size / GB).toFixed(3) + 'TB'
+		}
+	},
+	/**
+	 * 获取图片缩略图路径
+	 * @param {object} row 文件信息
+	 * @returns {string} 图片缩略图路径
+	 */
+	getImgMinPath: function (row) {
+		return `/api/filetransfer/preview?userFileId=${
+			row.userFileId
+		}&isMin=true&shareBatchNum=${row.shareBatchNum}&extractionCode=${
+			row.extractionCode
+		}&token=${globalFunction.getCookies('token')}`
+	},
+	/**
+	 * 获取文件查看路径
+	 * @param {object} row 文件信息
+	 * @returns {string} 文件路径
+	 */
+	getViewFilePath: function (row) {
+		return `/api/filetransfer/preview?userFileId=${
+			row.userFileId
+		}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${
+			row.extractionCode
+		}&token=${globalFunction.getCookies('token')}`
+	},
+	/**
+	 * 获取文件下载路径
+	 * @param {object} row 文件信息
+	 * @returns {string}  文件下载路径
+	 */
+	getDownloadFilePath: function (row) {
+		return `/api/filetransfer/downloadfile?userFileId=${
+			row.userFileId
+		}&shareBatchNum=${row.shareBatchNum}&extractionCode=${
+			row.extractionCode
+		}&token=${globalFunction.getCookies('token')}`
+	},
+	/**
+	 * 获取 Onlyoffice 文件创建路径
+	 * @param {object} row
+	 * @returns {string} office 文件创建路径
+	 */
+	createFileOnlineByOffice: function (data) {
+		let fileUrl = `${location.protocol}//${location.host}/api`
+		const { href } = this.$router.resolve({
+			name: 'Onlyoffice',
+			query: {
+				fileUrl: fileUrl,
+				fileName: data.fileName,
+				filePath: data.filePath,
+				extendName: data.extendName,
+				ot: 'add'
+			}
+		})
+		window.open(href, '_blank')
+	},
+	/**
+	 * 获取 Onlyoffice 文件在线预览路径
+	 * @param {object} row
+	 * @returns {string} office 文件在线预览路径
+	 */
+	getFileOnlineViewPathByOffice: function (row) {
+		let fileUrl = ''
+		let fileName = row.fileName + '.' + row.extendName
+		let filePath = row.fileUrl
+		let fileId = row.fileId
+		let userFileId = row.userFileId
+		let extendName = row.extendName
 
-    fileUrl = `${location.protocol}//${location.host}/api/filetransfer/preview?userFileId=${row.userFileId}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${row.extractionCode}&token=${globalFunction.getCookies('token')}`
-    const { href } = this.$router.resolve({
-      name: 'Onlyoffice',
-      query: {
-        fileUrl: fileUrl,
-        fileName: fileName,
-        filePath: filePath,
-        fileId: fileId,
-        userFileId: userFileId,
-        extendName: extendName,
-        ot: 'detail'
-      }
-    })
-    window.open(href, '_blank')
-  },
-  /**
-   * 获取 Onlyoffice 文件在线编辑路径
-   * @param {object} row 
-   * @returns {string} office 文件在线编辑路径
-   */
-  getFileOnlineEditPathByOffice: function (row) {
-    let fileUrl = ''
-    let fileName = row.fileName + "." + row.extendName
-    let filePath = row.fileUrl
-    let fileId = row.fileId
-    let userFileId = row.userFileId
-    let extendName = row.extendName
+		fileUrl = `${location.protocol}//${
+			location.host
+		}/api/filetransfer/preview?userFileId=${
+			row.userFileId
+		}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${
+			row.extractionCode
+		}&token=${globalFunction.getCookies('token')}`
+		const { href } = this.$router.resolve({
+			name: 'Onlyoffice',
+			query: {
+				fileUrl: fileUrl,
+				fileName: fileName,
+				filePath: filePath,
+				fileId: fileId,
+				userFileId: userFileId,
+				extendName: extendName,
+				ot: 'detail'
+			}
+		})
+		window.open(href, '_blank')
+	},
+	/**
+	 * 获取 Onlyoffice 文件在线编辑路径
+	 * @param {object} row
+	 * @returns {string} office 文件在线编辑路径
+	 */
+	getFileOnlineEditPathByOffice: function (row) {
+		let fileUrl = ''
+		let fileName = row.fileName + '.' + row.extendName
+		let filePath = row.fileUrl
+		let fileId = row.fileId
+		let userFileId = row.userFileId
+		let extendName = row.extendName
 
-    fileUrl = `${location.protocol}//${location.host}/api/filetransfer/preview?userFileId=${row.userFileId}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${row.extractionCode}&token=${globalFunction.getCookies('token')}`
-    const { href } = this.$router.resolve({
-      name: 'Onlyoffice',
-      query: {
-        fileUrl: fileUrl,
-        fileName: fileName,
-        filePath: filePath,
-        fileId: fileId,
-        userFileId: userFileId,
-        extendName: extendName,
-        ot: 'edit'
-      }
-    })
-    window.open(href, '_blank')
-  },
-  /**
-   * 设置 Cookies
-   * @param {string} name 名称
-   * @param {string} value 值
-   * @param {object} others 域名、路径、有效期等,封装到对象中
-   */
-  setCookies: function (name, value, others = null) {
-    Cookies.set(name, value, { domain: config.domain, ...others })
-  },
-  /**
-   * 获取 Cookies
-   * @param {string} name 名称
-   * @param {object} others 域名、路径等,封装到对象中
-   * @returns {string} Cookies 值
-   */
-  getCookies: function (name, others = null) {
-    return Cookies.get(name, { domain: config.domain, ...others })
-  },
-  /**
-   * 移除 Cookies
-   * @param {string} name 名称
-   * @param {object} others 域名、路径等,封装到对象中
-   */
-  removeCookies: function (name, others = null) {
-    Cookies.remove(name, { domain: config.domain, ...others })
-  },
-  /**
-   * 获取分享链接
-   * @param {string} shareBatchNum 
-   * @returns {string} 完整的分享链接
-   */
-  getShareLink: function (shareBatchNum) {
-    return `${location.protocol}//${location.host}/share/${shareBatchNum}`
-  },
-  /**
-   * 复制分享链接
-   * @param {string} shareBatchNum 
-   * @param {string} extractionCode 
-   */
-  copyShareLink: function (shareBatchNum, extractionCode) {
-    let input = document.createElement('textarea') // 直接构建textarea以保持换行
-    input.value =
-      extractionCode === null
-        ? `分享链接:${this.getShareLink(
-          shareBatchNum
-        )}\n复制链接到浏览器中并输入提取码即可查看文件`
-        : `分享链接:${this.getShareLink(shareBatchNum)}\n提取码:${extractionCode
-        }\n复制链接到浏览器中并输入提取码即可查看文件` // 设置内容
-    document.body.appendChild(input) // 添加临时实例
-    input.select() // 选择实例内容
-    document.execCommand('Copy') // 执行复制
-    document.body.removeChild(input) // 删除临时实例
-    Message.success('复制成功')
-  }
+		fileUrl = `${location.protocol}//${
+			location.host
+		}/api/filetransfer/preview?userFileId=${
+			row.userFileId
+		}&isMin=false&shareBatchNum=${row.shareBatchNum}&extractionCode=${
+			row.extractionCode
+		}&token=${globalFunction.getCookies('token')}`
+		const { href } = this.$router.resolve({
+			name: 'Onlyoffice',
+			query: {
+				fileUrl: fileUrl,
+				fileName: fileName,
+				filePath: filePath,
+				fileId: fileId,
+				userFileId: userFileId,
+				extendName: extendName,
+				ot: 'edit'
+			}
+		})
+		window.open(href, '_blank')
+	},
+	/**
+	 * 设置 Cookies
+	 * @param {string} name 名称
+	 * @param {string} value 值
+	 * @param {object} others 域名、路径、有效期等,封装到对象中
+	 */
+	setCookies: function (name, value, others = null) {
+		Cookies.set(name, value, { domain: config.domain, ...others })
+	},
+	/**
+	 * 获取 Cookies
+	 * @param {string} name 名称
+	 * @param {object} others 域名、路径等,封装到对象中
+	 * @returns {string} Cookies 值
+	 */
+	getCookies: function (name, others = null) {
+		return Cookies.get(name, { domain: config.domain, ...others })
+	},
+	/**
+	 * 移除 Cookies
+	 * @param {string} name 名称
+	 * @param {object} others 域名、路径等,封装到对象中
+	 */
+	removeCookies: function (name, others = null) {
+		Cookies.remove(name, { domain: config.domain, ...others })
+	},
+	/**
+	 * 获取分享链接
+	 * @param {string} shareBatchNum
+	 * @returns {string} 完整的分享链接
+	 */
+	getShareLink: function (shareBatchNum) {
+		return `${location.protocol}//${location.host}/share/${shareBatchNum}`
+	},
+	/**
+	 * 复制分享链接
+	 * @param {string} shareBatchNum
+	 * @param {string} extractionCode
+	 */
+	copyShareLink: function (shareBatchNum, extractionCode) {
+		let input = document.createElement('textarea') // 直接构建textarea以保持换行
+		input.value =
+			extractionCode === null
+				? `分享链接:${this.getShareLink(
+						shareBatchNum
+				  )}\n复制链接到浏览器中并输入提取码即可查看文件`
+				: `分享链接:${this.getShareLink(
+						shareBatchNum
+				  )}\n提取码:${extractionCode}\n复制链接到浏览器中并输入提取码即可查看文件` // 设置内容
+		document.body.appendChild(input) // 添加临时实例
+		input.select() // 选择实例内容
+		document.execCommand('Copy') // 执行复制
+		document.body.removeChild(input) // 删除临时实例
+		Message.success('复制成功')
+	}
 }
 
 export default globalFunction

+ 12 - 12
src/main.js

@@ -17,26 +17,26 @@ import element from './element.js'
  */
 import uploader from 'vue-simple-uploader'
 // collapse 展开折叠
-import CollapseTransition from 'element-ui/lib/transitions/collapse-transition';
+import CollapseTransition from 'element-ui/lib/transitions/collapse-transition'
 
 Vue.component(CollapseTransition.name, CollapseTransition)
 
-Vue.config.productionTip = false;
+Vue.config.productionTip = false
 
-for(let key in globalFunction) {
-  Vue.prototype[key] = globalFunction[key]
+for (let key in globalFunction) {
+	Vue.prototype[key] = globalFunction[key]
 }
 
-Vue.use(element);
-Vue.use(uploader);
+Vue.use(element)
+Vue.use(uploader)
 Vue.prototype.$EventBus = new Vue()
 
-Object.keys(filters).forEach(key => {
-  Vue.filter(key, filters[key])
+Object.keys(filters).forEach((key) => {
+	Vue.filter(key, filters[key])
 })
 
 new Vue({
-  router,
-  store,
-  render: h => h(App)
-}).$mount('#app')
+	router,
+	store,
+	render: (h) => h(App)
+}).$mount('#app')

+ 30 - 28
src/request/file.js

@@ -1,9 +1,9 @@
 // 文件模块相关接口
 import { get, post } from './http'
 /**
- * 以登录接口为例 
+ * 以登录接口为例
  * export const login = p => get('/user/login', p);
- * 
+ *
  * login ---------- 接口名称
  * p -------------- 传参,若需要在url中拼接其他信息,传参可以改为(p, other)
  * get ------------ 接口调用的方法,来自 http.js 中封装好的四个axios方法 get/post/put/axiosDelete
@@ -11,9 +11,9 @@ import { get, post } from './http'
  *                  首先需要在传参处改为(p, other1, other2)
  *                  然后将url改为`/user/${other1}/login/${other2}`
  * p -------------- 传递给 get/post/put/axiosDelete 中的查询参数/请求体
- * 
- * 
- * 
+ *
+ *
+ *
  * 除此之外,POST 请求支持请求体格式为 FormData,那么就需要多传递一个参数,true,如下示例:
  * export const example = p => post('/test/example', p, true);
  */
@@ -22,60 +22,62 @@ import { get, post } from './http'
  * 获取文件列表相关接口
  */
 // 获取文件列表(区分文件路径)
-export const getFileListByPath = p => get('/file/getfilelist', p);
+export const getFileListByPath = (p) => get('/file/getfilelist', p)
 // 获取文件列表(区分文件类型)
-export const getFileListByType = p => get('/file/selectfilebyfiletype', p);
+export const getFileListByType = (p) => get('/file/selectfilebyfiletype', p)
 // 获取回收站文件列表
-export const getRecoveryFile = p => post('/recoveryfile/list', p);
+export const getRecoveryFile = (p) => post('/recoveryfile/list', p)
 // 获取我已分享的文件列表
-export const getMyShareFileList = p => get('/share/shareList', p);
+export const getMyShareFileList = (p) => get('/share/shareList', p)
 // 获取存储占用
-export const getStorage = p => get('/filetransfer/getstorage', p);
+export const getStorage = (p) => get('/filetransfer/getstorage', p)
 // 获取文件目录树
-export const getFoldTree = p => get('/file/getfiletree', p);
+export const getFoldTree = (p) => get('/file/getfiletree', p)
 
 /**
  * 单文件操作相关接口
  */
 // 创建文件
-export const createFold = p => post('/file/createfile', p);
+export const createFold = (p) => post('/file/createfile', p)
 // 删除文件
-export const deleteFile = p => post('/file/deletefile', p);
+export const deleteFile = (p) => post('/file/deletefile', p)
 // 移动文件
-export const moveFile = p => post('/file/movefile', p);
+export const moveFile = (p) => post('/file/movefile', p)
 // 重命名文件
-export const renameFile = p => post('/file/renamefile', p);
+export const renameFile = (p) => post('/file/renamefile', p)
 // 解压文件
-export const unzipFile = p => post('/file/unzipfile', p);
+export const unzipFile = (p) => post('/file/unzipfile', p)
 // 全局搜索文件
-export const searchFile = p => get('/file/search', p);
+export const searchFile = (p) => get('/file/search', p)
 // 分享文件
-export const shareFile = p => post('/share/sharefile', p);
+export const shareFile = (p) => post('/share/sharefile', p)
 // 校验分享链接过期时间
-export const checkShareLinkEndtime = p => get('/share/checkendtime', p);
+export const checkShareLinkEndtime = (p) => get('/share/checkendtime', p)
 // 校验分享链接是否需要提取码
-export const checkShareLinkType = p => get('/share/sharetype', p);
+export const checkShareLinkType = (p) => get('/share/sharetype', p)
 // 校验分享链接提取码是否正确
-export const checkShareLinkCode = p => get('/share/checkextractioncode', p);
+export const checkShareLinkCode = (p) => get('/share/checkextractioncode', p)
 // 获取分享文件列表
-export const getShareFileList = p => get('/share/sharefileList', p);
+export const getShareFileList = (p) => get('/share/sharefileList', p)
 // 保存分享文件
-export const saveShareFile = p => post('/share/savesharefile', p);
+export const saveShareFile = (p) => post('/share/savesharefile', p)
 
 /**
  * 文件批量操作相关接口
  */
 // 批量删除文件
-export const batchDeleteFile = p => post('/file/batchdeletefile', p);
+export const batchDeleteFile = (p) => post('/file/batchdeletefile', p)
 // 批量移动文件
-export const batchMoveFile = p => post('/file/batchmovefile', p);
+export const batchMoveFile = (p) => post('/file/batchmovefile', p)
 
 /**
  * 回收站文件操作相关接口
  */
 // 回收站文件删除
-export const deleteRecoveryFile = p => post('/recoveryfile/deleterecoveryfile', p);
+export const deleteRecoveryFile = (p) =>
+	post('/recoveryfile/deleterecoveryfile', p)
 // 回收站文件还原
-export const restoreRecoveryFile = p => post('/recoveryfile/restorefile', p);
+export const restoreRecoveryFile = (p) => post('/recoveryfile/restorefile', p)
 // 回收站文件批量删除
-export const batchDeleteRecoveryFile = p => post('/recoveryfile/batchdelete', p);
+export const batchDeleteRecoveryFile = (p) =>
+	post('/recoveryfile/batchdelete', p)

+ 3 - 3
src/request/onlyoffice.js

@@ -2,8 +2,8 @@
 import { post } from './http'
 
 // 创建文档
-export const createOfficeFile = p => post('/office/createofficefile', p);
+export const createOfficeFile = (p) => post('/office/createofficefile', p)
 // 编辑文档
-export const editOfficeFile = p => post('/office/editofficefile', p);
+export const editOfficeFile = (p) => post('/office/editofficefile', p)
 // 查看文档
-export const previewOfficeFile = p => post('/office/previewofficefile', p);
+export const previewOfficeFile = (p) => post('/office/previewofficefile', p)

+ 8 - 8
src/request/user.js

@@ -2,9 +2,9 @@
 import { get, post } from './http'
 
 /**
- * 以登录接口为例 
+ * 以登录接口为例
  * export const login = p => get('/user/login', p);
- * 
+ *
  * login ---------- 接口名称
  * p -------------- 传参,若需要在url中拼接其他信息,传参可以改为(p, other)
  * get ------------ 接口调用的方法,来自 http.js 中封装好的四个axios方法 get/post/put/axiosDelete
@@ -12,16 +12,16 @@ import { get, post } from './http'
  *                  首先需要在传参处改为(p, other1, other2)
  *                  然后将url改为`/user/${other1}/login/${other2}`
  * p -------------- 传递给 get/post/put/axiosDelete 中的查询参数/请求体
- * 
- * 
- * 
+ *
+ *
+ *
  * 除此之外,POST 请求支持请求体格式为 FormData,那么就需要多传递一个参数,true,如下示例:
  * export const example = p => post('/test/example', p, true);
  */
 
 // 用户登录
-export const login = p => get('/user/login', p);
+export const login = (p) => get('/user/login', p)
 // 获取登录状态及用户信息
-export const checkUserLoginInfo = p => get('/user/checkuserlogininfo', p);
+export const checkUserLoginInfo = (p) => get('/user/checkuserlogininfo', p)
 // 用户注册
-export const addUser = p => post('/user/register', p);
+export const addUser = (p) => post('/user/register', p)

+ 2 - 2
src/router/before.js

@@ -21,11 +21,11 @@ router.beforeEach((to, from, next) => {
 		// 调用获取用户登录状态和信息的接口,以便显示顶部导航栏的用户登录信息
 		store.dispatch('getUserInfo')
 	}
-	// 路由发生变化修改页面title
+	// 路由发生变化修改页面 title
 	if (to.meta.title) {
 		document.title = to.meta.title
 	}
-	// 路由发生变化修改页面meta
+	// 路由发生变化修改页面 meta
 	if (to.meta.content) {
 		let head = document.getElementsByTagName('head')
 		let meta = document.createElement('meta')

+ 86 - 78
src/router/router.js

@@ -4,86 +4,94 @@ import Router from 'vue-router'
 Vue.use(Router)
 
 export default new Router({
-  mode: 'history',
-  base: process.env.BASE_URL,
-  routes: [
-    {
-      path: '/',
-      name: 'Home',
-      component: () => import(/* webpackChunkName: "home" */ '_v/Home'),
-      meta: { 
-        title: '奇文网盘' ,
-        content: {
-          description: '基于Spring Boot + Vue CLI@3 框架开发的Web文件系统,旨在为用户提供一个简单、方便的文件存储方案'
-        },
-      }
-    },
-    {
-      path: '/login',
-      name: 'Login',
-      component: () => import(/* webpackChunkName: "login" */ '_v/Login.vue'),
-      meta: { title: '登录 - 奇文网盘' }
-    },
-    {
-      path: '/register',
-      name: 'Register',
-      component: () => import(/* webpackChunkName: "register" */ '_v/Register.vue'),
-      meta: { title: '注册 - 奇文网盘' }
-    },
-    {
-      path: '/file',
-      name: 'File',
-      component: () => import(/* webpackChunkName: "file" */ '_v/file/File.vue'),
-      meta: {
-        requireAuth: true, //  当前路由是否需要登录才可进入
-        title: '奇文网盘',
-        content: {
-          description: '基于Spring Boot + Vue CLI@3 框架开发的Web文件系统,旨在为用户提供一个简单、方便的文件存储方案'
-        },
-        breadCrumbName: '全部文件'
-      }
-    },
-    {
-      path: '/onlyoffice',
-      name: 'Onlyoffice',
-      meta: {
-        title: '在线编辑预览 - 奇文网盘',
-        content: {
-          description: '在线编辑预览'
-        }
-      },
-      component: () => import(/* webpackChunkName: "onlyOffice" */ '_v/OnlyOffice/index.vue')
-    },
-    {
-      path: '/share/:shareBatchNum',
-      name: 'Share',
-      component: () => import(/* webpackChunkName: "share" */ '_v/Share/index.vue'),
-      meta: {
-        title: '分享 - 奇文网盘',
-        breadCrumbName: '分享文件'
-      },
-      props: true
-    },
-    {
-      path: '/myshare',
-      name: 'MyShare',
-      component: () => import(/* webpackChunkName: "my_share" */ '_v/MyShare/index.vue'),
-      meta: {
-        requireAuth: true,
-        title: '我的分享 - 奇文网盘',
-        breadCrumbName: '我的分享'
-      }
-    },
-    {
-      path: '*',
-      name: 'Error_404',
-      component: () => import(/* webpackChunkName: "error_404" */ '_v/ErrorPage/404.vue'),
-      meta: { title: '404 - 奇文网盘' }
-    }
-  ]
+	mode: 'history',
+	base: process.env.BASE_URL,
+	routes: [
+		{
+			path: '/',
+			name: 'Home',
+			component: () => import(/* webpackChunkName: "home" */ '_v/Home'),
+			meta: {
+				title: '奇文网盘',
+				content: {
+					description:
+						'基于Spring Boot + Vue CLI@3 框架开发的Web文件系统,旨在为用户提供一个简单、方便的文件存储方案'
+				}
+			}
+		},
+		{
+			path: '/login',
+			name: 'Login',
+			component: () => import(/* webpackChunkName: "login" */ '_v/Login.vue'),
+			meta: { title: '登录 - 奇文网盘' }
+		},
+		{
+			path: '/register',
+			name: 'Register',
+			component: () =>
+				import(/* webpackChunkName: "register" */ '_v/Register.vue'),
+			meta: { title: '注册 - 奇文网盘' }
+		},
+		{
+			path: '/file',
+			name: 'File',
+			component: () =>
+				import(/* webpackChunkName: "file" */ '_v/file/File.vue'),
+			meta: {
+				requireAuth: true, //  当前路由是否需要登录才可进入
+				title: '奇文网盘',
+				content: {
+					description:
+						'基于Spring Boot + Vue CLI@3 框架开发的Web文件系统,旨在为用户提供一个简单、方便的文件存储方案'
+				},
+				breadCrumbName: '全部文件'
+			}
+		},
+		{
+			path: '/onlyoffice',
+			name: 'Onlyoffice',
+			meta: {
+				title: '在线编辑预览 - 奇文网盘',
+				content: {
+					description: '在线编辑预览'
+				}
+			},
+			component: () =>
+				import(/* webpackChunkName: "onlyOffice" */ '_v/OnlyOffice/index.vue')
+		},
+		{
+			path: '/share/:shareBatchNum',
+			name: 'Share',
+			component: () =>
+				import(/* webpackChunkName: "share" */ '_v/Share/index.vue'),
+			meta: {
+				title: '分享 - 奇文网盘',
+				breadCrumbName: '分享文件'
+			},
+			props: true
+		},
+		{
+			path: '/myshare',
+			name: 'MyShare',
+			component: () =>
+				import(/* webpackChunkName: "my_share" */ '_v/MyShare/index.vue'),
+			meta: {
+				requireAuth: true,
+				title: '我的分享 - 奇文网盘',
+				breadCrumbName: '我的分享'
+			}
+		},
+		{
+			path: '*',
+			name: 'Error_404',
+			component: () =>
+				import(/* webpackChunkName: "error_404" */ '_v/ErrorPage/404.vue'),
+			meta: { title: '404 - 奇文网盘' }
+		}
+	]
 })
 
 const originalPush = Router.prototype.push
 Router.prototype.push = function push(location) {
-  return originalPush.call(this, location).catch((err) => err)
+	return originalPush.call(this, location).catch((err) => err)
 }

+ 46 - 42
src/store/index.js

@@ -1,50 +1,54 @@
-import Vue from "vue";
-import Vuex from "vuex";
+import Vue from 'vue'
+import Vuex from 'vuex'
 
 import config from '@/config'
 
-import user from './module/user'  //  用户模块
-import fileList from './module/fileList'  //  文件列表模块
-import sideMenu from './module/sideMenu'  //  左侧菜单模块
-import imgPreview from './module/imgPreview'  //  图片预览模块
-import videoPreview from './module/videoPreview'  //  视频预览模块
+import user from './module/user' //  用户模块
+import fileList from './module/fileList' //  文件列表模块
+import sideMenu from './module/sideMenu' //  左侧菜单模块
+import imgPreview from './module/imgPreview' //  图片预览模块
+import videoPreview from './module/videoPreview' //  视频预览模块
 
 Vue.use(Vuex)
 
 export default new Vuex.Store({
-  state: {
-    //
-  },
-  getters: {
-    // 登录状态
-    isLogin: (state) => state.user.isLogin,
-    // 用户姓名
-    username: (state) => state.user.userInfoObj.username,
-    // 用户ID
-    userId: (state) => state.user.userInfoObj.userId,
-    // 表格显示列
-    selectedColumnList: (state) =>
-      state.fileList.selectedColumnList === undefined
-        ? config.allColumnList
-        : state.fileList.selectedColumnList.split(","),
-    // 文件查看模式
-    fileModel: (state) => state.fileList.fileModel === undefined ? 0 : Number(state.fileList.fileModel),
-    // 网格模式 & 时间线模式下 文件图标大小
-    gridSize: (state) => state.fileList.gridSize,
-    // 剩余存储空间
-    remainderStorageValue: (state) =>  state.sideMenu.totalStorageValue - state.sideMenu.storageValue
-  },
-  mutations: {
-    //
-  },
-  actions: {
-    //
-  },
-  modules: {
-    user,
-    fileList,
-    sideMenu,
-    imgPreview,
-    videoPreview
-  }
+	state: {
+		//
+	},
+	getters: {
+		// 登录状态
+		isLogin: (state) => state.user.isLogin,
+		// 用户姓名
+		username: (state) => state.user.userInfoObj.username,
+		// 用户ID
+		userId: (state) => state.user.userInfoObj.userId,
+		// 表格显示列
+		selectedColumnList: (state) =>
+			state.fileList.selectedColumnList === undefined
+				? config.allColumnList
+				: state.fileList.selectedColumnList.split(','),
+		// 文件查看模式
+		fileModel: (state) =>
+			state.fileList.fileModel === undefined
+				? 0
+				: Number(state.fileList.fileModel),
+		// 网格模式 & 时间线模式下 文件图标大小
+		gridSize: (state) => state.fileList.gridSize,
+		// 剩余存储空间
+		remainderStorageValue: (state) =>
+			state.sideMenu.totalStorageValue - state.sideMenu.storageValue
+	},
+	mutations: {
+		//
+	},
+	actions: {
+		//
+	},
+	modules: {
+		user,
+		fileList,
+		sideMenu,
+		imgPreview,
+		videoPreview
+	}
 })

+ 41 - 42
src/store/module/fileList.js

@@ -1,46 +1,45 @@
 import globalFunction from '@/globalFunction.js'
 
 export default {
-  state: {
-    // 表格中显示的列
-    selectedColumnList: globalFunction.getCookies('selectedColumnList'),
-    // 文件展示模式 0 列表模式 | 1 网格模式 | 2 时间线模式
-    fileModel: globalFunction.getCookies('fileModel'),
-    // 网格模式 & 时间线模式下 图标大小 单位px
-    gridSize: 80
-  },
-  mutations: {
-    /**
-     * 改变表格显示列
-     * @description 表格显示列保存在 Vuex 和 cookie 中
-     * @param {object} state Vuex 的 state 对象
-     * @param {[]} data 表格需要显示的列数组
-     */
-    changeSelectedColumnList(state, data) {
-      globalFunction.setCookies('selectedColumnList', data.toString())
-      state.selectedColumnList = data.toString();
-    },
-    /**
-     * 改变文件展示模式
-     * @description 文件展示模式保存在 Vuex 和 cookie 中
-     * @param {object} state Vuex 的 state 对象 
-     * @param {string} data 文件展示模式
-     */
-    changeFileModel(state, data) {
-      globalFunction.setCookies('fileModel', data)
-      state.fileModel = data;
-    },
-    /**
-     * 网格模式 & 时间线模式 改变文件图标大小
-     * @description 文件图标大小保存在 Vuex 和 cookie 中
-     * @param {object} state Vuex 的 state 对象 
-     * @param {string} data 文件图标大小
-     */
-    changeGridSize(state, data) {
-      globalFunction.setCookies('gridSize', data)
-      state.gridSize = data;
-    }
-  },
-  actions: {
-  }
+	state: {
+		// 表格中显示的列
+		selectedColumnList: globalFunction.getCookies('selectedColumnList'),
+		// 文件展示模式 0 列表模式 | 1 网格模式 | 2 时间线模式
+		fileModel: globalFunction.getCookies('fileModel'),
+		// 网格模式 & 时间线模式下 图标大小 单位px
+		gridSize: 80
+	},
+	mutations: {
+		/**
+		 * 改变表格显示列
+		 * @description 表格显示列保存在 Vuex 和 cookie 中
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {[]} data 表格需要显示的列数组
+		 */
+		changeSelectedColumnList(state, data) {
+			globalFunction.setCookies('selectedColumnList', data.toString())
+			state.selectedColumnList = data.toString()
+		},
+		/**
+		 * 改变文件展示模式
+		 * @description 文件展示模式保存在 Vuex 和 cookie 中
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {string} data 文件展示模式
+		 */
+		changeFileModel(state, data) {
+			globalFunction.setCookies('fileModel', data)
+			state.fileModel = data
+		},
+		/**
+		 * 网格模式 & 时间线模式 改变文件图标大小
+		 * @description 文件图标大小保存在 Vuex 和 cookie 中
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {string} data 文件图标大小
+		 */
+		changeGridSize(state, data) {
+			globalFunction.setCookies('gridSize', data)
+			state.gridSize = data
+		}
+	},
+	actions: {}
 }

+ 24 - 25
src/store/module/imgPreview.js

@@ -1,27 +1,26 @@
 export default {
-  state: {
-    imgPreviewVisible: false,  //  图片查看组件显隐状态
-    imgPreviewList: [], //  图片列表
-    defaultActiveIndex: 0 //  默认当前打开的图片的索引
-  },
-  mutations: {
-    /**
-     * 存储图片预览组件所需要的数据
-     * @param {object} state Vuex 的 state 对象
-     * @param {object} data 图片数据
-     */
-    setImgPreviewData(state, data) {
-      if(data.imgPreviewVisible) {
-        state.imgPreviewVisible = data.imgPreviewVisible
-        state.imgPreviewList = data.imgPreviewList
-        state.defaultActiveIndex = data.activeIndex
-      } else {
-        state.imgPreviewVisible = data.false
-        state.imgPreviewList = []
-        state.defaultActiveIndex = 0
-      }
-    }
-  },
-  actions: {
-  }
+	state: {
+		imgPreviewVisible: false, //  图片查看组件显隐状态
+		imgPreviewList: [], //  图片列表
+		defaultActiveIndex: 0 //  默认当前打开的图片的索引
+	},
+	mutations: {
+		/**
+		 * 存储图片预览组件所需要的数据
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {object} data 图片数据
+		 */
+		setImgPreviewData(state, data) {
+			if (data.imgPreviewVisible) {
+				state.imgPreviewVisible = data.imgPreviewVisible
+				state.imgPreviewList = data.imgPreviewList
+				state.defaultActiveIndex = data.activeIndex
+			} else {
+				state.imgPreviewVisible = data.false
+				state.imgPreviewList = []
+				state.defaultActiveIndex = 0
+			}
+		}
+	},
+	actions: {}
 }

+ 38 - 32
src/store/module/sideMenu.js

@@ -1,36 +1,42 @@
 import { getStorage } from '_r/file.js'
 
 export default {
-  state: {
-    storageValue: 0 , //  文件已占用的存储空间大小
-    totalStorageValue:0
-  },
-  mutations: {
-    /**
-     * 保存文件已占用的存储空间大小
-     * @param {object} state Vuex 的 state 对象
-     * @param {number} data 存储大小
-     */
-    setStorageValue(state, data) {
-      state.storageValue = data;
-    },
-    setTotalStorageValue(state, data) {
-      state.totalStorageValue = data;
-    }
-  },
-  actions: {
-    /**
-     * 获取文件已占用的存储空间
-     */
-    showStorage(context) {
-      return getStorage().then(res => {
-        if (res.success) {
-          context.commit('setStorageValue', res.data ? Number(res.data.storageSize) : 0)
-          context.commit('setTotalStorageValue', res.data ? Number(res.data.totalStorageSize) : 0)
-        } else {
-          this.$message.error(res.message)
-        }
-      });
-    }
-  }
+	state: {
+		storageValue: 0, //  文件已占用的存储空间大小
+		totalStorageValue: 0
+	},
+	mutations: {
+		/**
+		 * 保存文件已占用的存储空间大小
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {number} data 存储大小
+		 */
+		setStorageValue(state, data) {
+			state.storageValue = data
+		},
+		setTotalStorageValue(state, data) {
+			state.totalStorageValue = data
+		}
+	},
+	actions: {
+		/**
+		 * 获取文件已占用的存储空间
+		 */
+		showStorage(context) {
+			return getStorage().then((res) => {
+				if (res.success) {
+					context.commit(
+						'setStorageValue',
+						res.data ? Number(res.data.storageSize) : 0
+					)
+					context.commit(
+						'setTotalStorageValue',
+						res.data ? Number(res.data.totalStorageSize) : 0
+					)
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		}
+	}
 }

+ 40 - 41
src/store/module/user.js

@@ -1,44 +1,43 @@
-import globalFunction from '@/globalFunction.js'
-import { checkUserLoginInfo } from "_r/user.js"; //引入axios封装
+import { checkUserLoginInfo } from '_r/user.js' //引入axios封装
 
 export default {
-  state: {
-    isLogin: false, //  用户登录状态
-    userInfoObj: {},  //  用户信息
-  },
-  mutations: {
-    /**
-     * 保存登录状态
-     * @param {object} state Vuex 的 state 对象
-     * @param {boolean} data 登录状态
-     */
-    changeIsLogin(state, data) {
-      state.isLogin = data;
-    },
-    /**
-     * 保存用户信息
-     * @param {object} state Vuex 的 state 对象
-     * @param {boolean} data 用户信息
-     */
-    changeUserInfoObj(state, data) {
-      state.userInfoObj = Object.assign({}, state.userInfoObj, data);
-    }
-  },
-  actions: {
-    /**
-     * 获取用户信息
-     */
-    getUserInfo(context) {
-      return checkUserLoginInfo().then((res) => {
-        if (res.success) {
-          // 改变登录状态
-          context.commit("changeIsLogin", res.success);
-          // 保存用户信息
-          context.commit("changeUserInfoObj", res.data); 
-        } else {
-          context.commit("changeIsLogin", res.success);
-        }
-      });
-    }
-  }
+	state: {
+		isLogin: false, //  用户登录状态
+		userInfoObj: {} //  用户信息
+	},
+	mutations: {
+		/**
+		 * 保存登录状态
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {boolean} data 登录状态
+		 */
+		changeIsLogin(state, data) {
+			state.isLogin = data
+		},
+		/**
+		 * 保存用户信息
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {boolean} data 用户信息
+		 */
+		changeUserInfoObj(state, data) {
+			state.userInfoObj = Object.assign({}, state.userInfoObj, data)
+		}
+	},
+	actions: {
+		/**
+		 * 获取用户信息
+		 */
+		getUserInfo(context) {
+			return checkUserLoginInfo().then((res) => {
+				if (res.success) {
+					// 改变登录状态
+					context.commit('changeIsLogin', res.success)
+					// 保存用户信息
+					context.commit('changeUserInfoObj', res.data)
+				} else {
+					context.commit('changeIsLogin', res.success)
+				}
+			})
+		}
+	}
 }

+ 24 - 25
src/store/module/videoPreview.js

@@ -1,27 +1,26 @@
 export default {
-  state: {
-    videoPreviewVisible: false,  //  视频查看组件显隐状态
-    videoPreviewList: [], //  视频列表
-    defaultActiveIndex: 0 //  默认当前打开的视频的索引
-  },
-  mutations: {
-    /**
-     * 存储视频预览组件所需要的数据
-     * @param {object} state Vuex 的 state 对象
-     * @param {object} data 视频数据
-     */
-    setVideoPreviewData(state, data) {
-      if(data.videoPreviewVisible) {
-        state.videoPreviewVisible = data.videoPreviewVisible
-        state.videoPreviewList = data.videoPreviewList
-        state.defaultActiveIndex = data.activeIndex
-      } else {
-        state.videoPreviewVisible = data.false
-        state.videoPreviewList = []
-        state.defaultActiveIndex = 0
-      }
-    }
-  },
-  actions: {
-  }
+	state: {
+		videoPreviewVisible: false, //  视频查看组件显隐状态
+		videoPreviewList: [], //  视频列表
+		defaultActiveIndex: 0 //  默认当前打开的视频的索引
+	},
+	mutations: {
+		/**
+		 * 存储视频预览组件所需要的数据
+		 * @param {object} state Vuex 的 state 对象
+		 * @param {object} data 视频数据
+		 */
+		setVideoPreviewData(state, data) {
+			if (data.videoPreviewVisible) {
+				state.videoPreviewVisible = data.videoPreviewVisible
+				state.videoPreviewList = data.videoPreviewList
+				state.defaultActiveIndex = data.activeIndex
+			} else {
+				state.videoPreviewVisible = data.false
+				state.videoPreviewList = []
+				state.defaultActiveIndex = 0
+			}
+		}
+	},
+	actions: {}
 }

+ 10 - 10
src/views/ErrorPage/404.vue

@@ -1,18 +1,18 @@
 <template>
-  <div class="error-404-wrapper">
-    <h2 class="title">您的页面飞走了……</h2>
-    <img :src="error_404_img" />
-  </div>
+	<div class="error-404-wrapper">
+		<h2 class="title">您的页面飞走了……</h2>
+		<img :src="error_404_img" />
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'Error_404',
-  data() {
-    return {
-      error_404_img: require('_a/images/error/404.png')
-    }
-  }
+	name: 'Error_404',
+	data() {
+		return {
+			error_404_img: require('_a/images/error/404.png')
+		}
+	}
 }
 </script>
 

+ 67 - 56
src/views/Home/components/Banner.vue

@@ -1,64 +1,75 @@
 <template>
-  <el-carousel height="580px" class="el-carousel">
-    <el-carousel-item class="carosel-inner" v-for="(item, index) in bannerList" :key="index">
-      <div class="carousel-wrap">
-        <div class="carousel-caption">
-          <h1 class="bounce">{{ item.title }}</h1>
-          <ul>
-            <li v-for="(descItem, descIndex) in item.descList" :key="`desc-${index}-${descIndex}`">
-              {{ descItem }}
-            </li>
-          </ul>
-          <el-button round @click="goFile">{{ item.btn }}</el-button>
-          <div class="version-wrapper">
-            <a
-              class="version-item"
-              v-for="(linkItem, linkIndex) in item.linkList"
-              :key="`link-${index}-${linkIndex}`"
-              :href="linkItem.link"
-              target="_blank"
-            >
-              <span class="version-number">{{ linkItem.versionNo }}</span>
-              <span>{{ linkItem.date }} &gt;&gt;</span>
-            </a>
-          </div>
-        </div>
-        <div class="carousel-img">
-          <img :src="item.bannerImg" />
-        </div>
-      </div>
-    </el-carousel-item>
-  </el-carousel>
+	<el-carousel height="580px" class="el-carousel">
+		<el-carousel-item
+			class="carosel-inner"
+			v-for="(item, index) in bannerList"
+			:key="index"
+		>
+			<div class="carousel-wrap">
+				<div class="carousel-caption">
+					<h1 class="bounce">{{ item.title }}</h1>
+					<ul>
+						<li
+							v-for="(descItem, descIndex) in item.descList"
+							:key="`desc-${index}-${descIndex}`"
+						>
+							{{ descItem }}
+						</li>
+					</ul>
+					<el-button round @click="goFile">{{ item.btn }}</el-button>
+					<div class="version-wrapper">
+						<a
+							class="version-item"
+							v-for="(linkItem, linkIndex) in item.linkList"
+							:key="`link-${index}-${linkIndex}`"
+							:href="linkItem.link"
+							target="_blank"
+						>
+							<span class="version-number">{{ linkItem.versionNo }}</span>
+							<span>{{ linkItem.date }} &gt;&gt;</span>
+						</a>
+					</div>
+				</div>
+				<div class="carousel-img">
+					<img :src="item.bannerImg" />
+				</div>
+			</div>
+		</el-carousel-item>
+	</el-carousel>
 </template>
 
 <script>
 export default {
-  name: 'Banner',
-  data() {
-    return {
-      bannerList: [
-        {
-          title: '一款功能齐全的文件管理系统',
-          descList: ['文件传输,安全快捷', '在线解压缩,一触即达', '回收站,防止文件误删'],
-          btn: '开源免费,立即体验',
-          linkList: [
-            {
-              versionNo: '最新版本v1.4.0',
-              date: '2021年5月14日发布',
-              link: 'https://gitee.com/qiwen-cloud/qiwen-file'
-            }
-          ],
-          bannerImg: require('_a/images/home/banner/banner1.png')
-        }
-      ]
-    }
-  },
-  methods: {
-    // 跳转到网盘页面
-    goFile() {
-      this.$router.push({ name: 'File', query: { filePath: '/', fileType: 0 } })
-    }
-  }
+	name: 'Banner',
+	data() {
+		return {
+			bannerList: [
+				{
+					title: '一款功能齐全的文件管理系统',
+					descList: [
+						'文件传输,安全快捷',
+						'在线解压缩,一触即达',
+						'回收站,防止文件误删'
+					],
+					btn: '开源免费,立即体验',
+					linkList: [
+						{
+							versionNo: '最新版本v1.4.0',
+							date: '2021年5月14日发布',
+							link: 'https://gitee.com/qiwen-cloud/qiwen-file'
+						}
+					],
+					bannerImg: require('_a/images/home/banner/banner1.png')
+				}
+			]
+		}
+	},
+	methods: {
+		// 跳转到网盘页面
+		goFile() {
+			this.$router.push({ name: 'File', query: { filePath: '/', fileType: 0 } })
+		}
+	}
 }
 </script>
 

+ 53 - 49
src/views/Home/components/Function.vue

@@ -1,57 +1,61 @@
 <template>
-  <div class="function-wrapper">
-    <div class="function-title">功能介绍</div>
-    <ul class="function-list">
-      <li class="function-item" v-for="(item, index) in functionList" :key="index">
-        <div class="img-wrapper">
-          <img class="img" :src="item.icon" />
-        </div>
-        <h3 class="title">{{ item.title }}</h3>
-        <p class="desc">{{ item.desc }}</p>
-      </li>
-    </ul>
-  </div>
+	<div class="function-wrapper">
+		<div class="function-title">功能介绍</div>
+		<ul class="function-list">
+			<li
+				class="function-item"
+				v-for="(item, index) in functionList"
+				:key="index"
+			>
+				<div class="img-wrapper">
+					<img class="img" :src="item.icon" />
+				</div>
+				<h3 class="title">{{ item.title }}</h3>
+				<p class="desc">{{ item.desc }}</p>
+			</li>
+		</ul>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'Function',
-  data() {
-    return {
-      functionList: [
-        {
-          icon: require('_a/images/home/function/icon1.png'),
-          title: '阿里云OSS存储',
-          desc: '支持多种文件存储方式,目前已经支持本地磁盘存储和阿里云OSS存储,并可以在使用中随意切换'
-        },
-        {
-          icon: require('_a/images/home/function/icon2.png'),
-          title: '文件极速秒传',
-          desc: '能够准确识别已上传文件,当上传的文件在磁盘上已存在,可以达到秒传效果'
-        },
-        {
-          icon: require('_a/images/home/function/icon3.png'),
-          title: '文件分块上传',
-          desc: '对文件进行分块上传,可以提高上传速度,并且能够更加精准的显示出文件传输速率和进度'
-        },
-        {
-          icon: require('_a/images/home/function/icon4.png'),
-          title: '多文件格式分类查看',
-          desc: '帮助用户更加快速的找到需要的文件,我们支持对文件进行分类显示并查看预览'
-        },
-        {
-          icon: require('_a/images/home/function/icon5.png'),
-          title: '支持回收站功能',
-          desc: '回收站可以轻松帮助找回误删文件,对回收站进行清理后文件才将彻底删除'
-        },
-        {
-          icon: require('_a/images/home/function/icon6.png'),
-          title: '列表和网格风格切换',
-          desc: '为了满足不同用户的视觉体验,我们提供了文件的列表显示和网格显示两种风格'
-        }
-      ]
-    }
-  }
+	name: 'Function',
+	data() {
+		return {
+			functionList: [
+				{
+					icon: require('_a/images/home/function/icon1.png'),
+					title: '阿里云OSS存储',
+					desc: '支持多种文件存储方式,目前已经支持本地磁盘存储和阿里云OSS存储,并可以在使用中随意切换'
+				},
+				{
+					icon: require('_a/images/home/function/icon2.png'),
+					title: '文件极速秒传',
+					desc: '能够准确识别已上传文件,当上传的文件在磁盘上已存在,可以达到秒传效果'
+				},
+				{
+					icon: require('_a/images/home/function/icon3.png'),
+					title: '文件分块上传',
+					desc: '对文件进行分块上传,可以提高上传速度,并且能够更加精准的显示出文件传输速率和进度'
+				},
+				{
+					icon: require('_a/images/home/function/icon4.png'),
+					title: '多文件格式分类查看',
+					desc: '帮助用户更加快速的找到需要的文件,我们支持对文件进行分类显示并查看预览'
+				},
+				{
+					icon: require('_a/images/home/function/icon5.png'),
+					title: '支持回收站功能',
+					desc: '回收站可以轻松帮助找回误删文件,对回收站进行清理后文件才将彻底删除'
+				},
+				{
+					icon: require('_a/images/home/function/icon6.png'),
+					title: '列表和网格风格切换',
+					desc: '为了满足不同用户的视觉体验,我们提供了文件的列表显示和网格显示两种风格'
+				}
+			]
+		}
+	}
 }
 </script>
 

+ 14 - 14
src/views/Home/index.vue

@@ -1,10 +1,10 @@
 <template>
-  <div class="home-swapper">
-    <!-- Banner图 -->
-    <Banner></Banner>
-    <!-- 功能介绍 -->
-    <Function></Function>
-  </div>
+	<div class="home-swapper">
+		<!-- Banner图 -->
+		<Banner></Banner>
+		<!-- 功能介绍 -->
+		<Function></Function>
+	</div>
 </template>
 
 <script>
@@ -12,14 +12,14 @@ import Banner from './components/Banner.vue'
 import Function from './components/Function.vue'
 
 export default {
-  name: 'Home',
-  components: {
-    Banner,
-    Function
-  },
-  data() {
-    return {}
-  }
+	name: 'Home',
+	components: {
+		Banner,
+		Function
+	},
+	data() {
+		return {}
+	}
 }
 </script>
 

+ 161 - 144
src/views/Login.vue

@@ -1,159 +1,176 @@
 <template>
-  <div class="login-wrapper" id="loginBackground">
-    <div class="form-wrapper">
-      <h1 class="login-title">登录</h1>
-      <p class="login-system">奇文网盘</p>
-      <!-- 登录表单 -->
-      <el-form
-        class="login-form"
-        ref="loginForm"
-        :model="loginForm"
-        :rules="loginFormRules"
-        label-width="100px"
-        hide-required-asterisk
-      >
-        <el-form-item prop="telephone">
-          <el-input prefix-icon="el-icon-mobile-phone" v-model="loginForm.telephone" placeholder="手机号"></el-input>
-        </el-form-item>
-        <el-form-item prop="password">
-          <el-input prefix-icon="el-icon-lock" v-model="loginForm.password" placeholder="密码" show-password></el-input>
-        </el-form-item>
-        <el-form-item>
-          <drag-verify
-            ref="dragVerifyRef"
-            text="请按住滑块拖动解锁"
-            successText="验证通过"
-            handlerIcon="el-icon-d-arrow-right"
-            successIcon="el-icon-circle-check"
-            handlerBg="#F5F7FA"
-            :width="375"
-            :isPassing.sync="isPassing"
-            @update:isPassing="updateIsPassing"
-          ></drag-verify>
-        </el-form-item>
-        <el-form-item class="login-btn-form-item">
-          <el-button class="login-btn" type="primary" :disabled="loginBtnDisabled" @click="submitForm('loginForm')"
-            >登录</el-button
-          >
-        </el-form-item>
-      </el-form>
-    </div>
-  </div>
+	<div class="login-wrapper" id="loginBackground">
+		<div class="form-wrapper">
+			<h1 class="login-title">登录</h1>
+			<p class="login-system">奇文网盘</p>
+			<!-- 登录表单 -->
+			<el-form
+				class="login-form"
+				ref="loginForm"
+				:model="loginForm"
+				:rules="loginFormRules"
+				label-width="100px"
+				hide-required-asterisk
+			>
+				<el-form-item prop="telephone">
+					<el-input
+						prefix-icon="el-icon-mobile-phone"
+						v-model="loginForm.telephone"
+						placeholder="手机号"
+					></el-input>
+				</el-form-item>
+				<el-form-item prop="password">
+					<el-input
+						prefix-icon="el-icon-lock"
+						v-model="loginForm.password"
+						placeholder="密码"
+						show-password
+					></el-input>
+				</el-form-item>
+				<el-form-item>
+					<drag-verify
+						ref="dragVerifyRef"
+						text="请按住滑块拖动解锁"
+						successText="验证通过"
+						handlerIcon="el-icon-d-arrow-right"
+						successIcon="el-icon-circle-check"
+						handlerBg="#F5F7FA"
+						:width="375"
+						:isPassing.sync="isPassing"
+						@update:isPassing="updateIsPassing"
+					></drag-verify>
+				</el-form-item>
+				<el-form-item class="login-btn-form-item">
+					<el-button
+						class="login-btn"
+						type="primary"
+						:disabled="loginBtnDisabled"
+						@click="submitForm('loginForm')"
+						>登录</el-button
+					>
+				</el-form-item>
+			</el-form>
+		</div>
+	</div>
 </template>
 
 <script>
 import CanvasNest from 'canvas-nest.js'
-import DragVerify from '_c/common/DragVerify.vue'  //  引入滑动解锁组件
+import DragVerify from '_c/common/DragVerify.vue' //  引入滑动解锁组件
 import { login } from '_r/user.js'
 
 // 配置
 const config = {
-  color: '64, 158, 255', // 线条颜色
-  pointColor: '64, 158, 255', // 节点颜色
-  opacity: 0.5, // 线条透明度
-  count: 99, // 线条数量
-  zIndex: -1 // 画面层级
+	color: '64, 158, 255', // 线条颜色
+	pointColor: '64, 158, 255', // 节点颜色
+	opacity: 0.5, // 线条透明度
+	count: 99, // 线条数量
+	zIndex: -1 // 画面层级
 }
 
 export default {
-  name: 'Login',
-  components: { DragVerify },
-  data() {
-    return {
-      // 登录表单数据
-      loginForm: {
-        telephone: '',
-        password: ''
-      },
-      // 登录表单验证规则
-      loginFormRules: {
-        telephone: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
-        password: [
-          { required: true, message: '请输入密码', trigger: 'blur' },
-          {
-            min: 5,
-            max: 20,
-            message: '长度在 5 到 20 个字符',
-            trigger: 'blur'
-          }
-        ]
-      },
-      isPassing: false, //  滑动解锁是否验证通过
-      loginBtnDisabled: true //  登录按钮是否禁用
-    }
-  },
-  computed: {
-    url() {
-      let _url = this.$route.query.Rurl //  获取路由前置守卫中 next 函数的参数,即登录后要去的页面
-      return _url ? { path: _url } : { name: 'File', query: { fileType: 0, filePath: '/' } }  //  若登录之前有页面,则登录后仍然进入该页面
-    }
-  },
-  watch: {
-    //  滑动解锁验证通过时,若重新输入用户名或密码,滑动解锁恢复原样
-    'loginForm.telephone'() {
-      this.isPassing = false
-      this.$refs.dragVerifyRef.reset()
-    },
-    'loginForm.password'() {
-      this.isPassing = false
-      this.$refs.dragVerifyRef.reset()
-    }
-  },
-  created() {
-    // 用户若已登录,自动跳转到首页
-    if (this.$store.getters.isLogin) {
-      let username = this.$store.getters.username
-      this.$message({
-        message: `${username} 您已登录!已跳转到首页`,
-        center: true,
-        type: 'success'
-      })
-      this.$router.replace({ name: 'Home' })
-    }
-    //  绘制背景图
-    this.$nextTick(() => {
-      let element = document.getElementById('loginBackground')
-      new CanvasNest(element, config)
-    })
-  },
-  methods: {
-    /**
-     * 滑动解锁完成 回调函数
-     * @param {boolean} isPassing 解锁是否通过
-     */
-    updateIsPassing(isPassing) {
-      if (isPassing) {
-        this.loginBtnDisabled = false
-      } else {
-        this.loginBtnDisabled = true
-      }
-    },
-    /**
-     * 登录按钮点击事件 表单验证&用户登录
-     * @param {boolean} formName 表单ref值
-     */
-    submitForm(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          // 表单各项校验通过
-          login(this.loginForm, true).then((res) => {
-            if (res.success) {
-              this.setCookies('token', res.data.token) //  存储登录状态
-              this.$refs[formName].resetFields() //  清空表单
-              this.$router.replace(this.url)  //  跳转到前一个页面或者网盘主页
-            } else {
-              this.$message.error('手机号或密码错误!')
-              this.isPassing = false
-              this.$refs.dragVerifyRef.reset()
-            }
-          })
-        } else {
-          this.$message.error('请完善信息!')
-          return false
-        }
-      })
-    }
-  }
+	name: 'Login',
+	components: { DragVerify },
+	data() {
+		return {
+			// 登录表单数据
+			loginForm: {
+				telephone: '',
+				password: ''
+			},
+			// 登录表单验证规则
+			loginFormRules: {
+				telephone: [
+					{ required: true, message: '请输入手机号', trigger: 'blur' }
+				],
+				password: [
+					{ required: true, message: '请输入密码', trigger: 'blur' },
+					{
+						min: 5,
+						max: 20,
+						message: '长度在 5 到 20 个字符',
+						trigger: 'blur'
+					}
+				]
+			},
+			isPassing: false, //  滑动解锁是否验证通过
+			loginBtnDisabled: true //  登录按钮是否禁用
+		}
+	},
+	computed: {
+		url() {
+			let _url = this.$route.query.Rurl //  获取路由前置守卫中 next 函数的参数,即登录后要去的页面
+			return _url
+				? { path: _url }
+				: { name: 'File', query: { fileType: 0, filePath: '/' } } //  若登录之前有页面,则登录后仍然进入该页面
+		}
+	},
+	watch: {
+		//  滑动解锁验证通过时,若重新输入用户名或密码,滑动解锁恢复原样
+		'loginForm.telephone'() {
+			this.isPassing = false
+			this.$refs.dragVerifyRef.reset()
+		},
+		'loginForm.password'() {
+			this.isPassing = false
+			this.$refs.dragVerifyRef.reset()
+		}
+	},
+	created() {
+		// 用户若已登录,自动跳转到首页
+		if (this.$store.getters.isLogin) {
+			let username = this.$store.getters.username
+			this.$message({
+				message: `${username} 您已登录!已跳转到首页`,
+				center: true,
+				type: 'success'
+			})
+			this.$router.replace({ name: 'Home' })
+		}
+		//  绘制背景图
+		this.$nextTick(() => {
+			let element = document.getElementById('loginBackground')
+			new CanvasNest(element, config)
+		})
+	},
+	methods: {
+		/**
+		 * 滑动解锁完成 回调函数
+		 * @param {boolean} isPassing 解锁是否通过
+		 */
+		updateIsPassing(isPassing) {
+			if (isPassing) {
+				this.loginBtnDisabled = false
+			} else {
+				this.loginBtnDisabled = true
+			}
+		},
+		/**
+		 * 登录按钮点击事件 表单验证&用户登录
+		 * @param {boolean} formName 表单ref值
+		 */
+		submitForm(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					// 表单各项校验通过
+					login(this.loginForm, true).then((res) => {
+						if (res.success) {
+							this.setCookies('token', res.data.token) //  存储登录状态
+							this.$refs[formName].resetFields() //  清空表单
+							this.$router.replace(this.url) //  跳转到前一个页面或者网盘主页
+						} else {
+							this.$message.error('手机号或密码错误!')
+							this.isPassing = false
+							this.$refs.dragVerifyRef.reset()
+						}
+					})
+				} else {
+					this.$message.error('请完善信息!')
+					return false
+				}
+			})
+		}
+	}
 }
 </script>
 <style lang="stylus" scoped>

+ 103 - 103
src/views/MyShare/index.vue

@@ -1,31 +1,31 @@
 <template>
-  <div class="my-share-wrapper">
-    <div class="operation-wrapper">
-      <!-- 面包屑导航栏 -->
-      <BreadCrumb class="breadcrumb" :fileType="8"></BreadCrumb>
-    </div>
-    <!-- 文件列表-表格模式 -->
-    <FileTable
-      :fileType="8"
-      :filePath="filePath"
-      :fileList="fileList"
-      :loading="loading"
-      @setSelectionFile="setSelectionFile"
-    ></FileTable>
-    <div class="pagination-wrapper">
-      <div class="current-page-count">当前页{{ fileList.length }}条</div>
-      <el-pagination
-        :current-page="pageData.currentPage"
-        :page-size="pageData.pageCount"
-        :total="pageData.total"
-        :page-sizes="[10, 50, 100, 200]"
-        layout="sizes, total, prev, pager, next"
-        @current-change="handleCurrentChange"
-        @size-change="handleSizeChange"
-      >
-      </el-pagination>
-    </div>
-  </div>
+	<div class="my-share-wrapper">
+		<div class="operation-wrapper">
+			<!-- 面包屑导航栏 -->
+			<BreadCrumb class="breadcrumb" :fileType="8"></BreadCrumb>
+		</div>
+		<!-- 文件列表-表格模式 -->
+		<FileTable
+			:fileType="8"
+			:filePath="filePath"
+			:fileList="fileList"
+			:loading="loading"
+			@setSelectionFile="setSelectionFile"
+		></FileTable>
+		<div class="pagination-wrapper">
+			<div class="current-page-count">当前页{{ fileList.length }}条</div>
+			<el-pagination
+				:current-page="pageData.currentPage"
+				:page-size="pageData.pageCount"
+				:total="pageData.total"
+				:page-sizes="[10, 50, 100, 200]"
+				layout="sizes, total, prev, pager, next"
+				@current-change="handleCurrentChange"
+				@size-change="handleSizeChange"
+			>
+			</el-pagination>
+		</div>
+	</div>
 </template>
 
 <script>
@@ -34,82 +34,82 @@ import FileTable from '_c/File/FileTable'
 import { getMyShareFileList } from '_r/file.js'
 
 export default {
-  name: 'MyShare',
-  components: {
-    BreadCrumb,
-    FileTable
-  },
-  data() {
-    return {
-      fileList: [],
-      loading: false,
-      pageData: {
-        currentPage: 1,
-        pageCount: 50,
-        total: 0
-      },
-      selectionFile: []
-    }
-  },
-  computed: {
-    filePath() {
-      return this.$route.query.filePath
-    },
-    shareBatchNum() {
-      return this.$route.query.shareBatchNum || null
-    }
-  },
-  watch: {
-    filePath() {
-      this.getMyShareList()
-    }
-  },
-  mounted() {
-    this.getMyShareList()
-  },
-  methods: {
-    /**
-     * 获取我的分享文件列表
-     */
-    getMyShareList() {
-      let data = {
-        shareFilePath: this.filePath,
-        shareBatchNum: this.shareBatchNum,
-        currentPage: this.pageData.currentPage,
-        pageCount: this.pageData.pageCount
-      }
-      getMyShareFileList(data).then((res) => {
-        if (res.success) {
-          this.fileList = res.data.list
-          this.pageData.total = res.data.total
-          this.loading = false
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 表格数据获取相关事件 | 分页组件 | 当前页码改变
-     */
-    handleCurrentChange(currentPage) {
-      this.pageData.currentPage = currentPage
-      this.getMyShareList()
-    },
-    /**
-     * 表格数据获取相关事件 | 分页组件 | 页大小改变时
-     */
-    handleSizeChange(pageCount) {
-      this.pageData.pageCount = pageCount
-      this.getMyShareList()
-    },
-    /**
-     * 表格勾选框事件 | 保存被勾选的文件
-     * @param {object[]} selection 被勾选的文件数组
-     */
-    setSelectionFile(selection) {
-      this.selectionFile = selection
-    }
-  }
+	name: 'MyShare',
+	components: {
+		BreadCrumb,
+		FileTable
+	},
+	data() {
+		return {
+			fileList: [],
+			loading: false,
+			pageData: {
+				currentPage: 1,
+				pageCount: 50,
+				total: 0
+			},
+			selectionFile: []
+		}
+	},
+	computed: {
+		filePath() {
+			return this.$route.query.filePath
+		},
+		shareBatchNum() {
+			return this.$route.query.shareBatchNum || null
+		}
+	},
+	watch: {
+		filePath() {
+			this.getMyShareList()
+		}
+	},
+	mounted() {
+		this.getMyShareList()
+	},
+	methods: {
+		/**
+		 * 获取我的分享文件列表
+		 */
+		getMyShareList() {
+			let data = {
+				shareFilePath: this.filePath,
+				shareBatchNum: this.shareBatchNum,
+				currentPage: this.pageData.currentPage,
+				pageCount: this.pageData.pageCount
+			}
+			getMyShareFileList(data).then((res) => {
+				if (res.success) {
+					this.fileList = res.data.list
+					this.pageData.total = res.data.total
+					this.loading = false
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 表格数据获取相关事件 | 分页组件 | 当前页码改变
+		 */
+		handleCurrentChange(currentPage) {
+			this.pageData.currentPage = currentPage
+			this.getMyShareList()
+		},
+		/**
+		 * 表格数据获取相关事件 | 分页组件 | 页大小改变时
+		 */
+		handleSizeChange(pageCount) {
+			this.pageData.pageCount = pageCount
+			this.getMyShareList()
+		},
+		/**
+		 * 表格勾选框事件 | 保存被勾选的文件
+		 * @param {object[]} selection 被勾选的文件数组
+		 */
+		setSelectionFile(selection) {
+			this.selectionFile = selection
+		}
+	}
 }
 </script>
 

+ 171 - 167
src/views/OnlyOffice/index.vue

@@ -1,177 +1,181 @@
 <template>
-  <div class="report-onlyoffice">
-    <div id="placeholder"></div>
-  </div>
+	<div class="report-onlyoffice">
+		<div id="placeholder"></div>
+	</div>
 </template>
 
 <script>
-import { createOfficeFile, editOfficeFile, previewOfficeFile } from '_r/onlyoffice.js'
+import {
+	createOfficeFile,
+	editOfficeFile,
+	previewOfficeFile
+} from '_r/onlyoffice.js'
 
 export default {
-  name: 'OnlyOffice',
-  data() {
-    return {
-      docEditor: null,  //  文档编辑器
-      platform: 'desktop' //  查看平台
-    }
-  },
-  computed: {
-    // 文件信息,来自于路由参数query
-    fileInfo() {
-      return this.$route.query
-    }
-  },
-  created() {
-    this.judgePlatform()
-  },
-  mounted() {
-    this.$nextTick(() => {
-      switch (this.fileInfo.ot) {
-        // 添加
-        case 'add':
-          this.initOnlyoffice()
-          break
-        // 编辑
-        case 'edit':
-          this.editDoc()
-          break
-        // 详情
-        case 'detail':
-          this.showDocDetail()
-          break
-      }
-    })
-  },
-  destroyed() {
-    this.docEditor.destroyEditor()
-  },
-  methods: {
-    /**
-     * 初始化 onlyoffice
-     */
-    initOnlyoffice() {
-      let data = {
-        userFileId: this.fileInfo.userFileId,
-        fileId: this.fileInfo.fileId,
-        fileName: this.fileInfo.fileName,
-        filePath: this.fileInfo.filePath,
-        fileCategory: this.fileInfo.fileCategory,
-        type: this.fileInfo.type,
-        memo: this.fileInfo.memo
-      }
-      createOfficeFile(data).then((res) => {
-        if (res.code === 200) {
-          let config = { 
-            ...res.data.file,
-            type: this.platform
-          }
-          // config.editorConfig.callbackUrl = config.editorConfig.callbackUrl.replace('/IndexServlet', ONLYOFFICE_BASE_URL + '/IndexServlet')
-          this.initDocEditor(res.data.docserviceApiUrl, config)
-        }
-      })
-    },
-    /**
-     * 初始化文档编辑器
-     * @param {string} docserviceApiUrl 文档服务API url
-     * @param {object} config 文件相关配置信息
-     */
-    initDocEditor(docserviceApiUrl, config) {
-      this.loadOnlyOfficeAPI(docserviceApiUrl).then(() => {
-        /* global DocsAPI */
-        this.docEditor = new DocsAPI.DocEditor('placeholder', {
-          ...config,
-          editorConfig: {
-            ...config.editorConfig,
-            lang: 'zh', //  语言设置为中文 
-            customization: {
-              ...config.editorConfig.customization,
-              zoom: 100 //  缩放比例为 100
-            }
-          }
-        })
-      })
-    },
-    /**
-     * 判断当前平台
-     */
-    judgePlatform() {
-      this.platform = 'desktop' // 浏览平台
-      if (
-        /AppleWebKit.*Mobile/i.test(navigator.userAgent) ||
-        /MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(
-          navigator.userAgent
-        )
-      ) {
-        if (window.location.href.indexOf('?mobile') < 0) {
-          try {
-            if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
-              this.platform = 'mobile'
-            }
-          } catch (e) {
-            console.log(e)
-          }
-        }
-      }
-    },
-    /**
-     * 展示文档详情
-     */
-    showDocDetail() {
-      let data = {
-        userFileId: this.fileInfo.userFileId,
-        previewUrl: this.fileInfo.fileUrl
-      }
-      previewOfficeFile(data).then((res) => {
-        if (res.code === 200) {
-          let config = {
-            ...res.data.file,
-            type: this.platform
-          }
-          config.document.permissions.edit = false  //  预览模式下编辑权限为 false
-          this.initDocEditor(res.data.docserviceApiUrl, config)
-        }
-      })
-    },
-    /**
-     * 编辑文档
-     */
-    editDoc() {
-      let data = {
-        userFileId: this.fileInfo.userFileId,
-        previewUrl: this.fileInfo.fileUrl
-      }
-      editOfficeFile(data).then((res) => {
-        if (res.code === 200) {
-          let config = {
-            ...res.data.file,
-            type: this.platform
-          }
-          this.initDocEditor(res.data.docserviceApiUrl, config)
-        }
-      })
-    },
-    /**
-     * 加载 onlyoffice api
-     * @return {Promise} 返回 api 加载状态
-     */
-    loadOnlyOfficeAPI(src) {
-      return new Promise((resolve, reject) => {
-        const script = document.createElement('script')
-        script.type = 'text/javascript'
-        script.src = src
-        document.body.appendChild(script);
-        script.onload = () => {
-          resolve()
-        }
-        script.onerror = () => {
-          reject()
-        }
-      })
-    }
-  }
+	name: 'OnlyOffice',
+	data() {
+		return {
+			docEditor: null, //  文档编辑器
+			platform: 'desktop' //  查看平台
+		}
+	},
+	computed: {
+		// 文件信息,来自于路由参数query
+		fileInfo() {
+			return this.$route.query
+		}
+	},
+	created() {
+		this.judgePlatform()
+	},
+	mounted() {
+		this.$nextTick(() => {
+			switch (this.fileInfo.ot) {
+				// 添加
+				case 'add':
+					this.initOnlyoffice()
+					break
+				// 编辑
+				case 'edit':
+					this.editDoc()
+					break
+				// 详情
+				case 'detail':
+					this.showDocDetail()
+					break
+			}
+		})
+	},
+	destroyed() {
+		this.docEditor.destroyEditor()
+	},
+	methods: {
+		/**
+		 * 初始化 onlyoffice
+		 */
+		initOnlyoffice() {
+			let data = {
+				userFileId: this.fileInfo.userFileId,
+				fileId: this.fileInfo.fileId,
+				fileName: this.fileInfo.fileName,
+				filePath: this.fileInfo.filePath,
+				fileCategory: this.fileInfo.fileCategory,
+				type: this.fileInfo.type,
+				memo: this.fileInfo.memo
+			}
+			createOfficeFile(data).then((res) => {
+				if (res.code === 200) {
+					let config = {
+						...res.data.file,
+						type: this.platform
+					}
+					// config.editorConfig.callbackUrl = config.editorConfig.callbackUrl.replace('/IndexServlet', ONLYOFFICE_BASE_URL + '/IndexServlet')
+					this.initDocEditor(res.data.docserviceApiUrl, config)
+				}
+			})
+		},
+		/**
+		 * 初始化文档编辑器
+		 * @param {string} docserviceApiUrl 文档服务API url
+		 * @param {object} config 文件相关配置信息
+		 */
+		initDocEditor(docserviceApiUrl, config) {
+			this.loadOnlyOfficeAPI(docserviceApiUrl).then(() => {
+				/* global DocsAPI */
+				this.docEditor = new DocsAPI.DocEditor('placeholder', {
+					...config,
+					editorConfig: {
+						...config.editorConfig,
+						lang: 'zh', //  语言设置为中文
+						customization: {
+							...config.editorConfig.customization,
+							zoom: 100 //  缩放比例为 100
+						}
+					}
+				})
+			})
+		},
+		/**
+		 * 判断当前平台
+		 */
+		judgePlatform() {
+			this.platform = 'desktop' // 浏览平台
+			if (
+				/AppleWebKit.*Mobile/i.test(navigator.userAgent) ||
+				/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(
+					navigator.userAgent
+				)
+			) {
+				if (window.location.href.indexOf('?mobile') < 0) {
+					try {
+						if (
+							/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)
+						) {
+							this.platform = 'mobile'
+						}
+					} catch (e) {
+						console.log(e)
+					}
+				}
+			}
+		},
+		/**
+		 * 展示文档详情
+		 */
+		showDocDetail() {
+			let data = {
+				userFileId: this.fileInfo.userFileId,
+				previewUrl: this.fileInfo.fileUrl
+			}
+			previewOfficeFile(data).then((res) => {
+				if (res.code === 200) {
+					let config = {
+						...res.data.file,
+						type: this.platform
+					}
+					config.document.permissions.edit = false //  预览模式下编辑权限为 false
+					this.initDocEditor(res.data.docserviceApiUrl, config)
+				}
+			})
+		},
+		/**
+		 * 编辑文档
+		 */
+		editDoc() {
+			let data = {
+				userFileId: this.fileInfo.userFileId,
+				previewUrl: this.fileInfo.fileUrl
+			}
+			editOfficeFile(data).then((res) => {
+				if (res.code === 200) {
+					let config = {
+						...res.data.file,
+						type: this.platform
+					}
+					this.initDocEditor(res.data.docserviceApiUrl, config)
+				}
+			})
+		},
+		/**
+		 * 加载 onlyoffice api
+		 * @return {Promise} 返回 api 加载状态
+		 */
+		loadOnlyOfficeAPI(src) {
+			return new Promise((resolve, reject) => {
+				const script = document.createElement('script')
+				script.type = 'text/javascript'
+				script.src = src
+				document.body.appendChild(script)
+				script.onload = () => {
+					resolve()
+				}
+				script.onerror = () => {
+					reject()
+				}
+			})
+		}
+	}
 }
-
-
 </script>
 
 <style lang="stylus" scoped>

+ 174 - 155
src/views/Register.vue

@@ -1,170 +1,189 @@
 <template>
-  <div class="register-wrapper" id="registerBackground">
-    <div class="form-wrapper">
-      <h1 class="register-title">注册</h1>
-      <p class="register-system">奇文网盘</p>
-      <!-- 注册表单 -->
-      <el-form
-        class="register-form"
-        ref="registerForm"
-        :model="registerForm"
-        :rules="registerFormRules"
-        label-width="100px"
-        hide-required-asterisk
-      >
-        <el-form-item prop="username">
-          <el-input prefix-icon="el-icon-user" v-model="registerForm.username" placeholder="用户名"></el-input>
-        </el-form-item>
-        <el-form-item prop="telephone">
-          <el-input prefix-icon="el-icon-mobile-phone" v-model="registerForm.telephone" placeholder="手机号"></el-input>
-        </el-form-item>
-        <el-form-item prop="password">
-          <el-input prefix-icon="el-icon-lock" v-model="registerForm.password" placeholder="密码" show-password></el-input>
-        </el-form-item>
-        <el-form-item style="user-select: none">
-          <drag-verify
-            ref="dragVerifyRef"
-            text="请按住滑块拖动解锁"
-            successText="验证通过"
-            handlerIcon="el-icon-d-arrow-right"
-            successIcon="el-icon-circle-check"
-            handlerBg="#F5F7FA"
-            :width="375"
-            :isPassing.sync="isPassing"
-            @update:isPassing="updateIsPassing"
-          ></drag-verify>
-        </el-form-item>
-        <el-form-item class="registerButtonWrapper">
-          <el-button class="registerButton" type="primary" :disabled="submitDisabled" @click="submitForm('registerForm')"
-            >注册</el-button
-          >
-        </el-form-item>
-      </el-form>
-    </div>
-  </div>
+	<div class="register-wrapper" id="registerBackground">
+		<div class="form-wrapper">
+			<h1 class="register-title">注册</h1>
+			<p class="register-system">奇文网盘</p>
+			<!-- 注册表单 -->
+			<el-form
+				class="register-form"
+				ref="registerForm"
+				:model="registerForm"
+				:rules="registerFormRules"
+				label-width="100px"
+				hide-required-asterisk
+			>
+				<el-form-item prop="username">
+					<el-input
+						prefix-icon="el-icon-user"
+						v-model="registerForm.username"
+						placeholder="用户名"
+					></el-input>
+				</el-form-item>
+				<el-form-item prop="telephone">
+					<el-input
+						prefix-icon="el-icon-mobile-phone"
+						v-model="registerForm.telephone"
+						placeholder="手机号"
+					></el-input>
+				</el-form-item>
+				<el-form-item prop="password">
+					<el-input
+						prefix-icon="el-icon-lock"
+						v-model="registerForm.password"
+						placeholder="密码"
+						show-password
+					></el-input>
+				</el-form-item>
+				<el-form-item style="user-select: none">
+					<drag-verify
+						ref="dragVerifyRef"
+						text="请按住滑块拖动解锁"
+						successText="验证通过"
+						handlerIcon="el-icon-d-arrow-right"
+						successIcon="el-icon-circle-check"
+						handlerBg="#F5F7FA"
+						:width="375"
+						:isPassing.sync="isPassing"
+						@update:isPassing="updateIsPassing"
+					></drag-verify>
+				</el-form-item>
+				<el-form-item class="registerButtonWrapper">
+					<el-button
+						class="registerButton"
+						type="primary"
+						:disabled="submitDisabled"
+						@click="submitForm('registerForm')"
+						>注册</el-button
+					>
+				</el-form-item>
+			</el-form>
+		</div>
+	</div>
 </template>
 
 <script>
 import CanvasNest from 'canvas-nest.js'
-import DragVerify from '_c/common/DragVerify.vue'  //  引入滑动解锁组件
+import DragVerify from '_c/common/DragVerify.vue' //  引入滑动解锁组件
 import { addUser } from '_r/user.js'
 
 // 配置
 const config = {
-  color: '230, 162, 60', // 线条颜色
-  pointColor: '230, 162, 60', // 节点颜色
-  opacity: 0.5, // 线条透明度
-  count: 99, // 线条数量
-  zIndex: -1 // 画面层级
+	color: '230, 162, 60', // 线条颜色
+	pointColor: '230, 162, 60', // 节点颜色
+	opacity: 0.5, // 线条透明度
+	count: 99, // 线条数量
+	zIndex: -1 // 画面层级
 }
 
 export default {
-  name: 'Register',
-  components: { DragVerify },
-  data() {
-    return {
-      // 注册表单
-      registerForm: {
-        telephone: '',
-        username: '',
-        password: ''
-      },
-      // 注册表单校验规则
-      registerFormRules: {
-        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
-        password: [
-          { required: true, message: '请输入密码', trigger: 'blur' },
-          {
-            min: 5,
-            max: 20,
-            message: '长度在 5 到 20 个字符',
-            trigger: 'blur'
-          }
-        ],
-        telephone: [
-          { required: true, message: '请输入手机号', trigger: 'blur' },
-          { min: 11, max: 11, message: '请输入11位手机号', trigger: 'blur' }
-        ]
-      },
-      isPassing: false, //  滑动解锁是否验证通过
-      submitDisabled: true  //  登录按钮是否禁用
-    }
-  },
-  computed: {
-    url() {
-      let _url = this.$route.query.Rurl //  获取路由前置守卫中 next 函数的参数,即登录后要去的页面
-      return _url ? _url : '/'  //  若登录之前有页面,则登录后仍然进入该页面
-    }
-  },
-  watch: {
-    //  滑动解锁验证通过时,若重新输入手机号、用户名或密码,滑动解锁恢复原样
-    'registerForm.telephone'() {
-      this.isPassing = false
-      this.$refs.dragVerifyRef.reset()
-    },
-    'registerForm.username'() {
-      this.isPassing = false
-      this.$refs.dragVerifyRef.reset()
-    },
-    'registerForm.password'() {
-      this.isPassing = false
-      this.$refs.dragVerifyRef.reset()
-    }
-  },
-  created() {
-    //  绘制背景图
-    this.$nextTick(() => {
-      let element = document.getElementById('registerBackground')
-      new CanvasNest(element, config)
-    })
-  },
-  methods: {
-    /**
-     * 滑动解锁完成 回调函数
-     * @param {boolean} isPassing 解锁是否通过
-     */
-    updateIsPassing(isPassing) {
-      if (isPassing) {
-        //  校验手机号
-        this.$refs.registerForm.validateField('telephone', (telephoneError) => {
-          if (telephoneError) {
-            this.submitDisabled = true
-          } else {
-            this.submitDisabled = false
-          }
-        })
-      } else {
-        this.submitDisabled = true
-      }
-    },
-    /**
-     * 注册按钮点击事件 表单验证&用户注册
-     * @param {boolean} formName 表单ref值
-     */
-    submitForm(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          // 表单各项校验通过
-          addUser(this.registerForm).then((res) => {
-            if (res.success) {
-              this.$notify({
-                title: '成功',
-                message: '注册成功!已跳转到登录页面',
-                type: 'success'
-              })
-              this.$refs[formName].resetFields()
-              this.$router.replace({ path: '/login' })
-            } else {
-              this.$message.error(res.message)
-            }
-          })
-        } else {
-          this.$message.error('请完善信息!')
-          return false
-        }
-      })
-    }
-  }
+	name: 'Register',
+	components: { DragVerify },
+	data() {
+		return {
+			// 注册表单
+			registerForm: {
+				telephone: '',
+				username: '',
+				password: ''
+			},
+			// 注册表单校验规则
+			registerFormRules: {
+				username: [
+					{ required: true, message: '请输入用户名', trigger: 'blur' }
+				],
+				password: [
+					{ required: true, message: '请输入密码', trigger: 'blur' },
+					{
+						min: 5,
+						max: 20,
+						message: '长度在 5 到 20 个字符',
+						trigger: 'blur'
+					}
+				],
+				telephone: [
+					{ required: true, message: '请输入手机号', trigger: 'blur' },
+					{ min: 11, max: 11, message: '请输入11位手机号', trigger: 'blur' }
+				]
+			},
+			isPassing: false, //  滑动解锁是否验证通过
+			submitDisabled: true //  登录按钮是否禁用
+		}
+	},
+	computed: {
+		url() {
+			let _url = this.$route.query.Rurl //  获取路由前置守卫中 next 函数的参数,即登录后要去的页面
+			return _url ? _url : '/' //  若登录之前有页面,则登录后仍然进入该页面
+		}
+	},
+	watch: {
+		//  滑动解锁验证通过时,若重新输入手机号、用户名或密码,滑动解锁恢复原样
+		'registerForm.telephone'() {
+			this.isPassing = false
+			this.$refs.dragVerifyRef.reset()
+		},
+		'registerForm.username'() {
+			this.isPassing = false
+			this.$refs.dragVerifyRef.reset()
+		},
+		'registerForm.password'() {
+			this.isPassing = false
+			this.$refs.dragVerifyRef.reset()
+		}
+	},
+	created() {
+		//  绘制背景图
+		this.$nextTick(() => {
+			let element = document.getElementById('registerBackground')
+			new CanvasNest(element, config)
+		})
+	},
+	methods: {
+		/**
+		 * 滑动解锁完成 回调函数
+		 * @param {boolean} isPassing 解锁是否通过
+		 */
+		updateIsPassing(isPassing) {
+			if (isPassing) {
+				//  校验手机号
+				this.$refs.registerForm.validateField('telephone', (telephoneError) => {
+					if (telephoneError) {
+						this.submitDisabled = true
+					} else {
+						this.submitDisabled = false
+					}
+				})
+			} else {
+				this.submitDisabled = true
+			}
+		},
+		/**
+		 * 注册按钮点击事件 表单验证&用户注册
+		 * @param {boolean} formName 表单ref值
+		 */
+		submitForm(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					// 表单各项校验通过
+					addUser(this.registerForm).then((res) => {
+						if (res.success) {
+							this.$notify({
+								title: '成功',
+								message: '注册成功!已跳转到登录页面',
+								type: 'success'
+							})
+							this.$refs[formName].resetFields()
+							this.$router.replace({ path: '/login' })
+						} else {
+							this.$message.error(res.message)
+						}
+					})
+				} else {
+					this.$message.error('请完善信息!')
+					return false
+				}
+			})
+		}
+	}
 }
 </script>
 <style lang="stylus" scoped>

+ 290 - 277
src/views/Share/index.vue

@@ -1,58 +1,71 @@
 <template>
-  <div class="share-wrapper">
-    <div class="share-file-wrapper" v-if="shareStep === 3">
-      <div class="operation-wrapper">
-        <!-- 面包屑导航栏 -->
-        <BreadCrumb class="breadcrumb" :fileType="7"></BreadCrumb>
-        <el-button type="primary" size="mini" icon="el-icon-takeaway-box" @click="handleSaveBtnClick"
-          >保存到网盘</el-button
-        >
-      </div>
-      <!-- 文件列表-表格模式 -->
-      <FileTable
-        ref="fileTableInstance"
-        :fileType="7"
-        :filePath="filePath"
-        :fileList="fileList"
-        :loading="loading"
-        @setSelectionFile="setSelectionFile"
-      ></FileTable>
-    </div>
-    <!-- 文件分享对话框 -->
-    <el-dialog
-      title="文件分享"
-      :visible.sync="dialogShareFile.visible"
-      :show-close="false"
-      :close-on-click-modal="false"
-      :close-on-press-escape="false"
-      width="500px"
-    >
-      <div class="end-time" v-if="shareStep === 1">此分享链接已过期</div>
-      <el-form
-        class="extraction-code-form"
-        v-if="shareStep === 2"
-        ref="codeForm"
-        :model="dialogShareFile.codeForm"
-        :rules="dialogShareFile.codeFormRules"
-        label-width="80px"
-      >
-        <el-form-item label="提取码" prop="extractionCode">
-          <el-input v-model="dialogShareFile.codeForm.extractionCode"></el-input>
-        </el-form-item>
-      </el-form>
-      <span slot="footer" class="dialog-footer">
-        <el-button v-if="shareStep === 1" @click="handleCloseBtnClick()">关 闭</el-button>
-        <el-button v-else type="primary" @click="handleSubmitBtnClick('codeForm')">提 交</el-button>
-      </span>
-    </el-dialog>
-    <!-- 保存到网盘 路径选择对话框 -->
-    <MoveFileDialog
-      :dialogData="dialogSelectPath"
-      @setSelectFilePath="setSelectFilePath"
-      @confirmDialog="confirmSelectPathDialog"
-      @setDialogData="setSelectPathDialogData"
-    ></MoveFileDialog>
-  </div>
+	<div class="share-wrapper">
+		<div class="share-file-wrapper" v-if="shareStep === 3">
+			<div class="operation-wrapper">
+				<!-- 面包屑导航栏 -->
+				<BreadCrumb class="breadcrumb" :fileType="7"></BreadCrumb>
+				<el-button
+					type="primary"
+					size="mini"
+					icon="el-icon-takeaway-box"
+					@click="handleSaveBtnClick"
+					>保存到网盘</el-button
+				>
+			</div>
+			<!-- 文件列表-表格模式 -->
+			<FileTable
+				ref="fileTableInstance"
+				:fileType="7"
+				:filePath="filePath"
+				:fileList="fileList"
+				:loading="loading"
+				@setSelectionFile="setSelectionFile"
+			></FileTable>
+		</div>
+		<!-- 文件分享对话框 -->
+		<el-dialog
+			title="文件分享"
+			:visible.sync="dialogShareFile.visible"
+			:show-close="false"
+			:close-on-click-modal="false"
+			:close-on-press-escape="false"
+			width="500px"
+		>
+			<div class="end-time" v-if="shareStep === 1">此分享链接已过期</div>
+			<el-form
+				class="extraction-code-form"
+				v-if="shareStep === 2"
+				ref="codeForm"
+				:model="dialogShareFile.codeForm"
+				:rules="dialogShareFile.codeFormRules"
+				label-width="80px"
+			>
+				<el-form-item label="提取码" prop="extractionCode">
+					<el-input
+						v-model="dialogShareFile.codeForm.extractionCode"
+					></el-input>
+				</el-form-item>
+			</el-form>
+			<span slot="footer" class="dialog-footer">
+				<el-button v-if="shareStep === 1" @click="handleCloseBtnClick()"
+					>关 闭</el-button
+				>
+				<el-button
+					v-else
+					type="primary"
+					@click="handleSubmitBtnClick('codeForm')"
+					>提 交</el-button
+				>
+			</span>
+		</el-dialog>
+		<!-- 保存到网盘 路径选择对话框 -->
+		<MoveFileDialog
+			:dialogData="dialogSelectPath"
+			@setSelectFilePath="setSelectFilePath"
+			@confirmDialog="confirmSelectPathDialog"
+			@setDialogData="setSelectPathDialogData"
+		></MoveFileDialog>
+	</div>
 </template>
 
 <script>
@@ -60,232 +73,232 @@ import BreadCrumb from '_c/BreadCrumb'
 import FileTable from '_c/File/FileTable'
 import MoveFileDialog from '_c/File/MoveFileDialog'
 import {
-  checkShareLinkEndtime,
-  checkShareLinkType,
-  checkShareLinkCode,
-  getShareFileList,
-  saveShareFile
+	checkShareLinkEndtime,
+	checkShareLinkType,
+	checkShareLinkCode,
+	getShareFileList,
+	saveShareFile
 } from '_r/file.js'
 
 export default {
-  name: 'Share',
-  components: {
-    BreadCrumb,
-    FileTable,
-    MoveFileDialog
-  },
-  data() {
-    return {
-      // 文件分享对话框数据
-      dialogShareFile: {
-        visible: false,
-        codeForm: {
-          extractionCode: ''
-        },
-        codeFormRules: {
-          extractionCode: [
-            {
-              required: true,
-              message: '请输入提取码',
-              trigger: 'blur'
-            }
-          ]
-        }
-      },
-      shareStep: 0,
-      fileList: [],
-      loading: false,
-      // 保存到网盘对话框数据
-      dialogSelectPath: {
-        visible: false //  是否可见
-      },
-      selectFilePath: '', //  保存到网盘的目标路径
-      selectionFile: [] //  表格勾选的文件列表
-    }
-  },
-  computed: {
-    shareBatchNum() {
-      return this.$route.params.shareBatchNum
-    },
-    filePath() {
-      return this.$route.query.filePath
-    },
-    shareFilePath() {
-      return this.$route.query.filePath
-    }
-  },
-  watch: {
-    filePath() {
-      this.getShareList()
-    }
-  },
-  created() {
-    if (!this.filePath) {
-      this.$router.replace({
-        query: {
-          filePath: '/'
-        }
-      })
-    }
-  },
-  mounted() {
-    this.checkEndTime()
-  },
-  methods: {
-    /**
-     * 表格勾选框事件 | 保存被勾选的文件
-     * @param {object[]} selection 被勾选的文件数组
-     */
-    setSelectionFile(selection) {
-      this.selectionFile = selection
-    },
-    /**
-     * 校验分享链接过期时间
-     */
-    checkEndTime() {
-      checkShareLinkEndtime({
-        shareBatchNum: this.shareBatchNum
-      }).then((res) => {
-        if (res.success) {
-          if (this.getCookies(`share_${this.shareBatchNum}`) === 'true') {
-            this.checkShareComplete()
-          } else {
-            this.dialogShareFile.visible = true
-            this.checkShareType()
-          }
-        } else {
-          this.dialogShareFile.visible = true
-          this.shareStep = 1 //  链接已过期
-        }
-      })
-    },
-    /**
-     * 校验分享类型
-     * @description 校验分享链接是公共还是私密
-     */
-    checkShareType() {
-      checkShareLinkType({
-        shareBatchNum: this.shareBatchNum
-      }).then((res) => {
-        if (res.success) {
-          // 0 公共 1 私密
-          if (res.data.shareType === 0) {
-            this.shareStep = 3 //  不是私密链接,直接展示文件列表
-            this.getShareList()
-            this.dialogShareFile.visible = false
-          }
-          if (res.data.shareType === 1) {
-            this.shareStep = 2 //  是私密链接时,让用户输入提取码
-          }
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 分享文件验证对话框 取消按钮
-     */
-    handleCloseBtnClick() {
-      this.dialogShareFile.visible = false
-      this.$router.push({ name: 'File', query: { fileType: 0, filePath: '/' } })
-    },
-    /**
-     * 提交按钮点击事件
-     */
-    handleSubmitBtnClick(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          checkShareLinkCode({
-            extractionCode: this.dialogShareFile.codeForm.extractionCode,
-            shareBatchNum: this.shareBatchNum
-          }).then((res) => {
-            if (res.success) {
-              this.setCookies(`share_${this.shareBatchNum}`, true)
-              this.$refs[formName].resetFields() //  清空表单
-              this.checkShareComplete()
-            } else {
-              this.$message.error(res.message)
-            }
-          })
-        } else {
-          return false
-        }
-      })
-    },
-    /**
-     * 校验全部通过
-     */
-    checkShareComplete() {
-      this.shareStep = 3 //  展示文件列表
-      this.dialogShareFile.visible = false
-      this.getShareList()
-    },
-    /**
-     * 获取分享文件列表
-     */
-    getShareList() {
-      this.loading = true
-      getShareFileList({
-        shareFilePath: this.shareFilePath,
-        shareBatchNum: this.shareBatchNum
-      }).then((res) => {
-        if (res.success) {
-          this.fileList = res.data
-          this.loading = false
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 保存到网盘按钮点击事件
-     */
-    handleSaveBtnClick() {
-      if (this.selectionFile.length) {
-        this.dialogSelectPath.visible = true
-      } else {
-        this.$message.warning('请先勾选要保存的文件')
-      }
-    },
-    /**
-     * 移动文件模态框 | 设置移动后的文件路径
-     * @param {string} selectFilePath 目标文件夹路径
-     */
-    setSelectFilePath(selectFilePath) {
-      this.selectFilePath = selectFilePath
-    },
-    /**
-     * 移动文件模态框 | 确定按钮事件
-     */
-    confirmSelectPathDialog() {
-      saveShareFile({
-        filePath: this.selectFilePath,
-        files: JSON.stringify(
-          this.selectionFile.map((item) => {
-            return {
-              userFileId: item.userFileId
-            }
-          })
-        )
-      }).then((res) => {
-        if (res.success) {
-          this.$message.success('保存成功')
-          this.dialogSelectPath.visible = false
-          this.$refs.fileTableInstance.clearSelectedTable() //  清空表格已选项
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 设置移动文件模态框相关数据
-     * @param {boolean} isBatchMove 是否批量移动,为 null时是确认移动,值由之前的值而定,在此业务中此致无用
-     * @param {boolean} visible 移动文件对话框状态
-     */
-    setSelectPathDialogData(isBatchMove, visible) {
-      this.dialogSelectPath.visible = visible
-    }
-  }
+	name: 'Share',
+	components: {
+		BreadCrumb,
+		FileTable,
+		MoveFileDialog
+	},
+	data() {
+		return {
+			// 文件分享对话框数据
+			dialogShareFile: {
+				visible: false,
+				codeForm: {
+					extractionCode: ''
+				},
+				codeFormRules: {
+					extractionCode: [
+						{
+							required: true,
+							message: '请输入提取码',
+							trigger: 'blur'
+						}
+					]
+				}
+			},
+			shareStep: 0,
+			fileList: [],
+			loading: false,
+			// 保存到网盘对话框数据
+			dialogSelectPath: {
+				visible: false //  是否可见
+			},
+			selectFilePath: '', //  保存到网盘的目标路径
+			selectionFile: [] //  表格勾选的文件列表
+		}
+	},
+	computed: {
+		shareBatchNum() {
+			return this.$route.params.shareBatchNum
+		},
+		filePath() {
+			return this.$route.query.filePath
+		},
+		shareFilePath() {
+			return this.$route.query.filePath
+		}
+	},
+	watch: {
+		filePath() {
+			this.getShareList()
+		}
+	},
+	created() {
+		if (!this.filePath) {
+			this.$router.replace({
+				query: {
+					filePath: '/'
+				}
+			})
+		}
+	},
+	mounted() {
+		this.checkEndTime()
+	},
+	methods: {
+		/**
+		 * 表格勾选框事件 | 保存被勾选的文件
+		 * @param {object[]} selection 被勾选的文件数组
+		 */
+		setSelectionFile(selection) {
+			this.selectionFile = selection
+		},
+		/**
+		 * 校验分享链接过期时间
+		 */
+		checkEndTime() {
+			checkShareLinkEndtime({
+				shareBatchNum: this.shareBatchNum
+			}).then((res) => {
+				if (res.success) {
+					if (this.getCookies(`share_${this.shareBatchNum}`) === 'true') {
+						this.checkShareComplete()
+					} else {
+						this.dialogShareFile.visible = true
+						this.checkShareType()
+					}
+				} else {
+					this.dialogShareFile.visible = true
+					this.shareStep = 1 //  链接已过期
+				}
+			})
+		},
+		/**
+		 * 校验分享类型
+		 * @description 校验分享链接是公共还是私密
+		 */
+		checkShareType() {
+			checkShareLinkType({
+				shareBatchNum: this.shareBatchNum
+			}).then((res) => {
+				if (res.success) {
+					// 0 公共 1 私密
+					if (res.data.shareType === 0) {
+						this.shareStep = 3 //  不是私密链接,直接展示文件列表
+						this.getShareList()
+						this.dialogShareFile.visible = false
+					}
+					if (res.data.shareType === 1) {
+						this.shareStep = 2 //  是私密链接时,让用户输入提取码
+					}
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 分享文件验证对话框 取消按钮
+		 */
+		handleCloseBtnClick() {
+			this.dialogShareFile.visible = false
+			this.$router.push({ name: 'File', query: { fileType: 0, filePath: '/' } })
+		},
+		/**
+		 * 提交按钮点击事件
+		 */
+		handleSubmitBtnClick(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					checkShareLinkCode({
+						extractionCode: this.dialogShareFile.codeForm.extractionCode,
+						shareBatchNum: this.shareBatchNum
+					}).then((res) => {
+						if (res.success) {
+							this.setCookies(`share_${this.shareBatchNum}`, true)
+							this.$refs[formName].resetFields() //  清空表单
+							this.checkShareComplete()
+						} else {
+							this.$message.error(res.message)
+						}
+					})
+				} else {
+					return false
+				}
+			})
+		},
+		/**
+		 * 校验全部通过
+		 */
+		checkShareComplete() {
+			this.shareStep = 3 //  展示文件列表
+			this.dialogShareFile.visible = false
+			this.getShareList()
+		},
+		/**
+		 * 获取分享文件列表
+		 */
+		getShareList() {
+			this.loading = true
+			getShareFileList({
+				shareFilePath: this.shareFilePath,
+				shareBatchNum: this.shareBatchNum
+			}).then((res) => {
+				if (res.success) {
+					this.fileList = res.data
+					this.loading = false
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 保存到网盘按钮点击事件
+		 */
+		handleSaveBtnClick() {
+			if (this.selectionFile.length) {
+				this.dialogSelectPath.visible = true
+			} else {
+				this.$message.warning('请先勾选要保存的文件')
+			}
+		},
+		/**
+		 * 移动文件模态框 | 设置移动后的文件路径
+		 * @param {string} selectFilePath 目标文件夹路径
+		 */
+		setSelectFilePath(selectFilePath) {
+			this.selectFilePath = selectFilePath
+		},
+		/**
+		 * 移动文件模态框 | 确定按钮事件
+		 */
+		confirmSelectPathDialog() {
+			saveShareFile({
+				filePath: this.selectFilePath,
+				files: JSON.stringify(
+					this.selectionFile.map((item) => {
+						return {
+							userFileId: item.userFileId
+						}
+					})
+				)
+			}).then((res) => {
+				if (res.success) {
+					this.$message.success('保存成功')
+					this.dialogSelectPath.visible = false
+					this.$refs.fileTableInstance.clearSelectedTable() //  清空表格已选项
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 设置移动文件模态框相关数据
+		 * @param {boolean} isBatchMove 是否批量移动,为 null时是确认移动,值由之前的值而定,在此业务中此致无用
+		 * @param {boolean} visible 移动文件对话框状态
+		 */
+		setSelectPathDialogData(isBatchMove, visible) {
+			this.dialogSelectPath.visible = visible
+		}
+	}
 }
 </script>
 

+ 17 - 17
src/views/file/File.vue

@@ -1,16 +1,16 @@
 <template>
-  <div class="file-wrapper">
-    <el-container class="el-container">
-      <el-aside width="auto">
-        <AsideMenu></AsideMenu>
-      </el-aside>
-      <el-container>
-        <el-main class="el-main">
-          <FileList></FileList>
-        </el-main>
-      </el-container>
-    </el-container>
-  </div>
+	<div class="file-wrapper">
+		<el-container class="el-container">
+			<el-aside width="auto">
+				<AsideMenu></AsideMenu>
+			</el-aside>
+			<el-container>
+				<el-main class="el-main">
+					<FileList></FileList>
+				</el-main>
+			</el-container>
+		</el-container>
+	</div>
 </template>
 
 <script>
@@ -18,11 +18,11 @@ import AsideMenu from './components/AsideMenu/AsideMenu'
 import FileList from './components/FileList'
 
 export default {
-  name: 'File',
-  components: {
-    AsideMenu,
-    FileList
-  }
+	name: 'File',
+	components: {
+		AsideMenu,
+		FileList
+	}
 }
 </script>
 

+ 127 - 108
src/views/file/components/AsideMenu/AsideMenu.vue

@@ -1,116 +1,135 @@
 <template>
-  <div class="side-menu-wrapper">
-    <!-- collapse 属性:控制菜单收缩展开 -->
-    <el-menu
-      class="side-menu"
-      :default-active="activeIndex"
-      :router="true"
-      :collapse="isCollapse"
-      background-color="#545c64"
-      text-color="#fff"
-      active-text-color="#ffd04b"
-    >
-      <el-menu-item index="0" :route="{ name: 'File', query: { fileType: 0, filePath: '/' } }">
-        <!-- 图标均来自 Element UI 官方图标库 https://element.eleme.cn/#/zh-CN/component/icon -->
-        <i class="el-icon-menu"></i>
-        <span slot="title">全部</span>
-      </el-menu-item>
-      <el-menu-item index="1" :route="{ name: 'File', query: { fileType: 1 } }">
-        <i class="el-icon-picture"></i>
-        <span slot="title">图片</span>
-      </el-menu-item>
-      <el-menu-item index="2" :route="{ name: 'File', query: { fileType: 2 } }">
-        <i class="el-icon-document"></i>
-        <span slot="title">文档</span>
-      </el-menu-item>
-      <el-menu-item index="3" :route="{ name: 'File', query: { fileType: 3 } }">
-        <i class="el-icon-video-camera-solid"></i>
-        <span slot="title">视频</span>
-      </el-menu-item>
-      <el-menu-item index="4" :route="{ name: 'File', query: { fileType: 4 } }">
-        <i class="el-icon-headset"></i>
-        <span slot="title">音乐</span>
-      </el-menu-item>
-      <el-menu-item index="5" :route="{ name: 'File', query: { fileType: 5 } }">
-        <i class="el-icon-takeaway-box"></i>
-        <span slot="title">其他</span>
-      </el-menu-item>
-      <el-menu-item index="6" :route="{ name: 'File', query: { fileType: 6 } }">
-        <i class="el-icon-box"></i>
-        <span slot="title">回收站</span>
-      </el-menu-item>
-    </el-menu>
-    <!-- 存储信息显示 -->
-    <div class="storage-wrapper" :class="{ fold: isCollapse }">
-      <el-progress
-        :percentage="storagePercentage"
-        :color="storageColor"
-        :show-text="false"
-        :type="isCollapse ? 'circle' : 'line'"
-        :width="32"
-        :stroke-width="isCollapse ? 4 : 6"
-        stroke-linecap="square"
-      ></el-progress>
-      <div class="text" v-show="!isCollapse">
-        <span class="label">存储</span>
-        <span>{{ storageValue | storageTrans }} / {{ totalStorageValue | storageTrans }}</span>
-      </div>
-      <div class="text" v-show="isCollapse">
-        <span>{{ storageValue | storageTrans }}</span>
-      </div>
-    </div>
-    <!-- 展开 & 收缩分类栏 -->
-    <el-tooltip effect="dark" :content="isCollapse ? '展开' : '收起'" placement="right">
-      <div class="aside-title" @click="isCollapse ? (isCollapse = false) : (isCollapse = true)">
-        <div class="top"></div>
-        <i class="icon el-icon-d-arrow-right" v-if="isCollapse" title="展开"></i>
-        <i class="icon el-icon-d-arrow-left" v-else title="收起"></i>
-        <div class="bottom"></div>
-      </div>
-    </el-tooltip>
-  </div>
+	<div class="side-menu-wrapper">
+		<!-- collapse 属性:控制菜单收缩展开 -->
+		<el-menu
+			class="side-menu"
+			:default-active="activeIndex"
+			:router="true"
+			:collapse="isCollapse"
+			background-color="#545c64"
+			text-color="#fff"
+			active-text-color="#ffd04b"
+		>
+			<el-menu-item
+				index="0"
+				:route="{ name: 'File', query: { fileType: 0, filePath: '/' } }"
+			>
+				<!-- 图标均来自 Element UI 官方图标库 https://element.eleme.cn/#/zh-CN/component/icon -->
+				<i class="el-icon-menu"></i>
+				<span slot="title">全部</span>
+			</el-menu-item>
+			<el-menu-item index="1" :route="{ name: 'File', query: { fileType: 1 } }">
+				<i class="el-icon-picture"></i>
+				<span slot="title">图片</span>
+			</el-menu-item>
+			<el-menu-item index="2" :route="{ name: 'File', query: { fileType: 2 } }">
+				<i class="el-icon-document"></i>
+				<span slot="title">文档</span>
+			</el-menu-item>
+			<el-menu-item index="3" :route="{ name: 'File', query: { fileType: 3 } }">
+				<i class="el-icon-video-camera-solid"></i>
+				<span slot="title">视频</span>
+			</el-menu-item>
+			<el-menu-item index="4" :route="{ name: 'File', query: { fileType: 4 } }">
+				<i class="el-icon-headset"></i>
+				<span slot="title">音乐</span>
+			</el-menu-item>
+			<el-menu-item index="5" :route="{ name: 'File', query: { fileType: 5 } }">
+				<i class="el-icon-takeaway-box"></i>
+				<span slot="title">其他</span>
+			</el-menu-item>
+			<el-menu-item index="6" :route="{ name: 'File', query: { fileType: 6 } }">
+				<i class="el-icon-box"></i>
+				<span slot="title">回收站</span>
+			</el-menu-item>
+		</el-menu>
+		<!-- 存储信息显示 -->
+		<div class="storage-wrapper" :class="{ fold: isCollapse }">
+			<el-progress
+				:percentage="storagePercentage"
+				:color="storageColor"
+				:show-text="false"
+				:type="isCollapse ? 'circle' : 'line'"
+				:width="32"
+				:stroke-width="isCollapse ? 4 : 6"
+				stroke-linecap="square"
+			></el-progress>
+			<div class="text" v-show="!isCollapse">
+				<span class="label">存储</span>
+				<span
+					>{{ storageValue | storageTrans }} /
+					{{ totalStorageValue | storageTrans }}</span
+				>
+			</div>
+			<div class="text" v-show="isCollapse">
+				<span>{{ storageValue | storageTrans }}</span>
+			</div>
+		</div>
+		<!-- 展开 & 收缩分类栏 -->
+		<el-tooltip
+			effect="dark"
+			:content="isCollapse ? '展开' : '收起'"
+			placement="right"
+		>
+			<div
+				class="aside-title"
+				@click="isCollapse ? (isCollapse = false) : (isCollapse = true)"
+			>
+				<div class="top"></div>
+				<i
+					class="icon el-icon-d-arrow-right"
+					v-if="isCollapse"
+					title="展开"
+				></i>
+				<i class="icon el-icon-d-arrow-left" v-else title="收起"></i>
+				<div class="bottom"></div>
+			</div>
+		</el-tooltip>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'SideMenu',
-  data() {
-    return {
-      isCollapse: false, //  控制菜单收缩展开
-      //  自定义进度条颜色,不同占比,进度条颜色不同
-      storageColor: [
-        { color: '#67C23A', percentage: 50 },
-        { color: '#E6A23C', percentage: 80 },
-        { color: '#F56C6C', percentage: 100 }
-      ]
-    }
-  },
-  computed: {
-    // 当前激活菜单的 index
-    activeIndex() {
-      return String(this.$route.query.fileType) //  获取当前路由参数中包含的文件类型
-    },
-    // 存储容量
-    storageValue() {
-      return this.$store.state.sideMenu.storageValue
-    },
-    totalStorageValue() {
-      return this.$store.state.sideMenu.totalStorageValue
-    },
-    // 存储百分比
-    storagePercentage() {
-      return this.totalStorageValue ? (this.storageValue / this.totalStorageValue) * 100 : 0
-    }
-  },
-  watch: {
-    // 监听收缩状态变化,存储在sessionStorage中,保证页面刷新时仍然保存设置的状态
-    isCollapse(newValue) {
-      this.setCookies('isCollapse', newValue)
-    }
-  },
-  created() {
-    this.isCollapse = this.getCookies('isCollapse') === 'true' //  读取保存的状态
-  }
+	name: 'SideMenu',
+	data() {
+		return {
+			isCollapse: false, //  控制菜单收缩展开
+			//  自定义进度条颜色,不同占比,进度条颜色不同
+			storageColor: [
+				{ color: '#67C23A', percentage: 50 },
+				{ color: '#E6A23C', percentage: 80 },
+				{ color: '#F56C6C', percentage: 100 }
+			]
+		}
+	},
+	computed: {
+		// 当前激活菜单的 index
+		activeIndex() {
+			return String(this.$route.query.fileType) //  获取当前路由参数中包含的文件类型
+		},
+		// 存储容量
+		storageValue() {
+			return this.$store.state.sideMenu.storageValue
+		},
+		totalStorageValue() {
+			return this.$store.state.sideMenu.totalStorageValue
+		},
+		// 存储百分比
+		storagePercentage() {
+			return this.totalStorageValue
+				? (this.storageValue / this.totalStorageValue) * 100
+				: 0
+		}
+	},
+	watch: {
+		// 监听收缩状态变化,存储在sessionStorage中,保证页面刷新时仍然保存设置的状态
+		isCollapse(newValue) {
+			this.setCookies('isCollapse', newValue)
+		}
+	},
+	created() {
+		this.isCollapse = this.getCookies('isCollapse') === 'true' //  读取保存的状态
+	}
 }
 </script>
 

+ 735 - 666
src/views/file/components/FileList/components/FileGrid.vue

@@ -1,678 +1,747 @@
 <template>
-  <!-- 文件平铺 -->
-  <div class="file-grid-wrapper">
-    <ul
-      class="file-list"
-      v-loading="loading"
-      element-loading-text="文件加载中……"
-      @click.self="rightMenu.isShow = false"
-      @scroll="rightMenu.isShow = false"
-    >
-      <li
-        class="file-item"
-        v-for="(item, index) in fileListSorted"
-        :key="index"
-        :title="item | fileNameComplete"
-        :style="`width: ${gridSize + 40}px; `"
-        :class="item.userFileId === selectedFile.userFileId ? 'active' : ''"
-        @click="handleFileNameClick(item, index, fileListSorted)"
-        @contextmenu.prevent="handleContextMenu(item, index, $event)"
-      >
-        <img class="file-img" :src="setFileImg(item)" :style="`width: ${gridSize}px; height: ${gridSize}px;`" />
-        <div class="file-name">{{ item | fileNameComplete }}</div>
-        <div
-          class="file-checked-wrapper"
-          :class="{ checked: item.checked }"
-          v-show="batchOperate"
-          @click.stop.self="item.checked = !item.checked"
-        >
-          <el-checkbox
-            class="file-checked"
-            v-model="item.checked"
-            @click.stop="item.checked = !item.checked"
-          ></el-checkbox>
-        </div>
-      </li>
-    </ul>
-    <transition name="el-fade-in-linear">
-      <ul
-        class="right-menu-list"
-        id="rightMenuList"
-        v-show="rightMenu.isShow"
-        :style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
-      >
-        <li class="right-menu-item" @click="handleFileNameClick(selectedFile, selectedIndex, fileListSorted)" v-if="seeBtnShow">
-          <i class="el-icon-view"></i> 查看
-        </li>
-        <li class="right-menu-item" @click="handleDeleteFileBtnClick(selectedFile)" v-if="deleteBtnShow">
-          <i class="el-icon-delete"></i> 删除
-        </li>
-        <li class="right-menu-item" @click="handleRestoreFileBtnClick(selectedFile)" v-if="restoreBtnShow">
-          <i class="el-icon-refresh-left"></i> 还原
-        </li>
-        <li class="right-menu-item" @click="handleMoveFileBtnClick(selectedFile)" v-if="moveBtnShow">
-          <i class="el-icon-s-promotion"></i> 移动
-        </li>
-        <li class="right-menu-item" @click="handleRenameFileBtnClick(selectedFile)" v-if="renameBtnShow">
-          <i class="el-icon-edit-outline"></i> 重命名
-        </li>
-        <li class="right-menu-item" @click="handleShareFileBtnClick(selectedFile)" v-if="shareBtnShow">
-          <i class="el-icon-share"></i> 分享
-        </li>
-        <li class="right-menu-item" @click="rightMenu.isShow = false" v-if="downloadBtnShow">
-          <a
-            target="_blank"
-            style="display: block; color: inherit"
-            :href="getDownloadFilePath(selectedFile)"
-            :download="selectedFile.fileName + '.' + selectedFile.extendName"
-          >
-            <i class="el-icon-download"></i> 下载
-          </a>
-        </li>
-        <li class="right-menu-item" @click="handleUnzipFileBtnClick(selectedFile)" v-if="unzipBtnShow">
-          <i class="el-icon-files"></i> 解压缩
-        </li>
-        <li class="right-menu-item" @click="getFileOnlineEditPathByOffice(selectedFile)" v-if="onlineEditBtnShow">
-          <i class="el-icon-edit"></i> 在线编辑
-        </li>
-        <li
-          class="right-menu-item"
-          @click="copyShareLink(selectedFile.shareBatchNum, selectedFile.extractionCode)"
-          v-if="copyLinkBtnShow"
-        >
-          <i class="el-icon-edit"></i> 复制链接
-        </li>
-      </ul>
-    </transition>
-  </div>
+	<!-- 文件平铺 -->
+	<div class="file-grid-wrapper">
+		<ul
+			class="file-list"
+			v-loading="loading"
+			element-loading-text="文件加载中……"
+			@click.self="rightMenu.isShow = false"
+			@scroll="rightMenu.isShow = false"
+		>
+			<li
+				class="file-item"
+				v-for="(item, index) in fileListSorted"
+				:key="index"
+				:title="item | fileNameComplete"
+				:style="`width: ${gridSize + 40}px; `"
+				:class="item.userFileId === selectedFile.userFileId ? 'active' : ''"
+				@click="handleFileNameClick(item, index, fileListSorted)"
+				@contextmenu.prevent="handleContextMenu(item, index, $event)"
+			>
+				<img
+					class="file-img"
+					:src="setFileImg(item)"
+					:style="`width: ${gridSize}px; height: ${gridSize}px;`"
+				/>
+				<div class="file-name">{{ item | fileNameComplete }}</div>
+				<div
+					class="file-checked-wrapper"
+					:class="{ checked: item.checked }"
+					v-show="batchOperate"
+					@click.stop.self="item.checked = !item.checked"
+				>
+					<el-checkbox
+						class="file-checked"
+						v-model="item.checked"
+						@click.stop="item.checked = !item.checked"
+					></el-checkbox>
+				</div>
+			</li>
+		</ul>
+		<transition name="el-fade-in-linear">
+			<ul
+				class="right-menu-list"
+				id="rightMenuList"
+				v-show="rightMenu.isShow"
+				:style="`top: ${rightMenu.top};right: ${rightMenu.right};bottom: ${rightMenu.bottom};left: ${rightMenu.left};`"
+			>
+				<li
+					class="right-menu-item"
+					@click="
+						handleFileNameClick(selectedFile, selectedIndex, fileListSorted)
+					"
+					v-if="seeBtnShow"
+				>
+					<i class="el-icon-view"></i> 查看
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleDeleteFileBtnClick(selectedFile)"
+					v-if="deleteBtnShow"
+				>
+					<i class="el-icon-delete"></i> 删除
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleRestoreFileBtnClick(selectedFile)"
+					v-if="restoreBtnShow"
+				>
+					<i class="el-icon-refresh-left"></i> 还原
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleMoveFileBtnClick(selectedFile)"
+					v-if="moveBtnShow"
+				>
+					<i class="el-icon-s-promotion"></i> 移动
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleRenameFileBtnClick(selectedFile)"
+					v-if="renameBtnShow"
+				>
+					<i class="el-icon-edit-outline"></i> 重命名
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleShareFileBtnClick(selectedFile)"
+					v-if="shareBtnShow"
+				>
+					<i class="el-icon-share"></i> 分享
+				</li>
+				<li
+					class="right-menu-item"
+					@click="rightMenu.isShow = false"
+					v-if="downloadBtnShow"
+				>
+					<a
+						target="_blank"
+						style="display: block; color: inherit"
+						:href="getDownloadFilePath(selectedFile)"
+						:download="selectedFile.fileName + '.' + selectedFile.extendName"
+					>
+						<i class="el-icon-download"></i> 下载
+					</a>
+				</li>
+				<li
+					class="right-menu-item"
+					@click="handleUnzipFileBtnClick(selectedFile)"
+					v-if="unzipBtnShow"
+				>
+					<i class="el-icon-files"></i> 解压缩
+				</li>
+				<li
+					class="right-menu-item"
+					@click="getFileOnlineEditPathByOffice(selectedFile)"
+					v-if="onlineEditBtnShow"
+				>
+					<i class="el-icon-edit"></i> 在线编辑
+				</li>
+				<li
+					class="right-menu-item"
+					@click="
+						copyShareLink(
+							selectedFile.shareBatchNum,
+							selectedFile.extractionCode
+						)
+					"
+					v-if="copyLinkBtnShow"
+				>
+					<i class="el-icon-edit"></i> 复制链接
+				</li>
+			</ul>
+		</transition>
+	</div>
 </template>
 
 <script>
-import { unzipFile, deleteFile, renameFile, deleteRecoveryFile, restoreRecoveryFile } from '_r/file.js'
+import {
+	unzipFile,
+	deleteFile,
+	renameFile,
+	deleteRecoveryFile,
+	restoreRecoveryFile
+} from '_r/file.js'
 import { mapGetters } from 'vuex'
 import 'element-ui/lib/theme-chalk/base.css'
 
 export default {
-  name: 'FileGrid',
-  props: {
-    // 文件类型
-    fileType: {
-      required: true,
-      type: Number
-    },
-    // 文件路径
-    filePath: {
-      required: true,
-      type: String
-    },
-    fileList: Array, //  文件列表
-    loading: Boolean,
-    batchOperate: Boolean
-  },
-  data() {
-    return {
-      fileListSorted: [],
-      //  可以识别的文件类型
-      fileImgTypeList: [
-        'png',
-        'jpg',
-        'jpeg',
-        'docx',
-        'doc',
-        'ppt',
-        'pptx',
-        'xls',
-        'xlsx',
-        'avi',
-        'mp4',
-        'css',
-        'csv',
-        'chm',
-        'rar',
-        'zip',
-        'dmg',
-        'mp3',
-        'open',
-        'pdf',
-        'rtf',
-        'txt',
-        'oa',
-        'js',
-        'html',
-        'img',
-        'sql',
-        'jar',
-        'svg',
-        'gif',
-        'json',
-        'exe'
-      ],
-      //  文件图片Map映射
-      fileImgMap: {
-        dir: require('_a/images/file/dir.png'),
-        chm: require('_a/images/file/file_chm.png'),
-        css: require('_a/images/file/file_css.png'),
-        csv: require('_a/images/file/file_csv.png'),
-        png: require('_a/images/file/file_pic.png'),
-        jpg: require('_a/images/file/file_pic.png'),
-        jpeg: require('_a/images/file/file_pic.png'),
-        docx: require('_a/images/file/file_word.png'),
-        doc: require('_a/images/file/file_word.png'),
-        ppt: require('_a/images/file/file_ppt.png'),
-        pptx: require('_a/images/file/file_ppt.png'),
-        xls: require('_a/images/file/file_excel.png'),
-        xlsx: require('_a/images/file/file_excel.png'),
-        mp4: require('_a/images/file/file_video.png'),
-        avi: require('_a/images/file/file_avi.png'),
-        rar: require('_a/images/file/file_rar.png'),
-        zip: require('_a/images/file/file_zip.png'),
-        dmg: require('_a/images/file/file_dmg.png'),
-        mp3: require('_a/images/file/file_music.png'),
-        open: require('_a/images/file/file_open.png'),
-        pdf: require('_a/images/file/file_pdf.png'),
-        rtf: require('_a/images/file/file_rtf.png'),
-        txt: require('_a/images/file/file_txt.png'),
-        oa: require('_a/images/file/file_oa.png'),
-        unknown: require('_a/images/file/file_unknown.png'),
-        js: require('_a/images/file/file_js.png'),
-        html: require('_a/images/file/file_html.png'),
-        img: require('_a/images/file/file_img.png'),
-        sql: require('_a/images/file/file_sql.png'),
-        jar: require('_a/images/file/file_jar.png'),
-        svg: require('_a/images/file/file_svg.png'),
-        json: require('_a/images/file/file_json.png'),
-        exe: require('_a/images/file/file_exe.png')
-      },
-      officeFileType: ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx'],
-      downloadFilePath: '',
-      viewFilePath: '',
-      // 右键菜单
-      rightMenu: {
-        isShow: false,
-        top: 0,
-        left: 0
-      },
-      selectedFile: {},
-      selectedIndex: 0,
-      // 音频预览
-      audioObj: {
-        src: ''
-      }
-    }
-  },
-  computed: {
-    /**
-     * selectedColumnList: 列显隐
-     * fileModel: 文件查看模式 0列表模式 1网格模式
-     *  */
-    ...mapGetters(['selectedColumnList', 'fileModel']),
-    //  判断当前路径下是否有普通文件
-    isIncludeNormalFile() {
-      return this.fileList.map((data) => data.isDir).includes(0)
-    },
-    //  判断当前路径下是否有压缩文件
-    isIncludeZipRarFile() {
-      return (
-        this.fileList.map((data) => data.extendName).includes('zip') ||
-        this.fileList.map((data) => data.extendName).includes('rar')
-      )
-    },
-    // 批量操作模式 - 被选中的文件
-    selectedFileList() {
-      let res = this.fileListSorted.filter((item) => item.checked)
-      return res
-    },
-    // 图标大小
-    gridSize() {
-      return this.$store.getters.gridSize
-    },
-    // 查看按钮是否显示
-    seeBtnShow() {
-      return this.fileType !== 6
-    },
-    // 删除按钮是否显示
-    deleteBtnShow() {
-      return !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 还原按钮是否显示
-    restoreBtnShow() {
-      return this.fileType === 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 移动按钮是否显示
-    moveBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 重命名按钮是否显示
-    renameBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 删除按钮是否显示
-    shareBtnShow() {
-      return this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
-    },
-    // 下载按钮是否显示
-    downloadBtnShow() {
-      return this.fileType !== 6 && !['MyShare'].includes(this.routeName)
-    },
-    // 解压缩按钮是否显示
-    unzipBtnShow() {
-      return (
-        this.fileType !== 6 &&
-        !['Share', 'MyShare'].includes(this.routeName) &&
-        ['zip', 'rar'].includes(this.selectedFile.extendName)
-      )
-    },
-    // 在线编辑按钮是否显示
-    onlineEditBtnShow() {
-      return (
-        this.fileType !== 6 &&
-        this.officeFileType.includes(this.selectedFile.extendName) &&
-        !['Share', 'MyShare'].includes(this.routeName)
-      )
-    },
-    // 复制链接按钮是否显示
-    copyLinkBtnShow() {
-      return this.routeName === 'MyShare'
-    }
-  },
-  watch: {
-    // 文件平铺模式 排序-文件夹在前
-    fileList(newValue) {
-      this.fileListSorted = [...newValue]
-        .sort((pre, next) => {
-          return next.isDir - pre.isDir
-        })
-        .map((item) => {
-          return {
-            ...item,
-            checked: false
-          }
-        })
-    },
-    // 批量操作模式 - 被选中的文件
-    selectedFileList(newValue) {
-      this.$emit('setSelectionFile', newValue, this.batchOperate)
-    },
-    /**
-     * 监听右键列表状态
-     * @description 右键列表打开时,body 添加点击事件的监听
-     */
-    'rightMenu.isShow'(newValue) {
-      if (newValue) {
-        document.body.addEventListener('click', this.closeRightMenu)
-      } else {
-        document.body.removeEventListener('click', this.closeRightMenu)
-      }
-    }
-  },
-  methods: {
-    /**
-     * 文件鼠标右键事件
-     * @param {object} item 文件信息
-     * @param {number} index 文件索引
-     * @param {object} event 鼠标事件信息
-     */
-    handleContextMenu(item, index, event) {
-      if (!this.batchOperate) {
-        event.preventDefault()
-        this.selectedFile = item
-        this.selectedIndex = index
-        // 纵坐标设置
-        if (
-          document.body.clientHeight - event.clientY <
-          document.querySelectorAll('#rightMenuList > .right-menu-item').length * 36 + 10
-        ) {
-          // 如果到底部的距离小于元素总高度
-          this.rightMenu.top = 'auto'
-          this.rightMenu.bottom = `${document.body.clientHeight - event.clientY}px`
-        } else {
-          this.rightMenu.top = `${event.clientY}px`
-          this.rightMenu.bottom = 'auto'
-        }
-        // 横坐标设置
-        if (document.body.clientWidth - event.clientX < 120) {
-          // 如果到右边的距离小于元素总宽度
-          this.rightMenu.left = 'auto'
-          this.rightMenu.right = `${document.body.clientWidth - event.clientX}px`
-        } else {
-          this.rightMenu.left = `${event.clientX + 8}px`
-          this.rightMenu.right = 'auto'
-        }
-        this.rightMenu.isShow = true
-        }
-    },
-    /**
-     * 关闭右键列表
-     */
-    closeRightMenu() {
-      this.rightMenu.isShow = false
-      this.selectedFile = {}
-    },
-    /**
-     * 根据文件扩展名设置文件图片
-     * @param {object} row 文件信息
-     */
-    setFileImg(row) {
-      if (row.isDir === 1) {
-        //  文件夹
-        return this.fileImgMap.dir
-      } else if (!this.fileImgTypeList.includes(row.extendName)) {
-        //  无法识别文件类型的文件
-        return this.fileImgMap.unknown
-      } else if (this.fileType !== 6 && ['jpg', 'png', 'jpeg', 'gif', 'mp4'].includes(row.extendName)) {
-        // 图片类型,直接显示缩略图
-        return this.getImgMinPath(row)
-      } else {
-        //  可以识别文件类型的文件
-        return this.fileImgMap[row.extendName]
-      }
-    },
+	name: 'FileGrid',
+	props: {
+		// 文件类型
+		fileType: {
+			required: true,
+			type: Number
+		},
+		// 文件路径
+		filePath: {
+			required: true,
+			type: String
+		},
+		fileList: Array, //  文件列表
+		loading: Boolean,
+		batchOperate: Boolean
+	},
+	data() {
+		return {
+			fileListSorted: [],
+			//  可以识别的文件类型
+			fileImgTypeList: [
+				'png',
+				'jpg',
+				'jpeg',
+				'docx',
+				'doc',
+				'ppt',
+				'pptx',
+				'xls',
+				'xlsx',
+				'avi',
+				'mp4',
+				'css',
+				'csv',
+				'chm',
+				'rar',
+				'zip',
+				'dmg',
+				'mp3',
+				'open',
+				'pdf',
+				'rtf',
+				'txt',
+				'oa',
+				'js',
+				'html',
+				'img',
+				'sql',
+				'jar',
+				'svg',
+				'gif',
+				'json',
+				'exe'
+			],
+			//  文件图片Map映射
+			fileImgMap: {
+				dir: require('_a/images/file/dir.png'),
+				chm: require('_a/images/file/file_chm.png'),
+				css: require('_a/images/file/file_css.png'),
+				csv: require('_a/images/file/file_csv.png'),
+				png: require('_a/images/file/file_pic.png'),
+				jpg: require('_a/images/file/file_pic.png'),
+				jpeg: require('_a/images/file/file_pic.png'),
+				docx: require('_a/images/file/file_word.png'),
+				doc: require('_a/images/file/file_word.png'),
+				ppt: require('_a/images/file/file_ppt.png'),
+				pptx: require('_a/images/file/file_ppt.png'),
+				xls: require('_a/images/file/file_excel.png'),
+				xlsx: require('_a/images/file/file_excel.png'),
+				mp4: require('_a/images/file/file_video.png'),
+				avi: require('_a/images/file/file_avi.png'),
+				rar: require('_a/images/file/file_rar.png'),
+				zip: require('_a/images/file/file_zip.png'),
+				dmg: require('_a/images/file/file_dmg.png'),
+				mp3: require('_a/images/file/file_music.png'),
+				open: require('_a/images/file/file_open.png'),
+				pdf: require('_a/images/file/file_pdf.png'),
+				rtf: require('_a/images/file/file_rtf.png'),
+				txt: require('_a/images/file/file_txt.png'),
+				oa: require('_a/images/file/file_oa.png'),
+				unknown: require('_a/images/file/file_unknown.png'),
+				js: require('_a/images/file/file_js.png'),
+				html: require('_a/images/file/file_html.png'),
+				img: require('_a/images/file/file_img.png'),
+				sql: require('_a/images/file/file_sql.png'),
+				jar: require('_a/images/file/file_jar.png'),
+				svg: require('_a/images/file/file_svg.png'),
+				json: require('_a/images/file/file_json.png'),
+				exe: require('_a/images/file/file_exe.png')
+			},
+			officeFileType: ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx'],
+			downloadFilePath: '',
+			viewFilePath: '',
+			// 右键菜单
+			rightMenu: {
+				isShow: false,
+				top: 0,
+				left: 0
+			},
+			selectedFile: {},
+			selectedIndex: 0,
+			// 音频预览
+			audioObj: {
+				src: ''
+			}
+		}
+	},
+	computed: {
+		/**
+		 * selectedColumnList: 列显隐
+		 * fileModel: 文件查看模式 0列表模式 1网格模式
+		 *  */
+		...mapGetters(['selectedColumnList', 'fileModel']),
+		//  判断当前路径下是否有普通文件
+		isIncludeNormalFile() {
+			return this.fileList.map((data) => data.isDir).includes(0)
+		},
+		//  判断当前路径下是否有压缩文件
+		isIncludeZipRarFile() {
+			return (
+				this.fileList.map((data) => data.extendName).includes('zip') ||
+				this.fileList.map((data) => data.extendName).includes('rar')
+			)
+		},
+		// 批量操作模式 - 被选中的文件
+		selectedFileList() {
+			let res = this.fileListSorted.filter((item) => item.checked)
+			return res
+		},
+		// 图标大小
+		gridSize() {
+			return this.$store.getters.gridSize
+		},
+		// 查看按钮是否显示
+		seeBtnShow() {
+			return this.fileType !== 6
+		},
+		// 删除按钮是否显示
+		deleteBtnShow() {
+			return !['Share', 'MyShare'].includes(this.routeName)
+		},
+		// 还原按钮是否显示
+		restoreBtnShow() {
+			return (
+				this.fileType === 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 移动按钮是否显示
+		moveBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 重命名按钮是否显示
+		renameBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 删除按钮是否显示
+		shareBtnShow() {
+			return (
+				this.fileType !== 6 && !['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 下载按钮是否显示
+		downloadBtnShow() {
+			return this.fileType !== 6 && !['MyShare'].includes(this.routeName)
+		},
+		// 解压缩按钮是否显示
+		unzipBtnShow() {
+			return (
+				this.fileType !== 6 &&
+				!['Share', 'MyShare'].includes(this.routeName) &&
+				['zip', 'rar'].includes(this.selectedFile.extendName)
+			)
+		},
+		// 在线编辑按钮是否显示
+		onlineEditBtnShow() {
+			return (
+				this.fileType !== 6 &&
+				this.officeFileType.includes(this.selectedFile.extendName) &&
+				!['Share', 'MyShare'].includes(this.routeName)
+			)
+		},
+		// 复制链接按钮是否显示
+		copyLinkBtnShow() {
+			return this.routeName === 'MyShare'
+		}
+	},
+	watch: {
+		// 文件平铺模式 排序-文件夹在前
+		fileList(newValue) {
+			this.fileListSorted = [...newValue]
+				.sort((pre, next) => {
+					return next.isDir - pre.isDir
+				})
+				.map((item) => {
+					return {
+						...item,
+						checked: false
+					}
+				})
+		},
+		// 批量操作模式 - 被选中的文件
+		selectedFileList(newValue) {
+			this.$emit('setSelectionFile', newValue, this.batchOperate)
+		},
+		/**
+		 * 监听右键列表状态
+		 * @description 右键列表打开时,body 添加点击事件的监听
+		 */
+		'rightMenu.isShow'(newValue) {
+			if (newValue) {
+				document.body.addEventListener('click', this.closeRightMenu)
+			} else {
+				document.body.removeEventListener('click', this.closeRightMenu)
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 文件鼠标右键事件
+		 * @param {object} item 文件信息
+		 * @param {number} index 文件索引
+		 * @param {object} event 鼠标事件信息
+		 */
+		handleContextMenu(item, index, event) {
+			if (!this.batchOperate) {
+				event.preventDefault()
+				this.selectedFile = item
+				this.selectedIndex = index
+				// 纵坐标设置
+				if (
+					document.body.clientHeight - event.clientY <
+					document.querySelectorAll('#rightMenuList > .right-menu-item')
+						.length *
+						36 +
+						10
+				) {
+					// 如果到底部的距离小于元素总高度
+					this.rightMenu.top = 'auto'
+					this.rightMenu.bottom = `${
+						document.body.clientHeight - event.clientY
+					}px`
+				} else {
+					this.rightMenu.top = `${event.clientY}px`
+					this.rightMenu.bottom = 'auto'
+				}
+				// 横坐标设置
+				if (document.body.clientWidth - event.clientX < 120) {
+					// 如果到右边的距离小于元素总宽度
+					this.rightMenu.left = 'auto'
+					this.rightMenu.right = `${
+						document.body.clientWidth - event.clientX
+					}px`
+				} else {
+					this.rightMenu.left = `${event.clientX + 8}px`
+					this.rightMenu.right = 'auto'
+				}
+				this.rightMenu.isShow = true
+			}
+		},
+		/**
+		 * 关闭右键列表
+		 */
+		closeRightMenu() {
+			this.rightMenu.isShow = false
+			this.selectedFile = {}
+		},
+		/**
+		 * 根据文件扩展名设置文件图片
+		 * @param {object} row 文件信息
+		 */
+		setFileImg(row) {
+			if (row.isDir === 1) {
+				//  文件夹
+				return this.fileImgMap.dir
+			} else if (!this.fileImgTypeList.includes(row.extendName)) {
+				//  无法识别文件类型的文件
+				return this.fileImgMap.unknown
+			} else if (
+				this.fileType !== 6 &&
+				['jpg', 'png', 'jpeg', 'gif', 'mp4'].includes(row.extendName)
+			) {
+				// 图片类型,直接显示缩略图
+				return this.getImgMinPath(row)
+			} else {
+				//  可以识别文件类型的文件
+				return this.fileImgMap[row.extendName]
+			}
+		},
 
-    /**
-     * 文件名点击事件
-     * @description 若当前点击的为文件夹,则进入文件夹内部;若是文件,则进行相应的预览。
-     * @param {object} row 文件信息
-     * @param {number} activeIndex 文件索引
-     * @param {[]} fileList 文件列表
-     */
-    handleFileNameClick(row, activeIndex, fileList) {
-      this.rightMenu.isShow = false
-      //  若是目录则进入目录
-      if (row.isDir) {
-        this.$router.push({
-          query: {
-            filePath: row.filePath + row.fileName + '/',
-            fileType: 0
-          }
-        })
-      } else {
-        //  若是文件,则进行相应的预览
-        //  若当前点击项是图片
-        const PIC = ['png', 'jpg', 'jpeg', 'gif', 'svg']
-        if (PIC.includes(row.extendName)) {
-          if (this.fileType === 1) {
-            //  图片分类下 - 大图查看
-            let data = {
-              imgPreviewVisible: true,
-              imgPreviewList: fileList.map((item) => {
-                return {
-                  fileUrl: this.getViewFilePath(item),
-                  downloadLink: this.getDownloadFilePath(item),
-                  fileName: item.fileName,
-                  extendName: item.extendName
-                }
-              }),
-              activeIndex: activeIndex
-            }
-            this.$store.commit('setImgPreviewData', data)
-          } else {
-            //  非图片分类下 - 大图查看
-            let data = {
-              imgPreviewVisible: true,
-              imgPreviewList: [
-                {
-                  fileUrl: this.getViewFilePath(row),
-                  downloadLink: this.getDownloadFilePath(row),
-                  fileName: row.fileName,
-                  extendName: row.extendName
-                }
-              ],
-              activeIndex: 0
-            }
-            this.$store.commit('setImgPreviewData', data)
-          }
-        }
-        //  若当前点击项是可以使用office在线预览的
-        if ([...this.officeFileType, 'pdf'].includes(row.extendName)) {
-          this.getFileOnlineViewPathByOffice(row)
-        }
-        //  若当前点击项是代码或文本文件
-        const CODE = ['html', 'js', 'css', 'json', 'c', 'java', 'txt']
-        if (CODE.includes(row.extendName)) {
-          window.open(this.getViewFilePath(row), '_blank')
-        }
-        //  若当前点击项是视频mp4格式
-        const VIDEO = ['mp4']
-        if (VIDEO.includes(row.extendName)) {
-          if (this.fileType === 3) {
-            // 视频分类下 加载播放列表
-            let data = {
-              videoPreviewVisible: true,
-              videoPreviewList: fileList.map((item) => {
-                return {
-                  ...item,
-                  fileUrl: this.getViewFilePath(item),
-                  downloadLink: this.getDownloadFilePath(item),
-                  fileName: item.fileName,
-                  extendName: item.extendName
-                }
-              }),
-              activeIndex: activeIndex
-            }
-            this.$store.commit('setVideoPreviewData', data)
-          } else {
-            // 非视频分类下 - 单个视频预览
-            let data = {
-              videoPreviewVisible: true,
-              videoPreviewList: [
-                {
-                  ...row,
-                  fileUrl: this.getViewFilePath(row),
-                  downloadLink: this.getDownloadFilePath(row),
-                  fileName: row.fileName,
-                  extendName: row.extendName
-                }
-              ],
-              activeIndex: 0
-            }
-            this.$store.commit('setVideoPreviewData', data)
-          }
-        }
-        //  若当前点击项是音频mp3格式
-        const AUDIO = ['mp3']
-        if (AUDIO.includes(row.extendName)) {
-          if (this.audioObj.src !== this.getViewFilePath(row)) {
-            this.$notify.closeAll()
-            this.audioObj.src = this.getViewFilePath(row)
-            this.$notify({
-              title: `${row.fileName}.${row.extendName}`,
-              dangerouslyUseHTMLString: true,
-              message: `<audio class="audio-preview" src="${
-                this.audioObj.src
-              }" controls autoplay style="padding-right: 16px; margin-top: 16px;"></audio>`,
-              duration: 0, //  不自动关闭
-              offset: 100,
-              onClose: () => {
-                this.audioObj.src = ''
-              }
-            })
-          }
-        }
-      }
-    },
-    /**
-     * 移动按钮点击事件
-     * @description 向父组件传递当前操作的文件信息,并打开“移动文件对话框”
-     * @param {object} file 文件信息
-     */
-    handleMoveFileBtnClick(file) {
-      this.rightMenu.isShow = false
-      this.$emit('setOperationFile', file)
-      //  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件模态框
-      this.$emit('setMoveFileDialogData', false, true)
-    },
-    /**
-     * 解压缩按钮点击事件
-     * @description 调用解压缩文件接口,并展示新的文件列表
-     * @param {object} fileInfo 文件信息
-     */
-    handleUnzipFileBtnClick(fileInfo) {
-      this.rightMenu.isShow = false
-      const loading = this.$loading({
-        lock: true,
-        text: '正在解压缩,请稍等片刻...',
-        spinner: 'el-icon-loading',
-        background: 'rgba(0, 0, 0, 0.7)'
-      })
-      unzipFile(fileInfo).then((res) => {
-        if (res.success) {
-          this.$emit('getTableDataByType')
-          this.$store.dispatch('showStorage')
-          this.$message.success('解压成功')
-          loading.close()
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 删除按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
-     * @param {object} fileInfo 文件信息
-     */
-    handleDeleteFileBtnClick(fileInfo) {
-      this.rightMenu.isShow = false
-      if (this.fileType === 6) {
-        //  回收站里 - 彻底删除
-        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmDeleteFile(fileInfo, true)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      } else {
-        //  非回收站
-        this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmDeleteFile(fileInfo, false)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      }
-    },
-    /**
-     * 删除文件确认对话框 | 确定按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
-     * @param {object} fileInfo 文件信息
-     * @param {boolean} type 文件类型,true 在回收站中彻底删除 false 删除到回收站
-     */
-    confirmDeleteFile(fileInfo, type) {
-      if (type) {
-        //  回收站中删除
-        deleteRecoveryFile({
-          recoveryFileId: fileInfo.recoveryFileId
-        }).then((res) => {
-          if (res.success) {
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-            this.$message.success('删除成功')
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      } else {
-        //  非回收站删除
-        deleteFile(fileInfo).then((res) => {
-          if (res.success) {
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-            this.$message.success('删除成功')
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      }
-    },
-    /**
-     * 还原按钮点击事件
-     * @description 调用接口,在回收站中还原文件
-     * @param {object} fileInfo 文件信息
-     */
-    handleRestoreFileBtnClick(fileInfo) {
-      restoreRecoveryFile({
-        deleteBatchNum: fileInfo.deleteBatchNum,
-        filePath: fileInfo.filePath
-      }).then((res) => {
-        if (res.success) {
-          this.$emit('getTableDataByType')
-          this.$store.dispatch('showStorage')
-          this.$message.success('已还原')
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 文件重命名按钮点击事件
-     * @description 打开确认对话框让用户输入新的文件名
-     * @param {object} fileInfo 文件信息
-     */
-    handleRenameFileBtnClick(fileInfo) {
-      this.rightMenu.isShow = false
-      var fileName = fileInfo.fileName
-      this.$prompt('请输入文件名', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        inputValue: fileName,
-        inputPattern: /\S/, //  文件名不能为空
-        inputErrorMessage: '请输入文件名',
-        closeOnClickModal: false
-      })
-        .then(({ value }) => {
-          fileInfo.oldFileName = fileInfo.fileName
-          fileInfo.fileName = value
-          this.confirmRenameFile(fileInfo)
-        })
-        .catch(() => {
-          this.$message({
-            type: 'info',
-            message: '取消输入'
-          })
-        })
-    },
-    /**
-     * 文件重命名对话框 | 确定按钮点击事件
-     * @description 调用文件重命名接口
-     * @param {object} fileInfo 文件信息
-     */
-    confirmRenameFile(fileInfo) {
-      renameFile(fileInfo).then((res) => {
-        if (res.success) {
-          this.$emit('getTableDataByType')
-          this.$store.dispatch('showStorage')
-          this.$message.success('重命名成功')
-        } else {
-          fileInfo.fileName = fileInfo.oldFileName
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 文件分享按钮点击事件
-     * @description 打开对话框让用户选择过期时间和提取码
-     * @param {object} fileInfo 文件信息
-     */
-    handleShareFileBtnClick(fileInfo) {
-      this.$emit('setSelectionFile', [fileInfo])
-      this.$emit('setShareFileDialogData')
-    }
-  }
+		/**
+		 * 文件名点击事件
+		 * @description 若当前点击的为文件夹,则进入文件夹内部;若是文件,则进行相应的预览。
+		 * @param {object} row 文件信息
+		 * @param {number} activeIndex 文件索引
+		 * @param {[]} fileList 文件列表
+		 */
+		handleFileNameClick(row, activeIndex, fileList) {
+			this.rightMenu.isShow = false
+			//  若是目录则进入目录
+			if (row.isDir) {
+				this.$router.push({
+					query: {
+						filePath: row.filePath + row.fileName + '/',
+						fileType: 0
+					}
+				})
+			} else {
+				//  若是文件,则进行相应的预览
+				//  若当前点击项是图片
+				const PIC = ['png', 'jpg', 'jpeg', 'gif', 'svg']
+				if (PIC.includes(row.extendName)) {
+					if (this.fileType === 1) {
+						//  图片分类下 - 大图查看
+						let data = {
+							imgPreviewVisible: true,
+							imgPreviewList: fileList.map((item) => {
+								return {
+									fileUrl: this.getViewFilePath(item),
+									downloadLink: this.getDownloadFilePath(item),
+									fileName: item.fileName,
+									extendName: item.extendName
+								}
+							}),
+							activeIndex: activeIndex
+						}
+						this.$store.commit('setImgPreviewData', data)
+					} else {
+						//  非图片分类下 - 大图查看
+						let data = {
+							imgPreviewVisible: true,
+							imgPreviewList: [
+								{
+									fileUrl: this.getViewFilePath(row),
+									downloadLink: this.getDownloadFilePath(row),
+									fileName: row.fileName,
+									extendName: row.extendName
+								}
+							],
+							activeIndex: 0
+						}
+						this.$store.commit('setImgPreviewData', data)
+					}
+				}
+				//  若当前点击项是可以使用office在线预览的
+				if ([...this.officeFileType, 'pdf'].includes(row.extendName)) {
+					this.getFileOnlineViewPathByOffice(row)
+				}
+				//  若当前点击项是代码或文本文件
+				const CODE = ['html', 'js', 'css', 'json', 'c', 'java', 'txt']
+				if (CODE.includes(row.extendName)) {
+					window.open(this.getViewFilePath(row), '_blank')
+				}
+				//  若当前点击项是视频mp4格式
+				const VIDEO = ['mp4']
+				if (VIDEO.includes(row.extendName)) {
+					if (this.fileType === 3) {
+						// 视频分类下 加载播放列表
+						let data = {
+							videoPreviewVisible: true,
+							videoPreviewList: fileList.map((item) => {
+								return {
+									...item,
+									fileUrl: this.getViewFilePath(item),
+									downloadLink: this.getDownloadFilePath(item),
+									fileName: item.fileName,
+									extendName: item.extendName
+								}
+							}),
+							activeIndex: activeIndex
+						}
+						this.$store.commit('setVideoPreviewData', data)
+					} else {
+						// 非视频分类下 - 单个视频预览
+						let data = {
+							videoPreviewVisible: true,
+							videoPreviewList: [
+								{
+									...row,
+									fileUrl: this.getViewFilePath(row),
+									downloadLink: this.getDownloadFilePath(row),
+									fileName: row.fileName,
+									extendName: row.extendName
+								}
+							],
+							activeIndex: 0
+						}
+						this.$store.commit('setVideoPreviewData', data)
+					}
+				}
+				//  若当前点击项是音频mp3格式
+				const AUDIO = ['mp3']
+				if (AUDIO.includes(row.extendName)) {
+					if (this.audioObj.src !== this.getViewFilePath(row)) {
+						this.$notify.closeAll()
+						this.audioObj.src = this.getViewFilePath(row)
+						this.$notify({
+							title: `${row.fileName}.${row.extendName}`,
+							dangerouslyUseHTMLString: true,
+							message: `<audio class="audio-preview" src="${this.audioObj.src}" controls autoplay style="padding-right: 16px; margin-top: 16px;"></audio>`,
+							duration: 0, //  不自动关闭
+							offset: 100,
+							onClose: () => {
+								this.audioObj.src = ''
+							}
+						})
+					}
+				}
+			}
+		},
+		/**
+		 * 移动按钮点击事件
+		 * @description 向父组件传递当前操作的文件信息,并打开“移动文件对话框”
+		 * @param {object} file 文件信息
+		 */
+		handleMoveFileBtnClick(file) {
+			this.rightMenu.isShow = false
+			this.$emit('setOperationFile', file)
+			//  第一个参数: 是否批量移动;第二个参数:打开/关闭移动文件模态框
+			this.$emit('setMoveFileDialogData', false, true)
+		},
+		/**
+		 * 解压缩按钮点击事件
+		 * @description 调用解压缩文件接口,并展示新的文件列表
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleUnzipFileBtnClick(fileInfo) {
+			this.rightMenu.isShow = false
+			const loading = this.$loading({
+				lock: true,
+				text: '正在解压缩,请稍等片刻...',
+				spinner: 'el-icon-loading',
+				background: 'rgba(0, 0, 0, 0.7)'
+			})
+			unzipFile(fileInfo).then((res) => {
+				if (res.success) {
+					this.$emit('getTableDataByType')
+					this.$store.dispatch('showStorage')
+					this.$message.success('解压成功')
+					loading.close()
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 删除按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,打开确认对话框
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleDeleteFileBtnClick(fileInfo) {
+			this.rightMenu.isShow = false
+			if (this.fileType === 6) {
+				//  回收站里 - 彻底删除
+				this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmDeleteFile(fileInfo, true)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			} else {
+				//  非回收站
+				this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmDeleteFile(fileInfo, false)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			}
+		},
+		/**
+		 * 删除文件确认对话框 | 确定按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
+		 * @param {object} fileInfo 文件信息
+		 * @param {boolean} type 文件类型,true 在回收站中彻底删除 false 删除到回收站
+		 */
+		confirmDeleteFile(fileInfo, type) {
+			if (type) {
+				//  回收站中删除
+				deleteRecoveryFile({
+					recoveryFileId: fileInfo.recoveryFileId
+				}).then((res) => {
+					if (res.success) {
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+						this.$message.success('删除成功')
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			} else {
+				//  非回收站删除
+				deleteFile(fileInfo).then((res) => {
+					if (res.success) {
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+						this.$message.success('删除成功')
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			}
+		},
+		/**
+		 * 还原按钮点击事件
+		 * @description 调用接口,在回收站中还原文件
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleRestoreFileBtnClick(fileInfo) {
+			restoreRecoveryFile({
+				deleteBatchNum: fileInfo.deleteBatchNum,
+				filePath: fileInfo.filePath
+			}).then((res) => {
+				if (res.success) {
+					this.$emit('getTableDataByType')
+					this.$store.dispatch('showStorage')
+					this.$message.success('已还原')
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 文件重命名按钮点击事件
+		 * @description 打开确认对话框让用户输入新的文件名
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleRenameFileBtnClick(fileInfo) {
+			this.rightMenu.isShow = false
+			var fileName = fileInfo.fileName
+			this.$prompt('请输入文件名', '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputValue: fileName,
+				inputPattern: /\S/, //  文件名不能为空
+				inputErrorMessage: '请输入文件名',
+				closeOnClickModal: false
+			})
+				.then(({ value }) => {
+					fileInfo.oldFileName = fileInfo.fileName
+					fileInfo.fileName = value
+					this.confirmRenameFile(fileInfo)
+				})
+				.catch(() => {
+					this.$message({
+						type: 'info',
+						message: '取消输入'
+					})
+				})
+		},
+		/**
+		 * 文件重命名对话框 | 确定按钮点击事件
+		 * @description 调用文件重命名接口
+		 * @param {object} fileInfo 文件信息
+		 */
+		confirmRenameFile(fileInfo) {
+			renameFile(fileInfo).then((res) => {
+				if (res.success) {
+					this.$emit('getTableDataByType')
+					this.$store.dispatch('showStorage')
+					this.$message.success('重命名成功')
+				} else {
+					fileInfo.fileName = fileInfo.oldFileName
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 文件分享按钮点击事件
+		 * @description 打开对话框让用户选择过期时间和提取码
+		 * @param {object} fileInfo 文件信息
+		 */
+		handleShareFileBtnClick(fileInfo) {
+			this.$emit('setSelectionFile', [fileInfo])
+			this.$emit('setShareFileDialogData')
+		}
+	}
 }
 </script>
 

+ 103 - 90
src/views/file/components/FileList/components/FileTimeLine.vue

@@ -1,98 +1,111 @@
 <template>
-  <!-- 时间线模式 -->
-  <div class="image-timeline-wrapper">
-    <div class="radio">
-      排序:
-      <el-radio-group v-model="reverse">
-        <el-radio :label="true">倒序</el-radio>
-        <el-radio :label="false">正序</el-radio>
-      </el-radio-group>
-    </div>
-    <el-timeline class="image-timeline-list" :reverse="reverse" v-if="imageTimelineData.length">
-      <el-timeline-item
-        class="image-timeline-item"
-        v-for="(item, index) in imageTimelineData"
-        :key="index"
-        :timestamp="item.uploadDate"
-        color="#409EFF"
-        placement="top"
-      >
-        <ul class="image-list">
-          <li class="image-item" v-for="(image, imageIndex) in item.imageList" :key="`${index}-${imageIndex}`" :style="`width: ${gridSize + 40}px; `">
-            <img
-              class="image"
-              :src="getImgMinPath(image)"
-              :alt="item | fileNameComplete"
-              :style="`width: ${gridSize}px; height: ${gridSize}px;`"
-              @click="handleImgClick(item.imageList, imageIndex)"
-            />
-            <div class="image-name">{{ image | fileNameComplete }}</div>
-          </li>
-        </ul>
-      </el-timeline-item>
-    </el-timeline>
-  </div>
+	<!-- 时间线模式 -->
+	<div class="image-timeline-wrapper">
+		<div class="radio">
+			排序:
+			<el-radio-group v-model="reverse">
+				<el-radio :label="true">倒序</el-radio>
+				<el-radio :label="false">正序</el-radio>
+			</el-radio-group>
+		</div>
+		<el-timeline
+			class="image-timeline-list"
+			:reverse="reverse"
+			v-if="imageTimelineData.length"
+		>
+			<el-timeline-item
+				class="image-timeline-item"
+				v-for="(item, index) in imageTimelineData"
+				:key="index"
+				:timestamp="item.uploadDate"
+				color="#409EFF"
+				placement="top"
+			>
+				<ul class="image-list">
+					<li
+						class="image-item"
+						v-for="(image, imageIndex) in item.imageList"
+						:key="`${index}-${imageIndex}`"
+						:style="`width: ${gridSize + 40}px; `"
+					>
+						<img
+							class="image"
+							:src="getImgMinPath(image)"
+							:alt="item | fileNameComplete"
+							:style="`width: ${gridSize}px; height: ${gridSize}px;`"
+							@click="handleImgClick(item.imageList, imageIndex)"
+						/>
+						<div class="image-name">{{ image | fileNameComplete }}</div>
+					</li>
+				</ul>
+			</el-timeline-item>
+		</el-timeline>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'FileTimeLine',
-  props: {
-    // 文件列表
-    fileList: {
-      required: true,
-      type: Array
-    }
-  },
-  data() {
-    return {
-      reverse: true
-    }
-  },
-  computed: {
-    //  按年-月-日分组排序
-    imageTimelineData() {
-      let res = []
-      //  去重,获取返回的所有日期年-月-日
-      let uploadTimeSet = new Set(this.fileList.map((item) => item.uploadTime.split(' ')[0]))
-      let uploadDate = [...uploadTimeSet]
-      //  分组
-      uploadDate.forEach((element) => {
-        res.push({
-          uploadDate: element,
-          imageList: this.fileList.filter((item) => item.uploadTime.split(' ')[0] === element) //  过滤
-        })
-      })
-      return res
-    },
-    // 图标大小
-    gridSize() {
-      return this.$store.getters.gridSize
-    }
-  },
-  methods: {
-    /**
-     * 图片点击事件
-     * @description 打开图片预览,查看大图
-     * @param {[]} imgList 图片列表
-     * @param {number} imageIndex 图片索引
-     */
-    handleImgClick(imgList, imageIndex) {
-      let data = {
-        imgPreviewVisible: true,
-        imgPreviewList: imgList.map((item) => {
-          return {
-            fileUrl: this.getViewFilePath(item),
-            downloadLink: this.getDownloadFilePath(item),
-            fileName: item.fileName,
-            extendName: item.extendName
-          }
-        }),
-        activeIndex: imageIndex
-      }
-      this.$store.commit('setImgPreviewData', data)
-    }
-  }
+	name: 'FileTimeLine',
+	props: {
+		// 文件列表
+		fileList: {
+			required: true,
+			type: Array
+		}
+	},
+	data() {
+		return {
+			reverse: true
+		}
+	},
+	computed: {
+		//  按年-月-日分组排序
+		imageTimelineData() {
+			let res = []
+			//  去重,获取返回的所有日期年-月-日
+			let uploadTimeSet = new Set(
+				this.fileList.map((item) => item.uploadTime.split(' ')[0])
+			)
+			let uploadDate = [...uploadTimeSet]
+			//  分组
+			uploadDate.forEach((element) => {
+				res.push({
+					uploadDate: element,
+					imageList: this.fileList.filter(
+						(item) => item.uploadTime.split(' ')[0] === element
+					) //  过滤
+				})
+			})
+			return res
+		},
+		// 图标大小
+		gridSize() {
+			return this.$store.getters.gridSize
+		}
+	},
+	methods: {
+		/**
+		 * 图片点击事件
+		 * @description 打开图片预览,查看大图
+		 * @param {[]} imgList 图片列表
+		 * @param {number} imageIndex 图片索引
+		 */
+		handleImgClick(imgList, imageIndex) {
+			let data = {
+				imgPreviewVisible: true,
+				imgPreviewList: imgList.map((item) => {
+					return {
+						fileUrl: this.getViewFilePath(item),
+						downloadLink: this.getDownloadFilePath(item),
+						fileName: item.fileName,
+						extendName: item.extendName
+					}
+				}),
+				activeIndex: imageIndex
+			}
+			this.$store.commit('setImgPreviewData', data)
+		}
+	}
 }
 </script>
 

+ 452 - 386
src/views/file/components/FileList/components/OperationMenu.vue

@@ -1,150 +1,213 @@
 <template>
-  <div class="operation-menu-wrapper" :class="'file-type-' + fileType">
-    <el-button-group class="operate-group">
-      <el-dropdown class="drop-btn" trigger="hover">
-        <el-button size="mini" type="primary" icon="el-icon-upload2" id="uploadFileId" :disabled="selectionFile.length && batchOperate || fileType !== 0"
-          >上传<i class="el-icon-arrow-down el-icon--right"></i
-        ></el-button>
-        <el-dropdown-menu slot="dropdown" :disabled="selectionFile.length && batchOperate || fileType !== 0">
-          <el-dropdown-item @click.native="handleUploadFileBtnClick(0)">上传文件</el-dropdown-item>
-          <el-dropdown-item @click.native="handleUploadFileBtnClick(1)">上传文件夹</el-dropdown-item>
-          <el-dropdown-item @click.native="handleUploadFileBtnClick(2)" title="截图粘贴或拖拽上传">拖拽上传</el-dropdown-item>
-        </el-dropdown-menu>
-      </el-dropdown>
-      <el-button
-        size="mini"
-        type="primary"
-        icon="el-icon-plus"
-        @click="dialogAddFolder.visible = true"
-        :disabled="selectionFile.length && batchOperate || fileType !== 0"
-        >新建文件夹</el-button
-      >
-      <el-dropdown class="drop-btn" trigger="hover">
-        <el-button size="mini" type="primary" icon="el-icon-edit-outline" id="uploadFileId" :disabled="selectionFile.length && batchOperate || fileType !== 0"
-          >新建在线文档<i class="el-icon-arrow-down el-icon--right"></i
-        ></el-button>
-        <el-dropdown-menu slot="dropdown" :disabled="selectionFile.length && batchOperate || fileType !== 0">
-          <el-dropdown-item @click.native="handleCreateFile('docx')">
-            <img
-            src="_a/images/file/file_word.png"
-            style="width: 30px; max-height: 30px; cursor: pointer"/>Word文档</el-dropdown-item>
-          <el-dropdown-item @click.native="handleCreateFile('xlsx')"><img
-            src="_a/images/file/file_excel.png"
-            style="width: 30px; max-height: 30px; cursor: pointer"/>Excel工作表</el-dropdown-item>
-          <el-dropdown-item @click.native="handleCreateFile('pptx')"><img
-            src="_a/images/file/file_ppt.png"
-            style="width: 30px; max-height: 30px; cursor: pointer"/>PPT演示文稿</el-dropdown-item>
-        </el-dropdown-menu>
-      </el-dropdown>
-      
-      <el-button
-        size="mini"
-        type="primary"
-        v-if="selectionFile.length && batchOperate"
-        icon="el-icon-delete"
-        @click="handleBatchDeleteBtnClick()"
-        >批量删除</el-button
-      >
-      <el-button
-        size="mini"
-        type="primary"
-        v-if="selectionFile.length && !fileType && fileType !== 6 && batchOperate"
-        icon="el-icon-rank"
-        @click="handleBatchMoveBtnClick()"
-        >批量移动</el-button
-      >
-      <el-button
-        size="mini"
-        type="primary"
-        v-if="selectionFile.length && fileType !== 6 && batchOperate"
-        icon="el-icon-download"
-        @click="handleBatchDownloadBtnClick()"
-        >批量下载</el-button
-      >
-      <el-button
-        size="mini"
-        type="primary"
-        v-if="selectionFile.length && fileType !== 6 && $route.name !== 'Share' && batchOperate"
-        icon="el-icon-share"
-        @click="handleBatchShareBtnClick()"
-        >批量分享</el-button
-      >
-    </el-button-group>
+	<div class="operation-menu-wrapper" :class="'file-type-' + fileType">
+		<el-button-group class="operate-group">
+			<el-dropdown class="drop-btn" trigger="hover">
+				<el-button
+					size="mini"
+					type="primary"
+					icon="el-icon-upload2"
+					id="uploadFileId"
+					:disabled="(selectionFile.length && batchOperate) || fileType !== 0"
+					>上传<i class="el-icon-arrow-down el-icon--right"></i
+				></el-button>
+				<el-dropdown-menu
+					slot="dropdown"
+					:disabled="(selectionFile.length && batchOperate) || fileType !== 0"
+				>
+					<el-dropdown-item @click.native="handleUploadFileBtnClick(0)"
+						>上传文件</el-dropdown-item
+					>
+					<el-dropdown-item @click.native="handleUploadFileBtnClick(1)"
+						>上传文件夹</el-dropdown-item
+					>
+					<el-dropdown-item
+						@click.native="handleUploadFileBtnClick(2)"
+						title="截图粘贴或拖拽上传"
+						>拖拽上传</el-dropdown-item
+					>
+				</el-dropdown-menu>
+			</el-dropdown>
+			<el-button
+				size="mini"
+				type="primary"
+				icon="el-icon-plus"
+				@click="dialogAddFolder.visible = true"
+				:disabled="(selectionFile.length && batchOperate) || fileType !== 0"
+				>新建文件夹</el-button
+			>
+			<el-dropdown class="drop-btn" trigger="hover">
+				<el-button
+					size="mini"
+					type="primary"
+					icon="el-icon-edit-outline"
+					id="uploadFileId"
+					:disabled="(selectionFile.length && batchOperate) || fileType !== 0"
+					>新建在线文档<i class="el-icon-arrow-down el-icon--right"></i
+				></el-button>
+				<el-dropdown-menu
+					slot="dropdown"
+					:disabled="(selectionFile.length && batchOperate) || fileType !== 0"
+				>
+					<el-dropdown-item @click.native="handleCreateFile('docx')">
+						<img
+							:src="wordImg"
+							style="width: 30px; max-height: 30px; cursor: pointer"
+						/>Word 文档</el-dropdown-item
+					>
+					<el-dropdown-item @click.native="handleCreateFile('xlsx')">
+						<img
+							:src="excelImg"
+							style="width: 30px; max-height: 30px; cursor: pointer"
+						/>Excel 工作表</el-dropdown-item
+					>
+					<el-dropdown-item @click.native="handleCreateFile('pptx')"
+						><img
+							:src="pptImg"
+							style="width: 30px; max-height: 30px; cursor: pointer"
+						/>PPT 演示文稿</el-dropdown-item
+					>
+				</el-dropdown-menu>
+			</el-dropdown>
 
-    <!-- 全局搜索文件 -->
-    <el-input
-      v-if="fileType === 0"
-      class="select-file-input"
-      v-model="searchFile.fileName"
-      placeholder="搜索您的文件"
-      size="mini"
-      maxlength="255"
-      :clearable="true"
-      @change="handleSearchInputChange"
-      @clear="$emit('getTableDataByType')"
-      @keyup.enter.native="handleSearchInputChange(searchFile.fileName)"
-    >
-      <i slot="prefix" class="el-input__icon el-icon-search" title="点击搜索" @click="handleSearchClick"></i>
-    </el-input>
+			<el-button
+				size="mini"
+				type="primary"
+				v-if="selectionFile.length && batchOperate"
+				icon="el-icon-delete"
+				@click="handleBatchDeleteBtnClick()"
+				>批量删除</el-button
+			>
+			<el-button
+				size="mini"
+				type="primary"
+				v-if="
+					selectionFile.length && !fileType && fileType !== 6 && batchOperate
+				"
+				icon="el-icon-rank"
+				@click="handleBatchMoveBtnClick()"
+				>批量移动</el-button
+			>
+			<el-button
+				size="mini"
+				type="primary"
+				v-if="selectionFile.length && fileType !== 6 && batchOperate"
+				icon="el-icon-download"
+				@click="handleBatchDownloadBtnClick()"
+				>批量下载</el-button
+			>
+			<el-button
+				size="mini"
+				type="primary"
+				v-if="
+					selectionFile.length &&
+					fileType !== 6 &&
+					$route.name !== 'Share' &&
+					batchOperate
+				"
+				icon="el-icon-share"
+				@click="handleBatchShareBtnClick()"
+				>批量分享</el-button
+			>
+		</el-button-group>
 
-    <!-- 批量操作 -->
-    <i
-      class="batch-icon el-icon-finished"
-      :class="batchOperate ? 'active' : ''"
-      :title="batchOperate ? '取消批量操作' : '批量操作'"
-      v-if="fileModel === 1"
-      @click="handleBatchOperationChange()"
-    ></i>
-    <el-divider direction="vertical" v-if="fileModel === 1"></el-divider>
+		<!-- 全局搜索文件 -->
+		<el-input
+			v-if="fileType === 0"
+			class="select-file-input"
+			v-model="searchFile.fileName"
+			placeholder="搜索您的文件"
+			size="mini"
+			maxlength="255"
+			:clearable="true"
+			@change="handleSearchInputChange"
+			@clear="$emit('getTableDataByType')"
+			@keyup.enter.native="handleSearchInputChange(searchFile.fileName)"
+		>
+			<i
+				slot="prefix"
+				class="el-input__icon el-icon-search"
+				title="点击搜索"
+				@click="handleSearchClick"
+			></i>
+		</el-input>
 
-    <!-- 操作栏收纳 -->
-    <el-popover placement="bottom" trigger="hover">
-      <i slot="reference" class="setting-icon el-icon-setting"></i>
-      <!-- 选择表格列 -->
-      <SelectColumn></SelectColumn>
-      <el-divider class="split-line"></el-divider>
-      <!-- 文件展示模式 -->
-      <div class="change-file-model">
-        <div class="title">查看模式</div>
-        <el-radio-group v-model="fileGroupLable" size="mini" @change="handleFileDisplayModelChange">
-          <el-radio-button :label="0"> <i class="el-icon-tickets"></i> 列表 </el-radio-button>
-          <el-radio-button :label="1"> <i class="el-icon-s-grid"></i> 网格 </el-radio-button>
-          <el-radio-button :label="2" v-if="fileType === 1"> <i class="el-icon-date"></i> 时间线 </el-radio-button>
-        </el-radio-group>
-      </div>
-      <!-- 图标大小调整 -->
-      <div class="change-grid-size" v-if="fileGroupLable === 1 || fileGroupLable === 2">
-        <div class="title">调整图标大小</div>
-        <el-slider v-model="gridSize" :min="40" :max="150" :step="10" :format-tooltip="formatTooltip"></el-slider>
-      </div>
-    </el-popover>
+		<!-- 批量操作 -->
+		<i
+			class="batch-icon el-icon-finished"
+			:class="batchOperate ? 'active' : ''"
+			:title="batchOperate ? '取消批量操作' : '批量操作'"
+			v-if="fileModel === 1"
+			@click="handleBatchOperationChange()"
+		></i>
+		<el-divider direction="vertical" v-if="fileModel === 1"></el-divider>
 
-    <!-- 新建文件夹对话框 -->
-    <AddFolderDialog
-      :visible.sync="dialogAddFolder.visible"
-      :filePath="filePath"
-      @confirmDialog="$emit('getTableDataByType')"
-    ></AddFolderDialog>
+		<!-- 操作栏收纳 -->
+		<el-popover placement="bottom" trigger="hover">
+			<i slot="reference" class="setting-icon el-icon-setting"></i>
+			<!-- 选择表格列 -->
+			<SelectColumn></SelectColumn>
+			<el-divider class="split-line"></el-divider>
+			<!-- 文件展示模式 -->
+			<div class="change-file-model">
+				<div class="title">查看模式</div>
+				<el-radio-group
+					v-model="fileGroupLable"
+					size="mini"
+					@change="handleFileDisplayModelChange"
+				>
+					<el-radio-button :label="0">
+						<i class="el-icon-tickets"></i> 列表
+					</el-radio-button>
+					<el-radio-button :label="1">
+						<i class="el-icon-s-grid"></i> 网格
+					</el-radio-button>
+					<el-radio-button :label="2" v-if="fileType === 1">
+						<i class="el-icon-date"></i> 时间线
+					</el-radio-button>
+				</el-radio-group>
+			</div>
+			<!-- 图标大小调整 -->
+			<div
+				class="change-grid-size"
+				v-if="fileGroupLable === 1 || fileGroupLable === 2"
+			>
+				<div class="title">调整图标大小</div>
+				<el-slider
+					v-model="gridSize"
+					:min="40"
+					:max="150"
+					:step="10"
+					:format-tooltip="formatTooltip"
+				></el-slider>
+			</div>
+		</el-popover>
 
-    <!-- 新建文件对话框 -->
-    <AddFileDialog
-      :visible.sync="dialogAddFile.visible"
-      :filePath="filePath"
-      :extendName="extendName"
-      @confirmDialog="$emit('getTableDataByType')"
-    ></AddFileDialog>
+		<!-- 新建文件夹对话框 -->
+		<AddFolderDialog
+			:visible.sync="dialogAddFolder.visible"
+			:filePath="filePath"
+			@confirmDialog="$emit('getTableDataByType')"
+		></AddFolderDialog>
 
-    <!-- 多选文件下载,页面隐藏 -->
-    <a
-      target="_blank"
-      v-for="(item, index) in selectionFile"
-      :key="index"
-      :href="getDownloadFilePath(item)"
-      :download="item.fileName + '.' + item.extendName"
-      :title="'downloadLink' + index"
-      :ref="'downloadLink' + index"
-    ></a>
-  </div>
+		<!-- 新建文件对话框 -->
+		<AddFileDialog
+			:visible.sync="dialogAddFile.visible"
+			:filePath="filePath"
+			:extendName="extendName"
+			@confirmDialog="$emit('getTableDataByType')"
+		></AddFileDialog>
+
+		<!-- 多选文件下载,页面隐藏 -->
+		<a
+			target="_blank"
+			v-for="(item, index) in selectionFile"
+			:key="index"
+			:href="getDownloadFilePath(item)"
+			:download="item.fileName + '.' + item.extendName"
+			:title="'downloadLink' + index"
+			:ref="'downloadLink' + index"
+		></a>
+	</div>
 </template>
 
 <script>
@@ -154,253 +217,256 @@ import AddFileDialog from '_c/File/AddFileDialog.vue'
 import SelectColumn from './SelectColumn'
 
 export default {
-  name: 'OperationMenu',
-  props: {
-    // 文件类型
-    fileType: {
-      required: true,
-      type: Number
-    },
-    // 文件路径
-    filePath: {
-      required: true,
-      type: String
-    },
-    selectionFile: Array,
-    operationFile: Object,
-    batchOperate: Boolean
-  },
-  components: {
-    AddFolderDialog,
-    AddFileDialog,
-    SelectColumn
-  },
-  data() {
-    return {
-      // 文件搜索数据
-      searchFile: {
-        fileName: ''
-      },
-      // 新建文件夹对话框数据
-      dialogAddFolder: {
-        visible: false
-      },
-      // 新建文件夹对话框数据
-      dialogAddFile: {
-        visible: false
-      },
-      extendName: '',
-      batchDeleteFileDialog: false,
-      fileGroupLable: 0 //  文件展示模式
-    }
-  },
-  computed: {
-    //  上传文件组件参数
-    uploadFileData: {
-      get() {
-        let res = {
-          filePath: this.filePath,
-          isDir: 0
-        }
-        return res
-      },
-      set() {
-        return {
-          filePath: '/',
-          isDir: 0
-        }
-      }
-    },
-    // 文件查看模式 0 列表模式 1 网格模式 2 时间线模式
-    fileModel() {
-      return this.$store.getters.fileModel
-    },
-    // 图标大小
-    gridSize: {
-      get() {
-        return this.$store.getters.gridSize
-      },
-      set(val) {
-        this.$store.commit('changeGridSize', val)
-      }
-    }
-  },
-  watch: {
-    fileType(newValue, oldValue) {
-      if (oldValue === 1 && this.fileModel === 2) {
-        this.$store.commit('changeFileModel', 0)
-        this.fileGroupLable = 0
-      }
-    }
-  },
-  mounted() {
-    this.fileGroupLable = this.fileModel
-    this.$EventBus.$on('refreshList', () => {
-      this.$emit('getTableDataByType')
-    })
-    this.$EventBus.$on('refreshStorage', () => {
-      this.$store.dispatch('showStorage')
-    })
-  },
-  methods: {
-    /**
-     * 新建文档
-     */
-    handleCreateFile(extendName) {
-      this.extendName = extendName
-      this.dialogAddFile.visible = true
-    },
-    /**
-     * 上传文件按钮点击事件
-     * @description 通过Bus通信,开启全局上传文件流程
-     * @param {boolean} type 上传方式 true 直接上传  false 拖拽上传
-     */
-    handleUploadFileBtnClick(type) {
-      this.$EventBus.$emit('openUploader', this.uploadFileData, type)
-    },
+	name: 'OperationMenu',
+	props: {
+		// 文件类型
+		fileType: {
+			required: true,
+			type: Number
+		},
+		// 文件路径
+		filePath: {
+			required: true,
+			type: String
+		},
+		selectionFile: Array,
+		operationFile: Object,
+		batchOperate: Boolean
+	},
+	components: {
+		AddFolderDialog,
+		AddFileDialog,
+		SelectColumn
+	},
+	data() {
+		return {
+			// 文件搜索数据
+			searchFile: {
+				fileName: ''
+			},
+			// 新建文件夹对话框数据
+			dialogAddFolder: {
+				visible: false
+			},
+			// 新建文件夹对话框数据
+			dialogAddFile: {
+				visible: false
+			},
+			extendName: '',
+			batchDeleteFileDialog: false,
+			fileGroupLable: 0, //  文件展示模式
+			wordImg: require('_a/images/file/file_word.png'),
+			excelImg: require('_a/images/file/file_excel.png'),
+			pptImg: require('_a/images/file/file_ppt.png')
+		}
+	},
+	computed: {
+		//  上传文件组件参数
+		uploadFileData: {
+			get() {
+				let res = {
+					filePath: this.filePath,
+					isDir: 0
+				}
+				return res
+			},
+			set() {
+				return {
+					filePath: '/',
+					isDir: 0
+				}
+			}
+		},
+		// 文件查看模式 0 列表模式 1 网格模式 2 时间线模式
+		fileModel() {
+			return this.$store.getters.fileModel
+		},
+		// 图标大小
+		gridSize: {
+			get() {
+				return this.$store.getters.gridSize
+			},
+			set(val) {
+				this.$store.commit('changeGridSize', val)
+			}
+		}
+	},
+	watch: {
+		fileType(newValue, oldValue) {
+			if (oldValue === 1 && this.fileModel === 2) {
+				this.$store.commit('changeFileModel', 0)
+				this.fileGroupLable = 0
+			}
+		}
+	},
+	mounted() {
+		this.fileGroupLable = this.fileModel
+		this.$EventBus.$on('refreshList', () => {
+			this.$emit('getTableDataByType')
+		})
+		this.$EventBus.$on('refreshStorage', () => {
+			this.$store.dispatch('showStorage')
+		})
+	},
+	methods: {
+		/**
+		 * 新建文档
+		 */
+		handleCreateFile(extendName) {
+			this.extendName = extendName
+			this.dialogAddFile.visible = true
+		},
+		/**
+		 * 上传文件按钮点击事件
+		 * @description 通过Bus通信,开启全局上传文件流程
+		 * @param {boolean} type 上传方式 true 直接上传  false 拖拽上传
+		 */
+		handleUploadFileBtnClick(type) {
+			this.$EventBus.$emit('openUploader', this.uploadFileData, type)
+		},
 
-    /**
-     * 批量删除按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
-     */
-    handleBatchDeleteBtnClick() {
-      if (this.fileType === 6) {
-        //  回收站里 - 彻底删除
-        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmBatchDeleteFile(true)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      } else {
-        //  非回收站
-        this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        })
-          .then(() => {
-            this.confirmBatchDeleteFile(false)
-          })
-          .catch(() => {
-            this.$message({
-              type: 'info',
-              message: '已取消删除'
-            })
-          })
-      }
-    },
-    /**
-     * 批量删除文件对话框 | 确定按钮点击事件
-     * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
-     * @param {boolean} type 文件类型,true 在回收站中彻底删除 false 删除到回收站
-     */
-    confirmBatchDeleteFile(type) {
-      if (type) {
-        //  回收站中删除
-        batchDeleteRecoveryFile({
-          recoveryFileIds: JSON.stringify(this.selectionFile)
-        }).then((res) => {
-          if (res.success) {
-            this.$message({
-              message: "删除成功",
-              type: 'success'
-            })
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-          } else {
-            this.$message.error('失败' + res.message)
-          }
-        })
-      } else {
-        //  非回收站删除
-        batchDeleteFile({
-          files: JSON.stringify(this.selectionFile)
-        }).then((res) => {
-          if (res.success) {
-            this.$message({
-              message: "删除成功",
-              type: 'success'
-            })
-            this.$emit('getTableDataByType')
-            this.$store.dispatch('showStorage')
-          } else {
-            this.$message.error('失败' + res.message)
-          }
-        })
-      }
-    },
-    /**
-     * 批量移动按钮点击事件
-     */
-    handleBatchMoveBtnClick() {
-      /**
-       * 第一个参数 是否批量移动
-       * 第二个参数 打开/关闭移动文件对话框
-       */
-      this.$emit('setMoveFileDialogData', true, true)
-    },
-    /**
-     * 分享按钮点击事件
-     */
-    handleBatchShareBtnClick() {
-      this.$emit('setShareFileDialogData')
-    },
-    /**
-     * 批量下载按钮点击事件
-     */
-    handleBatchDownloadBtnClick() {
-      for (let i = 0; i < this.selectionFile.length; i++) {
-        let name = 'downloadLink' + i
-        this.$refs[name][0].click()
-      }
-    },
-    /**
-     * 搜索输入框搜索事件
-     * @param {string} value 搜索内容
-     */
-    handleSearchInputChange(value) {
-      if (value === '') {
-        this.$emit('getTableDataByType')
-      } else {
-        this.$emit('getSearchFileList', value)
-      }
-    },
-    /**
-     * 搜索框图标点击事件
-     */
-    handleSearchClick() {
-      this.$emit('getSearchFileList', this.searchFile.fileName)
-    },
-    /**
-     * 网格模式下,批量操作状态切换
-     */
-    handleBatchOperationChange() {
-      this.$emit('update:batchOperate', !this.batchOperate)
-    },
-    /**
-     * 文件查看模式切换
-     * @param {number} label 0 列表 1 网格 2 时间线
-     */
-    handleFileDisplayModelChange(label) {
-      this.$store.commit('changeFileModel', label)
-    },
-    /**
-     * 格式化图标大小显示
-     * @param {number} val 改变后的数值
-     */
-    formatTooltip(val) {
-      return `${val}px`
-    }
-  }
+		/**
+		 * 批量删除按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
+		 */
+		handleBatchDeleteBtnClick() {
+			if (this.fileType === 6) {
+				//  回收站里 - 彻底删除
+				this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmBatchDeleteFile(true)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			} else {
+				//  非回收站
+				this.$confirm('删除后可在回收站查看, 是否继续删除?', '提示', {
+					confirmButtonText: '确定',
+					cancelButtonText: '取消',
+					type: 'warning'
+				})
+					.then(() => {
+						this.confirmBatchDeleteFile(false)
+					})
+					.catch(() => {
+						this.$message({
+							type: 'info',
+							message: '已取消删除'
+						})
+					})
+			}
+		},
+		/**
+		 * 批量删除文件对话框 | 确定按钮点击事件
+		 * @description 区分 删除到回收站中 | 在回收站中彻底删除,调用相应的删除文件接口
+		 * @param {boolean} type 文件类型,true 在回收站中彻底删除 false 删除到回收站
+		 */
+		confirmBatchDeleteFile(type) {
+			if (type) {
+				//  回收站中删除
+				batchDeleteRecoveryFile({
+					recoveryFileIds: JSON.stringify(this.selectionFile)
+				}).then((res) => {
+					if (res.success) {
+						this.$message({
+							message: '删除成功',
+							type: 'success'
+						})
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+					} else {
+						this.$message.error('失败' + res.message)
+					}
+				})
+			} else {
+				//  非回收站删除
+				batchDeleteFile({
+					files: JSON.stringify(this.selectionFile)
+				}).then((res) => {
+					if (res.success) {
+						this.$message({
+							message: '删除成功',
+							type: 'success'
+						})
+						this.$emit('getTableDataByType')
+						this.$store.dispatch('showStorage')
+					} else {
+						this.$message.error('失败' + res.message)
+					}
+				})
+			}
+		},
+		/**
+		 * 批量移动按钮点击事件
+		 */
+		handleBatchMoveBtnClick() {
+			/**
+			 * 第一个参数 是否批量移动
+			 * 第二个参数 打开/关闭移动文件对话框
+			 */
+			this.$emit('setMoveFileDialogData', true, true)
+		},
+		/**
+		 * 分享按钮点击事件
+		 */
+		handleBatchShareBtnClick() {
+			this.$emit('setShareFileDialogData')
+		},
+		/**
+		 * 批量下载按钮点击事件
+		 */
+		handleBatchDownloadBtnClick() {
+			for (let i = 0; i < this.selectionFile.length; i++) {
+				let name = 'downloadLink' + i
+				this.$refs[name][0].click()
+			}
+		},
+		/**
+		 * 搜索输入框搜索事件
+		 * @param {string} value 搜索内容
+		 */
+		handleSearchInputChange(value) {
+			if (value === '') {
+				this.$emit('getTableDataByType')
+			} else {
+				this.$emit('getSearchFileList', value)
+			}
+		},
+		/**
+		 * 搜索框图标点击事件
+		 */
+		handleSearchClick() {
+			this.$emit('getSearchFileList', this.searchFile.fileName)
+		},
+		/**
+		 * 网格模式下,批量操作状态切换
+		 */
+		handleBatchOperationChange() {
+			this.$emit('update:batchOperate', !this.batchOperate)
+		},
+		/**
+		 * 文件查看模式切换
+		 * @param {number} label 0 列表 1 网格 2 时间线
+		 */
+		handleFileDisplayModelChange(label) {
+			this.$store.commit('changeFileModel', label)
+		},
+		/**
+		 * 格式化图标大小显示
+		 * @param {number} val 改变后的数值
+		 */
+		formatTooltip(val) {
+			return `${val}px`
+		}
+	}
 }
 </script>
 

+ 74 - 64
src/views/file/components/FileList/components/SelectColumn.vue

@@ -1,70 +1,80 @@
 <template>
-  <div class="select-column">
-    <div class="text" @click="handleSetShowColumnBtnClick">
-      <i class="el-icon-s-operation"></i>
-      设置显示字段
-    </div>
-    <!-- 对话框 当点击"设置显示列"按钮时弹出对话框 -->
-    <el-dialog title="设置表格列显隐" width="700px" :append-to-body="true" :visible.sync="dialogVisible">
-      <!-- 多选框组件 勾选需要在表格中显示的列 -->
-      <el-checkbox-group v-model="selectedColumn">
-        <el-checkbox v-for="item in columnOptions" :key="item.value" :label="item.value">{{ item.label }}</el-checkbox>
-      </el-checkbox-group>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="dialogVisible = false">取 消</el-button>
-        <el-button type="primary" @click="dialogOk()">确 定</el-button>
-      </span>
-    </el-dialog>
-  </div>
+	<div class="select-column">
+		<div class="text" @click="handleSetShowColumnBtnClick">
+			<i class="el-icon-s-operation"></i>
+			设置显示字段
+		</div>
+		<!-- 对话框 当点击"设置显示列"按钮时弹出对话框 -->
+		<el-dialog
+			title="设置表格列显隐"
+			width="700px"
+			:append-to-body="true"
+			:visible.sync="dialogVisible"
+		>
+			<!-- 多选框组件 勾选需要在表格中显示的列 -->
+			<el-checkbox-group v-model="selectedColumn">
+				<el-checkbox
+					v-for="item in columnOptions"
+					:key="item.value"
+					:label="item.value"
+					>{{ item.label }}</el-checkbox
+				>
+			</el-checkbox-group>
+			<span slot="footer" class="dialog-footer">
+				<el-button @click="dialogVisible = false">取 消</el-button>
+				<el-button type="primary" @click="dialogOk()">确 定</el-button>
+			</span>
+		</el-dialog>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'SelectColumn',
-  data() {
-    return {
-      dialogVisible: false,
-      selectedColumn: [], //  被选中的表格需要显示的列
-      columnOptions: [
-        {
-          value: 'extendName',
-          label: '类型'
-        },
-        {
-          value: 'fileSize',
-          label: '大小'
-        },
-        {
-          value: 'uploadTime',
-          label: '修改日期'
-        },
-        {
-          value: 'deleteTime',
-          label: '删除日期'
-        }
-      ]
-    }
-  },
-  methods: {
-    /**
-     * 设置显示列按钮点击事件
-     * @description 获取 Vuex 中存储的表格显示列
-     *              并打开对话框
-     */
-    handleSetShowColumnBtnClick() {
-      this.selectedColumn = this.$store.getters.selectedColumnList
-      this.dialogVisible = true
-    },
-    /**
-     * 对话框 确定按钮点击事件
-     * @description 通过提交 mutation 更新表格显示列 
-     *              并关闭对话框
-     */
-    dialogOk() {
-      this.$store.commit('changeSelectedColumnList', this.selectedColumn)
-      this.dialogVisible = false
-    }
-  }
+	name: 'SelectColumn',
+	data() {
+		return {
+			dialogVisible: false,
+			selectedColumn: [], //  被选中的表格需要显示的列
+			columnOptions: [
+				{
+					value: 'extendName',
+					label: '类型'
+				},
+				{
+					value: 'fileSize',
+					label: '大小'
+				},
+				{
+					value: 'uploadTime',
+					label: '修改日期'
+				},
+				{
+					value: 'deleteTime',
+					label: '删除日期'
+				}
+			]
+		}
+	},
+	methods: {
+		/**
+		 * 设置显示列按钮点击事件
+		 * @description 获取 Vuex 中存储的表格显示列
+		 *              并打开对话框
+		 */
+		handleSetShowColumnBtnClick() {
+			this.selectedColumn = this.$store.getters.selectedColumnList
+			this.dialogVisible = true
+		},
+		/**
+		 * 对话框 确定按钮点击事件
+		 * @description 通过提交 mutation 更新表格显示列
+		 *              并关闭对话框
+		 */
+		dialogOk() {
+			this.$store.commit('changeSelectedColumnList', this.selectedColumn)
+			this.dialogVisible = false
+		}
+	}
 }
 </script>
 
@@ -78,6 +88,6 @@ export default {
     &:hover {
       color $Primary
     }
-  }  
+  }
 }
-</style>
+</style>

+ 177 - 158
src/views/file/components/FileList/components/ShareFileDialog.vue

@@ -1,166 +1,185 @@
 <template>
-  <div>
-    <!-- 分享对话框 -->
-    <el-dialog
-      title="分享文件"
-      :visible.sync="dialogShareFile.visible"
-      :close-on-click-modal="false"
-      width="550px"
-      @close="handleShareFileDialogCancel('shareFileForm')"
-    >
-      <el-form
-        v-show="!dialogShareFile.success"
-        class="share-file-form"
-        :model="form"
-        ref="shareFileForm"
-        label-suffix=":"
-        label-width="130px"
-        :rules="rules"
-      >
-        <el-form-item label="链接有效期至" prop="endTime">
-          <el-date-picker
-            v-model="form.endTime"
-            type="datetime"
-            placeholder="选择日期时间"
-            align="right"
-            value-format="yyyy-MM-dd HH:mm:ss"
-            :editable="false"
-            :clearable="false"
-            :picker-options="pickerOptions"
-          >
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="是否需要提取码" prop="shareType">
-          <el-radio-group v-model="form.shareType">
-            <el-radio :label="1">是</el-radio>
-            <el-radio :label="0">否</el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-      <el-form
-        v-if="dialogShareFile.success"
-        class="share-success-form"
-        :model="dialogShareFile.shareData"
-        ref="shareSuccessForm"
-        label-suffix=":"
-        label-width="90px"
-      >
-        <div class="success-tip">
-          <i class="el-icon-success"></i>
-          <span class="text">成功创建分享链接</span>
-        </div>
-        <el-form-item label="分享链接" prop="shareBatchNum">
-          <el-input
-            :value="getShareLink(dialogShareFile.shareData.shareBatchNum)"
-            :readonly="true"
-            type="textarea"
-            autosize
-          ></el-input>
-        </el-form-item>
-        <el-form-item label="提取码" prop="extractionCode" v-if="dialogShareFile.shareData.extractionCode">
-          <el-input v-model="dialogShareFile.shareData.extractionCode" :readonly="true"></el-input>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button
-          v-if="dialogShareFile.success"
-          type="primary"
-          @click="copyShareLink(dialogShareFile.shareData.shareBatchNum, dialogShareFile.shareData.extractionCode)"
-          >复制链接及提取码</el-button
-        >
-        <template v-else>
-          <el-button @click="handleShareFileDialogCancel('shareFileForm')">取 消</el-button>
-          <el-button type="primary" :loading="dialogShareFile.loading" @click="handleShareFileDialogOk('shareFileForm')"
-            >确 定</el-button
-          >
-        </template>
-      </div>
-    </el-dialog>
-  </div>
+	<div>
+		<!-- 分享对话框 -->
+		<el-dialog
+			title="分享文件"
+			:visible.sync="dialogShareFile.visible"
+			:close-on-click-modal="false"
+			width="550px"
+			@close="handleShareFileDialogCancel('shareFileForm')"
+		>
+			<el-form
+				v-show="!dialogShareFile.success"
+				class="share-file-form"
+				:model="form"
+				ref="shareFileForm"
+				label-suffix=":"
+				label-width="130px"
+				:rules="rules"
+			>
+				<el-form-item label="链接有效期至" prop="endTime">
+					<el-date-picker
+						v-model="form.endTime"
+						type="datetime"
+						placeholder="选择日期时间"
+						align="right"
+						value-format="yyyy-MM-dd HH:mm:ss"
+						:editable="false"
+						:clearable="false"
+						:picker-options="pickerOptions"
+					>
+					</el-date-picker>
+				</el-form-item>
+				<el-form-item label="是否需要提取码" prop="shareType">
+					<el-radio-group v-model="form.shareType">
+						<el-radio :label="1">是</el-radio>
+						<el-radio :label="0">否</el-radio>
+					</el-radio-group>
+				</el-form-item>
+			</el-form>
+			<el-form
+				v-if="dialogShareFile.success"
+				class="share-success-form"
+				:model="dialogShareFile.shareData"
+				ref="shareSuccessForm"
+				label-suffix=":"
+				label-width="90px"
+			>
+				<div class="success-tip">
+					<i class="el-icon-success"></i>
+					<span class="text">成功创建分享链接</span>
+				</div>
+				<el-form-item label="分享链接" prop="shareBatchNum">
+					<el-input
+						:value="getShareLink(dialogShareFile.shareData.shareBatchNum)"
+						:readonly="true"
+						type="textarea"
+						autosize
+					></el-input>
+				</el-form-item>
+				<el-form-item
+					label="提取码"
+					prop="extractionCode"
+					v-if="dialogShareFile.shareData.extractionCode"
+				>
+					<el-input
+						v-model="dialogShareFile.shareData.extractionCode"
+						:readonly="true"
+					></el-input>
+				</el-form-item>
+			</el-form>
+			<div slot="footer" class="dialog-footer">
+				<el-button
+					v-if="dialogShareFile.success"
+					type="primary"
+					@click="
+						copyShareLink(
+							dialogShareFile.shareData.shareBatchNum,
+							dialogShareFile.shareData.extractionCode
+						)
+					"
+					>复制链接及提取码</el-button
+				>
+				<template v-else>
+					<el-button @click="handleShareFileDialogCancel('shareFileForm')"
+						>取 消</el-button
+					>
+					<el-button
+						type="primary"
+						:loading="dialogShareFile.loading"
+						@click="handleShareFileDialogOk('shareFileForm')"
+						>确 定</el-button
+					>
+				</template>
+			</div>
+		</el-dialog>
+	</div>
 </template>
 
 <script>
 export default {
-  name: 'ShareFileDialog',
-  props: {
-    dialogShareFile: {
-      required: true,
-      type: Object
-    }
-  },
-  data() {
-    return {
-      // 分享文件对话框数据
-      form: {
-        // endTime: (new Date()).getTime() + 3600 * 1000 * 24,
-        endTime: '',
-        shareType: 0
-      },
-      rules: {
-        endTime: [{ required: true, message: '请选择链接有效期', trigger: 'blur' }]
-      },
-      loading: false,
-      pickerOptions: {
-        shortcuts: [
-          {
-            text: '今天',
-            onClick(picker) {
-              picker.$emit('pick', new Date())
-            }
-          },
-          {
-            text: '1天',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() + 3600 * 1000 * 24)
-              picker.$emit('pick', date)
-            }
-          },
-          {
-            text: '7天',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() + 3600 * 1000 * 24 * 7)
-              picker.$emit('pick', date)
-            }
-          },
-          {
-            text: '30天',
-            onClick(picker) {
-              const date = new Date()
-              date.setTime(date.getTime() + 3600 * 1000 * 24 * 30)
-              picker.$emit('pick', date)
-            }
-          }
-        ]
-      }
-    }
-  },
-  methods: {
-    /**
-     * 分享文件对话框 | 取消按钮点击事件
-     * @description 关闭对话框,重置表单
-     * @param {string} formName 表单ref值
-     */
-    handleShareFileDialogCancel(formName) {
-      this.$emit('setDialogShareFileData', false)
-      this.$refs[formName].resetFields()
-    },
-    /**
-     * 分享文件对话框 | 确定按钮点击事件
-     * @description 校验表单,校验通过后调用分享文件接口
-     * @param {string} formName 表单ref值
-     */
-    handleShareFileDialogOk(formName) {
-      this.$refs[formName].validate((valid) => {
-        if (valid) {
-          this.$emit('setDialogShareFileData', true, this.form)
-        } else {
-          return false
-        }
-      })
-    }
-  }
+	name: 'ShareFileDialog',
+	props: {
+		dialogShareFile: {
+			required: true,
+			type: Object
+		}
+	},
+	data() {
+		return {
+			// 分享文件对话框数据
+			form: {
+				// endTime: (new Date()).getTime() + 3600 * 1000 * 24,
+				endTime: '',
+				shareType: 0
+			},
+			rules: {
+				endTime: [
+					{ required: true, message: '请选择链接有效期', trigger: 'blur' }
+				]
+			},
+			loading: false,
+			pickerOptions: {
+				shortcuts: [
+					{
+						text: '今天',
+						onClick(picker) {
+							picker.$emit('pick', new Date())
+						}
+					},
+					{
+						text: '1天',
+						onClick(picker) {
+							const date = new Date()
+							date.setTime(date.getTime() + 3600 * 1000 * 24)
+							picker.$emit('pick', date)
+						}
+					},
+					{
+						text: '7天',
+						onClick(picker) {
+							const date = new Date()
+							date.setTime(date.getTime() + 3600 * 1000 * 24 * 7)
+							picker.$emit('pick', date)
+						}
+					},
+					{
+						text: '30天',
+						onClick(picker) {
+							const date = new Date()
+							date.setTime(date.getTime() + 3600 * 1000 * 24 * 30)
+							picker.$emit('pick', date)
+						}
+					}
+				]
+			}
+		}
+	},
+	methods: {
+		/**
+		 * 分享文件对话框 | 取消按钮点击事件
+		 * @description 关闭对话框,重置表单
+		 * @param {string} formName 表单ref值
+		 */
+		handleShareFileDialogCancel(formName) {
+			this.$emit('setDialogShareFileData', false)
+			this.$refs[formName].resetFields()
+		},
+		/**
+		 * 分享文件对话框 | 确定按钮点击事件
+		 * @description 校验表单,校验通过后调用分享文件接口
+		 * @param {string} formName 表单ref值
+		 */
+		handleShareFileDialogOk(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					this.$emit('setDialogShareFileData', true, this.form)
+				} else {
+					return false
+				}
+			})
+		}
+	}
 }
 </script>
 

+ 475 - 469
src/views/file/components/FileList/index.vue

@@ -1,78 +1,82 @@
 <template>
-  <div class="file-list-wrapper">
-    <!-- 操作按钮 -->
-    <el-header>
-      <OperationMenu
-        :fileType="fileType"
-        :filePath="filePath"
-        :operationFile="operationFile"
-        :selectionFile="selectionFile"
-        :batchOperate.sync="batchOperate"
-        @getSearchFileList="getSearchFileList"
-        @getTableDataByType="getTableDataByType"
-        @setMoveFileDialogData="setMoveFileDialogData"
-        @setShareFileDialogData="setShareFileDialogData"
-      ></OperationMenu>
-    </el-header>
-    <div class="middle-wrapper">
-      <!-- 面包屑导航栏 -->
-      <BreadCrumb class="breadcrumb" :fileType="fileType"></BreadCrumb>
-    </div>
-    <!-- 文件列表-表格模式 -->
-    <FileTable
-      :fileType="fileType"
-      :filePath="filePath"
-      :fileList="fileList"
-      :loading="loading"
-      v-if="fileModel === 0"
-      @setMoveFileDialogData="setMoveFileDialogData"
-      @setShareFileDialogData="setShareFileDialogData"
-      @setOperationFile="setOperationFile"
-      @setSelectionFile="setSelectionFile"
-      @getTableDataByType="getTableDataByType"
-    ></FileTable>
-    <!-- 文件列表-网格模式 -->
-    <FileGrid
-      :fileType="fileType"
-      :filePath="filePath"
-      :fileList="fileList"
-      :loading="loading"
-      :batchOperate="batchOperate"
-      v-if="fileModel === 1"
-      @setMoveFileDialogData="setMoveFileDialogData"
-      @setShareFileDialogData="setShareFileDialogData"
-      @setOperationFile="setOperationFile"
-      @setSelectionFile="setSelectionFile"
-      @getTableDataByType="getTableDataByType"
-    ></FileGrid>
-    <!-- 图片-时间线模式 -->
-    <FileTimeLine class="image-model" v-if="fileModel === 2" :fileList="fileList"></FileTimeLine>
-    <div class="pagination-wrapper">
-      <div class="current-page-count">当前页{{ fileList.length }}条</div>
-      <el-pagination
-        :current-page="pageData.currentPage"
-        :page-size="pageData.pageCount"
-        :total="pageData.total"
-        :page-sizes="[10, 50, 100, 200]"
-        layout="sizes, total, prev, pager, next"
-        @current-change="handleCurrentChange"
-        @size-change="handleSizeChange"
-      >
-      </el-pagination>
-    </div>
-    <!-- 移动文件模态框 -->
-    <MoveFileDialog
-      :dialogData="dialogMoveFile"
-      @setSelectFilePath="setSelectFilePath"
-      @confirmDialog="confirmMoveFile"
-      @setDialogData="setMoveFileDialogData"
-    ></MoveFileDialog>
-    <!-- 分享文件模态框 -->
-    <ShareFileDialog
-      :dialogShareFile="dialogShareFile"
-      @setDialogShareFileData="setDialogShareFileData"
-    ></ShareFileDialog>
-  </div>
+	<div class="file-list-wrapper">
+		<!-- 操作按钮 -->
+		<el-header>
+			<OperationMenu
+				:fileType="fileType"
+				:filePath="filePath"
+				:operationFile="operationFile"
+				:selectionFile="selectionFile"
+				:batchOperate.sync="batchOperate"
+				@getSearchFileList="getSearchFileList"
+				@getTableDataByType="getTableDataByType"
+				@setMoveFileDialogData="setMoveFileDialogData"
+				@setShareFileDialogData="setShareFileDialogData"
+			></OperationMenu>
+		</el-header>
+		<div class="middle-wrapper">
+			<!-- 面包屑导航栏 -->
+			<BreadCrumb class="breadcrumb" :fileType="fileType"></BreadCrumb>
+		</div>
+		<!-- 文件列表-表格模式 -->
+		<FileTable
+			:fileType="fileType"
+			:filePath="filePath"
+			:fileList="fileList"
+			:loading="loading"
+			v-if="fileModel === 0"
+			@setMoveFileDialogData="setMoveFileDialogData"
+			@setShareFileDialogData="setShareFileDialogData"
+			@setOperationFile="setOperationFile"
+			@setSelectionFile="setSelectionFile"
+			@getTableDataByType="getTableDataByType"
+		></FileTable>
+		<!-- 文件列表-网格模式 -->
+		<FileGrid
+			:fileType="fileType"
+			:filePath="filePath"
+			:fileList="fileList"
+			:loading="loading"
+			:batchOperate="batchOperate"
+			v-if="fileModel === 1"
+			@setMoveFileDialogData="setMoveFileDialogData"
+			@setShareFileDialogData="setShareFileDialogData"
+			@setOperationFile="setOperationFile"
+			@setSelectionFile="setSelectionFile"
+			@getTableDataByType="getTableDataByType"
+		></FileGrid>
+		<!-- 图片-时间线模式 -->
+		<FileTimeLine
+			class="image-model"
+			v-if="fileModel === 2"
+			:fileList="fileList"
+		></FileTimeLine>
+		<div class="pagination-wrapper">
+			<div class="current-page-count">当前页{{ fileList.length }}条</div>
+			<el-pagination
+				:current-page="pageData.currentPage"
+				:page-size="pageData.pageCount"
+				:total="pageData.total"
+				:page-sizes="[10, 50, 100, 200]"
+				layout="sizes, total, prev, pager, next"
+				@current-change="handleCurrentChange"
+				@size-change="handleSizeChange"
+			>
+			</el-pagination>
+		</div>
+		<!-- 移动文件模态框 -->
+		<MoveFileDialog
+			:dialogData="dialogMoveFile"
+			@setSelectFilePath="setSelectFilePath"
+			@confirmDialog="confirmMoveFile"
+			@setDialogData="setMoveFileDialogData"
+		></MoveFileDialog>
+		<!-- 分享文件模态框 -->
+		<ShareFileDialog
+			:dialogShareFile="dialogShareFile"
+			@setDialogShareFileData="setDialogShareFileData"
+		></ShareFileDialog>
+	</div>
 </template>
 
 <script>
@@ -85,406 +89,408 @@ import MoveFileDialog from '_c/File/MoveFileDialog'
 import ShareFileDialog from './components/ShareFileDialog'
 
 import {
-  getFileListByPath,
-  getFileListByType,
-  getRecoveryFile,
-  moveFile,
-  batchMoveFile,
-  searchFile,
-  shareFile
+	getFileListByPath,
+	getFileListByType,
+	getRecoveryFile,
+	moveFile,
+	batchMoveFile,
+	searchFile,
+	shareFile
 } from '_r/file.js'
 
 export default {
-  name: 'FileList',
-  components: {
-    OperationMenu,
-    BreadCrumb,
-    FileTable,
-    FileGrid,
-    FileTimeLine,
-    MoveFileDialog,
-    ShareFileDialog
-  },
-  data() {
-    return {
-      fileNameSearch: '',
-      loading: true, //  表格数据-loading
-      fileList: [], //  表格数据-文件列表
-      pageData: {
-        currentPage: 1,
-        pageCount: 50,
-        total: 0
-      },
-      //  移动文件模态框数据
-      dialogMoveFile: {
-        isBatchMove: false,
-        visible: false //  是否可见
-      },
-      selectFilePath: '', //  移动文件路径
-      operationFile: {}, // 当前操作行
-      selectionFile: [], // 勾选的文件
-      // 分享文件对话框数据
-      dialogShareFile: {
-        visible: false,
-        loading: false,
-        success: false,
-        shareData: {}
-      },
-      //  可以识别的文件类型
-      fileImgTypeList: [
-        'png',
-        'jpg',
-        'jpeg',
-        'docx',
-        'doc',
-        'ppt',
-        'pptx',
-        'xls',
-        'xlsx',
-        'avi',
-        'mp4',
-        'css',
-        'csv',
-        'chm',
-        'rar',
-        'zip',
-        'dmg',
-        'mp3',
-        'open',
-        'pdf',
-        'rtf',
-        'txt',
-        'oa',
-        'js',
-        'html',
-        'img',
-        'sql',
-        'jar',
-        'svg',
-        'gif',
-        'json',
-        'exe'
-      ],
-      //  文件图片Map映射
-      fileImgMap: {
-        dir: require('_a/images/file/dir.png'),
-        chm: require('_a/images/file/file_chm.png'),
-        css: require('_a/images/file/file_css.png'),
-        csv: require('_a/images/file/file_csv.png'),
-        png: require('_a/images/file/file_pic.png'),
-        jpg: require('_a/images/file/file_pic.png'),
-        jpeg: require('_a/images/file/file_pic.png'),
-        docx: require('_a/images/file/file_word.png'),
-        doc: require('_a/images/file/file_word.png'),
-        ppt: require('_a/images/file/file_ppt.png'),
-        pptx: require('_a/images/file/file_ppt.png'),
-        xls: require('_a/images/file/file_excel.png'),
-        xlsx: require('_a/images/file/file_excel.png'),
-        mp4: require('_a/images/file/file_video.png'),
-        avi: require('_a/images/file/file_avi.png'),
-        rar: require('_a/images/file/file_rar.png'),
-        zip: require('_a/images/file/file_zip.png'),
-        dmg: require('_a/images/file/file_dmg.png'),
-        mp3: require('_a/images/file/file_music.png'),
-        open: require('_a/images/file/file_open.png'),
-        pdf: require('_a/images/file/file_pdf.png'),
-        rtf: require('_a/images/file/file_rtf.png'),
-        txt: require('_a/images/file/file_txt.png'),
-        oa: require('_a/images/file/file_oa.png'),
-        unknown: require('_a/images/file/file_unknown.png'),
-        js: require('_a/images/file/file_js.png'),
-        html: require('_a/images/file/file_html.png'),
-        img: require('_a/images/file/file_img.png'),
-        sql: require('_a/images/file/file_sql.png'),
-        jar: require('_a/images/file/file_jar.png'),
-        svg: require('_a/images/file/file_svg.png'),
-        gif: require('_a/images/file/file_gif.png'),
-        json: require('_a/images/file/file_json.png'),
-        exe: require('_a/images/file/file_exe.png')
-      },
-      batchOperate: false //  批量操作模式
-    }
-  },
-  computed: {
-    // 左侧菜单选中的文件类型
-    fileType() {
-      return this.$route.query.fileType ? Number(this.$route.query.fileType) : 0
-    },
-    // 当前所在路径
-    filePath() {
-      return this.$route.query.filePath ? this.$route.query.filePath : '/'
-    },
-    // 文件查看模式 0列表模式 1网格模式 2 时间线模式
-    fileModel() {
-      return this.$store.getters.fileModel
-    }
-  },
-  watch: {
-    filePath() {
-      // 当左侧菜单选择全部,文件路径发生变化时,再重新获取文件列表
-      if (this.$route.name === 'File' && this.fileType === 0) {
-        this.setPageCount()
-        this.getTableDataByType()
-      }
-    },
-    fileType() {
-      if (this.$route.name === 'File') {
-        this.setPageCount()
-        this.getTableDataByType()
-      }
-    },
-    // 监听文件查看模式
-    fileModel() {
-      this.setPageCount()
-      this.getTableDataByType()
-    },
-    batchOperate(value) {
-      if (!value) {
-        this.selectionFile = []
-      }
-    }
-  },
-  created() {
-    this.setPageCount()
-    this.getTableDataByType()
-  },
-  methods: {
-    /**
-     * 表格数据获取相关事件 | 调整分页大小
-     */
-    setPageCount() {
-      this.pageData.currentPage = 1
-      if (this.fileModel === 0) {
-        this.pageData.pageCount = 50
-      }
-      if (this.fileModel === 1) {
-        this.pageData.pageCount = 100
-      }
-    },
-    /**
-     * 表格数据获取相关事件 | 获取文件列表数据
-     */
-    getTableDataByType() {
-      this.batchOperate = false
-      this.loading = true
-      // 分类型
-      if (Number(this.fileType)) {
-        if (Number(this.fileType) === 6) {
-          this.shwoFileRecovery() //  回收站
-        } else {
-          this.showFileListByType()
-        }
-      } else {
-        // 全部文件
-        this.showFileList()
-      }
-      this.$store.dispatch('showStorage')
-    },
-    /**
-     * 表格数据获取相关事件 | 获取当前路径下的文件列表
-     */
-    showFileList() {
-      let data = {
-        filePath: this.filePath,
-        currentPage: this.pageData.currentPage,
-        pageCount: this.pageData.pageCount
-      }
-      getFileListByPath(data).then((res) => {
-        if (res.success) {
-          this.fileList = res.data.list
-          this.pageData.total = res.data.total
-          this.loading = false
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 表格数据获取相关事件 | 分页组件 | 当前页码改变
-     */
-    handleCurrentChange(currentPage) {
-      this.pageData.currentPage = currentPage
-      this.getTableDataByType()
-    },
-    /**
-     * 表格数据获取相关事件 | 分页组件 | 页大小改变时
-     */
-    handleSizeChange(pageCount) {
-      this.pageData.pageCount = pageCount
-      this.getTableDataByType()
-    },
-    /**
-     * 表格数据获取相关事件 | 获取回收站文件列表
-     */
-    shwoFileRecovery() {
-      getRecoveryFile().then((res) => {
-        if (res.success) {
-          this.fileList = res.data
-          this.loading = false
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 表格数据获取相关事件 | 根据文件类型展示文件列表
-     */
-    showFileListByType() {
-      //  分类型
-      let data = {
-        fileType: this.fileType,
-        currentPage: this.pageData.currentPage,
-        pageCount: this.pageData.pageCount
-      }
-      getFileListByType(data).then((res) => {
-        if (res.success) {
-          this.fileList = res.data.list
-          this.pageData.total = res.data.total
-          this.loading = false
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
+	name: 'FileList',
+	components: {
+		OperationMenu,
+		BreadCrumb,
+		FileTable,
+		FileGrid,
+		FileTimeLine,
+		MoveFileDialog,
+		ShareFileDialog
+	},
+	data() {
+		return {
+			fileNameSearch: '',
+			loading: true, //  表格数据-loading
+			fileList: [], //  表格数据-文件列表
+			pageData: {
+				currentPage: 1,
+				pageCount: 50,
+				total: 0
+			},
+			//  移动文件模态框数据
+			dialogMoveFile: {
+				isBatchMove: false,
+				visible: false //  是否可见
+			},
+			selectFilePath: '', //  移动文件路径
+			operationFile: {}, // 当前操作行
+			selectionFile: [], // 勾选的文件
+			// 分享文件对话框数据
+			dialogShareFile: {
+				visible: false,
+				loading: false,
+				success: false,
+				shareData: {}
+			},
+			//  可以识别的文件类型
+			fileImgTypeList: [
+				'png',
+				'jpg',
+				'jpeg',
+				'docx',
+				'doc',
+				'ppt',
+				'pptx',
+				'xls',
+				'xlsx',
+				'avi',
+				'mp4',
+				'css',
+				'csv',
+				'chm',
+				'rar',
+				'zip',
+				'dmg',
+				'mp3',
+				'open',
+				'pdf',
+				'rtf',
+				'txt',
+				'oa',
+				'js',
+				'html',
+				'img',
+				'sql',
+				'jar',
+				'svg',
+				'gif',
+				'json',
+				'exe'
+			],
+			//  文件图片Map映射
+			fileImgMap: {
+				dir: require('_a/images/file/dir.png'),
+				chm: require('_a/images/file/file_chm.png'),
+				css: require('_a/images/file/file_css.png'),
+				csv: require('_a/images/file/file_csv.png'),
+				png: require('_a/images/file/file_pic.png'),
+				jpg: require('_a/images/file/file_pic.png'),
+				jpeg: require('_a/images/file/file_pic.png'),
+				docx: require('_a/images/file/file_word.png'),
+				doc: require('_a/images/file/file_word.png'),
+				ppt: require('_a/images/file/file_ppt.png'),
+				pptx: require('_a/images/file/file_ppt.png'),
+				xls: require('_a/images/file/file_excel.png'),
+				xlsx: require('_a/images/file/file_excel.png'),
+				mp4: require('_a/images/file/file_video.png'),
+				avi: require('_a/images/file/file_avi.png'),
+				rar: require('_a/images/file/file_rar.png'),
+				zip: require('_a/images/file/file_zip.png'),
+				dmg: require('_a/images/file/file_dmg.png'),
+				mp3: require('_a/images/file/file_music.png'),
+				open: require('_a/images/file/file_open.png'),
+				pdf: require('_a/images/file/file_pdf.png'),
+				rtf: require('_a/images/file/file_rtf.png'),
+				txt: require('_a/images/file/file_txt.png'),
+				oa: require('_a/images/file/file_oa.png'),
+				unknown: require('_a/images/file/file_unknown.png'),
+				js: require('_a/images/file/file_js.png'),
+				html: require('_a/images/file/file_html.png'),
+				img: require('_a/images/file/file_img.png'),
+				sql: require('_a/images/file/file_sql.png'),
+				jar: require('_a/images/file/file_jar.png'),
+				svg: require('_a/images/file/file_svg.png'),
+				gif: require('_a/images/file/file_gif.png'),
+				json: require('_a/images/file/file_json.png'),
+				exe: require('_a/images/file/file_exe.png')
+			},
+			batchOperate: false //  批量操作模式
+		}
+	},
+	computed: {
+		// 左侧菜单选中的文件类型
+		fileType() {
+			return this.$route.query.fileType ? Number(this.$route.query.fileType) : 0
+		},
+		// 当前所在路径
+		filePath() {
+			return this.$route.query.filePath ? this.$route.query.filePath : '/'
+		},
+		// 文件查看模式 0列表模式 1网格模式 2 时间线模式
+		fileModel() {
+			return this.$store.getters.fileModel
+		}
+	},
+	watch: {
+		filePath() {
+			// 当左侧菜单选择全部,文件路径发生变化时,再重新获取文件列表
+			if (this.$route.name === 'File' && this.fileType === 0) {
+				this.setPageCount()
+				this.getTableDataByType()
+			}
+		},
+		fileType() {
+			if (this.$route.name === 'File') {
+				this.setPageCount()
+				this.getTableDataByType()
+			}
+		},
+		// 监听文件查看模式
+		fileModel() {
+			this.setPageCount()
+			this.getTableDataByType()
+		},
+		batchOperate(value) {
+			if (!value) {
+				this.selectionFile = []
+			}
+		}
+	},
+	created() {
+		this.setPageCount()
+		this.getTableDataByType()
+	},
+	methods: {
+		/**
+		 * 表格数据获取相关事件 | 调整分页大小
+		 */
+		setPageCount() {
+			this.pageData.currentPage = 1
+			if (this.fileModel === 0) {
+				this.pageData.pageCount = 50
+			}
+			if (this.fileModel === 1) {
+				this.pageData.pageCount = 100
+			}
+		},
+		/**
+		 * 表格数据获取相关事件 | 获取文件列表数据
+		 */
+		getTableDataByType() {
+			this.batchOperate = false
+			this.loading = true
+			// 分类型
+			if (Number(this.fileType)) {
+				if (Number(this.fileType) === 6) {
+					this.shwoFileRecovery() //  回收站
+				} else {
+					this.showFileListByType()
+				}
+			} else {
+				// 全部文件
+				this.showFileList()
+			}
+			this.$store.dispatch('showStorage')
+		},
+		/**
+		 * 表格数据获取相关事件 | 获取当前路径下的文件列表
+		 */
+		showFileList() {
+			let data = {
+				filePath: this.filePath,
+				currentPage: this.pageData.currentPage,
+				pageCount: this.pageData.pageCount
+			}
+			getFileListByPath(data).then((res) => {
+				if (res.success) {
+					this.fileList = res.data.list
+					this.pageData.total = res.data.total
+					this.loading = false
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 表格数据获取相关事件 | 分页组件 | 当前页码改变
+		 */
+		handleCurrentChange(currentPage) {
+			this.pageData.currentPage = currentPage
+			this.getTableDataByType()
+		},
+		/**
+		 * 表格数据获取相关事件 | 分页组件 | 页大小改变时
+		 */
+		handleSizeChange(pageCount) {
+			this.pageData.pageCount = pageCount
+			this.getTableDataByType()
+		},
+		/**
+		 * 表格数据获取相关事件 | 获取回收站文件列表
+		 */
+		shwoFileRecovery() {
+			getRecoveryFile().then((res) => {
+				if (res.success) {
+					this.fileList = res.data
+					this.loading = false
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 表格数据获取相关事件 | 根据文件类型展示文件列表
+		 */
+		showFileListByType() {
+			//  分类型
+			let data = {
+				fileType: this.fileType,
+				currentPage: this.pageData.currentPage,
+				pageCount: this.pageData.pageCount
+			}
+			getFileListByType(data).then((res) => {
+				if (res.success) {
+					this.fileList = res.data.list
+					this.pageData.total = res.data.total
+					this.loading = false
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
 
-    /**
-     * 表格勾选框事件 | 保存被勾选的文件
-     * @param {object[]} selection 被勾选的文件数组
-     */
-    setSelectionFile(selection, batchOperate) {
-      this.selectionFile = selection
-      this.batchOperate = batchOperate
-    },
+		/**
+		 * 表格勾选框事件 | 保存被勾选的文件
+		 * @param {object[]} selection 被勾选的文件数组
+		 */
+		setSelectionFile(selection, batchOperate) {
+			this.selectionFile = selection
+			this.batchOperate = batchOperate
+		},
 
-    /**
-     * 移动按钮相关事件 | 当前操作行
-     * @param {object} operationFile
-     */
-    setOperationFile(operationFile) {
-      this.operationFile = operationFile
-    },
-    /**
-     * 移动按钮相关事件 | 设置移动文件模态框相关数据
-     * @param {boolean} isBatchMove 是否批量移动,为 null时是确认移动,值由之前的值而定
-     * @param {boolean} visible 移动文件对话框状态
-     */
-    setMoveFileDialogData(isBatchMove, visible) {
-      this.dialogMoveFile.isBatchMove = isBatchMove ? isBatchMove : this.dialogMoveFile.isBatchMove
-      this.dialogMoveFile.visible = visible
-    },
-    /**
-     * 移动文件模态框 | 设置移动后的文件路径
-     * @param {string} selectFilePath 目标文件夹路径
-     */
-    setSelectFilePath(selectFilePath) {
-      this.selectFilePath = selectFilePath
-    },
-    /**
-     * 移动文件模态框 | 确定按钮事件
-     */
-    confirmMoveFile() {
-      if (this.dialogMoveFile.isBatchMove) {
-        //  批量移动
-        let data = {
-          filePath: this.selectFilePath,
-          files: JSON.stringify(this.selectionFile)
-        }
-        batchMoveFile(data).then((res) => {
-          if (res.success) {
-            this.$message.success(res.data)
-            this.getTableDataByType()
-            this.dialogMoveFile.visible = false
-            this.selectionFile = []
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      } else {
-        //  单文件移动
-        let data = {
-          oldFilePath: this.operationFile.filePath,
-          filePath: this.selectFilePath,
-          fileName: this.operationFile.fileName,
-          extendName: this.operationFile.extendName
-        }
-        moveFile(data).then((res) => {
-          if (res.success) {
-            this.$message.success('移动文件成功')
-            this.getTableDataByType()
-            this.dialogMoveFile.visible = false
-          } else {
-            this.$message.error(res.message)
-          }
-        })
-      }
-    },
-    /**
-     * 获取搜索文件结果列表
-     * @param {string} fileName 文件名称
-     */
-    getSearchFileList(fileName) {
-      this.loading = true
-      searchFile({
-        currentPage: this.pageData.currentPage,
-        pageCount: this.pageData.pageCount,
-        fileName: fileName
-      }).then((res) => {
-        this.loading = false
-        if (res.success) {
-          this.fileList = res.data.searchHits.map((item) => item.content)
-          this.pageData.total = res.data.totalHits
-        } else {
-          this.$message.error(res.message)
-        }
-      })
-    },
-    /**
-     * 设置分享文件对话框状态
-     */
-    setShareFileDialogData() {
-      this.dialogShareFile.visible = true
-    },
-    /**
-     * 分享文件对话框确定|取消按钮点击事件
-     * @param {boolean} status 对话框状态
-     * @param {object} data 分享文件数据
-     */
-    setDialogShareFileData(status, data) {
-      if (status) {
-        this.dialogShareFile.loading = true
-        shareFile({
-          ...data,
-          remarks: '',
-          files: JSON.stringify(
-            this.selectionFile.map((item) => {
-              return {
-                userFileId: item.userFileId
-              }
-            })
-          )
-        }).then(
-          (res) => {
-            this.dialogShareFile.loading = false
-            if (res.success) {
-              this.dialogShareFile.success = true
-              this.dialogShareFile.shareData = res.data
-            } else {
-              this.$message.error(res.message)
-            }
-          },
-          (error) => {
-            console.log(error)
-            this.$message.error(error.message)
-            this.dialogShareFile.loading = false
-          }
-        )
-      } else {
-        this.dialogShareFile.visible = false
-        this.dialogShareFile.loading = false
-        this.dialogShareFile.success = false
-      }
-    }
-  }
+		/**
+		 * 移动按钮相关事件 | 当前操作行
+		 * @param {object} operationFile
+		 */
+		setOperationFile(operationFile) {
+			this.operationFile = operationFile
+		},
+		/**
+		 * 移动按钮相关事件 | 设置移动文件模态框相关数据
+		 * @param {boolean} isBatchMove 是否批量移动,为 null时是确认移动,值由之前的值而定
+		 * @param {boolean} visible 移动文件对话框状态
+		 */
+		setMoveFileDialogData(isBatchMove, visible) {
+			this.dialogMoveFile.isBatchMove = isBatchMove
+				? isBatchMove
+				: this.dialogMoveFile.isBatchMove
+			this.dialogMoveFile.visible = visible
+		},
+		/**
+		 * 移动文件模态框 | 设置移动后的文件路径
+		 * @param {string} selectFilePath 目标文件夹路径
+		 */
+		setSelectFilePath(selectFilePath) {
+			this.selectFilePath = selectFilePath
+		},
+		/**
+		 * 移动文件模态框 | 确定按钮事件
+		 */
+		confirmMoveFile() {
+			if (this.dialogMoveFile.isBatchMove) {
+				//  批量移动
+				let data = {
+					filePath: this.selectFilePath,
+					files: JSON.stringify(this.selectionFile)
+				}
+				batchMoveFile(data).then((res) => {
+					if (res.success) {
+						this.$message.success(res.data)
+						this.getTableDataByType()
+						this.dialogMoveFile.visible = false
+						this.selectionFile = []
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			} else {
+				//  单文件移动
+				let data = {
+					oldFilePath: this.operationFile.filePath,
+					filePath: this.selectFilePath,
+					fileName: this.operationFile.fileName,
+					extendName: this.operationFile.extendName
+				}
+				moveFile(data).then((res) => {
+					if (res.success) {
+						this.$message.success('移动文件成功')
+						this.getTableDataByType()
+						this.dialogMoveFile.visible = false
+					} else {
+						this.$message.error(res.message)
+					}
+				})
+			}
+		},
+		/**
+		 * 获取搜索文件结果列表
+		 * @param {string} fileName 文件名称
+		 */
+		getSearchFileList(fileName) {
+			this.loading = true
+			searchFile({
+				currentPage: this.pageData.currentPage,
+				pageCount: this.pageData.pageCount,
+				fileName: fileName
+			}).then((res) => {
+				this.loading = false
+				if (res.success) {
+					this.fileList = res.data.searchHits.map((item) => item.content)
+					this.pageData.total = res.data.totalHits
+				} else {
+					this.$message.error(res.message)
+				}
+			})
+		},
+		/**
+		 * 设置分享文件对话框状态
+		 */
+		setShareFileDialogData() {
+			this.dialogShareFile.visible = true
+		},
+		/**
+		 * 分享文件对话框确定|取消按钮点击事件
+		 * @param {boolean} status 对话框状态
+		 * @param {object} data 分享文件数据
+		 */
+		setDialogShareFileData(status, data) {
+			if (status) {
+				this.dialogShareFile.loading = true
+				shareFile({
+					...data,
+					remarks: '',
+					files: JSON.stringify(
+						this.selectionFile.map((item) => {
+							return {
+								userFileId: item.userFileId
+							}
+						})
+					)
+				}).then(
+					(res) => {
+						this.dialogShareFile.loading = false
+						if (res.success) {
+							this.dialogShareFile.success = true
+							this.dialogShareFile.shareData = res.data
+						} else {
+							this.$message.error(res.message)
+						}
+					},
+					(error) => {
+						console.log(error)
+						this.$message.error(error.message)
+						this.dialogShareFile.loading = false
+					}
+				)
+			} else {
+				this.dialogShareFile.visible = false
+				this.dialogShareFile.loading = false
+				this.dialogShareFile.success = false
+			}
+		}
+	}
 }
 </script>
 

+ 26 - 29
vue.config.js

@@ -2,38 +2,35 @@ const productConfig = require('./public/config.json')
 const path = require('path')
 
 module.exports = {
-  // 选项...
-  publicPath: '/',
+	// 选项...
+	publicPath: '/',
 
-  //是否开启eslint校验
-  lintOnSave: false,
+	devServer: {
+		disableHostCheck: true,
+		host: '0.0.0.0',
+		proxy: {
+			//配置代理,解决跨域请求后台数据的问题
+			'/api': {
+				target: productConfig.baseUrl, //后台接口,连接本地服务
+				ws: true, //是否跨域
+				changeOrigin: true,
+				pathRewrite: {
+					'^/api': '/'
+				}
+			}
+		}
+	},
 
-  devServer: {
-    disableHostCheck: true,
-    host: '0.0.0.0',
-    proxy: { //配置代理,解决跨域请求后台数据的问题
-      '/api': {
-        target: productConfig.baseUrl, //后台接口,连接本地服务
-        ws: true, //是否跨域
-        changeOrigin: true,
-        pathRewrite: {
-          '^/api':'/'
-        }
-      }
-      
-    }
-  },
+	productionSourceMap: false,
 
-  productionSourceMap: false,
+	pluginOptions: {
+		'style-resources-loader': {
+			preProcessor: 'stylus',
+			patterns: []
+		}
+	},
 
-  pluginOptions: {
-    'style-resources-loader': {
-      preProcessor: 'stylus',
-      patterns: []
-    }
-  },
-	
-	configureWebpack: config => {
+	configureWebpack: (config) => {
 		config.resolve.alias = {
 			'@': path.resolve(__dirname, './src'),
 			_v: path.resolve(__dirname, './src/views'),
@@ -42,4 +39,4 @@ module.exports = {
 			_r: path.resolve(__dirname, './src/request')
 		}
 	}
-}
+}

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