소스 검색

Merge remote-tracking branch 'origin/feature' into feature

# Conflicts:
#	src/api/project/index.js
#	src/views/resource/component/floder.vue
scorpioyq 2 년 전
부모
커밋
1278caff45

+ 23 - 21
src/api/index.js

@@ -13,27 +13,29 @@ import search from './search/index.js'
 import dispatch from './dispatch/index.js'
 import store from './store/index.js'
 import msg from './msg/index.js'
-import contract from "@/api/contract/index.js";
-import role from "@/api/role/index.js";
+import contract from '@/api/contract/index.js'
+import role from '@/api/role/index.js'
+import resource from '@/api/resource/index.js'
 
 export default {
-    offices: ['pdf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'PDF'],
-    uploadPath: '/api/wutong-file/minio/file/upload', // 上传
-    login,
-    system,
-    project,
-    common,
-    recycle,
-    database,
-    task,
-    company,
-    inspect,
-    params,
-    invest,
-    search,
-    dispatch,
-    store,
-    msg,
-    contract,
-    role
+  offices: ['pdf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'PDF'],
+  uploadPath: '/api/wutong-file/minio/file/upload', // 上传
+  login,
+  system,
+  project,
+  common,
+  recycle,
+  database,
+  task,
+  company,
+  inspect,
+  params,
+  invest,
+  search,
+  dispatch,
+  store,
+  msg,
+  contract,
+  role,
+  resource
 }

+ 10 - 1
src/api/project/index.js

@@ -113,7 +113,11 @@ export default {
   },
   folderList(params) {
     // 阶段包含文件夹列表
-    return fetch('/blade-project-manage-v2/folder/v2/listByStageId', params)
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/listByStageId',
+      params,
+      'post'
+    )
   },
   sqRecord(params) {
     // 文件夹授权记录
@@ -131,6 +135,11 @@ export default {
     // 删除文件夹
     return fetch('/blade-project-manage-v2/folder/v2/remove', params, 'post')
   },
+  /**
+   * 新增文件夹
+   * @param params
+   * @returns {Promise | Promise<unknown>}
+   */
   folderAdd(params) {
     // 添加文件夹
     return fetch(

+ 67 - 0
src/api/resource/index.js

@@ -0,0 +1,67 @@
+import fetch from '../fetch.js'
+
+export default {
+  /**
+   * 文件夹创建、修改
+   * @param params
+   * @returns {Promise | Promise<unknown>}
+   */
+  folderAddUpdate(params) {
+    // 添加文件夹
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/submit',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 获取阶段下的文件夹
+   * @param params
+   * @returns {Promise | Promise<unknown>}
+   */
+  folderList(params) {
+    // 阶段包含文件夹列表
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/listByStageId',
+      params,
+      'post'
+    )
+  },
+  /**
+   * 文件上传接口
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  fileSave(params) {
+    // 上传(新增)文件
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/saveFile',
+      params,
+      'post',
+      'json'
+    )
+  },
+  /**
+   * 获取文件夹下面的文件及文件夹
+   * @param params
+   * @returns {Promise | Promise<unknown>}
+   */
+  fileList(params) {
+    // 文件夹里包含文件列表
+    return fetch('/blade-project-manage-v2/folder/v2/getListByFolderId', params)
+  },
+  /**
+   * 文件引用接口
+   * @param params
+   * @returns {Promise<unknown>}
+   */
+  filePicker(params) {
+    return fetch(
+      '/blade-project-manage-v2/folder/v2/queryPage',
+      params,
+      'post',
+      'json'
+    )
+  }
+}

+ 77 - 0
src/components/file-way/index.vue

@@ -0,0 +1,77 @@
+<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>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    next: {
+      type: Object,
+      default: {
+        title: ''
+      }
+    }
+  },
+  watch: {
+    next: {
+      handler(val) {
+        const item = {
+          id: val.id,
+          title: val.title,
+          projectId: val.projectId,
+          stageId: val.stageId,
+          parentId: val.parentId,
+          type: val.type
+        }
+        const tmp = this.list.find(ele => ele.id === item.id)
+        if (tmp === undefined || tmp === null) {
+          console.log(item.type)
+          if (item.type === 2) {
+            this.data = item
+            this.list.push(item)
+          }
+        }
+      },
+      immediate: false
+    }
+  },
+  data() {
+    return {
+      list: [],
+      data: null
+    }
+  },
+  methods: {
+    goHome() {
+      this.list.length = 0
+      this.data = null
+      this.$emit('goHome')
+    },
+    goBefore() {
+      this.list.pop()
+      if (this.list.length > 0) {
+        this.data = this.list[this.list.length - 1]
+        this.$emit('before', this.data)
+      } else {
+        this.goHome()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 367 - 0
src/components/filepicker/index.vue

@@ -0,0 +1,367 @@
+<template>
+  <div>
+    <el-button type="primary" @click="show = true">文件上传</el-button>
+    <el-dialog
+      v-model="show"
+      width="1200px"
+      :show-close="false"
+      :close-on-click-modal="false"
+      @close="onClose"
+    >
+      <template #header>
+        <div class="full-width flex flex-center flex-justify-between">
+          <h4>选择文件</h4>
+          <div class="flex flex-center flex-justify-end">
+            <div class="flex flex-center" v-show="activeName === '2'">
+              <span class="mr-10">项目阶段:</span>
+              <el-select
+                v-model="stageId"
+                remote
+                filterable
+                clearable
+                placeholder="筛选项目阶段"
+                style="width: 200px"
+                @change="stageChange"
+              >
+                <el-option
+                  v-for="item in stageList"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+                >
+                </el-option>
+              </el-select>
+              <upload-file
+                class="ml-10"
+                btn-text="本地上传"
+                :max="9"
+                v-if="!topFolder"
+                :project-id="projectId"
+                :stage-id="stageId"
+                :parent-id="parentId"
+                @on-success="uploadSuccess"
+              />
+            </div>
+            <el-button
+              type="info"
+              class="ml-10"
+              circle
+              icon="Close"
+              @click="show = false"
+            >
+            </el-button>
+          </div>
+        </div>
+      </template>
+      <div class="flex flex-justify-start flex-align-start flex-col">
+        <div class="full-width flex">
+          <el-tabs
+            v-model="activeName"
+            tab-position="left"
+            @tab-change="tabClick"
+          >
+            <el-tab-pane label="最近上传" name="1"></el-tab-pane>
+            <el-tab-pane label="全部文件" name="2"></el-tab-pane>
+            <el-tab-pane label="要件" name="3"></el-tab-pane>
+            <el-tab-pane label="合同" name="4"></el-tab-pane>
+          </el-tabs>
+          <div class="area">
+            <div class="full-width flex flex-center flex-justify-start ml-20">
+              <file-way
+                v-if="activeName === '2'"
+                :next="currentRow ? currentRow : ''"
+                @before="goBefore"
+                @goHome="getFolderList"
+              />
+              <div class="tips flex flex-center flex-justify-start" v-else>
+                <el-icon class="mr-10" color="#409eff" :size="20"
+                  ><WarningFilled
+                /></el-icon>
+                {{ tips }}
+              </div>
+            </div>
+            <div class="files full-height">
+              <xtable
+                :data="list"
+                :option="option"
+                :loading="loading"
+                :total="page.total"
+                :max="max"
+                @selected="selected"
+                @row-click="rowClick"
+                @current-change="currentChange"
+              />
+            </div>
+          </div>
+        </div>
+        <div
+          class="full-width flex flex-center flex-justify-between"
+          style="margin-top: 80px"
+        >
+          <span class="bold">已选择 {{ selectedList.length }}/9 项</span>
+          <div>
+            <el-button type="primary" plain @click="show = false"
+              >取 消
+            </el-button>
+            <el-button type="primary">确 定</el-button>
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import xtable from '@/views/resource/component/xtable.vue'
+import uploadFile from '@/components/upload-file/index.vue'
+import fileWay from '@/components/file-way/index.vue'
+
+export default {
+  components: {
+    xtable,
+    uploadFile,
+    fileWay
+  },
+  props: {
+    projectId: {
+      type: String,
+      default: ''
+    },
+    max: {
+      type: Number,
+      default: 9
+    }
+  },
+  watch: {
+    show: {
+      handler(val) {
+        if (val) {
+          this.getStage()
+          this.fetchData()
+        }
+      },
+      immediate: true
+    },
+    stageId: {
+      handler(val) {
+        if (this.activeName === '2') {
+          this.tabClick()
+        }
+      },
+      immediate: false
+    }
+  },
+  data() {
+    return {
+      stageId: '',
+      parentId: '',
+      stageList: [],
+      topFolder: true,
+      show: false,
+      activeName: '1',
+      tips: '最近15天内上传的文件',
+      list: [],
+      selectedList: [],
+      isLatest: 0,
+      dictKey: '',
+      loading: false,
+      currentRow: null,
+      page: {
+        current: 1,
+        size: 10,
+        total: 0
+      },
+      option: {
+        showMenu: false,
+        showCheckBox: true,
+        height: 500,
+        column: [
+          {
+            label: '名称',
+            prop: 'title',
+            display: false
+          },
+          {
+            label: '上传人',
+            prop: 'createUserName'
+          },
+          {
+            label: '上传时间',
+            prop: 'createTime'
+          }
+        ]
+      }
+    }
+  },
+  methods: {
+    tabClick() {
+      this.list.length = 0
+      if (this.activeName === '1') {
+        this.isLatest = 0
+        this.dictKey = ''
+        this.tips = '最近15天内上传的文件'
+        this.fetchData()
+      } else if (this.activeName === '2') {
+        this.isLatest = 0
+        this.dictKey = ''
+        this.getFolderList()
+      } else if (this.activeName === '3') {
+        this.isLatest = ''
+        this.dictKey = 1
+        this.tips = '该项目的相关要件'
+        this.fetchData()
+      } else {
+        this.isLatest = this.activeName
+        this.isLatest = ''
+        this.dictKey = 2
+        this.tips = '该项目的相关合同'
+        this.fetchData()
+      }
+    },
+    getStage() {
+      this.$api.project
+        .includeStage({ projectId: this.projectId })
+        .then(res => {
+          if (res.code === 200) {
+            this.stageList = res.data
+            const tmp = this.stageList.find(ele => ele.isLastSelect === 1)
+            if (tmp) {
+              this.stageId = tmp.id
+            } else {
+              this.stageId = this.stageList[0].id
+            }
+            console.log(this.stageId)
+          }
+        })
+    },
+    /**
+     * 获取全部文件
+     */
+    getFolderList() {
+      console.log('dddddd')
+      this.loading = true
+      const row = {
+        stageId: this.stageId,
+        dictKey: 1,
+        current: this.page.current,
+        size: this.page.size
+      }
+      this.$api.resource.folderList(row).then(res => {
+        this.loading = false
+        if (res.code === 200) {
+          this.list = res.data.records
+          this.page.total = res.data.total
+        }
+      })
+    },
+    /**
+     * 获取文件夹下面的文件及文件夹
+     * @param row
+     */
+    getFileList(row) {
+      this.topFolder = false
+      const item = {
+        id: row.id,
+        current: this.page.current,
+        size: this.page.size
+      }
+      this.loading = true
+      this.$api.resource.fileList(item).then(res => {
+        this.loading = false
+        if (res.code === 200) {
+          this.list = res.data.records
+          this.page.total = res.data.total
+        } else {
+          this.$message.error(res.msg)
+        }
+      })
+    },
+    /**
+     * 获取文件
+     */
+    fetchData() {
+      const data = {
+        projectId: this.projectId,
+        isLatest: this.isLatest,
+        dictKey: this.dictKey,
+        current: this.page.current,
+        size: this.page.size
+      }
+      this.loading = true
+      this.$api.resource.filePicker(data).then(res => {
+        this.loading = false
+        if (res.code === 200) {
+          this.list = res.data.records
+          this.page.total = res.data.total
+        }
+      })
+    },
+    selected(list) {
+      this.selectedList = list
+    },
+    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) {
+        tmp.checked = !tmp.checked
+      } else {
+        this.list.length = 0
+        this.getFileList(this.currentRow)
+      }
+    },
+    currentChange(current) {
+      this.page.current = current
+      this.tabClick()
+    },
+    uploadSuccess(res) {
+      this.getFileList(this.currentRow)
+    },
+    /**
+     * 阶段发生改变
+     */
+    stageChange() {
+      this.topFolder = true
+    },
+    onClose() {
+      this.page.current = 1
+      this.selectedList.length = 0
+      this.list.length = 0
+      this.activeName = '1'
+      this.parentId = ''
+    },
+
+    /**
+     * 返回上一级
+     */
+    goBefore(res) {
+      if (!this.topFolder) {
+        this.getFileList(res)
+      } else {
+        console.log('top')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.area {
+  height: 630px;
+  width: 88%;
+}
+
+.tips {
+  width: 100%;
+  height: 22px;
+  padding: 5px 5px;
+  border-radius: 4px;
+  background-color: #e2eaf5;
+}
+
+.files {
+  overflow-y: scroll;
+  padding: 0 10px;
+}
+</style>

+ 5 - 4
src/components/upload-file.vue

@@ -22,8 +22,8 @@
       <div class="flex flex-col flex-justify-start full-width">
         <div class="flex flex-align-center flex-justify-start">
           <el-button slot="trigger" size="small" type="primary"
-            >选取文件</el-button
-          >
+            >选取文件
+          </el-button>
           <span class="ml-10"
             >共{{ tmpFileList.length }}个文件,上传速度:{{ speed }}</span
           >
@@ -63,8 +63,8 @@
     <div class="full-width flex flex-justify-end">
       <el-button plain size="small" @click="close">取消上传</el-button>
       <el-button size="small" type="primary" @click="submint"
-        >开始上传</el-button
-      >
+        >开始上传
+      </el-button>
     </div>
   </div>
 </template>
@@ -211,6 +211,7 @@ export default {
   :deep(.el-upload) {
     width: 100%;
   }
+
   .box {
     height: 300px;
     overflow-x: scroll;

+ 152 - 0
src/components/upload-file/index.vue

@@ -0,0 +1,152 @@
+<template>
+  <div>
+    <div>
+      <el-upload
+        :action="action"
+        v-model:file-list="fileList"
+        :headers="headers"
+        :data="data"
+        :limit="max"
+        :accept="accept"
+        :multiple="max > 1"
+        :on-success="success"
+        :on-progress="progress"
+        :show-file-list="false"
+      >
+        <el-button type="primary" icon="Plus">{{ btnText }}</el-button>
+      </el-upload>
+    </div>
+    <div class="upload" v-if="drawer">
+      <div>
+        <div class="full-width flex flex-justify-end">
+          <el-icon @click="drawer = false">
+            <CircleClose />
+          </el-icon>
+        </div>
+        <div class="mt-20 file-content">
+          <div v-for="file in fileList" :key="file.name" class="mb-20">
+            <div class="flex flex-align-center">
+              <div>{{ file.name }} , ({{ bytesToSize(file.size) }})</div>
+              <div></div>
+            </div>
+            <el-progress :percentage="file.percentage" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { bytesToSize } from '@/utils/tools.js'
+import api from '@/api/index.js'
+import { getToken } from '@/utils/auth.js'
+import website from '@/config/website.js'
+import { Base64 } from 'js-base64'
+
+export default {
+  props: {
+    btnText: {
+      type: String,
+      default: '文件上传'
+    },
+    accept: {
+      type: String,
+      default: ''
+    },
+    max: {
+      type: Number,
+      default: 9
+    },
+    data: Object,
+    action: {
+      type: String,
+      default: api.uploadPath
+    },
+    projectId: {
+      type: String,
+      required: true,
+      default: ''
+    },
+    stageId: {
+      type: String,
+      required: true,
+      default: ''
+    },
+    parentId: {
+      type: String,
+      required: true,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      headers: {
+        Authorization: `Basic ${Base64.encode(
+          `${website.clientId}:${website.clientSecret}`
+        )}`,
+        'Blade-Auth': 'bearer ' + getToken()
+      },
+      drawer: false,
+      fileList: [],
+      resultList: []
+    }
+  },
+  methods: {
+    bytesToSize,
+    progress(res) {
+      console.log(res)
+      this.drawer = true
+    },
+    success(res) {
+      if (res.code === 200) {
+        this.resultList.push(res.data)
+      }
+      if (this.resultList.length === this.fileList.length) {
+        this.saveFile()
+      }
+    },
+    /**
+     * 保存文件
+     */
+    saveFile() {
+      const data = this.resultList.map(e => {
+        return {
+          fileId: e.id,
+          parentId: this.parentId,
+          projectId: this.projectId,
+          stageId: this.stageId
+        }
+      })
+      // fixme 重复文件未处理
+      this.$api.resource.fileSave(data).then(res => {
+        if (res.code === 200) {
+          this.$message.success('文件上传完成')
+          this.$emit('on-success', this.resultList)
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.upload {
+  position: fixed;
+  z-index: 99;
+  bottom: 0;
+  right: 0;
+  background-color: white;
+  height: 300px;
+  width: 480px;
+  border-top-left-radius: 10px;
+  border: #eeeeee solid 1px;
+  box-shadow: -2px 2px 20px rgba(0, 0, 0, 0.1);
+  padding: 20px;
+}
+
+.file-content {
+  height: 280px;
+  overflow-y: scroll;
+}
+</style>

+ 2 - 2
src/layout/left.vue

@@ -20,7 +20,7 @@
               :key="item.name"
             >
               <template #title>
-                <div class="flex flex-center flex-justify-start">
+                <div class="flex flex-center flex-justify-start pointer">
                   <img :src="item.source" style="width: 25px" class="mr-5" />
                   {{ item.name }}
                 </div>
@@ -32,7 +32,7 @@
                 :key="sub.name"
               >
                 <div
-                  class="item flex flex-center flex-justify-start"
+                  class="item flex flex-center flex-justify-start pointer"
                   style="margin-left: 20px"
                   :style="sub.checked ? 'color:#ECAB56' : ''"
                 >

+ 2 - 2
src/page/login.vue

@@ -226,8 +226,8 @@ export default {
     return {
       flag: false,
       form: {
-        name: 'adminzj',
-        pass: '123456'
+        name: '',
+        pass: ''
       },
       rules: {
         name: [

+ 38 - 36
src/views/database/component/list.vue

@@ -9,28 +9,30 @@
       <!--      />-->
       <div class="flex flex-align-center tip mt-10">
         <el-icon class="ml-20" color="#ECAB56">
-          <WarningFilled/>
+          <WarningFilled />
         </el-icon>
         <span class="ml-5">共找到相关资料{{ page.total }}份</span>
       </div>
     </div>
     <div class="crud">
-      <avue-crud ref="crud"
-                 v-model="form"
-                 v-model:page="page"
-                 :before-open="beforeOpen"
-                 :data="data"
-                 :option="option"
-                 :table-loading="loading"
-                 @row-del="rowDel"
-                 @current-change="currentChange"
-                 @size-change="sizeChange"
-                 @refresh-change="refreshChange"
-                 @on-load="onLoad">
+      <avue-crud
+        ref="crud"
+        v-model="form"
+        v-model:page="page"
+        :before-open="beforeOpen"
+        :data="data"
+        :option="option"
+        :table-loading="loading"
+        @row-del="rowDel"
+        @current-change="currentChange"
+        @size-change="sizeChange"
+        @refresh-change="refreshChange"
+        @on-load="onLoad"
+      >
       </avue-crud>
     </div>
     <el-dialog v-model="showInfo" append-to-body width="45%">
-      <dialog-info :id="id"/>
+      <dialog-info :id="id" />
     </el-dialog>
   </div>
 </template>
@@ -40,7 +42,7 @@ import dialogInfo from './dialog_info.vue'
 
 export default {
   name: 'list',
-  components: {dialogInfo},
+  components: { dialogInfo },
   data() {
     return {
       showInfo: false,
@@ -61,17 +63,17 @@ export default {
         index: true,
         align: 'center',
         viewBtn: true,
-        menuWidth: 320,
         dialogClickModal: false,
         column: [
           {
             label: '文件名称',
             prop: 'title',
-            width: 380
+            width: 340
           },
           {
             label: '所属项目',
-            prop: 'projectName'
+            prop: 'projectName',
+            width: 240
           },
           {
             label: '文件格式',
@@ -83,8 +85,10 @@ export default {
           },
           {
             label: '上传时间',
-            prop: 'createTime'
-          }]
+            prop: 'createTime',
+            width: 200
+          }
+        ]
       },
       page: {
         current: 1,
@@ -95,7 +99,7 @@ export default {
     }
   },
   created() {
-    this.$bus.on('serachFile', (res) => {
+    this.$bus.on('serachFile', res => {
       this.onLoad(res)
     })
   },
@@ -103,7 +107,7 @@ export default {
     onLoad(query = {}) {
       this.page.current = this.page.currentPage
       this.page.size = this.page.pageSize
-      const data = {...query, ...this.page}
+      const data = { ...query, ...this.page }
       this.loading = true
       this.$api.database.fileList(data).then(res => {
         this.loading = false
@@ -130,7 +134,7 @@ export default {
       } else if (type === 'edit') {
         this.$router.push({
           path: '/home/details',
-          query: {id: this.form.id, type: '1'}
+          query: { id: this.form.id, type: '1' }
         })
       }
     },
@@ -139,17 +143,16 @@ export default {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
+      }).then(() => {
+        this.$api.database.fileRemove({ ids: row.id }).then(res => {
+          if (res.code === 200) {
+            this.$message.success(res.msg)
+            this.onLoad()
+          } else {
+            this.$message.error(res.msg)
+          }
+        })
       })
-          .then(() => {
-            this.$api.database.fileRemove({ids: row.id}).then(res => {
-              if (res.code === 200) {
-                this.$message.success(res.msg)
-                this.onLoad()
-              } else {
-                this.$message.error(res.msg)
-              }
-            })
-          })
     },
     choise(index) {
       this.active = index
@@ -168,11 +171,10 @@ export default {
 .tip {
   width: 260px;
   height: 32px;
-  background-color: #FBF6ED;
-  color: #ECAB56;
+  background-color: #fbf6ed;
+  color: #ecab56;
   font-weight: 500;
   flex-wrap: nowrap;
   margin-left: 20px;
 }
-
 </style>

+ 4 - 2
src/views/home/component/dash.vue

@@ -5,7 +5,7 @@
         <el-icon class="ml-20" color="#BC002D">
           <WarningFilled />
         </el-icon>
-        <span class="ml-5"
+        <span class="ml-5 font-16"
           >项目总投资额<span class="main-color bold">{{
             num ? Number.parseFloat(num).toLocaleString() : '0'
           }}</span
@@ -472,8 +472,10 @@ export default {
             type: 'number',
             precision: 2,
             formatter: (val, value, label) => {
-              if (val && val.length > 0) {
+              if (value) {
                 return val.total_amount.toLocaleString()
+              } else {
+                return 0
               }
             }
           },

+ 1 - 3
src/views/invest/index.vue

@@ -43,9 +43,6 @@
                     placement="bottom"
                     raw-content
                   >
-                    <el-icon size="16">
-                      <Warning />
-                    </el-icon>
                   </el-tooltip>
                 </div>
                 <div
@@ -133,6 +130,7 @@ import { useStore } from '@/store/user.js'
 
 export default {
   name: 'index',
+  // eslint-disable-next-line vue/no-unused-components
   components: { BasicContainer, left, years, amount, chart, chart2, complete },
   setup() {
     const user = useStore()

+ 20 - 0
src/views/resource/component/archives.vue

@@ -0,0 +1,20 @@
+<template>
+  <div>
+    <el-button type="primary" text @click="show = true">归档</el-button>
+    <el-dialog v-model="show">
+      <div>dd</div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      show: false
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 6 - 6
src/views/resource/component/floder.vue

@@ -1,14 +1,13 @@
 <template>
   <div class="flex flex-center flex-col">
-    <img src="../../../assets/svg/folder.svg" style="margin-top: -20px" />
+    <img src="@/assets/svg/folder.svg" style="margin-top: -20px" />
     <el-input
       v-model="title"
       placeholder="请输入文件夹名称"
       prefix-icon="EditPen"
     />
-    <div class="mt-20 flex flex-justify-between full-width">
-      <div></div>
-      <el-button type="primary" @click="folderAdd">确定</el-button>
+    <div class="mt-20 flex flex-justify-end full-width">
+      <el-button type="primary" @click="folderAdd">确 定</el-button>
     </div>
   </div>
 </template>
@@ -35,13 +34,14 @@ export default {
       const data = {
         projectId: this.info.projectId,
         stageId: this.info.stageId,
-        title: this.title
+        title: this.title,
+        parentId: this.info.id
       }
       if (this.info.stageId === '') {
         this.$message.error('请先选择相关项目阶段!')
         this.$emit('close')
       }
-      this.$api.project.folderAdd(data).then(res => {
+      this.$api.resource.folderAddUpdate(data).then(res => {
         if (res.code === 200) {
           this.$message.success(res.msg)
           this.$emit('close')

+ 32 - 0
src/views/resource/component/move.vue

@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <el-button type="primary" text @click="show = true">移动</el-button>
+    <el-dialog v-model="show" width="800">
+      <div class="full-width content">
+        <div v-for="i in 20" class="padding light-green-bg mb-5">333</div>
+      </div>
+      <div class="full-width flex flex-justify-end flex-center mt-20">
+        <el-button type="primary" plain>取 消</el-button>
+        <el-button type="primary">移动到此</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      show: false
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.content {
+  height: 500px;
+  overflow-y: scroll;
+  background-color: red;
+}
+</style>

+ 81 - 0
src/views/resource/component/row1.vue

@@ -0,0 +1,81 @@
+<template>
+  <div class="row full-width">
+    <div
+      v-if="index === 0"
+      class="flex flex-align-center flex-justify-start full-height padding-left"
+    >
+      <el-checkbox
+        v-if="showCheckBox"
+        v-model="info.checked"
+        :disabled="info.type === 2"
+        class="padding-right"
+        @change="rowChecked(row)"
+      />
+      <img
+        v-if="info.type === 2"
+        src="../../../assets/svg/folder/invisible.svg"
+      />
+      <img v-else src="../../../assets/svg/folder/pdf.svg" />
+      {{ info[column.prop] }}
+    </div>
+    <div
+      v-else
+      class="flex flex-align-center flex-center full-height flex-child-average"
+    >
+      {{ info[column.prop] }}
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    row: {
+      type: Object,
+      default: null
+    },
+    column: {
+      type: Object,
+      default: null
+    },
+    index: {
+      type: Number,
+      default: 0
+    },
+    showCheckBox: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    row: {
+      handler(val) {
+        this.info = val
+      },
+      immediate: true
+    }
+  },
+  data() {
+    return {
+      info: null
+    }
+  },
+  methods: {
+    rowChecked(res) {
+      this.$emit('row-change', res)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.row {
+  height: 55px;
+  border-bottom: #f7f8fa solid 1px;
+  img {
+    width: 40px;
+    height: auto;
+    margin-right: 10px;
+  }
+}
+</style>

+ 122 - 35
src/views/resource/component/xtable.vue

@@ -1,51 +1,98 @@
 <template>
-  <div>
-    <div class="flex flex-center flex-justify-between">
+  <div class="full-height">
+    <div class="flex flex-center flex-justify-between border-bottom">
       <div v-for="header in headers" :key="header.id" class="mt-20 full-width">
         <div
-          v-if="header.label !== '操作'"
-          class="padding-top padding-bottom border-bottom"
-          :style="`min-width:` + header.width + `px`"
+          v-if="header.label === '操作'"
+          class="padding-top padding-bottom"
+          style="width: 280px"
         >
-          {{ header.label }}{{ header.width }}
+          {{ header.label }}
         </div>
-        <div v-else class="border-bottom menu flex flex-center">
-          {{ header.label }}{{ header.width }}
+        <div
+          v-else
+          class="menu flex flex-center"
+          :style="header.width ? `width:` + header.width + `px` : ''"
+        >
+          {{ header.label }}
         </div>
       </div>
     </div>
     <div class="full-width">
-      <div
-        v-for="row in data"
-        :key="row.id"
-        class="flex flex-center row pointer"
-        @click="rowClick(row)"
-      >
+      <div v-if="data.length !== 0">
         <div
-          v-for="(prop, cell) in headers"
-          :key="prop.id"
-          class="flex-child-average flex"
+          v-for="row in data"
+          :key="row.id"
+          class="flex flex-center row pointer"
         >
           <div
-            v-if="prop.label === '操作'"
-            class="nowrap menu flex flex-center"
+            v-for="(prop, index) in headers"
+            :key="prop.id"
+            class="flex-child-average flex"
           >
-            <el-button type="primary" size="small" text>查看</el-button>
-            <el-button type="primary" size="small" text>归档</el-button>
-            <el-button type="primary" size="small" text>重命名</el-button>
-          </div>
-          <div v-else class="row" :style="`min-width:` + prop.width + `px`">
-            <slot name="row" class="row" :index="cell" :row="row" :ele="prop" />
+            <div
+              v-if="prop.label === '操作'"
+              class="nowrap menu flex flex-center"
+              style="width: 280px"
+            >
+              <el-button type="primary" size="small" text>查看</el-button>
+              <el-button v-if="row.type === 2" type="primary" size="small" text
+                >重命名</el-button
+              >
+              <archives v-if="row.type === 2" />
+              <move v-if="row.type === 1" />
+              <slot name="menu"></slot>
+            </div>
+            <div
+              v-else
+              class="row full-width"
+              :style="`min-width:` + prop.width + `px`"
+            >
+              <div class="cell flex flex-center full-width">
+                <row1
+                  :row="row"
+                  :column="prop"
+                  :index="index"
+                  :show-check-box="showCheckBox"
+                  @click="rowClick(row)"
+                ></row1>
+              </div>
+            </div>
           </div>
         </div>
+        <div class="full-width flex flex-center flex-justify-end">
+          <el-pagination
+            layout="prev, pager, next"
+            class="mt-10 bottom"
+            :total="total"
+            @current-change="currentChange"
+          />
+        </div>
+      </div>
+      <div v-else class="mt-20">
+        <el-empty v-if="loading === false" description="暂无数据"></el-empty>
+        <el-skeleton v-else :rows="10" animated />
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import row1 from '@/views/resource/component/row1.vue'
+import move from '@/views/resource/component/move.vue'
+import archives from '@/views/resource/component/archives.vue'
+
 export default {
+  components: {
+    row1,
+    move,
+    archives
+  },
   props: {
+    total: {
+      type: Number,
+      default: 0
+    },
     data: {
       type: Array,
       default: null
@@ -53,6 +100,14 @@ export default {
     option: {
       type: Object,
       default: null
+    },
+    max: {
+      type: Number,
+      default: 9
+    },
+    loading: {
+      type: Boolean,
+      default: false
     }
   },
   watch: {
@@ -62,9 +117,17 @@ export default {
         const menu = {
           label: '操作'
         }
+        this.showMenu =
+          this.option.showMenu === undefined ? true : this.option.showMenu
+        this.showCheckBox =
+          this.option.showCheckBox === undefined
+            ? false
+            : this.option.showCheckBox
         this.headers = val.column
-        if (this.headers.findIndex(e => e.label === '操作') === -1) {
-          this.headers.push(menu)
+        if (this.showMenu) {
+          if (this.headers.findIndex(e => e.label === '操作') === -1) {
+            this.headers.push(menu)
+          }
         }
       },
       immediate: true
@@ -72,12 +135,33 @@ export default {
   },
   data() {
     return {
-      headers: []
+      showMenu: true,
+      showCheckBox: false,
+      headers: [],
+      selectedList: []
     }
   },
   methods: {
+    currentChange(current) {
+      this.$emit('current-change', current)
+    },
     rowClick(row) {
+      if (this.selectedList.length === this.max) {
+        this.$message.error('可选择文件数量最大为' + this.max)
+        return
+      }
       this.$emit('row-click', row)
+      if (row.checked) {
+        const tmps = this.data.filter(ele => ele.checked)
+        tmps.forEach(ele => {
+          if (this.selectedList.findIndex(sub => sub.id === ele.id) === -1) {
+            this.selectedList.push(ele)
+          }
+        })
+      } else {
+        this.selectedList = this.selectedList.filter(ele => ele.id !== row.id)
+      }
+      this.$emit('selected', this.selectedList)
     }
   }
 }
@@ -85,24 +169,27 @@ export default {
 
 <style lang="scss" scoped>
 .row {
-  margin: 1px;
   min-height: 40px;
 }
 
 .row:hover {
   min-height: 40px;
-  margin: 1px;
-  background-color: #eeeeee;
+  background-color: #f7f9fc;
 }
 
 .cell {
-  min-height: 40px;
-  border-bottom: #dcdfe6 solid 1px;
+  min-height: 45px;
 }
 
 .menu {
-  width: 280px;
+  display: flex;
+  flex: 1;
   height: 45px;
-  background-color: wheat;
+  border-bottom: #f7f8fa solid 1px;
+}
+
+.bottom {
+  position: absolute;
+  bottom: 80px;
 }
 </style>

+ 111 - 64
src/views/resource/index.vue

@@ -10,7 +10,6 @@
             filterable
             clearable
             placeholder="筛选项目阶段"
-            :remote-method="remoteMethod"
             style="width: 100%"
             @change="folderResult"
           >
@@ -27,15 +26,30 @@
     </tips-custom>
     <!--    content-->
     <el-card shadow="hover" class="content">
-      <div v-if="top">
+      <div>
         <div class="full-width flex flex-center flex-justify-between">
-          <div class="full-width flex flex-justify-start flex-align-center">
-            <base-button
-              title="新建文件夹"
-              icon="Plus"
+          <div class="full-width flex flex-justify-start flex-center">
+            <upload-file
+              v-if="!top"
+              @on-success="uploadSuccess"
+              :project-id="folderInfo.projectId"
+              :stage-id="folderInfo.stageId"
+              :parent-id="currentFolder !== null ? currentFolder.id : ''"
+            />
+            <el-button
+              class="ml-10"
+              type="primary"
+              icon="Folder"
+              :plain="!top"
               @click="showDialog(1)"
+              >新建文件夹
+            </el-button>
+            <el-button type="primary" plain icon="User">批量授权</el-button>
+            <filepicker
+              class="ml-10"
+              :project-id="folderInfo.projectId"
+              :stage-id="folderInfo.stageId"
             />
-            <base-button title="批量授权" icon="User" />
           </div>
           <div class="flex flex-center">
             <span class="nowrap mr-10">文件搜索</span>
@@ -46,50 +60,19 @@
             />
           </div>
         </div>
-        <el-breadcrumb
-          separator-icon="ArrowRight"
-          class="mt-20 main-color pointer"
-        >
-          <el-breadcrumb-item>提示说明</el-breadcrumb-item>
-        </el-breadcrumb>
-        <xtable :data="data" :option="option" @row-click="folderOpen">
-          <template #row="{ row, ele }">
-            <div class="flex">
-              {{ row[ele.prop] }}
-            </div>
-          </template>
-        </xtable>
-      </div>
-      <!--      下级目录-->
-      <div v-else>
-        <div class="full-width flex flex-center flex-justify-between">
-          <div class="full-width flex flex-justify-start flex-align-center">
-            <el-button type="primary">上传</el-button>
-            <el-button type="primary" plain>新建文件夹</el-button>
-            <el-button type="primary" plain>批量授权</el-button>
-          </div>
-          <el-button round icon="el-icon-search" />
-        </div>
-        <el-breadcrumb
-          separator-icon="ArrowRight"
-          class="mt-20 main-color pointer"
-        >
-          <el-breadcrumb-item @click="top = true"
-            >返回上一层
+        <el-breadcrumb separator-icon="ArrowRight" class="mt-20 main-color">
+          <el-breadcrumb-item>
+            <div class="pointer" @click="getFolderList">全部文件</div>
           </el-breadcrumb-item>
-          <el-breadcrumb-item>全部文件</el-breadcrumb-item>
-          <el-breadcrumb-item>{{ data.title }}</el-breadcrumb-item>
         </el-breadcrumb>
-        <xtable :data="data" :option="option">
-          <template #row="{ index, row, ele }">
-            <div v-if="index === 0" class="light-purple-bg flex flex-center">
-              <img src="@/assets/svg/folder/edit.svg" style="width: 40px" />
-              <div>
-                {{ row[ele.prop] }}
-              </div>
-            </div>
-            <el-empty v-else />
-          </template>
+        <xtable
+          :data="data"
+          :option="top ? option : option2"
+          :loading="loading"
+          :total="page.total"
+          @row-click="getFileList"
+          @current-change="currentChange"
+        >
         </xtable>
       </div>
     </el-card>
@@ -98,7 +81,7 @@
       <floder
         v-if="showType === 1"
         :info="folderInfo"
-        @close="colseDialog"
+        @close="closeDialog"
       ></floder>
     </el-dialog>
   </div>
@@ -115,14 +98,16 @@ meta: { 'show': false }
 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 baseButton from '@/components/base-button.vue'
+import uploadFile from '@/components/upload-file/index.vue'
+import filepicker from '@/components/filepicker/index.vue'
 
 export default {
   components: {
     tipsCustom,
     xtable,
     floder,
-    baseButton
+    uploadFile,
+    filepicker
   },
 
   data() {
@@ -132,7 +117,9 @@ export default {
       width: 380,
       title: '新建文件夹',
       top: true,
-      data: [{ title: '@2' }, { title: '@3333', status: '555' }],
+      loading: false,
+      currentFolder: null,
+      data: [],
       option: {
         column: [
           {
@@ -155,7 +142,20 @@ export default {
           },
           {
             label: '创建人',
-            prop: 'createUser'
+            prop: 'createUserName'
+          }
+        ]
+      },
+      option2: {
+        column: [
+          {
+            label: '名称2',
+            prop: 'title',
+            display: false
+          },
+          {
+            label: '创建人',
+            prop: 'createUserName'
           }
         ]
       },
@@ -166,14 +166,14 @@ export default {
       },
       page: {
         current: 1,
-        size: 10
+        size: 10,
+        total: 0
       },
       total: ''
     }
   },
   created() {
     this.folderInfo.projectId = this.$route.query.id
-    this.getFolderList()
     this.getStage()
   },
   methods: {
@@ -181,28 +181,52 @@ export default {
       this.showType = type
       this.show = true
     },
-    colseDialog() {
+    folderAdd() {
+      this.$api.resource.folderAddUpdate().then(res => {
+        if (res.code === 200) {
+          console.log(res)
+        }
+      })
+    },
+    closeDialog() {
       this.show = false
+      if (this.top) {
+        this.getFolderList()
+      } else {
+        this.getFileList()
+      }
     },
     getFolderList() {
       const data = {
         stageId: this.folderInfo.stageId,
-        dictKey: 1
+        dictKey: 1,
+        current: this.page.current,
+        size: this.page.size
       }
-      this.$api.project.folderList(Object.assign(data, this.page)).then(res => {
+      this.loading = true
+      this.top = true
+      this.$api.resource.folderList(data).then(res => {
+        this.loading = false
         if (res.code === 200) {
           this.data = res.data.records
+          this.page.total = res.data.total
           this.total = res.data.total
         }
       })
     },
-    folderOpen(row) {
-      console.log(row)
+    getFileList(row) {
+      this.folderInfo = Object.assign(this.folderInfo, row)
       this.top = !this.top
-      const data = { id: row.id, isHistory: 0 }
-      this.$api.project.fileList(Object.assign(data, this.page)).then(res => {
+      const data = {
+        id: row.id,
+        current: this.page.current,
+        size: this.page.size
+      }
+      this.loading = true
+      this.$api.resource.fileList(data).then(res => {
+        this.loading = false
         if (res.code === 200) {
-          this.data = res.data
+          this.data = res.data.records
         } else {
           this.$message.error(res.msg)
         }
@@ -217,12 +241,35 @@ 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
+            } else {
+              this.folderInfo.stageId = this.stage[0].id
+            }
+            this.getFolderList()
           }
         })
     },
     folderResult(res) {
+      this.loading = true
       this.stageId = res
       this.getFolderList()
+    },
+    uploadSuccess(files) {
+      console.log('refresh')
+    },
+    refreshData() {
+      if (this.top) {
+        this.getFolderList()
+      } else {
+        this.getFileList()
+      }
+    },
+    currentChange(current) {
+      this.page.current = current
+      this.refreshData()
     }
   }
 }

+ 2 - 2
vite.config.js

@@ -57,8 +57,8 @@ export default defineConfig({
     proxy: {
       '/api': {
         // 正式环境地址
-        // target: 'https://dev.wutongresearch.club/api',
-        target: 'https://prod.wutongshucloud.com/api',
+        target: 'https://dev.wutongresearch.club/api',
+        // target: 'https://prod.wutongshucloud.com/api',
         // target: 'http://192.168.31.181:8110',
         changeOrigin: true,
         rewrite: path => path.replace(/^\/api/, '')