Ver Fonte

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	vue.config.js
liuyc há 3 anos atrás
pai
commit
0d8b8dfa31

+ 12 - 2
src/api/exctab/excelmodel.js

@@ -66,17 +66,27 @@ export const Excelmodify = (row) => {
 // 上传清表
 export const uploadExcel = (row) => {
     return request({
+        // ty  application/json
         url: '/api/blade-manager/exceltab/put-file-attach',
         method: 'post',
         data: row
     })
 }
 
-// 删除
+// 删除excel文件
 export const deleteExcel = (row) => {
     return request({
-        url: '/api/blade-manager/exceltab/remove',
+        url: '/api/blade-manager/exceltab/update',
         method: 'post',
         data: row
     })
+}
+export const deleteExcelshu = (ids) => {
+    return request({
+        url: '/api/blade-manager/exceltab/remove',
+        method: 'post',
+        params: {
+            ids,
+        }
+    })
 }

+ 21 - 0
src/api/manager/contractinfo.js

@@ -107,3 +107,24 @@ export const resetPasswordByUserId = (userId) => {
     }
   })
 }
+
+export const submitWbsTreeInContract = (obj) => {
+  return request({
+    url: '/api/blade-manager/contractInfo/submitWbsTreeInContract',
+    method: 'post',
+    data: obj
+  })
+}
+
+export const getContractInfoTree = (wbsId,projectId,contractId) => {
+  return request({
+    url: '/api/blade-manager/contractInfo/tree',
+    method: 'get',
+    params: {
+      wbsId,
+      projectId,
+      contractId,
+    }
+  })
+}
+

+ 30 - 0
src/api/manager/projectinfo.js

@@ -29,3 +29,33 @@ export const getProjectDeatil = (id) => {
     }
   })
 }
+
+export const findWbsTreeList = (type) => {
+  return request({
+    url: '/api/blade-manager/projectInfo/findWbsTreeList',
+    method: 'get',
+    params: {
+      type
+    }
+  })
+}
+
+export const findProjectTree = (projectId,wbsId) => {
+  return request({
+    url: '/api/blade-manager/projectInfo/tree',
+    method: 'get',
+    params: {
+      projectId,
+      wbsId
+    }
+  })
+}
+
+export const submitWbsTreeInProject = (obj) => {
+  return request({
+    url: '/api/blade-manager/projectInfo/submitWbsTreeInProject',
+    method: 'post',
+    data: obj
+  })
+}
+

+ 21 - 3
src/api/manager/wbsformelement.js

@@ -22,12 +22,14 @@ export const getDetail = (id) => {
   })
 }
 
-export const remove = (ids) => {
+export const remove = (ids,initTableName,eKey) => {
   return request({
     url: '/api/blade-manager/wbsFormElement/remove',
     method: 'post',
     params: {
       ids,
+      initTableName,
+      eKey
     }
   })
 }
@@ -54,11 +56,27 @@ export const saveElement = (row) => {
     data: row
   })
 }
-export const updateBatchElements = (list) => {
+
+export const updateBatchElements = (list,initTableName) => {
   return request({
-    url: '/api/blade-manager/wbsTree/updateBatchElements',
+    url: '/api/blade-manager/wbsTree/updateBatchElements?initTableName='+initTableName,
     method: 'post',
     data: list
   })
 }
 
+export const getTemplate = () => {
+  return request({
+    url: '/api/blade-manager/wbsFormElement/export-template',
+    method: 'get',
+    responseType:'arraybuffer'
+  })
+}
+
+export const importWbsElement = (formData) => {
+  return request({
+    url: '/api/blade-manager/wbsFormElement/import-wbsElement',
+    method: 'post',
+    data: formData
+  })
+}

+ 1 - 1
src/api/manager/wbsinfo.js

@@ -2,7 +2,7 @@ import request from '@/router/axios';
 
 export const getList = (current, size, params) => {
   return request({
-    url: '/api/blade-manager/wbsInfo/list',
+    url: '/api/blade-manager/wbsInfo/page',
     method: 'get',
     params: {
       ...params,

+ 59 - 1
src/components/tree-tree/main.vue

@@ -1,8 +1,9 @@
 <template>
   <div class="flex pd-20">
     <el-card class="box-card flex1">
-      <div slot="header" class="clearfix">
+      <div slot="header" class="flex jc-sb">
         <span>{{leftNum}}项</span>
+        <el-checkbox v-if="showAllCheck" v-model="allChecked" @change="checkChang">默认全部引用</el-checkbox>
       </div>
       <div>
         <el-scrollbar :style="scrollbarStyle">
@@ -51,6 +52,10 @@ export default {
     scrollbarStyle:{
       type:String,
       default:'height:calc(100vh - 400px)'
+    },
+    showAllCheck:{
+      type:Boolean,
+      default:false
     }
   },
   computed: {
@@ -66,6 +71,7 @@ export default {
       rightTreeData:[],
       rightNum:0,
       rightExpands:[],
+      allChecked:false,
     }
   },
 
@@ -80,6 +86,7 @@ export default {
       //console.log(allTree,'allTree');
       this.getRightTree(allTree,keys);
       this.rightTreeData = allTree;
+      this.$emit('onAddTree',this.rightTreeData);
     },
     getRightTree(arr,keys){
       //对比所有的node和选中的key
@@ -114,6 +121,8 @@ export default {
       })
       this.rightNum = this.$refs.rightTree.getCheckedKeys().length;
       this.leftNum = this.$refs.leftTree.getCheckedKeys().length;
+
+      this.$emit('onDelTree',delNodes);
     },
 
     nodeExpand(data){
@@ -130,6 +139,55 @@ export default {
           break;
       }
     },
+
+    setRightTree(data){
+      this.rightTreeData = data;
+
+      let ids = [];
+      for (let i = 0; i < data.length; i++) {
+        this.getLeafIds(ids,data[i])
+      }
+      //在左边把右边的节点勾选上
+      this.$nextTick(()=>{
+        this.$refs.leftTree.setCheckedKeys(ids,true);
+      })
+    },
+
+    getTreeAllId(treeName){
+      let tree = this.$refs[treeName];
+      if(this.allChecked){
+        tree = this.$refs.leftTree;
+      }
+      //console.log(tree.data);
+      let ids = [];
+      for (let i = 0; i < tree.data.length; i++) {
+        this.getIds(ids,tree.data[i]);
+      }
+      //console.log(obj)
+      return ids.join(',');
+    },
+    getIds(ids,data){
+      ids.push(data.id);
+      if(data.children && data.children.length){
+        for (let i = 0; i < data.children.length; i++) {
+          this.getIds(ids,data.children[i]);
+        }
+      }
+    },
+
+    getLeafIds(ids,data){
+      if(data.children && data.children.length){
+        for (let i = 0; i < data.children.length; i++) {
+          this.getLeafIds(ids,data.children[i]);
+        }
+      }else{
+        ids.push(data.id)
+      }
+    },
+
+    checkChang(){
+      this.$emit('onCheckAll');
+    }
   }
 };
 </script>

+ 14 - 0
src/router/views/index.js

@@ -144,4 +144,18 @@ export default [{
                 import ( /* webpackChunkName: "views" */ '@/views/exctab/excelmodel/excelmodel')
         }]
     },
+    {
+        path: '/manager',
+        component: Layout,
+        redirect: '/manager/privateWBS',
+        children: [{
+            path: 'privateWBS/:id',
+            name: '编辑WBS库',
+            meta: {
+                i18n: 'privateWBS'
+            },
+            component: () =>
+                import ( /* webpackChunkName: "views" */ '@/views/manager/projectinfo/privateWBS')
+        }]
+    },
 ]

+ 3 - 0
src/styles/common.scss

@@ -106,6 +106,9 @@ a{
   color: #f56c6c;
 }
 
+.text-success{color: #34c362;}
+.text-warning{color: #ec6421;}
+
 .text-align-c{text-align: center;}
 
 .custom-tree-node {

+ 4 - 4
src/styles/icon/index.scss

@@ -1,5 +1,5 @@
-@import 'icon';
-@import 'lib';
-@import 'cicon';
+//@import 'icon';
+//@import 'lib';
+//@import 'cicon';
 @import "hcicon";
-@import "HIcon";
+//@import "HIcon";

+ 372 - 51
src/views/exctab/excelmodel/excelmodel.vue

@@ -21,20 +21,23 @@
                   <div>
                     <span> {{ data.name }} </span>
                     <!-- <span> {{ node}} </span> -->
+                    <!-- 添加 -->
                     <i
                       class="el-icon-circle-plus-outline marleft10"
                       @click.stop="addExcel(data)"
-                      v-if="!data.fileUrl"
+                      v-if="data.fileType!=3"
                     ></i>
+                    <!-- 编辑 -->
                     <i
                       class="el-icon-edit marleft10"
-                      @click.stop="editExcel()"
-                      v-if="data.fileUrl"
+                      @click.stop="editExcel(data)"
+                      v-if="data.fileType!=3"
                     ></i>
+                    <!-- 删除 -->
                     <i
                       class="el-icon-delete marleft10"
                       @click.stop="deleteExcelM(data)"
-                      v-if="data.fileUrl"
+                      v-if="!data.hasChildren"
                     ></i>
                   </div>
                 </span>
@@ -51,25 +54,76 @@
         <el-scrollbar>
           <basic-container>
             <!-- 上传、删除、下载操作栏 -->
-            <div class="rightHeader">
+            <div
+              class="rightHeader"
+              v-show="from.checkd&&from.fileUrl"
+            >
               <div class="excelname">
-                <div>名ssssssssssssssssssssssssssssss称</div>
+                <div>{{from.extension}}</div>
                 <i
                   class="el-icon-success marleft10"
                   style="color: rgb(0, 168, 112);"
                 ></i>
               </div>
-              <el-button
-                size="mini"
+              <el-upload
                 class="marleft10"
-              >重新上传</el-button>
-              <el-link class="marleft10 colorblue">删除</el-link>
+                :auto-upload="false"
+                :show-file-list="false"
+                action="#"
+                :limit="1"
+                :file-list='fileList'
+                accept=".xls,.xlsx"
+                :on-change="uploadChange"
+              >
+                <el-button
+                  type="primary"
+                  size="mini"
+                >重新上传</el-button>
+              </el-upload>
+              <el-link
+                class="marleft10 colorblue"
+                @click="delectExcelMS"
+              >删除</el-link>
               <el-link
                 underline
                 class="marleft10 colorblue"
                 style="text-decoration:underline;"
+                @click="downloadExcel()"
               >下载EXCEL</el-link>
             </div>
+            <div
+              class="rightHeader"
+              v-show="from.checkd&&!from.fileUrl"
+            >
+              <el-upload
+                :auto-upload="false"
+                :show-file-list="false"
+                action="#"
+                :limit="1"
+                :file-list='fileList'
+                accept=".xls,.xlsx"
+                :on-change="uploadChange"
+              >
+                <el-button
+                  type="primary"
+                  size="mini"
+                >上传 excel</el-button>
+              </el-upload>
+            </div>
+            <el-empty
+              v-show="!from.checkd"
+              description="该目录为根目录没有EXCEL文件"
+            ></el-empty>
+            <div
+              style="height:700px;margin-top:20px;"
+              v-if="from.fileUrl"
+            >
+              <iframe
+                :src="excelSrc"
+                width="100%"
+                height="100%"
+              ></iframe>
+            </div>
           </basic-container>
         </el-scrollbar>
       </el-col>
@@ -77,7 +131,7 @@
 
     <!-- 弹出框 -->
     <el-dialog
-      title="新增编辑"
+      :title="!excelForm.id?'添加':'编辑'"
       class="dialogModel"
       :visible.sync="dialogTap"
       width="800px"
@@ -90,12 +144,14 @@
           ref="excelForm"
           :model="excelForm"
           label-width="80px"
+          rules="rules"
         >
           <div style="display: flex;justify-content: space-between;">
             <el-form-item
               label="清表名称"
               style="width: 370px;"
               size="small"
+              prop="nodeName"
             >
               <el-input v-model="excelForm.nodeName"></el-input>
             </el-form-item>
@@ -103,9 +159,10 @@
               label="清表类型"
               style="width: 370px;"
               size="small"
+              prop="tabType"
             >
               <el-select
-                v-model="excelForm.name"
+                v-model="excelForm.tabType"
                 style="width:100%;"
                 placeholder="请选择清表类型"
               >
@@ -119,7 +176,10 @@
             </el-form-item>
           </div>
         </el-form>
-        <div class="middle">
+        <div
+          class="middle"
+          v-if="wbsmiddle"
+        >
           <div class="left">
             <div class="select">
               <el-select
@@ -156,6 +216,7 @@
               </avue-tree>
             </div>
           </div>
+          <!-- 右侧关联 -->
           <template>
             <table
               class="right"
@@ -174,17 +235,19 @@
                   v-for="(val,index) in tableData"
                   :key="index"
                 >
-                  <td>{{val.tableName}}</td>
+                  <td style="width:50%;">{{val.tableName}}</td>
                   <td style="text-align: center;height:30px;">
                     <el-button
-                      v-if="val.isLinkTable!=2"
+                      v-if="val.isLinkTable!==2"
                       type="info"
                       size="small"
+                      @click="relation(index)"
                     >关联</el-button>
                     <el-button
                       v-if="val.isLinkTable==2"
                       type="warning"
                       size="small"
+                      @click="Disassociate(index)"
                     >取消关联</el-button>
                   </td>
                 </tr>
@@ -210,16 +273,47 @@
 </template>
 
 <script>
-import { detailExcel, excelType, tabLazytree, getWbsTypeList, wbstree, selectByNodeTable, Excelmodify, uploadExcel } from '@/api/exctab/excelmodel'
+import { detailExcel, excelType, tabLazytree, getWbsTypeList, wbstree, selectByNodeTable, Excelmodify, uploadExcel, deleteExcelshu, deleteExcel } from '@/api/exctab/excelmodel'
 export default {
   data () {
     return {
       loading: false,//懒加载
       option: {
         filter: false,
+        lazy: true,
+        treeLoad: (async (node, resolve) => {
+          console.log(node);
+          if (node.data.hasChildren) {
+            const { data: res } = await tabLazytree({ modeId: node.data.id })
+            console.log(res);
+            if (res.code === 200) {
+              if (Array.isArray(res.data)) {
+                res.data.forEach((val) => {
+                  if (!val.hasChildren) {
+                    val.leaf = true
+                  }
+                })
+              }
+              return resolve(res.data)
+            }
+          } else {
+            return resolve([])
+          }
+        }),
       },
       data: [],//清表模板
       wbsdata: [],//wbs模板
+      //#region 右侧数据
+      from: {
+        checkd: false,//判断是否可以进行上传、重新上传excel
+        id: '',//清表树ID
+        extension: '', //文件名称
+        fileUrl: '',//文件路径
+      },
+      fileList: [],//选中的文件
+      excelSrc: '',//
+      //#endregion
+
       //#region   弹框
       dialogTap: false,
       option2: {
@@ -230,11 +324,13 @@ export default {
             const { data: res } = await wbstree({ parentId: node.data.id, wbsId: this.excelForm.wbsId, wbsType: this.excelForm.wbsType })
             console.log(res);
             if (res.code === 200) {
-              res.data.forEach((val) => {
-                if (!val.hasChildren) {
-                  val.leaf = true
-                }
-              })
+              if (res.msg != '未查询到信息') {
+                res.data.forEach((val) => {
+                  if (!val.hasChildren) {
+                    val.leaf = true
+                  }
+                })
+              }
               return resolve(res.data)
             }
           } else {
@@ -244,11 +340,28 @@ export default {
       },//弹框里面的wbs树
       excelForm: {
         nodeName: '',//清表名称
-        parentId: '',//清表Id
+        tabType: '',//清表类型
+        id: '',//清表Id,编辑时用
+        parentId: '',//清表Id,添加时用
         wbsId: '',//WBS模板Id
         wbsType: '',//WBS模板类型
       },
+      rules: {
+        nodeName: [
+          { required: true, message: '请输入清表名称', trigger: 'blur' },
+        ],
+        tabType: [
+          { required: true, message: '请选择清表类型', trigger: 'blur' },
+        ],
+      },
+      wbsform: {
+        id: '',
+        wbsType: '',
+        wbsName: '',
+      },//wbs树选中的值
       tableData: [],//右侧表数据
+      wbsmiddle: false,//选择wbs模板那块是否有
+      tableList: [],//进行处理的wbs关联表
       exceltypeData: [],//清表类型枚举
       wbsmodel: [],//wbs模板名称枚举
       //#endregion
@@ -260,6 +373,13 @@ export default {
       const { data: res } = await tabLazytree({ modeId })
       console.log(res);
       if (res.code === 200) {
+        if (Array.isArray(res.data)) {
+          res.data.forEach((val) => {
+            if (!val.hasChildren) {
+              val.leaf = true
+            }
+          })
+        }
         this.data = res.data
       }
     },
@@ -267,7 +387,12 @@ export default {
       const { data: res } = await detailExcel({ id })
       console.log(res);
       if (res.code === 200) {
-        console.log(res.data.alias);
+        this.from.id = res.data.id
+        this.from.extension = res.data.extension  //文件名称
+        this.from.fileUrl = res.data.fileUrl      //文件路径
+        let routeUrl = res.data.fileUrl
+        let pSrc = routeUrl + '?r=' + new Date()
+        this.excelSrc = 'http://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(pSrc)
       }
     },
     async getWbsTypeList () {//清表编辑 wbs 下拉框选择
@@ -288,47 +413,151 @@ export default {
       const { data: res } = await wbstree({ parentId: 0, wbsId: this.excelForm.wbsId, wbsType: this.excelForm.wbsType })
       console.log(res);
       if (res.code === 200) {
-        res.data.forEach((val) => {
-          if (!val.hasChildren) {
-            val.leaf = true
-          }
-        })
-        this.wbsdata = res.data
+        if (res.msg != "未查询到信息") {
+          res.data.forEach((val) => {
+            if (!val.hasChildren) {
+              val.leaf = true
+            }
+          })
+          this.wbsdata = res.data
+        }
       }
     },
     async selectByNodeTable (id, wbsType) {//wbs树获取表
       const { data: res } = await selectByNodeTable({ id, wbsType })
       console.log(res);
       if (res.code === 200) {
-        this.tableData = res.data
+        if (res.msg == "未查询到信息") {
+          this.tableData = []
+        } else {
+          this.tableData = res.data
+          this.tableData.forEach(val => {
+            val.changeTable = val.isLinkTable
+          })
+        }
       }
     },
-    async deleteExcel (ids) {//删除清表
-      const { data: res } = await deleteExcel({ ids })
+    async deleteExcelshu (ids) {//删除清表
+      const { data: res } = await deleteExcelshu(ids)
       console.log(res);
       if (res.code === 200) {
-
+        this.$message({
+          message: '删除清表树成功',
+          type: 'success'
+        });
+        // this.tabLazytree(0)
+        this.tabLazytree(this.$route.params.id)//获取清表树
+        this.from = {
+          checkd: false,//判断是否可以进行上传、重新上传excel
+          id: '',//清表树ID
+          extension: '', //文件名称
+          fileUrl: '',//文件路径
+        }
       }
     },
-    async Excelmodify () {//编辑添加清表
-      const { data: res } = await Excelmodify()
+    async Excelmodify (wbsExclTabParmVO) {//编辑添加清表
+      console.log(wbsExclTabParmVO);
+      const { data: res } = await Excelmodify(wbsExclTabParmVO)
       console.log(res);
+      if (res.code === 200) {
+        // await this.tabLazytree(0)
+        await this.tabLazytree(this.$route.params.id)//获取清表树
+        this.dialogTap = false
+      }
     },
-    async uploadExcel () {//上传清表
-      const { data: res } = await uploadExcel()
+    async uploadExcel (data) {//上传清表
+      const { data: res } = await uploadExcel(data)
       console.log(res);
+      if (res.code === 200) {
+        this.$message({
+          message: '上传文件成功',
+          type: 'success'
+        })
+        this.detailExcel(this.from.id)
+      }
+      this.fileList = []
+    },
+    async deleteExcel (data) {//删除excel表
+      const { data: res } = await deleteExcel(data)
+      if (res.code === 200) {
+        this.$message({
+          message: '删除excel表成功',
+          type: 'success'
+        })
+        this.detailExcel(this.from.id)
+      }
+    },
+    //#endregion
+
+    //#region 右侧
+    uploadChange (file, fileList) {//选中表后触发
+      console.log(file, fileList);
+      this.fileList = [file.raw]
+      let formData = new FormData()
+      formData.append('file', ...this.fileList)
+      formData.append('nodeId', this.from.id)
+      this.uploadExcel(formData)
+    },
+    delectExcelMS () {//删除excel表点击事件、
+      let _that = this
+      this.$confirm('确认删除该文件?', '', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        _that.deleteExcel({ id: _that.from.id, fileUrl: '' })
+      }).catch(() => {
+      })
+    },
+    downloadExcel () {//下载excel表
+      window.open(this.from.fileUrl)
     },
     //#endregion
 
     //#region  外层左侧事件
     nodeClick (data) {//外层树结构
       console.log(data);
-      // this.detailExcel(data.id)
+      if (data.hasChildren == false || data.fileType == 3) {
+        this.from.checkd = true
+      } else {
+        this.from.checkd = false
+      }
+      if (this.from.checkd) {
+        this.detailExcel(data.id)
+      } else {
+        this.from = {
+          checkd: false,//判断是否可以进行上传、重新上传excel
+          id: '',//清表树ID
+          extension: '', //文件名称
+          fileUrl: '',//文件路径
+        }
+      }
     },
-    editExcel () {//编辑
-      console.log(111);
+    async editExcel (data) {//编辑
+      console.log(data);
+      if (data.fileType != 3 && data.hasChildren) {
+        this.wbsmiddle = false
+      } else {
+        this.wbsmiddle = true
+        this.getWbsTypeList()//wbs模板名称
+      }
+      const { data: res } = await detailExcel({ id: data.id })
+      console.log(res);
+      if (res.code === 200) {
+        this.excelForm.id = res.data.id
+        this.excelForm.nodeName = res.data.name      //清表名称
+        this.excelForm.tabType = res.data.tabType    //清表类型
+        this.dialogTap = true
+      }
     },
-    addExcel (data) {//添加
+    async addExcel (data) {//添加
+      console.log(data);
+      if (data.fileType != 3 && data.hasChildren) {
+        this.wbsmiddle = false
+      } else {
+        this.wbsmiddle = true
+        this.getWbsTypeList()//wbs模板名称
+      }
       this.excelForm.parentId = data.id
       this.dialogTap = true
     },
@@ -338,8 +567,8 @@ export default {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'error'
-      }).then(async () => {
-        await _that.deleteExcel(data.id)
+      }).then(() => {
+        _that.deleteExcelshu(data.id)
       }).catch(() => {
       });
     },
@@ -349,12 +578,20 @@ export default {
     handleClose () {//关闭弹框触发事件
       this.excelForm = {
         nodeName: '',//清表名称
-        parentId: '',//清表Id
+        tabType: '',//清表类型
+        id: '',//清表Id,编辑时用
+        parentId: '',//清表Id,添加时用
         wbsId: '',//WBS模板Id
         wbsType: '',//WBS模板类型
       }
+      this.wbsform = {
+        id: '',
+        wbsType: '',
+        wbsName: '',
+      }//wbs树选中的值
       this.wbsdata = []  //wbs树数据
       this.tableData = []//弹框table数据
+      this.tableList = []//关联取消关联的数据
       this.dialogTap = false
     },
     wbsmodelchange (val) {//wbs模板change事件
@@ -367,20 +604,102 @@ export default {
       }
       this.wbstree()
     },
-    async nodeClickExcel (data) {//wbs树点击事件
+    nodeClickExcel (data) {//wbs树点击事件
       console.log(data);
-      this.selectByNodeTable(data.id, data.type)
+      this.wbsform.id = data.id
+      this.wbsform.wbsType = data.type
+      this.wbsform.wbsName = data.deptName
+      if (this.tableList == '') {
+        this.selectByNodeTable(data.id, data.type)
+      } else {
+        let tag = true
+        this.tableList.forEach((val) => {
+          if (val.id == data.id) {
+            this.tableData = val.arrs
+            tag = false
+          }
+        })
+        if (tag) {
+          this.selectByNodeTable(data.id, data.type)
+        }
+      }
+
+    },
+    relation (key) {//关联
+      this.tableData[key].isLinkTable = 2
+      let tap = this.tableList.find((val) => {
+        return val.id == this.wbsform.id
+      })
+      if (!tap) {
+        this.tableList.push({
+          id: this.wbsform.id,
+          wbsType: this.wbsform.wbsType,
+          wbsName: this.wbsform.wbsName,
+          arrs: this.tableData
+        })
+      }
+    },
+    Disassociate (key) {//取消关联
+      this.tableData[key].isLinkTable = 1
+      const tap = this.tableList.find((val) => {
+        return val.id == this.wbsform.id
+      })
+      if (!tap) {
+        this.tableList.push({
+          id: this.wbsform.id,
+          wbsType: this.wbsform.wbsType,
+          wbsName: this.wbsform.wbsName,
+          arrs: this.tableData
+        })
+      }
     },
     saveExcel () {//保存按钮
-
+      this.$refs.excelForm.validate(async (valid) => {
+        if (valid) {
+          let linkDataInfo = []
+          if (this.tableList.length > 0) {
+            this.tableList.forEach(val => {
+              let linkIds = ''
+              val.arrs.forEach(da => {
+                if (da.isLinkTable != da.changeTable) {
+                  linkIds = `${linkIds}${linkIds != '' ? ',' : ''}${da.id}`
+                }
+              })
+              if (linkIds != '') {
+                linkDataInfo.push({
+                  id: val.id,
+                  linkIds: linkIds,
+                  wbsName: val.wbsName,
+                  wbsType: val.wbsType
+                })
+              }
+            })
+          }
+          if (this.excelForm.parentId && !this.excelForm.id) {
+            await this.Excelmodify({
+              nodeName: this.excelForm.nodeName,
+              tabType: this.excelForm.tabType,
+              parentId: this.excelForm.parentId,
+              linkDataInfo: linkDataInfo
+            })
+          } else {
+            await this.Excelmodify({
+              nodeName: this.excelForm.nodeName,
+              tabType: this.excelForm.tabType,
+              id: this.excelForm.id,
+              linkDataInfo: linkDataInfo
+            })
+          }
+          this.handleClose()
+        }
+      });
     },
     //#endregion
   },
   created () {
     this.excelType()//清表类型
-    this.getWbsTypeList()//wbs模板名称
-    // this.tabLazytree(this.$route.params.id)//获取清表树
-    this.tabLazytree(0)
+    // this.tabLazytree(0)
+    this.tabLazytree(this.$route.params.id)//获取清表树
   }
 }
 </script>
@@ -389,7 +708,9 @@ export default {
 .marleft10 {
   margin-left: 10px;
 }
-
+/deep/.el-tree-node__expand-icon {
+  font-size: 16px;
+}
 .colorblue {
   color: rgb(0, 82, 217);
 }

+ 114 - 60
src/views/manager/contractinfo/detail.vue

@@ -181,13 +181,8 @@
         </el-tab-pane>
         <el-tab-pane label="分配WBS" name="2">
           <div>
-            <div class="text-align-c">
-              <span class="mg-r-20">选择WBS</span>
-              <el-select v-model="wbsId" @change="wbsChange" placeholder="请选择WBS" style="width:500px;">
-                <el-option v-for="item in wbsList" :key="item.id" :label="item.wbsName" :value="item.id"></el-option>
-              </el-select>
-            </div>
-            <tree-tree :left-tree-data="leftTreeData"></tree-tree>
+            <div v-if="!wbsId" class="text-align-c">项目暂未分配wbs树</div>
+            <tree-tree :left-tree-data="leftTreeData" ref="treetotree" @onAddTree="treeChang" @onDelTree="treeChang" ></tree-tree>
           </div>
         </el-tab-pane>
         <el-tab-pane label="分配项目人员" name="3">
@@ -226,7 +221,7 @@
                   </template>
                 </el-table-column>
               </el-table>
-               <el-input v-model="copyText" ref="copyInput" type="textarea" style='opacity: 0;position: absolute;'></el-input>
+               <el-input v-model="copyText" ref="copyInput" type="textarea" style='opacity: 0;position: absolute;height:1px;overflow:hidden;'></el-input>
             </div>
             <div class="flex jc-al-c mg-t-20">
               <span>添加项目人员</span>
@@ -256,13 +251,12 @@
 </template>
 
 <script>
-  import {getProjectDeatil} from "@/api/manager/projectinfo";
+  import {getProjectDeatil,findProjectTree} from "@/api/manager/projectinfo";
   import {submitContractInfo,getContractInfo,delFileFromUrl,
           findJobByRoleId,findAllUserByCondition,findUserByName,
-          saveUserInfoByProject,removeUsersByIds,resetPasswordByUserId} from "@/api/manager/contractinfo";
+          saveUserInfoByProject,removeUsersByIds,resetPasswordByUserId,
+          submitWbsTreeInContract,getContractInfoTree} from "@/api/manager/contractinfo";
   import {getRoleTree} from "@/api/system/role";
-  import {getList as getwbsList} from "@/api/manager/wbsinfo";
-  import {getAlltree} from "@/api/manager/wbstree";
   import {getDictionary} from "@/api/system/dict";
   import {remove as removeFile} from "@/api/resource/attach";
   import website from '@/config/website';
@@ -318,7 +312,6 @@
         copyText:'',
 
         wbsId:'',
-        wbsList:[],
         leftTreeData:[],
       }
     },
@@ -332,12 +325,13 @@
         },
         deep: true
       },
-      activeType: function (newValue) {
+      activeType: async function (newValue) {
         if(newValue == '3'){
           this.getRoleList();
           this.getUserByName();
         }else if(newValue == '2'){
-          this.getWBSList();
+          await this.getLeftTree();
+          this.getRightTree();
         }
       },
       rId:function(newValue){
@@ -371,68 +365,94 @@
       })
     },
     methods: {
-      init(){
+      async init(){
         this.pid = this.$route.query.pid;
         this.cid = this.$route.query.cid;
         if(!this.cid){
           this.contractForm.pid = this.pid;
         }else{
-          this.getContractInfo();
+          await this.getContractInfo();
         }
+        await this.getProjectDeatil();
         if(this.$route.query.type){
           this.activeType = this.$route.query.type;
         }
 
         this.getContractTypeList();
-        this.getProjectDeatil();
         this.setHeaders(); 
       },
       beforeLeave(activeName, oldActiveName){
-        if(oldActiveName == '1' && !this.contractForm.id){
-          this.$message({
-            type: "warning",
-            message: "请先保存合同段后,再进行合同段的分配"
-          });
-          return false;
-        }
+        return new Promise((resolve,reject)=>{
+          if(oldActiveName == '1' && !this.contractForm.id){
+            this.$message({
+              type: "warning",
+              message: "请先保存合同段后,再进行合同段的分配"
+            });
+            reject();
+          }
 
-       if(this.typeChang[oldActiveName]){
-         this.$confirm('检测到新编辑内容, 是否保存?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '不用',
-          type: 'warning'
-        }).then(() => {
-          switch (oldActiveName) {
-            case '1':
-              this.savecontract().then((res)=>{
-                this.contractForm.id = res.data.data.id;
-                this.$message({
-                  type: "success",
-                  message: "保存成功!"
-                });
-              });
-              break;
+          if(this.typeChang[oldActiveName]){
+            this.$confirm('检测到新编辑内容, 是否保存?', '提示', {
+              confirmButtonText: '确定',
+              cancelButtonText: '不用',
+              type: 'warning'
+            }).then(() => {
+              switch (oldActiveName) {
+                case '1':
+                  this.savecontract().then((res)=>{
+                    this.contractForm.id = res.data.data.id;
+                    resolve();
+                    this.$message({
+                      type: "success",
+                      message: "保存成功!"
+                    });
+                  });
+                  break;
+                case '2':
+                  this.saveWbsTree().then(()=>{
+                    resolve();
+                    this.$message({
+                      type: "success",
+                      message: "保存成功!"
+                    });
+                  })
+                  break;
+              }
+            }).catch(()=>{
+              reject();
+            })
+          }else{
+            resolve();
           }
         })
-       }
       },
 
       getProjectDeatil(){
-        getProjectDeatil(this.pid).then((res)=>{
-          this.projectInfo = res.data.data;
+        return new Promise((resolve)=>{
+          getProjectDeatil(this.pid).then((res)=>{
+            this.projectInfo = res.data.data;
+            this.wbsId = this.projectInfo.referenceWbsTemplateId;
+            resolve();
+          }).finally(()=>{
+            resolve();
+          })
         })
       },
       getContractInfo(){
-        getContractInfo(this.cid).then((res)=>{
-          this.contractForm = res.data.data;
-          if(this.contractForm.startFileUrl){
-            this.isBackShow = true;
-          }
-          if(this.contractForm.projectPlace){
-            this.flageData = ['','',this.contractForm.projectPlace]
-          }
-          this.$nextTick(()=>{
-            this.typeChang['1'] = false;
+        return new Promise((resolve)=>{
+          getContractInfo(this.cid).then((res)=>{
+            this.contractForm = res.data.data;
+            if(this.contractForm.startFileUrl){
+              this.isBackShow = true;
+            }
+            if(this.contractForm.projectPlace){
+              this.flageData = ['','',this.contractForm.projectPlace]
+            }
+            this.$nextTick(()=>{
+              this.typeChang['1'] = false;
+            })
+          }).finally(()=>{
+            resolve();
           })
         })
       },
@@ -440,6 +460,8 @@
       async saveQuit(){
         if(this.activeType == '1'){
           await this.savecontract();
+        }else if(this.activeType == '2'){
+          await this.saveWbsTree();
         }
         this.$message({
           type: "success",
@@ -451,6 +473,8 @@
         if(this.activeType == '1'){
           let res = await this.savecontract();
           this.contractForm.id = res.data.data.id;
+        }else if(this.activeType == '2'){
+          await this.saveWbsTree();
         }
         this.$message({
           type: "success",
@@ -666,17 +690,47 @@
        })
      },
 
-    getWBSList(){
-      getwbsList().then((res)=>{
-        this.wbsList = res.data.data.records;
+    getLeftTree(){
+      return new Promise((resolve)=>{
+        if(!this.leftTreeData.length){
+          findProjectTree(this.projectInfo.id,this.wbsId).then((res)=>{
+            if(Array.isArray(res.data.data)){
+              this.leftTreeData = res.data.data;
+            }else{
+              this.leftTreeData = [];
+            }
+            resolve();
+          }).finally(()=>{
+            resolve();
+          })
+        }
+        resolve();
       })
     },
-    wbsChange(wbsid){
-      getAlltree(this.userInfo.tenant_id,'',wbsid).then((res)=>{
-        this.leftTreeData = res.data.data;
+    getRightTree(){
+      getContractInfoTree(this.wbsId,this.projectInfo.id,this.contractForm.id).then((res)=>{
+        if(Array.isArray(res.data.data)){
+          this.$refs.treetotree.setRightTree(res.data.data);
+        }
       })
     },
 
+    saveWbsTree(){
+      let obj = {};
+      let ids = this.$refs.treetotree.getTreeAllId('rightTree');
+      obj = {
+        wbsId:this.wbsId,
+        projectId:this.projectInfo.id,
+        contractId:this.contractForm.id,
+        wbsTreeIds:ids
+      }
+      return submitWbsTreeInContract(obj);
+     },
+
+     treeChang(){
+      this.typeChang[2] = true;
+    }
+
     }
   };
 </script>

+ 161 - 34
src/views/manager/projectinfo/detail.vue

@@ -62,17 +62,27 @@
           <div>
             <div class="text-align-c">
               <el-radio-group v-model="templateType">
-                <el-radio :label="1">试验</el-radio>
-                <el-radio :label="2">质检</el-radio>
+                <el-radio :label="2">试验</el-radio>
+                <el-radio :label="1">质检</el-radio>
               </el-radio-group>
             </div>
             <div class="text-align-c mg-t-20">
               <span class="mg-r-20">选择WBS</span>
               <el-select v-model="wbsId" @change="wbsChange" placeholder="请选择WBS" style="width:500px;">
-                <el-option v-for="item in wbsList" :key="item.id" :label="item.wbsName" :value="item.id"></el-option>
+                <el-option-group
+                  v-for="group in treeList"
+                  :key="group.label"
+                  :label="group.label">
+                  <el-option
+                    v-for="(item,index) in group.options"
+                    :key="index"
+                    :label="item.label"
+                    :value="item.value">
+                  </el-option>
+                </el-option-group>
               </el-select>
             </div>
-            <tree-tree :left-tree-data="leftTreeData" scrollbarStyle="height:calc(100vh - 500px)"></tree-tree>
+            <tree-tree :left-tree-data="leftTreeData" scrollbarStyle="height:calc(100vh - 500px)" ref="treetotree" :show-all-check="true" @onAddTree="treeChang" @onDelTree="treeChang" @onCheckAll="treeChang"></tree-tree>
           </div>
         </el-tab-pane>
         <el-tab-pane label="分配系统维护人员" name="3">
@@ -89,7 +99,7 @@
             <el-divider></el-divider>
             <div class="flex jc-al-c mg-b-10">
               <span>维护人员角色</span>
-              <avue-input-tree :check-strictly="true" v-model="rId" placeholder="请选择" type="tree" :dic="roleList" :props="treeProps"></avue-input-tree>
+              <avue-input-tree :check-strictly="true" v-model="rId" placeholder="请选择" type="tree" :dic="roleList" :props="treeProps" @change="getUserByCondition"></avue-input-tree>
               <!-- <el-select v-model="rId" clearable placeholder="请选择" @change="getUserByCondition">
                 <el-option v-for="item in roleList" :key="item.id" :label="item.title"  :value="item.id"></el-option>
               </el-select> -->
@@ -110,7 +120,7 @@
               </el-table>
             </div>
             <div class="flex jc-al-c mg-t-20">
-              <span>添加系内部人员</span>
+              <span>添加系内部人员</span>
               <el-select v-model="userId" filterable placeholder="请输入搜索">
                 <el-option v-for="item in userList" :key="item.id" :label="item.name"  :value="item.id"></el-option>
               </el-select>
@@ -136,10 +146,11 @@
 </template>
 
 <script>
-  import {submitProject,getProjectDeatil} from "@/api/manager/projectinfo";
+  import {submitProject,getProjectDeatil,findWbsTreeList,findProjectTree,submitWbsTreeInProject} from "@/api/manager/projectinfo";
   import {findContractByProjectId,saveUserInfoByProject,findUserListByCondition,
           findUserByName,removeUsersByIds} from "@/api/manager/contractinfo";
   import {getRoleTree} from "@/api/system/role";
+  import {getAlltree} from "@/api/manager/wbstree";
   import {getDictionary} from "@/api/system/dict";
   import {mapGetters} from "vuex";
 
@@ -184,8 +195,10 @@
           value:"id"
         },
 
-        templateType:2,
-
+        templateType:1,
+        treeList:[],
+        wbsId:'',
+        leftTreeData:[],
       }
     },
     computed: {
@@ -198,12 +211,31 @@
         },
         deep: true
       },
-      activeType: function (newValue) {
+      activeType: async function (newValue) {
         if(newValue == '3'){
           this.getContractList();
           this.getRoleList();
           this.getUserByCondition();
           this.getUserByName();
+        }else if(newValue == '2'){
+          let refId = this.projectForm.referenceWbsTemplateId;
+          if(refId && refId>0){
+            //有引用id,回显
+            this.wbsId = refId;
+            let projectTree = await findProjectTree(this.projectForm.id,refId)
+            if(Array.isArray(projectTree.data.data)){
+              this.templateType = projectTree.data.data[0].wbsType;
+              let leftData = await getAlltree(this.userInfo.tenant_id,'1',refId)
+              if(Array.isArray(leftData.data.data)){
+                this.leftTreeData = leftData.data.data;
+              }else{
+                this.leftTreeData = [];
+              }
+              this.$refs.treetotree.setRightTree(projectTree.data.data);
+            }
+          }
+          
+          this.getTreeList();
         }
       }
     },
@@ -229,33 +261,49 @@
        }
      },
       beforeLeave(activeName, oldActiveName){
-        if(oldActiveName == '1' && !this.projectForm.id){
-          this.$message({
-            type: "warning",
-            message: "请先保存项目后,再进行项目的分配"
-          });
-          return false;
-        }
+        return new Promise((resolve,reject)=>{
+          if(oldActiveName == '1' && !this.projectForm.id){
+            this.$message({
+              type: "warning",
+              message: "请先保存项目后,再进行项目的分配"
+            });
+            reject();
+          }
 
-       if(this.typeChang[oldActiveName]){
-         this.$confirm('检测到新编辑内容, 是否保存?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '不用',
-          type: 'warning'
-        }).then(() => {
-          switch (oldActiveName) {
-            case '1':
-              this.saveProject().then((res)=>{
-                this.projectForm.id = res.data.data.id;
-                this.$message({
-                  type: "success",
-                  message: "保存成功!"
-                });
-              });
-              break;
+          if(this.typeChang[oldActiveName]){
+            this.$confirm('检测到新编辑内容, 是否保存?', '提示', {
+              confirmButtonText: '确定',
+              cancelButtonText: '不用',
+              type: 'warning'
+            }).then(() => {
+              switch (oldActiveName) {
+                case '1':
+                  this.saveProject().then((res)=>{
+                    this.projectForm.id = res.data.data.id;
+                    resolve();
+                    this.$message({
+                      type: "success",
+                      message: "保存成功!"
+                    });
+                  });
+                  break;
+                case '2':
+                  this.saveWbsTree().then(()=>{
+                    resolve();
+                    this.$message({
+                      type: "success",
+                      message: "保存成功!"
+                    });
+                  })
+                  break;
+              }
+            }).catch(()=>{
+              reject();
+            })
+          }else{
+              resolve();
           }
         })
-       }
      },
 
      getProjectDeatil(){
@@ -270,6 +318,8 @@
      async saveQuit(){
        if(this.activeType == '1'){
           await this.saveProject();
+        }else if(this.activeType == '2'){
+          await this.saveWbsTree();
         }
        this.$message({
           type: "success",
@@ -281,6 +331,8 @@
         if(this.activeType == '1'){
           let res = await this.saveProject();
           this.projectForm.id = res.data.data.id;
+        }else if(this.activeType == '2'){
+          await this.saveWbsTree();
         }
         this.$message({
           type: "success",
@@ -309,6 +361,17 @@
        })
      },
 
+     saveWbsTree(){
+      let obj = {};
+      let ids = this.$refs.treetotree.getTreeAllId('rightTree');
+      obj = {
+        wbsId:this.wbsId,
+        projectId:this.projectForm.id,
+        wbsTreeIds:ids
+      }
+      return submitWbsTreeInProject(obj);
+     },
+
      addUserToProject(){
        if(!this.userId){
          this.$message({
@@ -417,6 +480,70 @@
         getRoleTree().then((res)=>{
           this.roleList = res.data.data
         })
+      },
+
+      wbsChange(value){
+        //console.log(value)
+        if(value.toString().indexOf(',') >= 0){
+          //私有库
+          let ids = value.toString().split(',');
+          findProjectTree(ids[1],ids[0]).then((res)=>{
+            if(Array.isArray(res.data.data)){
+              this.leftTreeData = res.data.data;
+            }else{
+              this.leftTreeData = [];
+            }
+          })
+        }else{
+          //公有库
+          getAlltree(this.userInfo.tenant_id,'1',value).then((res)=>{
+            if(Array.isArray(res.data.data)){
+              this.leftTreeData = res.data.data;
+            }else{
+              this.leftTreeData = [];
+            }
+          })
+        }
+      },
+
+      getTreeList(){
+        return new Promise((resolve)=>{
+          if(this.treeList.length){
+            resolve();
+          }
+          findWbsTreeList(this.templateType).then((res)=>{
+            let arr = [{
+              label:'公有库',
+              options:[],
+            },
+            {
+              label:'私有库',
+              options:[],
+            }];
+            let data = res.data.data;
+            if(data.wbsInfos && data.wbsInfos.length){
+              data.wbsInfos.forEach((element)=>{
+                element.label = element.wbsName;
+                element.value = element.id;
+              })
+              arr[0].options = data.wbsInfos;
+            }
+            if(data.wbsTreePrivates && data.wbsTreePrivates.length){
+              data.wbsTreePrivates.forEach((element)=>{
+                element.label = element.projectName;
+                element.value = element.wbsId +','+ element.projectId;
+              })
+              arr[1].options = data.wbsTreePrivates;
+            }
+            this.treeList = arr;
+          }).finally(()=>{
+            resolve();
+          })
+        })
+      },
+
+      treeChang(){
+        this.typeChang[2] = true;
       }
 
     }

+ 259 - 183
src/views/manager/projectinfo/list.vue

@@ -3,14 +3,36 @@
     <div>
       <div class="pd-b-20 border-grey-b">
         <span class="mg-r-10">选择项目名称</span>
-        <el-select v-model="projectId" @change="projectChange" placeholder="请选择">
-          <el-option  v-for="item in projectList"  :key="item.id" :label="item.projectName" :value="item.id"></el-option>
+        <el-select
+          v-model="projectId"
+          @change="projectChange"
+          placeholder="请选择"
+        >
+          <el-option
+            v-for="item in projectList"
+            :key="item.id"
+            :label="item.projectName"
+            :value="item.id"
+          ></el-option>
         </el-select>
       </div>
       <div class="pd-t-20">
-        <el-row :gutter="20"  style="height:calc(100vh - 290px)">
-          <el-col :span="6" v-for="(item,index) in projectPageList" :key="item.id" style="height:20%;" class="mg-b-20 box-size-bb">
-            <el-card @click.native="projectClick(item)" class="box-card h-100p flex flex-center project_name" :class="getBg(index)">
+        <el-row
+          :gutter="20"
+          style="height:calc(100vh - 290px)"
+        >
+          <el-col
+            :span="6"
+            v-for="(item,index) in projectPageList"
+            :key="item.id"
+            style="height:20%;"
+            class="mg-b-20 box-size-bb"
+          >
+            <el-card
+              @click.native="projectClick(item)"
+              class="box-card h-100p flex flex-center project_name"
+              :class="getBg(index)"
+            >
               {{item.projectAlias}}
             </el-card>
           </el-col>
@@ -18,41 +40,92 @@
       </div>
       <div>
         <el-pagination
-          layout="prev, pager, next" class="text-align-c"
+          layout="prev, pager, next"
+          class="text-align-c"
           @current-change="handleCurrentChange"
           :current-page.sync="page.currentPage"
-          :total="page.total" :page-size="page.pageSize">
+          :total="page.total"
+          :page-size="page.pageSize"
+        >
         </el-pagination>
       </div>
     </div>
 
-    <el-dialog title="项目信息" :visible.sync="projectVisible" width="800px" append-to-body>
+    <el-dialog
+      title="项目信息"
+      :visible.sync="projectVisible"
+      width="800px"
+      append-to-body
+    >
       <div class="flex jc-sb pd-b-10">
         <span>{{curProjiect.projectName}}</span>
         <div>
-          <el-button size="small" type="success">WBS树管理</el-button>
-          <el-button size="small" @click="editProject" type="primary">编辑项目信息</el-button>
-          <el-button size="small" @click="addContract" type="info">创建新合同段</el-button>
-          <el-button size="small" @click="projectVisible = false">返回</el-button>
+          <el-button
+            size="small"
+            type="success"
+            @click="wbsManage()"
+          >WBS树管理</el-button>
+          <el-button
+            size="small"
+            @click="editProject"
+            type="primary"
+          >编辑项目信息</el-button>
+          <el-button
+            size="small"
+            @click="addContract"
+            type="info"
+          >创建新合同段</el-button>
+          <el-button
+            size="small"
+            @click="projectVisible = false"
+          >返回</el-button>
         </div>
       </div>
-      <div style="height:400px;overflow: auto;" v-if="contractList.length > 0">
-        <el-card shadow="never" v-for="(item,index) in contractList" :key="item.id">
+      <div
+        style="height:400px;overflow: auto;"
+        v-if="contractList.length > 0"
+      >
+        <el-card
+          shadow="never"
+          v-for="(item,index) in contractList"
+          :key="item.id"
+        >
           <div class="flex jc-sb">
             <div class="flex jc-al-c">
-              <el-avatar :size="50" :class="getAvatarBg(item.contractType)">{{getFont(item.contractType)}}</el-avatar>
+              <el-avatar
+                :size="50"
+                :class="getAvatarBg(item.contractType)"
+              >{{getFont(item.contractType)}}</el-avatar>
               <span class="mg-l-10">{{item.contractName}}</span>
             </div>
             <div class="flex jc-al-c">
-              <el-link type="primary" @click="editContract(item)">编辑合同段信息</el-link>
-              <el-link type="primary" class="mg-l-10" @click="contractDetail(item,'2')">分配WBS</el-link>
-              <el-link type="primary" class="mg-l-10" @click="contractDetail(item,'3')">分配项目人员</el-link>
-              <el-link type="primary" class="mg-l-10" @click="delContract(item,index)">删除</el-link>
+              <el-link
+                type="primary"
+                @click="editContract(item)"
+              >编辑合同段信息</el-link>
+              <el-link
+                type="primary"
+                class="mg-l-10"
+                @click="contractDetail(item,'2')"
+              >分配WBS</el-link>
+              <el-link
+                type="primary"
+                class="mg-l-10"
+                @click="contractDetail(item,'3')"
+              >分配项目人员</el-link>
+              <el-link
+                type="primary"
+                class="mg-l-10"
+                @click="delContract(item,index)"
+              >删除</el-link>
             </div>
           </div>
         </el-card>
       </div>
-      <div class="text-align-c pd-t-20" v-else>
+      <div
+        class="text-align-c pd-t-20"
+        v-else
+      >
         暂无合同段,请先创建合同段
       </div>
     </el-dialog>
@@ -60,187 +133,190 @@
 </template>
 
 <script>
-  import {getProjectList} from "@/api/manager/projectinfo";
-  import {findContractByProjectId,removeContractInfo} from "@/api/manager/contractinfo";
-  import {getDictionary} from "@/api/system/dict";
-  import {mapGetters} from "vuex";
-  export default {
-    data() {
-      return {
-        projectId:'',
-        curProjiect:{},
-        projectList:[],
-        projectPageList:[],
+import { getProjectList } from "@/api/manager/projectinfo";
+import { findContractByProjectId, removeContractInfo } from "@/api/manager/contractinfo";
+// import {getDictionary} from "@/api/system/dict";
+import { mapGetters } from "vuex";
+export default {
+  data () {
+    return {
+      projectId: '',
+      curProjiect: {},
+      projectList: [],
+      projectPageList: [],
 
-        projectVisible:false,
-        contractList:[],
+      projectVisible: false,
+      contractList: [],
 
-        page:{
-          currentPage:1,
-          pageSize:16,
-          total:0
-        }
+      page: {
+        currentPage: 1,
+        pageSize: 16,
+        total: 0
       }
+    }
+  },
+  computed: {
+    ...mapGetters(["userInfo"]),
+  },
+  created () {
+    this.init();
+    //console.log(this.userInfo)
+  },
+  methods: {
+    init () {
+      this.getProjectList();
+      this.getProjectPageList();
     },
-    computed: {
-      ...mapGetters(["userInfo"]),
+
+    getProjectList () {
+      getProjectList(1, 999).then((res) => {
+        this.projectList = res.data.data.records;
+      })
     },
-    created() {
-      this.init();
-      //console.log(this.userInfo)
+    getProjectPageList () {
+      getProjectList(this.page.currentPage, this.page.pageSize).then((res) => {
+        this.projectPageList = res.data.data.records;
+        this.page.total = res.data.data.total;
+      })
     },
-    methods: {
-      init(){
-        this.getProjectList();
-        this.getProjectPageList();
-      },
 
-      getProjectList(){
-        getProjectList(1,999).then((res)=>{
-          this.projectList = res.data.data.records;
-        })
-      },
-      getProjectPageList(){
-        getProjectList(this.page.currentPage,this.page.pageSize).then((res)=>{
-          this.projectPageList = res.data.data.records;
-          this.page.total = res.data.data.total;
-        })
-      },
-
-      projectClick(item){
-        this.curProjiect = item;
-        findContractByProjectId(this.curProjiect.id).then((res)=>{
-          this.contractList = res.data.data;
-        })
-        this.projectVisible = true;
-      },
+    projectClick (item) {
+      this.curProjiect = item;
+      findContractByProjectId(this.curProjiect.id).then((res) => {
+        this.contractList = res.data.data;
+      })
+      this.projectVisible = true;
+    },
 
-      handleCurrentChange(val){
-        this.getProjectPageList();
-        this.page.currentPage = val;
-      },
+    handleCurrentChange (val) {
+      this.getProjectPageList();
+      this.page.currentPage = val;
+    },
 
-      projectChange(id){
-        for (let i = 0; i < this.projectList.length; i++) {
-          if(id == this.projectList[i].id){
-            this.curProjiect = this.projectList[i];
-            findContractByProjectId(this.curProjiect.id).then((res)=>{
-              this.contractList = res.data.data;
-            })
-            this.projectVisible = true;
-            return;
-          }
+    projectChange (id) {
+      for (let i = 0; i < this.projectList.length; i++) {
+        if (id == this.projectList[i].id) {
+          this.curProjiect = this.projectList[i];
+          findContractByProjectId(this.curProjiect.id).then((res) => {
+            this.contractList = res.data.data;
+          })
+          this.projectVisible = true;
+          return;
         }
-      },
+      }
+    },
 
-      addContract(){
-        this.$router.push({
-          path:'/contract/detail',
-          query:{pid:this.curProjiect.id}
-        });
-      },
-      editContract(item){
-        this.$router.push({
-          path:'/contract/detail',
-          query:{
-            pid:item.pid,
-            cid:item.id,
-          }
-        });
-      },
-      editProject(){
-        this.$router.push({
-          path:'/manager/projectinfo/detail',
-          query:{
-            id:this.curProjiect.id
-          }
-        });
-      },
-      contractDetail(item,type){
-        this.$router.push({
-          path:'/contract/detail',
-          query:{
-            pid:item.pid,
-            cid:item.id,
-            type,
-          }
-        });
-      },
+    addContract () {
+      this.$router.push({
+        path: '/contract/detail',
+        query: { pid: this.curProjiect.id }
+      });
+    },
+    editContract (item) {
+      this.$router.push({
+        path: '/contract/detail',
+        query: {
+          pid: item.pid,
+          cid: item.id,
+        }
+      });
+    },
+    editProject () {
+      this.$router.push({
+        path: '/manager/projectinfo/detail',
+        query: {
+          id: this.curProjiect.id
+        }
+      });
+    },
+    contractDetail (item, type) {
+      this.$router.push({
+        path: '/contract/detail',
+        query: {
+          pid: item.pid,
+          cid: item.id,
+          type,
+        }
+      });
+    },
 
-      delContract(item,index){
-        this.$confirm('是否删除【'+item.contractName+'】?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        }).then(() => {
-          removeContractInfo(item.id).then(()=>{
-            this.$message({
-              type: "success",
-              message: "删除成功!"
-            });
-            this.contractList.splice(index,1);
-          })
+    delContract (item, index) {
+      this.$confirm('是否删除【' + item.contractName + '】?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        removeContractInfo(item.id).then(() => {
+          this.$message({
+            type: "success",
+            message: "删除成功!"
+          });
+          this.contractList.splice(index, 1);
         })
-      },
+      })
+    },
 
-      getFont(type){
-        if(type == 1){
-          return '施';
-        }else if(type == 2){
-          return '监';
-        }else if(type == 3){
-          return '业';
-        }
-        return '';
-      },
-      getAvatarBg(type){
-        if(type == 1){
-          return {'abg1':true};
-        }else if(type == 2){
-          return {'abg2':true};
-        }else if(type == 3){
-          return {'abg3':true};
+    getFont (type) {
+      if (type == 1) {
+        return '施';
+      } else if (type == 2) {
+        return '监';
+      } else if (type == 3) {
+        return '业';
+      }
+      return '';
+    },
+    getAvatarBg (type) {
+      if (type == 1) {
+        return { 'abg1': true };
+      } else if (type == 2) {
+        return { 'abg2': true };
+      } else if (type == 3) {
+        return { 'abg3': true };
+      }
+      return {};
+    },
+    getBg (index) {
+      let num = Math.trunc(index / 4);
+      if ((num % 2) === 0) {//判定条件余数为0时为偶数
+        return {
+          'bg1': true
         }
-        return {};
-      },
-      getBg(index){
-        let num = Math.trunc(index/4);
-        if((num%2)===0){//判定条件余数为0时为偶数
-          return{
-            'bg1':true
-          }
-        }else{
-          return{
-            'bg2':true
-          }
+      } else {
+        return {
+          'bg2': true
         }
       }
-    }
-  };
+    },
+    wbsManage () {//wbs树管理按钮
+      this.$router.push('/manager/privateWBS/' + 111)
+    },
+  }
+};
 </script>
 
 <style scoped lang="scss">
-  .project_name{
-    font-size: 20px;
-    cursor: pointer;
-  }
-  .bg1{
-    background-color: rgb(127, 164, 221);
-    border-color: rgb(187, 187, 187);
-    box-shadow: rgba(0, 0, 0, .4) 0px 2px 6px 0px;
-  }
-  .bg2{
-    background-color: rgb(239, 240, 229);
-    border-color: rgb(187, 187, 187);
-    box-shadow: rgba(0, 0, 0, .4) 0px 2px 6px 0px;
-  }
-  .abg1{
-    background-color: rgb(42, 155, 121);
-  }
-  .abg2{
-    background-color: rgb(155, 108, 42);
-  }
-  .abg3{
-    background-color: rgb(42, 53, 155);
-  }
+.project_name {
+  font-size: 20px;
+  cursor: pointer;
+}
+.bg1 {
+  background-color: rgb(127, 164, 221);
+  border-color: rgb(187, 187, 187);
+  box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 6px 0px;
+}
+.bg2 {
+  background-color: rgb(239, 240, 229);
+  border-color: rgb(187, 187, 187);
+  box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 6px 0px;
+}
+.abg1 {
+  background-color: rgb(42, 155, 121);
+}
+.abg2 {
+  background-color: rgb(155, 108, 42);
+}
+.abg3 {
+  background-color: rgb(42, 53, 155);
+}
 </style>

+ 135 - 0
src/views/manager/projectinfo/privateWBS.vue

@@ -0,0 +1,135 @@
+<template>
+  <basic-container>
+    <el-row :gutter="20">
+      <el-col :span="6">
+        <div class="box">
+          <p>工程节点信息</p>
+          <div class="flex">
+            <el-input
+              placeholder="输入关键字进行过滤"
+              v-model="filterText"
+              @input="filterChange"
+            ></el-input>
+            <!-- <el-button type="info" class="mg-l-20">导入划分</el-button> -->
+          </div>
+          <el-scrollbar style="height:650px;">
+            <div
+              v-loading="treeLoad"
+              style="padding-top:10px;box-sizing: border-box;"
+            >
+              <el-tree
+                class="filter-tree"
+                :data="treeDta"
+                :load="loadNode"
+                @node-click="getNodeDetail"
+              >
+                <span
+                  class="custom-tree-node"
+                  slot-scope="{ node, data }"
+                >
+                  <span>
+                    {{ node.label }}
+                    <el-dropdown @click="command=>{setLeftType(command,data)}">
+                      <el-button
+                        type="text"
+                        icon="el-icon-more"
+                        class="normal-black"
+                      >
+                      </el-button>
+                      <el-dropdown-menu slot="dropdown">
+                        <el-dropdown-item
+                          @click.native="setLeftType(1,data,node)"
+                          icon="el-icon-circle-plus-outline"
+                        >新增子级</el-dropdown-item>
+                        <el-dropdown-item
+                          @click.native="setLeftType(2,data,node)"
+                          icon="el-icon-edit"
+                        >编辑节点</el-dropdown-item>
+                        <el-dropdown-item
+                          @click.native="setLeftType(3,data,node)"
+                          icon="el-icon-document-copy"
+                        >复制节点</el-dropdown-item>
+                        <el-dropdown-item
+                          @click.native="setLeftType(4,data,node)"
+                          icon="iconfont hcicon-danganziliao-biaogetianxie"
+                          class="font-s-12"
+                        >元素公式</el-dropdown-item>
+                        <el-dropdown-item
+                          @click.native="setLeftType(5,data,node)"
+                          icon="el-icon-coin"
+                        >元素设置</el-dropdown-item>
+                        <el-dropdown-item
+                          @click.native="nodeInfo(data,node)"
+                          icon="el-icon-help"
+                        >节点参数</el-dropdown-item>
+                      </el-dropdown-menu>
+                    </el-dropdown>
+                  </span>
+                </span>
+              </el-tree>
+            </div>
+          </el-scrollbar>
+        </div>
+      </el-col>
+      <el-col :span="18">
+
+        sss
+      </el-col>
+    </el-row>
+  </basic-container>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      filterText: '',//搜素框
+      treeLoad: false,//搜素旋转功能
+      treeDta: [{
+        id: 5,
+        label: '二级 2-1',
+        children: [{
+          label: '二级 1-1',
+          children: [{
+            label: '三级 1-1-1'
+          }]
+        }]
+      }, {
+        id: 9,
+        label: '三级 1-1-1',
+        children: [{
+          label: '二级 1-1',
+          children: [{
+            label: '三级 1-1-1'
+          }]
+        }]
+      }],
+      defaultProps: {
+        children: 'children',
+        label: 'label'
+      },
+    }
+  },
+  methods: {
+    //#region 
+    filterChange () {//收入改变事件
+
+    },
+    getNodeDetail () {//左侧树节点点击事件
+
+    },
+    //#endregion
+  },
+  created () {
+
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.box {
+  border: 1px solid #e0e0e0;
+  box-sizing: border-box;
+  padding: 10px 15px;
+}
+</style>

+ 2 - 2
src/views/manager/wbsinfo.vue

@@ -106,11 +106,11 @@
               dicData: [
                 {
                   label: "否",
-                  value: 1
+                  value: 0
                 },
                 {
                   label: "是",
-                  value: 2
+                  value: 1
                 }
               ],
             },

+ 269 - 33
src/views/manager/wbsinfo/edit.vue

@@ -16,10 +16,11 @@
                 :props="defaultProps" :expand-on-click-node="false"
                 highlight-current node-key="id"
                 ref="tree">
-                <span class="custom-tree-node" slot-scope="{ node, data }">
+                <span class="custom-tree-node" :class="data.moreShow?'show':''"  slot-scope="{ node, data }">
+                  <!--@mouseover="mouseover(data)" @mouseleave="mouseout(data)"-->
                   <span>
                     {{ node.label }}
-                    <el-dropdown @click="command=>{setLeftType(command,data)}">
+                    <el-dropdown @click="command=>{setLeftType(command,data)}" @visible-change="visiblechange($event,data)">
                       <el-button
                         type="text" icon="el-icon-more" class="normal-black">
                       </el-button>
@@ -29,6 +30,7 @@
                         <el-dropdown-item @click.native="setLeftType(3,data,node)" icon="el-icon-document-copy">复制节点</el-dropdown-item>
                         <el-dropdown-item @click.native="setLeftType(4,data,node)" icon="iconfont hcicon-danganziliao-biaogetianxie" class="font-s-12">元素公式</el-dropdown-item>
                         <el-dropdown-item @click.native="setLeftType(5,data,node)" icon="el-icon-coin">元素设置</el-dropdown-item>
+                        <el-dropdown-item @click.native="nodeInfo(data,node)" icon="el-icon-help">节点参数</el-dropdown-item>
                         <el-dropdown-item @click.native="importTemplate(data,node)" v-if="node.level == 2" icon="el-icon-upload">导入划分</el-dropdown-item>
                       </el-dropdown-menu>
                     </el-dropdown>
@@ -42,10 +44,10 @@
                 highlight-current node-key="id"
                 :filter-node-method="filterNode"
                 ref="treeall">
-                <span class="custom-tree-node" slot-scope="{ node, data }">
+                <span class="custom-tree-node" slot-scope="{ node, data }" :class="data.moreShow?'show':''">
                   <span>
                     {{ node.label }}
-                    <el-dropdown @click="command=>{setLeftType(command,data)}">
+                    <el-dropdown @click="command=>{setLeftType(command,data)}" @visible-change="visiblechange($event,data)">
                       <el-button
                         type="text" icon="el-icon-more" class="normal-black">
                       </el-button>
@@ -55,6 +57,7 @@
                         <el-dropdown-item @click.native="setLeftType(3,data,node)" icon="el-icon-document-copy">复制节点</el-dropdown-item>
                         <el-dropdown-item @click.native="setLeftType(4,data,node)" icon="iconfont hcicon-danganziliao-biaogetianxie" class="font-s-12">元素公式</el-dropdown-item>
                         <el-dropdown-item @click.native="setLeftType(5,data,node)" icon="el-icon-coin">元素设置</el-dropdown-item>
+                        <el-dropdown-item @click.native="nodeInfo(data,node)" icon="el-icon-help">节点参数</el-dropdown-item>
                         <el-dropdown-item @click.native="importTemplate(data,node)" v-if="node.level == 2" icon="el-icon-upload">导入划分</el-dropdown-item>
                       </el-dropdown-menu>
                     </el-dropdown>
@@ -66,7 +69,7 @@
       </div>
   </el-col>
   <el-col :span="14">
-      <template v-if="leftType==2 || leftType==1">
+      <template v-if="leftType==5">
         <p>节点信息</p>
         <el-table :data="tableData" border style="width: 100%">
           <el-table-column align="center" prop="deptName" label="当前节点" ></el-table-column>
@@ -189,7 +192,7 @@
         <div></div>
         <div>
           <el-link type="primary" @click="importVisible = true">快捷导入</el-link>
-          <el-link type="primary" class="mg-l-20">下载导入模版</el-link>
+          <el-link type="primary" class="mg-l-20" @click="downloadTmp">下载导入模版</el-link>
         </div>
       </div>
       <div class="border-grey">
@@ -210,7 +213,7 @@
             </el-table-column>
             <el-table-column align="center" prop="eLength" label="长度" width="120">
               <template slot-scope="scope">
-                <el-input v-model="scope.row.eLength" size="small" placeholder="请输入内容"></el-input>
+                <el-input v-model="scope.row.eLength" size="small" placeholder="请输入内容" :disabled="scope.row.eType == 4" ></el-input>
               </template>
             </el-table-column>
             <el-table-column align="center" prop="eAllowDeviation" label="允许偏差值">
@@ -248,22 +251,23 @@
     </el-dialog>
 
     <el-dialog title="模版导入" :visible.sync="importVisible" width="50%" append-to-body :close-on-click-modal="false">
-      <p>提示:必须按照系统要求的模版格式上传,否则系统识别无效  <el-link type="primary">下载导入模版</el-link></p>
+      <p>提示:必须按照系统要求的模版格式上传,否则系统识别无效  <el-link type="primary" @click="downloadTmp">下载导入模版</el-link></p>
       <div>
-        <el-button size="small" type="primary">本地上传</el-button>
+        <el-button size="small" type="primary" @click="fileClick2">本地上传</el-button>
+        <input @change="tmpImport" type="file" hidden ref="file2" accept=".xls, .xlsx">
       </div>
       <el-table :data="tempList" border style="width: 100%" >
-            <el-table-column align="center" prop="eName" label="元素名称" >
-            </el-table-column>
-            <el-table-column align="center" prop="eType" label="数据类型" width="120">
-            </el-table-column>
-            <el-table-column align="center" prop="eLength" label="长度" width="120">
-            </el-table-column>
-            <el-table-column align="center" prop="eAllowDeviation" label="允许偏差值">
-            </el-table-column>
-            <el-table-column align="center" prop="eInspectionMethod" label="检查方法和频率">
-            </el-table-column>
-          </el-table>
+        <el-table-column align="center" prop="eName" label="元素名称" >
+        </el-table-column>
+        <el-table-column align="center" prop="eType" label="数据类型" width="120">
+        </el-table-column>
+        <el-table-column align="center" prop="eLength" label="长度" width="120">
+        </el-table-column>
+        <el-table-column align="center" prop="eAllowDeviation" label="允许偏差值">
+        </el-table-column>
+        <el-table-column align="center" prop="eInspectionMethod" label="检查方法和频率">
+        </el-table-column>
+      </el-table>
       <span slot="footer" class="dialog-footer">
         <el-button @click="importVisible = false">取 消</el-button>
         <el-button type="primary" @click="importHandle">确 定</el-button>
@@ -288,7 +292,7 @@
           </el-table-column>
           <el-table-column align="center" prop="eLength" label="长度" width="120">
             <template slot-scope="scope">
-              <el-input v-model="scope.row.eLength" size="small" placeholder="请输入内容"></el-input>
+              <el-input v-model="scope.row.eLength" size="small" placeholder="请输入内容" :disabled="scope.row.eType == 4"></el-input>
             </template>
           </el-table-column>
           <el-table-column align="center" prop="eAllowDeviation" label="允许偏差值">
@@ -360,6 +364,119 @@
         <el-button type="primary" @click="importTemplateHandle" :loading="importLoading">导 入</el-button>
       </span>
     </el-dialog>
+
+    <el-dialog title="节点参数" :visible.sync="nodeInfoVisible" width="800px" append-to-body :close-on-click-modal="false" :show-close="false">
+      <div>
+        <el-button
+          type="text" icon="el-icon-s-operation" class="right-btn"
+          @click="infoNameVisible = true"></el-button>
+        <el-table :data="nodeInfoTable" border style="width: 100%" height="400">
+          <el-table-column align="center" prop="name" label="参数名称">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-select v-model="scope.row.name" placeholder="请选择" class="w-100p">
+                  <el-option v-for="item in namelist" :key="item.id" :label="item.dictValue"  :value="item.dictKey"></el-option>
+                </el-select>
+              </template>
+              <template v-else>
+                {{scope.row.name}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="value" label="参数值设置">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-input v-model="scope.row.value"></el-input>
+              </template>
+              <template v-else>
+                {{scope.row.value}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="describe" label="描述">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-input v-model="scope.row.describe"></el-input>
+              </template>
+              <template v-else>
+                {{scope.row.describe}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="120" align="center">
+            <template slot-scope="scope">
+              <el-button
+                type="text" size="small" v-show="scope.row.isEdit"
+                @click="saveNodeInfoHandle(scope.$index, scope.row)">保存</el-button>
+              <el-button
+                type="text" size="small" v-show="!scope.row.isEdit"
+                @click="editNodeInfo(scope.$index, scope.row)">编辑</el-button>
+              <el-button
+                type="text" size="small" class="text-icon-danger"
+                @click="delNodeInfo(scope.$index, scope.row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="nodeInfoVisible = false">取 消</el-button>
+        <el-button type="primary" @click="nodeInfoSave">保 存</el-button>
+      </span>
+    </el-dialog>
+
+    <el-dialog title="设置参数名称" :visible.sync="infoNameVisible" width="800px" append-to-body :close-on-click-modal="false">
+      <div>
+        <el-table :data="namelist" border style="width: 100%" height="400">
+          <el-table-column align="center" prop="name" label="参数名称">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-input v-model="scope.row.name"></el-input>
+              </template>
+              <template v-else>
+                {{scope.row.name}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="key" label="参数值KEY">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-input v-model="scope.row.key"></el-input>
+              </template>
+              <template v-else>
+                {{scope.row.key}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="describe" label="描述">
+            <template slot-scope="scope">
+              <template v-if="scope.row.isEdit">
+                <el-input v-model="scope.row.describe"></el-input>
+              </template>
+              <template v-else>
+                {{scope.row.describe}}
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="120" align="center">
+            <template slot-scope="scope">
+              <el-button
+                type="text" size="small" v-show="scope.row.isEdit"
+                @click="saveNodeInfoHandle(scope.$index, scope.row)">保存</el-button>
+              <el-button
+                type="text" size="small" v-show="!scope.row.isEdit"
+                @click="editNodeInfo(scope.$index, scope.row)">编辑</el-button>
+              <el-button
+                type="text" size="small" class="text-icon-danger"
+                @click="delNodeInfo(scope.$index, scope.row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="infoNameVisible = false">关 闭</el-button>
+      </span>
+    </el-dialog>
+
 </basic-container>
 </template>
 
@@ -367,7 +484,8 @@
   import {getLazytree,getDetail,update,selectByNodeTable,getAlltree,
             saveFormAndElement,selectFormElements,removeTableById,
             importWbsTree} from "@/api/manager/wbstree";
-  import {saveElement,remove as removeElement,updateBatchElements} from "@/api/manager/wbsformelement";
+  import {saveElement,remove as removeElement,updateBatchElements,getTemplate,
+          importWbsElement} from "@/api/manager/wbsformelement";
   import {getList as getAttchFromOriginalName} from "@/api/resource/attach";
   import {getDictionary} from "@/api/system/dict";
   import {mapGetters} from "vuex";
@@ -378,6 +496,7 @@
         filterText:'',
         treeData:[],
         treeLoad:false,
+        menuShow:false,
         defaultProps: {
           children: 'children',
           label: 'title',
@@ -385,11 +504,12 @@
             return !data.hasChildren;
           }
         },
-        leftType:2,
+        leftType:5,
         curTreeData:{},
         tableData:[],
         nodeDetail:{},
         formData:[],
+        editType:1,
 
         dialogVisible:false,
         deptCategorylist:[],
@@ -428,6 +548,7 @@
         curEleTable:{},
         editEleVisible:false,
         editEleList:[],
+        eleReg:/(≥|≤|±|【】)?([^≥≤±【】]*)/,
 
         editEleFormulaVisible:false,
         formulaInput:'',
@@ -436,6 +557,12 @@
         fileUrl:'',
         upFile:null,
         importLoading:false,
+
+        nodeInfoVisible:false,
+        nodeInfoTable:[],
+        namelist:[],
+
+        infoNameVisible:false,
       };
     },
     computed: {
@@ -496,9 +623,9 @@
       saveNode(){
         this.$refs['nodeDetail'].validate((valid) => {
           if (valid) {
-            if(this.leftType == 1){
+            if(this.editType == 1){
               this.addNode();
-            }else if(this.leftType == 2){
+            }else if(this.editType == 2){
               this.updateNode();
             }
           } else {
@@ -532,13 +659,16 @@
       },
 
       setLeftType(type,data,node){
-        this.leftType = type;
+        if(type == 4 || type == 5){
+          this.leftType = type;
+        }
         this.curTreeData = data;
         this.$refs.tree.setCurrentKey(data.id);
 
-        if(this.leftType == 1 || this.leftType == 2){
+        if(type == 1 || type == 2){
           this.getMajorDataTypeList();
           this.dialogVisible = true;
+          this.editType = type;
         }
 
         getDetail(data.id).then((res)=>{
@@ -548,7 +678,7 @@
           }
           res.data.data.parentName = parentName;
           this.tableData = [res.data.data];
-          if(this.leftType == 1){
+          if(type == 1){
             this.nodeDetail = {
               parentId:res.data.data.id,
               parentName:parentName
@@ -599,6 +729,9 @@
             this.eleForm.parentId = this.nodeDetail.id;
             this.eleForm.elementList.forEach((element)=>{
               element.eAllowDeviation = (element.allow?element.allow:'') + (element.deviation?element.deviation:'');
+              if(element.eType == 4){
+                element.eLength = 0;
+              }
             })
             saveFormAndElement(this.eleForm).then(()=>{
               //console.log(res)
@@ -640,9 +773,8 @@
       handleEdit(index,row){
         this.curEleTable = row;
         selectFormElements(this.curEleTable.id).then((res)=>{
-          let reg = /(≥|≤|±|【】)?([^≥≤±【】]*)/;
           res.data.data.forEach((element)=>{
-            reg.exec(element.eAllowDeviation);
+            this.eleReg.exec(element.eAllowDeviation);
             // console.log(RegExp.$1)
             // console.log(RegExp.$2)
             element.allow = RegExp.$1?RegExp.$1:'';
@@ -681,9 +813,14 @@
       saveNewEle(row){
         row.eAllowDeviation = (row.allow?row.allow:'') + (row.deviation?row.deviation:'');
         row.fId = this.curEleTable.id;
+        row.initTableName = this.curEleTable.initTableName;
+        if(row.eType == 4){
+          row.eLength = 0;
+        }
         saveElement(row).then((res)=>{
           if(res.data.data){
-            this.$set(row,'id',res.data.data);
+            this.$set(row,'id',res.data.data.id);
+            this.$set(row,'ekey',res.data.data.ekey);
             this.$message({
               type: "success",
               message: "保存成功!"
@@ -700,7 +837,7 @@
             confirmButtonText: '删除',
             cancelButtonText: '取消'
           }).then(() => {
-            removeElement(row.id).then(()=>{
+            removeElement(row.id,this.curEleTable.initTableName,row.ekey).then(()=>{
               list.splice(index,1);
             })
           })
@@ -719,7 +856,13 @@
           }
         }
         if(this.editEleList.length > 0){
-          updateBatchElements(this.editEleList).then(()=>{
+          this.editEleList.forEach((element)=>{
+            element.eAllowDeviation = (element.allow?element.allow:'') + (element.deviation?element.deviation:'');
+            if(element.eType == 4){
+              element.eLength = 0;
+            }
+          })
+          updateBatchElements(this.editEleList,this.curEleTable.initTableName).then(()=>{
             this.editEleVisible = false;
             this.updateNodeTable();
             this.$message({
@@ -796,6 +939,7 @@
           let node = this.$refs.tree.getNode(this.curTreeData.id);
           node.isLeaf = false;
           this.importTemplateVisible = false;
+          this.upFile = null;
         }).finally(()=>{
           this.importLoading = false;
         })
@@ -826,6 +970,77 @@
         this.upFile = file;
       },
 
+      nodeInfo(){
+        this.nodeInfoVisible = true;
+      },
+      nodeInfoSave(){
+
+      },
+
+      delNodeInfo(){
+
+      },
+      editNodeInfo(index,row){
+        this.$set(row,'isEdit',true);
+      },
+      saveNodeInfoHandle(index,row){
+        row.isEdit = false;
+      },
+
+      downloadTmp(){
+        getTemplate().then((res)=>{
+          //console.log(res)
+          let blob = new Blob([res.data], {
+                type: 'application/vnd.ms-excel'
+            });
+            //console.log(blob)
+            let filename = Date.parse(new Date()) + '.xls';
+            if (window.navigator.msSaveOrOpenBlob) {
+                // 兼容IE10
+                window.navigator.msSaveBlob(blob, filename);
+            } else {
+                //  兼容chrome/firefox
+                let aTag = document.createElement('a');
+                aTag.download = Date.parse(new Date()) + '.xls';
+                aTag.href = window.URL.createObjectURL(blob);
+                aTag.click();
+                URL.revokeObjectURL(aTag.href);
+            }
+        })
+      },
+
+      fileClick2(){
+        this.$refs.file2.click();
+      },
+      tmpImport(e){
+        const file = e.target.files[0];
+        const formData = new FormData();
+        formData.append('file', file);
+        //console.log(file.name)
+        importWbsElement(formData).then((res)=>{
+          res.data.data.forEach((element)=>{
+            element.eName = element.elementName;
+            element.eLength = element.elementLength;
+            element.eType = Number(element.elementType);
+            element.eAllowDeviation = element.elementAllowDeviation;
+            element.eInspectionMethod = element.elementInspectionMethod;
+            this.eleReg.exec(element.eAllowDeviation);
+            // console.log(RegExp.$1)
+            // console.log(RegExp.$2)
+            element.allow = RegExp.$1?RegExp.$1:'';
+            element.deviation = RegExp.$2?RegExp.$2:'';
+          })
+          this.eleForm.elementList = res.data.data;
+          this.importVisible = false;
+        }).finally(()=>{
+          e.target.value='';
+        })
+      },
+
+      visiblechange(value,data){
+        this.$set(data, 'moreShow', value)
+      },
+
       getDeptCategorylist(){
         if(this.deptCategorylist.length >1){
           return;
@@ -946,4 +1161,25 @@
   .el-popper[x-placement^=bottom]{
     margin-top: -6px;
   }
+  .right-btn{
+    position: absolute;
+    right: 20px;
+    top: 10px;
+    font-size: 20px;
+  }
+  .custom-tree-node {
+    .normal-black {
+        display: none;
+      }
+    &:hover {
+      .normal-black {
+        display: block;
+      }
+    }
+    &.show .normal-black{
+      display: block;
+    }
+    
+  }
+  
 </style>

+ 171 - 0
src/views/news/news.vue

@@ -0,0 +1,171 @@
+<template>
+<basic-container>
+  <el-menu :default-active="activeIndex" mode="horizontal">
+    <el-menu-item index="1">我的消息</el-menu-item>
+    <el-menu-item index="2">所有消息</el-menu-item>
+  </el-menu>
+  <avue-crud :data="data" :option="option" :table-loading="showLoading" :page.sync="page" :permission="permissionList">
+    <template slot="picture" slot-scope="scope" >
+      <el-button size="small" @click="openPreview(scope)">图片</el-button>
+    </template>
+    <template slot="cz" slot-scope="scope" >
+      <el-button size="small" @click="changeProgres(scope.row)">提交进度</el-button>
+    </template>
+    <template slot="state" slot-scope="scope" >
+      <div class="icon-font">
+        <i class="el-icon-success text-success" v-if="scope.row.state == 1"></i>
+        <i class="el-icon-warning text-warning" v-if="scope.row.state == 2"></i>
+      </div>
+    </template>
+  </avue-crud>
+  <el-dialog :visible.sync="dialogVisible" width="600px" append-to-body :close-on-click-modal="false">
+    <div class="flex jc-al-c">
+      <span class="mg-r-20 titl-font">提交进度</span>
+      <el-select v-model="progres" placeholder="请选择">
+        <el-option label="已解决" :value="1"></el-option>
+        <el-option label="进入人工预处理环境" :value="2"></el-option>
+      </el-select>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+    </span>
+  </el-dialog>
+</basic-container>
+</template>
+
+<script>
+  import {mapGetters} from "vuex";
+  export default {
+    data() {
+      return {
+        activeIndex:"1",
+        curRow:{},
+        dialogVisible:false,
+        progres:1,
+
+        page:{
+          total:1,
+          currentPage: 1
+        },
+        showLoading:false,
+        data: [
+          {
+            time:'2022-05-26 16:20:30',
+            remainingTime:'80',
+            project:'项目',
+            contract:'合同段',
+            newType:'消息类型',
+            describe:'问题描述',
+            picture:[
+              {url:'https://img.alicdn.com/tfs/TB1uevcCrj1gK0jSZFuXXcrHpXa-1880-640.jpg'},
+              {url:'https://img.alicdn.com/tfs/TB1v28TC8v0gK0jSZKbXXbK2FXa-1880-640.jpg'},
+            ],
+            state:1,
+          }, {
+            time:'2022-05-26 16:20:31',
+            remainingTime:'79',
+            project:'项目',
+            contract:'合同段',
+            newType:'消息类型',
+            describe:'问题描述',
+            picture:[
+              {url:'https://img.alicdn.com/tfs/TB1uevcCrj1gK0jSZFuXXcrHpXa-1880-640.jpg'},
+              {url:'https://img.alicdn.com/tfs/TB1v28TC8v0gK0jSZKbXXbK2FXa-1880-640.jpg'},
+            ],
+            state:2,
+          }
+        ],
+        option:{
+          border:true,
+          align:'center',
+          menuAlign:'center',
+          menu:false,
+          column:[
+            {
+              label:'时间',
+              prop:'time',
+            },
+            {
+              label:'剩余反馈用户时间(分钟)',
+              prop:'remainingTime'
+            },
+            {
+              label:'项目',
+              prop:'project',
+            },
+            {
+              label:'合同段',
+              prop:'contract',
+            },
+            {
+              label:'消息类型',
+              prop:'newType',
+            },
+            {
+              label:'问题描述',
+              prop:'describe',
+            },
+            {
+              label:'图片',
+              prop:'picture',
+              slot:true,
+            },
+            {
+              label:'操作',
+              prop:'cz',
+              slot:true,
+            },
+            {
+              label:'处理状态',
+              prop:'state',
+              slot:true,
+            },
+          ]
+         }
+      };
+    },
+    computed: {
+      ...mapGetters(["userInfo"]),
+
+      permissionList() {
+        return {
+          addBtn: false,
+          viewBtn: false,
+          delBtn: false,
+          editBtn: false
+        };
+      },
+    },
+    created() {
+      this.init();
+      //console.log(this.userInfo)
+    },
+    methods: {
+      init(){
+
+      },
+      openPreview(scope,index=0){
+        this.$ImagePreview(scope.row.picture, index,{
+        closeOnClickModal: true,
+        // beforeClose:()=>{
+        //   this.$message.success('关闭回调')
+        // }
+      });
+      },
+      changeProgres(row){
+        this.curRow = row;
+        this.dialogVisible = true;
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  .icon-font[class^="icon-"]{
+    font-size: 26px !important;
+  }
+  .titl-font{
+    font-size: 32px;
+  }
+</style>