Procházet zdrojové kódy

Merge branch 'feature' into develop

scorpio před 2 roky
rodič
revize
b8dfd3e87f

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "echarts": "^5.4.1",
     "element-plus": "^2.2.9",
     "js-base64": "^3.7.2",
+    "js-file-download": "^0.4.12",
     "js-md5": "^0.7.3",
     "npm": "^8.17.0",
     "nprogress": "^0.2.0",

+ 117 - 106
src/api/contract/index.js

@@ -1,110 +1,121 @@
 import fetch from '../fetch.js'
 
 export default {
-    /**
-     * 合同管理相关借口
-     * @returns {Promise<unknown>}
-     */
-    contractList(params) {
-        // 合同列表
-        return fetch(
-            '/blade-project-manage-v2/contracts-manage/v2/page',
-            params,
-            'post'
-        )
-    },
-    /**
-     * 详情
-     * @param params
-     */
-    detail(params) {
-        return fetch(
-            '/blade-project-manage-v2/contracts-manage/v2/detail',
-            params,
-            'post'
-        )
-    },
-    /**
-     * 台账列表
-     * @param params
-     */
-    ledgerList(params) {
-        return fetch(
-            '/blade-project-manage-v2/accountinformation/list',
-            params,
-            'get'
-        )
-    },
-    /**
-     * 新增台账
-     * @param params
-     */
-    ledgerAdd(params) {
-        return fetch(
-            '/blade-project-manage-v2/accountinformation/save',
-            params,
-            'post',
-            'json'
-        )
-    },
-    /**
-     * 修改台账
-     * @param params
-     * @returns {Promise<unknown>}
-     */
-    ledgerUpdate(params) {
-        return fetch(
-            '/blade-project-manage-v2/accountinformation/update',
-            params,
-            'post',
-            'json'
-        )
-    },
-    /**
-     * 删除凭证
-     * @param params
-     */
-    voucherDel(params) {
-        return fetch(
-            '/blade-project-manage-v2/accountinformationfile/remove',
-            params,
-            'post',
-        )
-    },
-    /**
-     * 删除合同
-     * @param params
-     * @returns {Promise<unknown>}
-     */
-    contractRemove(params) {
-        return fetch(
-            '/blade-project-manage-v2/contracts-manage/v2/delete-contracts',
-            params,
-            'post'
-        )
-    },
-    /**
-     * 删除台账
-     * @param params
-     * @returns {Promise<unknown>}
-     */
-    remove(params) {
-        return fetch(
-            '/blade-project-manage-v2/accountinformation/remove',
-            params,
-            'post'
-        )
-    },
-    /**
-     * 更新合同信息
-     * @returns {Promise | Promise<unknown>}
-     */
-    contractUpdate(params) {
-        return fetch(
-            '/blade-project-manage-v2/contracts-manage/v2/submit',
-            params,
-            'post',
-            'json'
-        )
-    }
+  /**
+   * 合同管理相关借口
+   * @returns {Promise<unknown>}
+   */
+  contractList(params) {
+    // 合同列表
+    return fetch(
+      '/blade-project-manage-v2/contracts-manage/v2/page',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 详情
+   * @param params
+   */
+  detail(params) {
+    return fetch(
+      '/blade-project-manage-v2/contracts-manage/v2/detail',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 台账列表
+   * @param params
+   */
+  ledgerList(params) {
+    return fetch(
+      '/blade-project-manage-v2/accountinformation/list',
+      params,
+      'get'
+    )
+  },
+  /**
+   * 新增台账
+   * @param params
+   */
+  ledgerAdd(params) {
+    return fetch(
+      '/blade-project-manage-v2/accountinformation/save',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 修改台账
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  ledgerUpdate(params) {
+    return fetch(
+      '/blade-project-manage-v2/accountinformation/update',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 删除凭证
+   * @param params
+   */
+  voucherDel(params) {
+    return fetch(
+      '/blade-project-manage-v2/accountinformationfile/remove',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 删除合同
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  contractRemove(params) {
+    return fetch(
+      '/blade-project-manage-v2/contracts-manage/v2/delete-contracts',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 删除台账
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  remove(params) {
+    return fetch(
+      '/blade-project-manage-v2/accountinformation/remove',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 更新合同信息
+   * @returns {Promise | Promise<unknown>}
+   */
+  contractUpdate(params) {
+    return fetch(
+      '/blade-project-manage-v2/contracts-manage/v2/submit',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 选择关联合同文件
+   */
+  linkContract(params) {
+    return fetch(
+      '/blade-project-manage-v2/contracts-manage/v2/contract-save-file',
+      params,
+      'post',
+      'json'
+    )
+  }
 }

+ 25 - 0
src/api/dispatch/index.js

@@ -47,5 +47,30 @@ export default {
       {},
       'blob'
     )
+  },
+  /**
+   * 关联文件
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  linkFile(params) {
+    return fetch(
+      '/blade-project-manage-v2/project-dispatch/v2/save-file',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 删除关联文件
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  removeFile(params) {
+    return fetch(
+      '/blade-project-manage-v2/project-dispatch/v2/delete-file',
+      params,
+      'post'
+    )
   }
 }

+ 41 - 1
src/api/resource/index.js

@@ -42,6 +42,28 @@ export default {
       'json'
     )
   },
+  /**
+   * 文件覆盖
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  fileCover(params) {
+    // 上传(新增)文件
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/coverFile',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 文件搜索
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  fileSearch(params) {
+    return fetch('/blade-project-manage-v2/folder/v2/findFileList', params)
+  },
   /**
    * 获取文件夹下面的文件及文件夹
    * @param params
@@ -74,7 +96,9 @@ export default {
       '/blade-project-manage-v2/folder/v2/fileFile',
       params,
       'post',
-      'json'
+      'json',
+      {},
+      'blob'
     )
   },
   /**
@@ -96,5 +120,21 @@ export default {
       'post',
       'json'
     )
+  },
+  /**
+   * 详情
+   * @param id
+   * @returns {Promise<unknown>}
+   */
+  fileDetail(id) {
+    return fetch('/wutong-library/library/detail/file/' + id)
+  },
+  /**
+   * 删除文件
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  fileDel(params) {
+    return fetch('/blade-project-manage-v2/folder/v2/remove', params, 'post')
   }
 }

+ 27 - 13
src/components/file-way/index.vue

@@ -1,18 +1,28 @@
 <template>
-  <div class="flex flex-center flex-justify-start">
-    <el-button text type="primary" size="mini" @click="goBefore"
-      >返回上一层
-    </el-button>
-    <el-divider direction="vertical" border-style="dashed" />
-    <el-button text type="primary" size="mini" @click="goHome"
-      >全部文件
-    </el-button>
-    <div v-if="data" class="flex flex-center">
-      <el-icon>
-        <ArrowRight />
-      </el-icon>
-      <el-button text type="primary" size="mini">{{ data.title }}</el-button>
+  <div class="flex flex-center flex-justify-between">
+    <div class="flex flex-center flex-justify-start">
+      <el-button text type="primary" size="mini" @click="goBefore"
+        >返回上一层
+      </el-button>
+      <el-divider direction="vertical" border-style="dashed" />
+      <el-button text type="primary" size="mini" @click="goHome"
+        >全部文件
+      </el-button>
+      <div v-if="data" class="flex flex-center">
+        <el-icon>
+          <ArrowRight />
+        </el-icon>
+        <el-button text type="primary" size="mini">{{ data.title }}</el-button>
+      </div>
     </div>
+    <el-tooltip content="刷新">
+      <el-button
+        icon="Refresh"
+        circle
+        v-if="refreshBtn"
+        @click="this.$emit('refresh')"
+      />
+    </el-tooltip>
   </div>
 </template>
 
@@ -24,6 +34,10 @@ export default {
       default: {
         title: ''
       }
+    },
+    refreshBtn: {
+      type: Boolean,
+      default: false
     }
   },
   watch: {

+ 45 - 7
src/components/filepicker/index.vue

@@ -1,13 +1,39 @@
 <template>
   <div>
-    <el-button type="primary" icon="Upload" @click="show = true"
-      >文件上传</el-button
-    >
+    <div v-if="command === null || command.length === 0">
+      <el-button
+        v-if="menuBtn"
+        text
+        type="primary"
+        icon="Upload"
+        @click="show = true"
+        >上传</el-button
+      >
+      <el-button v-else type="primary" icon="Upload" @click="show = true"
+        >文件上传</el-button
+      >
+    </div>
+    <el-dropdown v-else @command="openFile" class="ml-10">
+      <el-button type="primary">
+        文件上传
+        <el-icon class="el-icon--right">
+          <arrow-down />
+        </el-icon>
+      </el-button>
+      <template #dropdown>
+        <el-dropdown-menu>
+          <el-dropdown-item v-for="(item, index) in command" :command="index">
+            {{ item.label }}
+          </el-dropdown-item>
+        </el-dropdown-menu>
+      </template>
+    </el-dropdown>
     <el-dialog
       v-model="show"
       width="1200px"
       :show-close="false"
       :close-on-click-modal="false"
+      append-to-body
       @close="onClose"
     >
       <template #header>
@@ -105,7 +131,7 @@
             <el-button type="primary" plain @click="show = false"
               >取 消
             </el-button>
-            <el-button type="primary">确 定</el-button>
+            <el-button type="primary" @click="submit">确 定</el-button>
           </div>
         </div>
       </div>
@@ -126,12 +152,21 @@ export default {
   },
   props: {
     projectId: {
+      required: true,
       type: String,
       default: ''
     },
+    menuBtn: {
+      type: Boolean,
+      default: false
+    },
     max: {
       type: Number,
       default: 9
+    },
+    command: {
+      type: Array,
+      default: null
     }
   },
   watch: {
@@ -176,6 +211,8 @@ export default {
       option: {
         showMenu: false,
         showCheckBox: true,
+        folderChecked: false,
+        showCheckAll: false,
         height: 500,
         column: [
           {
@@ -232,7 +269,6 @@ export default {
             } else {
               this.stageId = this.stageList[0].id
             }
-            console.log(this.stageId)
           }
         })
     },
@@ -240,7 +276,6 @@ export default {
      * 获取全部文件
      */
     getFolderList() {
-      console.log('dddddd')
       this.loading = true
       const row = {
         stageId: this.stageId,
@@ -303,7 +338,6 @@ export default {
     },
     rowClick(res) {
       this.currentRow = res
-      console.log(this.currentRow)
       const tmp = this.list.find(ele => ele.id === res.id)
       this.parentId = tmp.id
       if (tmp && tmp.type !== 2) {
@@ -343,6 +377,10 @@ export default {
       } else {
         console.log('top')
       }
+    },
+    submit() {
+      this.show = false
+      this.$emit('submit', this.selectedList)
     }
   }
 }

+ 74 - 4
src/components/upload-file/index.vue

@@ -34,6 +34,24 @@
         </div>
       </div>
     </div>
+    <el-dialog v-model="show" title="文件名重复" width="400px">
+      <div class="flex flex-center flex-col">
+        <el-icon color="#409eff" :size="70"><WarningFilled /></el-icon>
+        <span class="mt-20">
+          此位置已经存在名称为
+          <span class="main-color">{{
+            repeatList.map(ele => ele.title).join(',')
+          }}</span>
+          的文件。您要使用当前文件进行替换吗?
+        </span>
+        <div class="mt-20 padding-top">
+          <el-button type="primary" plain @click="show = false"
+            >取 消</el-button
+          >
+          <el-button type="primary" @click="reset">替 换</el-button>
+        </div>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -81,6 +99,7 @@ export default {
   },
   data() {
     return {
+      show: false,
       headers: {
         Authorization: `Basic ${Base64.encode(
           `${website.clientId}:${website.clientSecret}`
@@ -89,7 +108,9 @@ export default {
       },
       drawer: false,
       fileList: [],
-      resultList: []
+      resultList: [],
+      repeatList: [],
+      params: null
     }
   },
   methods: {
@@ -106,11 +127,35 @@ export default {
         this.saveFile()
       }
     },
+    /**
+     * 保存到library
+     */
+    async saveLibrary() {
+      this.resultList
+        .filter(ele => api.offices.includes(ele.suffix))
+        .forEach(ele => {
+          const item = {
+            category: 4,
+            fileId: ele.id,
+            parentId: this.parentId,
+            projectId: this.projectId,
+            stageId: this.stageId,
+            type: 1,
+            title: ele.originalFileName,
+            content: ''
+          }
+          this.$api.common.submit(item).then(res => {
+            if (res.code === 200) {
+              console.log(res)
+            }
+          })
+        })
+    },
     /**
      * 保存文件
      */
     saveFile() {
-      const data = this.resultList.map(e => {
+      this.params = this.resultList.map(e => {
         return {
           fileId: e.id,
           parentId: this.parentId,
@@ -118,11 +163,36 @@ export default {
           stageId: this.stageId
         }
       })
-      // fixme 重复文件未处理
-      this.$api.resource.fileSave(data).then(res => {
+      this.$api.resource.fileSave(this.params).then(res => {
+        if (res.code === 200) {
+          console.log(typeof res.data)
+          if (res.msg.indexOf('存在重名文件,是否覆盖') === -1) {
+            this.saveLibrary()
+            this.$message.success('文件上传完成')
+            this.$emit('on-success', this.resultList)
+            setTimeout(() => {
+              this.drawer = false
+            }, 3000)
+          } else {
+            // 重名
+            this.repeatList = res.data
+            this.show = true
+          }
+        }
+      })
+    },
+    reset() {
+      this.show = false
+      this.$api.resource.fileCover(this.params).then(res => {
         if (res.code === 200) {
+          this.saveLibrary()
           this.$message.success('文件上传完成')
           this.$emit('on-success', this.resultList)
+          setTimeout(() => {
+            this.drawer = false
+          }, 3000)
+        } else {
+          this.$message.error(res.msg)
         }
       })
     }

+ 1 - 1
src/layout/index.vue

@@ -151,7 +151,7 @@ export default {
   .mp {
     top: 200px;
     right: 0;
-    z-index: 999;
+    z-index: 99;
     border-radius: 4px;
     position: fixed;
     background-color: white;

+ 12 - 10
src/page/404.vue

@@ -1,10 +1,14 @@
 <template>
-  <div class='full-screen flex flex-center'>
-    <img src='https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/4e993b2d27a544a893ddbc8f60cc2a65.svg'/>
-    <div class='ml-20'>
-      <h1 style='font-size: 82px' class='bold'>404</h1>
-      <div class='mt-10 bold'>抱歉,你访问的页面不存在</div>
-      <el-button type='primary' class='mt-20' @click='goHome'>返回首页</el-button>
+  <div class="full-screen flex flex-center">
+    <img
+      src="https://wutong-1302848345.cos.ap-chengdu.myqcloud.com/wtzx/4e993b2d27a544a893ddbc8f60cc2a65.svg"
+    />
+    <div class="ml-20">
+      <h1 style="font-size: 82px" class="bold">404</h1>
+      <div class="mt-10 bold">抱歉,您访问的页面不存在</div>
+      <el-button type="primary" class="mt-20" @click="goHome"
+        >返回首页</el-button
+      >
     </div>
   </div>
 </template>
@@ -21,13 +25,11 @@
 export default {
   name: '404',
   methods: {
-    goHome () {
+    goHome() {
       this.$router.push('/')
     }
   }
 }
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 34 - 18
src/views/contract/index.vue

@@ -1,7 +1,7 @@
 <template>
   <el-card shadow="hover">
     <el-form v-model="params" class="full-width" label-width="120px">
-      <div class="flex">
+      <div class="flex flex-center">
         <div class="flex flex-center mt-15 mr-10">
           <el-form-item label="关键字" class="full-width">
             <el-input
@@ -19,16 +19,6 @@
               clearable
             />
           </el-form-item>
-          <el-form-item class="full-width" label="合同类别">
-            <el-select v-model="params.type" clearable>
-              <el-option
-                v-for="item in typelist"
-                :key="item.dictKey"
-                :label="item.dictValue"
-                :value="item.dictKey"
-              />
-            </el-select>
-          </el-form-item>
           <el-form-item class="full-width" label="合同状态">
             <el-select v-model="params.status" clearable>
               <el-option
@@ -40,12 +30,12 @@
             </el-select>
           </el-form-item>
         </div>
+        <div class="flex flex-justify-end ml-20">
+          <base-button type="0" title="重置" icon="Refresh" @click="clearUp" />
+          <base-button class="ml-20" @click="onLoad" />
+        </div>
       </div>
     </el-form>
-    <div class="flex flex-justify-end ml-20">
-      <base-button type="0" title="重置" icon="Refresh" @click="clearUp" />
-      <base-button class="ml-20" @click="onLoad" />
-    </div>
     <avue-crud
       :option="option"
       :data="data"
@@ -62,7 +52,14 @@
         <div>{{ row.fileFolder.title }}</div>
       </template>
       <template #menu-left>
-        <div class="main-color ml-10 bold font-15">金额单位:万元</div>
+        <div class="flex flex-center">
+          <div class="main-color ml-10 mr-20 bold font-15">金额单位:万元</div>
+          <filepicker
+            :project-id="projectId"
+            @submit="selection"
+            :command="command"
+          />
+        </div>
       </template>
     </avue-crud>
   </el-card>
@@ -76,14 +73,20 @@ meta: { layout: 'empty','path':'/home/details','title':'资料管理','showMsg'
 </route>
 <script>
 import BaseButton from '@/components/base-button.vue'
+import filepicker from '@/components/filepicker/index.vue'
 
 export default {
-  components: { BaseButton },
+  components: { BaseButton, filepicker },
   data() {
     return {
       projectId: '',
       form: {},
       data: [],
+      command: [
+        {
+          label: '33'
+        }
+      ],
       option: {
         align: 'center',
         menuAlign: 'center',
@@ -93,7 +96,6 @@ export default {
         editBtn: false,
         viewBtn: true,
         delBtn: true,
-        refreshBtn: false,
         columnBtn: false,
         labelWidth: 140,
         border: true,
@@ -243,6 +245,20 @@ export default {
     },
     refreshChange() {
       this.onLoad()
+    },
+    selection(list) {
+      const tmps = list.map(ele => {
+        return {
+          fileId: ele.id,
+          projectId: ele.projectId,
+          title: ele.title
+        }
+      })
+      this.$api.contract.linkContract(tmps).then(res => {
+        if (res.code === 200) {
+          this.refreshChange()
+        }
+      })
     }
   }
 }

+ 79 - 67
src/views/home/component/dispatch.vue

@@ -10,27 +10,27 @@
           <span class="bold font-18 main-color">进度描述</span>
           <div class="flex flex-center">
             <base-button
-                type="0"
-                title="批量导出"
-                icon="upload"
-                @click="exportFile"
+              type="0"
+              title="批量导出"
+              icon="upload"
+              @click="exportFile"
             />
             <base-button
-                v-if="projectInfo.can_update"
-                class="ml-10"
-                :title="btnTitle"
-                icon="upload"
-                @click="edit"
+              v-if="projectInfo.can_update"
+              class="ml-10"
+              :title="btnTitle"
+              icon="upload"
+              @click="edit"
             />
           </div>
         </div>
         <div class="mt-20">
           <el-input
-              v-model="progress"
-              :rows="10"
-              type="textarea"
-              :disabled="btnTitle === '编辑'"
-              placeholder="填写项目进度信息"
+            v-model="progress"
+            :rows="10"
+            type="textarea"
+            :disabled="btnTitle === '编辑'"
+            placeholder="填写项目进度信息"
           />
         </div>
       </div>
@@ -40,40 +40,38 @@
           <span class="bold font-18 main-color">相关文件</span>
         </div>
         <avue-crud
-            ref="crud"
-            v-model="form"
-            v-model:page="page"
-            :data="data"
-            :option="option"
-            :table-loading="loading"
-            class="curd"
-            :before-open="beforeOpen"
-            @row-del="rowDel"
+          ref="crud"
+          v-model="form"
+          v-model:page="page"
+          :data="data"
+          :option="option"
+          :table-loading="loading"
+          class="curd"
+          :before-open="beforeOpen"
+          @row-del="rowDel"
         >
-          <template #menu="{ row }">
-            <el-button
-                v-if="projectInfo.can_update"
-                icon="Upload"
-                type="primary"
-                text
-                @click="openFile(row)"
-            >
-              上传
-            </el-button>
-            <el-button
+          <template #menu="{ row, index }">
+            <div class="flex flex-center">
+              <filepicker
+                :project-id="projectId"
+                :menu-btn="true"
+                @submit="selection($event, index + 1)"
+              />
+              <el-button
                 text
                 type="primary"
                 icon="Download"
                 @click="fileDownload(row)"
-            >下载
-            </el-button>
+                >下载
+              </el-button>
+            </div>
           </template>
           <template #menu-right>
             <div class="full-width">
               <el-button
-                  icon="el-icon-refresh"
-                  circle
-                  @click="detail"
+                icon="el-icon-refresh"
+                circle
+                @click="detail"
               ></el-button>
             </div>
           </template>
@@ -89,34 +87,27 @@
         <div class="flex flex-center flex-justify-between mt-20">
           <span class="bold font-18 main-color">施工现场图</span>
           <div class="flex flex-center">
-            <base-button
-                type="0"
-                v-if="projectInfo.can_update"
-                title="上传"
-                icon="upload"
-                @click="
-                openFile({
-                  dispatchType: 4
-                })
-              "
+            <filepicker
+              :project-id="projectId"
+              @submit="selection($event, 4)"
             />
           </div>
         </div>
         <div class="mt-20">
-          <el-empty description="暂无施工现场图" v-if="srcList.length === 0"/>
+          <el-empty description="暂无施工现场图" v-if="srcList.length === 0" />
           <el-carousel
-              v-else
-              autoplay
-              :interval="4000"
-              type="card"
-              height="400px"
-              :initial-index="0"
+            v-else
+            autoplay
+            :interval="4000"
+            type="card"
+            height="400px"
+            :initial-index="0"
           >
             <el-carousel-item v-for="(item, index) in srcList" :key="item">
               <el-image
-                  :src="item"
-                  fit="cover"
-                  @click="showImageView(item, index)"
+                :src="item"
+                fit="cover"
+                @click="showImageView(item, index)"
               />
             </el-carousel-item>
           </el-carousel>
@@ -124,10 +115,10 @@
       </div>
     </div>
     <el-image-viewer
-        v-if="showImage"
-        :url-list="preList"
-        :initial-index="imageIndex"
-        @close="showImage = false"
+      v-if="showImage"
+      :url-list="preList"
+      :initial-index="imageIndex"
+      @close="showImage = false"
     />
   </basic-container>
 </template>
@@ -136,10 +127,11 @@
 import BasicContainer from '@/components/basic-container/main.vue'
 import baseButton from '@/components/base-button.vue'
 import api from '@/api/index.js'
+import filepicker from '@/components/filepicker/index.vue'
 
 export default {
   name: 'dispatch',
-  components: {BasicContainer, baseButton},
+  components: { BasicContainer, baseButton, filepicker },
   props: {
     projectInfo: {
       type: Object,
@@ -210,7 +202,7 @@ export default {
         tip: false,
         columnBtn: false,
         selection: false,
-        editBtn: true,
+        editBtn: false,
         editBtnText: '打开',
         editBtnIcon: 'FolderOpened',
         addBtn: false,
@@ -369,7 +361,7 @@ export default {
       if (api.offices.includes(item.fileFolder.suffix)) {
         const routeData = this.$router.resolve({
           path: '/home/file_detail',
-          query: {id: item.fileFolder.fileId}
+          query: { id: item.fileFolder.fileId }
         })
         window.open(routeData.href, '_blank')
       } else {
@@ -388,7 +380,7 @@ export default {
         cancelButtonText: '取消',
         type: 'warning'
       }).then(() => {
-        this.$api.project.fileRemove({ids: row.fileId, type: 2}).then(res => {
+        this.$api.dispatch.removeFile({ ids: row.id, type: 2 }).then(res => {
           if (res.code === 200) {
             this.$message.success(res.msg)
             this.detail()
@@ -433,6 +425,26 @@ export default {
         this.$message.success('资料打包中,完成后系统将会发送通知消息给您')
         this.loading = false
       })
+    },
+    /**
+     * 选择关联文件
+     * @param list
+     */
+    selection(list, type) {
+      const tmps = list.map(e => {
+        return {
+          projectId: this.projectId,
+          year: this.year,
+          month: this.month,
+          fileId: e.id,
+          type
+        }
+      })
+      this.$api.dispatch.linkFile(tmps).then(res => {
+        if (res.code === 200) {
+          this.detail()
+        }
+      })
     }
   }
 }

+ 18 - 4
src/views/resource/component/archives.vue

@@ -1,7 +1,7 @@
 <template>
   <div>
-    <el-button class="ml-10" type="primary" text @click="this.show = true"
-      >归档
+    <el-button class="ml-10" type="primary" text @click="this.show = true">
+      {{ row.fileStatus === 1 ? '已归档' : '归档' }}
     </el-button>
     <el-dialog
       v-model="show"
@@ -171,6 +171,14 @@
           >
             <el-input v-model="from.fileLocation" placeholder="输入归档位置" />
           </el-form-item>
+          <el-form-item class="full-width" label="卷内张数:" prop="totalPage">
+            <el-input
+              v-model="from.totalPage"
+              type="Number"
+              placeholder="输入卷内张数"
+            />
+          </el-form-item>
+          <el-form-item class="full-width"> </el-form-item>
         </div>
         <div class="flex flex-center mt-20 mb-20">
           <base-button
@@ -197,6 +205,10 @@ import baseButton from '@/components/base-button.vue'
 export default {
   components: { baseButton },
   props: {
+    row: {
+      type: Object,
+      default: {}
+    },
     folderId: {
       type: String,
       default: ''
@@ -234,7 +246,8 @@ export default {
         quanzongNum: '', // 全宗号
         recordsNum: '', // 案卷号
         retentionPeriod: '1', // 保管期限
-        genus: '1' // 属别
+        genus: '1', // 属别
+        totalPage: ''
       },
       genus: [],
       category: [],
@@ -375,7 +388,8 @@ export default {
         quanzongNum: '', // 全宗号
         recordsNum: '', // 案卷号
         retentionPeriod: '1', // 保管期限
-        genus: '1' // 属别
+        genus: '1', // 属别
+        totalPage: ''
       }
     }
   }

+ 53 - 0
src/views/resource/component/defile.vue

@@ -0,0 +1,53 @@
+<template>
+  <div>
+    <el-button text type="primary" @click="show = true">删 除</el-button>
+    <el-dialog v-model="show" title="确定删除" width="400px">
+      <div class="flex flex-center flex-col">
+        <el-icon color="#409eff" :size="70"><WarningFilled /></el-icon>
+        <span class="mt-20"
+          >确定删除所选的文件吗?<br />删除的文件可在 10天
+          内通过回收站还原</span
+        >
+        <div class="mt-20 padding-top">
+          <el-button type="primary" plain @click="show = false"
+            >取 消</el-button
+          >
+          <el-button type="primary" @click="del">确 定</el-button>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    row: {
+      type: Object,
+      default: null
+    }
+  },
+  data() {
+    return {
+      show: false
+    }
+  },
+  methods: {
+    del() {
+      this.$api.resource.fileDel({ ids: this.row.id }).then(res => {
+        this.show = false
+        if (res.code === 200) {
+          this.$message.success(res.msg)
+          this.$emit('row-del')
+        } else {
+          this.$confirm(res.msg, {
+            type: 'warning'
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 112 - 0
src/views/resource/component/preview.vue

@@ -0,0 +1,112 @@
+<template>
+  <div>
+    <el-button type="primary" text @click="openFile">查看</el-button>
+    <el-image-viewer
+      v-if="showImage"
+      :url-list="preList"
+      @close="showImage = false"
+    />
+    <el-drawer v-model="show" :size="1200">
+      <template #title>
+        <h4
+          class="ml-20 black flex flex-center flex-justify-start full-width font-16 bold"
+        >
+          {{ data ? data.title : '' }}
+        </h4>
+      </template>
+      <div>
+        <div v-if="data">
+          <el-empty
+            v-if="data.imgs.length === 0"
+            style="height: 90vh"
+            description="暂时无法预览,您可以点击 下载 按钮,下载原文件 "
+            class="full-height flex flex-center"
+          />
+          <div v-else v-for="item in data.imgs" :key="item.id">
+            <img :src="item.filePath" />
+          </div>
+        </div>
+        <div class="bottom flex flex-center flex-justify-center">
+          <el-button type="primary" icon="Download" @click="downloadClick"
+            >下 载</el-button
+          >
+          <el-button type="primary" icon="Share">分享</el-button>
+        </div>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import api from '@/api/index.js'
+
+export default {
+  props: {
+    info: {
+      type: Object,
+      default: null
+    }
+  },
+  watch: {
+    show: {
+      handler(val) {
+        if (val) {
+          this.detail()
+        }
+      },
+      immediate: true
+    }
+  },
+  data() {
+    return {
+      show: false,
+      data: null,
+      preList: [],
+      showImage: false
+    }
+  },
+  methods: {
+    openFile() {
+      if (api.offices.includes(this.info.suffix)) {
+        this.show = true
+      } else {
+        this.preList.length = 0
+        this.preList.push(this.info.url)
+        this.showImage = true
+      }
+    },
+    detail() {
+      this.$api.resource.fileDetail(this.info.fileId).then(res => {
+        if (res.code === 200) {
+          this.data = res.data
+          console.log(this.data)
+        } else {
+          console.log(res)
+        }
+      })
+    },
+    async downloadClick() {
+      const link = document.createElement('a')
+      link.href = this.info.url
+      link.download = this.info.title
+      link.click()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.bottom {
+  position: fixed;
+  bottom: 0;
+  box-shadow: -2px 0px 2px rgba(0, 0, 0, 0.1);
+  background-color: white;
+  height: 30px;
+  padding: 10px;
+  width: 1200px;
+  border: #e6e8ed solid 1px;
+}
+:deep(.el-drawer__body) {
+  padding: 0;
+}
+</style>

+ 1 - 1
src/views/resource/component/row1.vue

@@ -7,7 +7,7 @@
       <el-checkbox
         v-if="showCheckBox"
         v-model="info.checked"
-        :disabled="folderChecked"
+        :disabled="folderChecked === false && row.type === 2"
         class="padding-right"
         @change="rowChecked(row)"
       />

+ 160 - 0
src/views/resource/component/search.vue

@@ -0,0 +1,160 @@
+<template>
+  <div>
+    <el-icon size="26" @click="show = true">
+      <Search />
+    </el-icon>
+    <el-dialog
+      v-model="show"
+      title="文件搜索"
+      width="860"
+      :close-on-click-modal="false"
+      @close="closeDialog"
+    >
+      <div class="flex flex-center flex-col padding" style="margin-top: -20px">
+        <div class="full-width flex flex-center">
+          <el-input
+            v-model="searchForm.keyword"
+            style="width: 100%"
+            clearable
+            placeholder="输入关键字进行文件搜索"
+            @clear="clearList"
+            @keyup.enter="searchList"
+          />
+          <base-button class="ml-20" @click="searchList" />
+        </div>
+        <div
+          v-loading="loading"
+          class="full-width mt-20 flex flex-align-start flex-col hide-scrollbar"
+          style="min-height: 30vh; overflow-y: auto"
+        >
+          <div class="full-width" v-if="resultList && resultList.length === 0">
+            <el-empty></el-empty>
+          </div>
+          <div
+            v-else
+            class="flex flex-align-center border-bottom full-width"
+            v-for="item in resultList"
+            :key="item.id"
+            @click="goFoleDetail(item)"
+          >
+            <img
+              v-if="['doc', 'docx'].includes(item.suffix)"
+              src="../../../assets/svg/folder/doc.svg"
+              class="icon1"
+            />
+            <img
+              v-else-if="['png', 'jpg', 'jpeg'].includes(item.suffix)"
+              src="../../../assets/svg/folder/other.svg"
+              class="icon1"
+            />
+            <img
+              v-else-if="item.suffix === 'pdf'"
+              src="../../../assets/svg/folder/pdf.svg"
+              class="icon1"
+            />
+            <img
+              v-else-if="item.suffix === 'xlsx'"
+              src="../../../assets/svg/folder/xls.svg"
+              class="icon1"
+            />
+            <span class="bold ml-10">{{ item.title }}</span>
+          </div>
+        </div>
+        <div class="flex flex-align-start mt-15 border-top full-width">
+          <span class="grey-9 mt-15"
+            >共计查询到<span class="ml-5 mr-5 font-16 bold main-color">{{
+              total ? total : 0
+            }}</span
+            >个相关文件</span
+          >
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import baseButton from '@/components/base-button.vue'
+
+export default {
+  components: { baseButton },
+  props: {
+    stageId: {
+      type: String,
+      required: true,
+      default: ''
+    },
+    folderId: {
+      type: String,
+      required: true,
+      default: ''
+    }
+  },
+  watch: {
+    stageId: {
+      handler(val) {
+        this.searchForm.stageId = val
+      },
+      immediate: true
+    },
+    folderId: {
+      handler(val) {
+        this.searchForm.fileFolderId = val
+      },
+      immediate: true
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      show: false,
+      searchForm: {
+        fileFolderId: '',
+        keyword: '',
+        stageId: ''
+      },
+      resultList: [],
+      total: ''
+    }
+  },
+  methods: {
+    searchList() {
+      this.loading = true
+      setTimeout(() => {
+        this.$api.resource.fileSearch(this.searchForm).then(res => {
+          if (res.code === 200) {
+            this.loading = false
+            this.resultList = res.data
+            this.total = res.data.length
+          } else {
+            this.$message.error(res.msg)
+          }
+        })
+      }, 800)
+    },
+    clearList() {
+      this.resultList = []
+      this.total = 0
+    },
+    goFoleDetail(item) {
+      const routeData = this.$router.resolve(
+        '/home/file_detail?id=' + item.fileId
+      )
+      window.open(routeData.href, '_blank')
+      this.show = false
+    },
+    closeDialog() {
+      this.searchForm.keyword = ''
+      this.resultList = []
+      this.total = 0
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.icon1 {
+  width: 50px;
+  height: 50px;
+}
+</style>

+ 30 - 6
src/views/resource/component/xtable.vue

@@ -19,7 +19,7 @@
           :style="header.width ? `width:` + header.width + `px` : ''"
         >
           <el-checkbox
-            v-if="index === 0"
+            v-if="index === 0 && showCheckAll"
             class="ml-10"
             label=""
             @change="selection"
@@ -47,8 +47,12 @@
               class="nowrap menu flex flex-center"
               style="width: 280px"
             >
-              <el-button type="primary" text>查看</el-button>
-              <archives v-if="row.type === 2" :folder-id="row.id" />
+              <preview :info="row" v-if="row.type === 1" />
+              <archives
+                v-if="row.type === 2 && row.parentId === '0'"
+                :folder-id="row.id"
+                :row="row"
+              />
               <move
                 v-if="row.type === 1"
                 :project-id="row.projectId"
@@ -56,6 +60,7 @@
                 @on-success="refresh"
               />
               <slot name="menu" :row="row"></slot>
+              <defile :row="row" @row-del="refresh" />
             </div>
             <div
               v-else
@@ -69,6 +74,7 @@
                   :index="index"
                   :show-check-box="showCheckBox"
                   :folder-checked="folderChecked"
+                  :show-check-all="showCheckAll"
                   @click="rowClick(row)"
                 ></row1>
               </div>
@@ -97,12 +103,15 @@
 import row1 from '@/views/resource/component/row1.vue'
 import move from '@/views/resource/component/move.vue'
 import archives from '@/views/resource/component/archives.vue'
-
+import preview from '@/views/resource/component/preview.vue'
+import defile from '@/views/resource/component/defile.vue'
 export default {
   components: {
     row1,
     move,
-    archives
+    archives,
+    preview,
+    defile
   },
   props: {
     page: {
@@ -113,6 +122,10 @@ export default {
         total: 0
       }
     },
+    topFolder: {
+      type: Boolean,
+      default: true
+    },
     data: {
       type: Array,
       default: null
@@ -137,16 +150,25 @@ export default {
         const menu = {
           label: '操作'
         }
+        // 是否显示列表操作栏
         this.showMenu =
           this.option.showMenu === undefined ? true : this.option.showMenu
+        // 文件夹前面的checkbox 是否默认不可以选择
         this.folderChecked =
           this.option.folderChecked === undefined
             ? false
             : this.option.folderChecked
+        // 是显示 选中框
         this.showCheckBox =
           this.option.showCheckBox === undefined
             ? false
             : this.option.showCheckBox
+        // 是否选择全选按钮
+        this.showCheckAll =
+          this.option.showCheckAll === undefined
+            ? true
+            : this.option.showCheckAll
+
         this.headers = val.column
         if (this.showMenu) {
           if (this.headers.findIndex(e => e.label === '操作') === -1) {
@@ -159,7 +181,8 @@ export default {
     selectedList: {
       handler(val) {
         this.$emit('selected', this.selectedList)
-      }
+      },
+      immediate: true
     }
   },
   data() {
@@ -167,6 +190,7 @@ export default {
       showMenu: true,
       showCheckBox: false,
       folderChecked: false,
+      showCheckAll: true,
       headers: [],
       selectedList: []
     }

+ 14 - 18
src/views/resource/index.vue

@@ -33,6 +33,7 @@
             <upload-file
               v-if="!top"
               @on-success="uploadSuccess"
+              :data="{ type: 1 }"
               :project-id="folderInfo.projectId"
               :stage-id="folderInfo.stageId"
               :parent-id="currentFolder !== null ? currentFolder.id : ''"
@@ -46,25 +47,20 @@
               >新建文件夹
             </el-button>
             <authorize class="ml-10" :list="selectedList" />
-            <filepicker
-              class="ml-10"
-              :project-id="folderInfo.projectId"
-              :stage-id="folderInfo.stageId"
-            />
           </div>
-          <div class="flex flex-center">
-            <span class="nowrap mr-10">文件搜索</span>
-            <el-input
-              v-model="folderInfo.keyword"
-              placeholder="输入文件关键字"
-              style="width: 100%"
+          <div class="flex flex-center main-color mr-10">
+            <search
+              :stage-id="folderInfo.stageId"
+              :folder-id="currentFolder ? currentFolder.id : ''"
             />
           </div>
         </div>
         <file-way
           :next="currentFolder"
+          :refresh-btn="true"
           @before="goBefore"
           @goHome="getFolderList"
+          @refresh="refreshData"
           class="mt-20"
         />
         <xtable
@@ -72,6 +68,7 @@
           :option="option"
           :loading="loading"
           :page="page"
+          :top-folder="top"
           @selected="selected"
           @row-click="getFileList"
           @current-change="currentChange"
@@ -80,7 +77,7 @@
         >
           <template #menu="{ row }">
             <el-button
-              v-if="row.type === 2"
+              v-if="row.type === 2 && row.fileStatus === 0"
               type="primary"
               text
               @click="renameFolder(row)"
@@ -110,7 +107,7 @@
 <route>
 {
 name: '资料管理',
-meta: { 'show': false }
+meta: { 'show': false, 'back':true}
 }
 </route>
 
@@ -119,9 +116,9 @@ import tipsCustom from '@/components/tips-custom/index.vue'
 import xtable from '@/views/resource/component/xtable.vue'
 import floder from '@/views/resource/component/floder.vue'
 import uploadFile from '@/components/upload-file/index.vue'
-import filepicker from '@/components/filepicker/index.vue'
 import fileWay from '@/components/file-way/index.vue'
 import authorize from '@/views/resource/component/authorize.vue'
+import search from '@/views/resource/component/search.vue'
 
 export default {
   components: {
@@ -129,9 +126,9 @@ export default {
     xtable,
     floder,
     uploadFile,
-    filepicker,
     fileWay,
-    authorize
+    authorize,
+    search
   },
 
   data() {
@@ -148,7 +145,7 @@ export default {
       data: [],
       option: {
         showCheckBox: false,
-        folderChecked: false,
+        folderChecked: true,
         column: [
           {
             label: '名称',
@@ -271,7 +268,6 @@ export default {
         .then(res => {
           if (res.code === 200) {
             this.stage = res.data
-
             const tmp = this.stage.find(ele => ele.isLastSelect === 1)
             if (tmp) {
               this.folderInfo.stageId = tmp.id

+ 5 - 0
yarn.lock

@@ -2384,6 +2384,11 @@ js-cookie@^3.0.1:
   resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc"
   integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==
 
+js-file-download@^0.4.12:
+  version "0.4.12"
+  resolved "https://registry.yarnpkg.com/js-file-download/-/js-file-download-0.4.12.tgz#10c70ef362559a5b23cdbdc3bd6f399c3d91d821"
+  integrity sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==
+
 js-md5@^0.7.3:
   version "0.7.3"
   resolved "https://registry.yarnpkg.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2"