Explorar o código

看板上线了

panxiandiao_i %!s(int64=5) %!d(string=hai) anos
pai
achega
221773578c

+ 45 - 1
src/views/Platform/defectManagement.vue

@@ -20,7 +20,7 @@
             <el-select v-model="queryCode.repairResult" size="medium" style="width:15%;margin-right: 10px;" clearable placeholder="修复状态">
               <el-option v-for="item in repairResultStr" :key="item.code" :label="item.name" :value="item.code" />
             </el-select>
-            <el-button type="primary" size="medium" style="margin-right:10px;" icon="el-icon-plus" circle @click="timeShow=! timeShow" />
+            <el-button type="primary" size="medium" style="margin-right:10px;" icon="el-icon-plus" circle @click="timeShow = !timeShow, isPlatformShow = !isPlatformShow, queryCode.platformType = '', isBusinessShow === true ? isBusinessShow = false : isBusinessShow = false" />
           </div>
           <div class="set-between">
             <el-button type="primary" size="medium" plain @click="dataQuery(queryCode)">查询</el-button>
@@ -37,6 +37,12 @@
           end-placeholder="创建结束时间"
           clearable
         />
+        <el-select v-if="isPlatformShow" v-model="queryCode.platformType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="平台类型" @change="clickChangeBusiness(queryCode.platformType)">
+          <el-option v-for="item in platformTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+        </el-select>
+        <el-select v-if="isBusinessShow" v-model="queryCode.clientType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="业务模块" @change="clickChangeModule(queryCode.clientType)">
+          <el-option v-for="item in businessTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+        </el-select>
         <div class="set-locate">
           <el-table
             :data="tableData"
@@ -374,13 +380,17 @@
 
 <script>
 import { bugList, bugGet, bugDelete, bugUpdate, bugCreate, bugCopy, taskListCreate, bugGetEnum } from '@/api/defectManage'
+import { projectGetTypeMap } from '@/api/projectPage.js'
 
 export default {
   name: 'DefectManage',
   data() {
     return {
+      isPlatformShow: false,
+      isBusinessShow: false,
       bugTypeStr: [],
       bugStatusStr: [],
+      bizOptionsRR: [],
       bizOptions: [{ name: '万象', value: 101 }, { name: '企业级', value: 100 }, { name: '滴滴代驾', value: 261 }, { name: 'prado', value: 330 }, { name: 'carbo', value: 331 }, { name: '海马', value: 309 }],
       bugLevelStr: [{ name: 'p0', value: 0 }, { name: 'p1', value: 1 }, { name: 'p2', value: 2 }, { name: 'p3', value: 3 }],
       reasonStr: [],
@@ -442,6 +452,7 @@ export default {
   },
   created() {
     this.getList()
+    this.forkDown()
     this.bugListSelect()
   },
   mounted() {
@@ -507,6 +518,39 @@ export default {
         this.statistics = res.query
       })
     },
+    // 业务线数据获取
+    forkDown() {
+      projectGetTypeMap().then(res => {
+        if (res.code === 200) {
+          this.bizOptionsRR = res.data
+          if (this.bizJson) {
+            this.platformTypeStr = this.bizOptionsRR.filter(value => value.code === parseInt(this.bizJson))[0].child
+            this.$set(this.queryCode, 'platformType', '')
+            this.$set(this.queryCode, 'clientType', '')
+          } else {
+            this.isPlatformShow = false
+            this.isBusinessShow = false
+          }
+        } else {
+          this.errorFun('业务线数据获取失败')
+        }
+      })
+    },
+    // 业务线取子数据
+    clickChangeBusiness(e) {
+      if (e && this.platformTypeStr.filter(value => value.code === e)[0].child) {
+        this.isBusinessShow = true
+        this.businessTypeStr = this.platformTypeStr.filter(value => value.code === e)[0].child
+        this.$set(this.queryCode, 'clientType', '')
+      } else {
+        this.isBusinessShow = false
+      }
+    },
+    clickChangeModule(e) {
+      if (!e) {
+        this.isBusinessShow = false
+      }
+    },
     dataQueryInSearch(e) {
       this.bizJson = localStorage.getItem('key')
       this.indexPage = e

+ 53 - 8
src/views/projectManage/projectList/projectListIndex.vue

@@ -5,19 +5,23 @@
         <el-form :model="queryCode">
           <div class="set-between">
             <!-- <el-form-item label="创建时间" label-width="70px"><el-date-picker v-model="queryCode.dateQuery" align="left" size="medium" type="datetime" style="width:76%;" placeholder="选择日期" /></el-form-item> -->
-            <el-form-item label="项目名称" label-width="70px"><el-input v-model="queryCode.name" placeholder="请选择项目" autocomplete="off" clearable size="medium" style="width:76%;" /></el-form-item>
-            <el-form-item label="状态" label-width="40px">
-              <el-select v-model="queryCode.statusString" size="medium" style="width:60%;" clearable placeholder="状态">
-                <el-option v-for="item in statusOptionss" :key="item.code" :label="item.name" :value="item.code" />
-              </el-select>
-            </el-form-item>
+            <el-input v-model="queryCode.name" placeholder="请选择项目" autocomplete="off" clearable size="medium" style="width:17.5%;margin-right: 15px;" />
+            <el-select v-model="queryCode.statusString" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="状态">
+              <el-option v-for="item in statusOptionss" :key="item.code" :label="item.name" :value="item.code" />
+            </el-select>
+            <el-select v-show="isPlatformShow" v-model="queryCode.platformType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="平台类型" @change="clickChangeBusiness(queryCode.platformType)">
+              <el-option v-for="item in platformTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+            </el-select>
+            <el-select v-show="isBusinessShow" v-model="queryCode.clientType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="业务模块" @change="clickChangeModule(queryCode.clientType)">
+              <el-option v-for="item in businessTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+            </el-select>
           </div>
           <div class="set-between">
             <el-button type="primary" size="medium" plain @click="dataQuery(queryCode)">查询</el-button>
             <el-button type="primary" size="medium" plain @click="createdCode()">新增</el-button>
           </div>
         </el-form>
-        <div class="set-locate">
+        <div style="margin-top:22px">
           <el-table
             :data="list"
             border
@@ -91,11 +95,15 @@
 </template>
 
 <script>
-import { projectInit, deleteProject } from '@/api/projectPage.js'
+import { projectInit, deleteProject, projectGetTypeMap } from '@/api/projectPage.js'
 
 export default {
   data() {
     return {
+      isPlatformShow: false,
+      isBusinessShow: false,
+      platformTypeStr: [],
+      businessTypeStr: [],
       list: [],
       form: {},
       queryCode: {
@@ -116,6 +124,7 @@ export default {
   },
   created() {
     this.getList()
+    this.forkDown()
   },
   mounted() {
     document.getElementsByClassName('app-main')[0].style.cssText = 'overflow:auto'
@@ -164,6 +173,40 @@ export default {
         res.code === 200 ? this.list = res.data : this.errorFun(res.msg)
       })
     },
+    // 业务线数据获取
+    forkDown() {
+      projectGetTypeMap().then(res => {
+        if (res.code === 200) {
+          this.bizOptions = res.data
+          if (this.bizJson) {
+            this.isPlatformShow = true
+            this.platformTypeStr = this.bizOptions.filter(value => value.code === parseInt(this.bizJson))[0].child
+            this.$set(this.form, 'platformType', '')
+            this.$set(this.form, 'clientType', '')
+          } else {
+            this.isPlatformShow = false
+            this.isBusinessShow = false
+          }
+        } else {
+          this.errorFun('业务线数据获取失败')
+        }
+      })
+    },
+    // 业务线取子数据
+    clickChangeBusiness(e) {
+      if (e && this.platformTypeStr.filter(value => value.code === e)[0].child) {
+        this.isBusinessShow = true
+        this.businessTypeStr = this.platformTypeStr.filter(value => value.code === e)[0].child
+        this.$set(this.form, 'clientType', '')
+      } else {
+        this.isBusinessShow = false
+      }
+    },
+    clickChangeModule(e) {
+      if (!e) {
+        this.isBusinessShow = false
+      }
+    },
     dataQueryInSearch(queryCode) {
       this.Arra = []
       queryCode.statusString !== '' ? this.Arra.push(queryCode.statusString) : ''
@@ -239,6 +282,8 @@ export default {
       background-color #F0F2F4 !important
     .set-between
       display flex
+    .set-between:first-child
+      width 80%
     .set-between >>> .el-button
       height 36px
     .set-between >>> .el-form-item

+ 437 - 50
src/views/projectManage/taskList/taskListIndex.vue

@@ -7,19 +7,23 @@
             <el-form :model="form">
               <div class="set-between">
                 <!-- <el-form-item label="创建时间" label-width="70px"><el-date-picker v-model="form.createTime" align="left" size="medium" type="datetime" style="width:76%;" placeholder="选择日期" /></el-form-item> -->
-                <el-form-item label="任务名称" label-width="70px"><el-input v-model="form.name" placeholder="填写任务名称" autocomplete="off" clearable size="medium" style="width:76%;" /></el-form-item>
-                <el-form-item label="状态" label-width="40px">
-                  <el-select v-model="form.status" size="medium" style="width:60%;" clearable placeholder="状态">
-                    <el-option v-for="item in processStatusEnumList" :key="item.code" :label="item.name" :value="item.code" />
-                  </el-select>
-                </el-form-item>
+                <el-input v-model="form.name" placeholder="任务名称" autocomplete="off" clearable size="medium" style="width:17.5%;margin-right: 15px;" />
+                <el-select v-model="form.status" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="状态">
+                  <el-option v-for="item in processStatusEnumList" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
+                <el-select v-show="isPlatformShow" v-model="form.platformType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="平台类型" @change="clickChangeBusiness(form.platformType)">
+                  <el-option v-for="item in platformTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
+                <el-select v-show="isBusinessShow" v-model="form.clientType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="业务模块" @change="clickChangeModule(form.clientType)">
+                  <el-option v-for="item in businessTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
               </div>
               <div class="set-between">
                 <el-button type="primary" plain size="medium" @click="dataQuery(form)">查询</el-button>
                 <el-button type="primary" plain size="medium" @click="createdCode()">新增</el-button>
               </div>
             </el-form>
-            <div class="set-locate">
+            <div style="margin-top:22px">
               <el-table
                 :data="tableData"
                 border
@@ -93,13 +97,17 @@
             <el-form :model="formKanBan">
               <div class="set-between-kanban">
                 <!-- <el-form-item label="创建时间" label-width="70px"><el-date-picker v-model="form.createTime" align="left" size="medium" type="datetime" style="width:76%;" placeholder="选择日期" /></el-form-item> -->
-                <el-form-item label="状态" label-width="40px">
-                  <el-select v-model="formKanBan.status" size="medium" style="width:70%;" clearable placeholder="状态">
-                    <el-option v-for="item in processStatusEnumListKanBan" :key="item.code" :label="item.name" :value="item.code" />
-                  </el-select>
-                </el-form-item>
-                <el-form-item label="分组" label-width="40px"><el-input v-model="formKanBan.group" placeholder="填写分组名称" autocomplete="off" clearable size="medium" style="width:70%;" /></el-form-item>
-                <el-form-item label="标签" label-width="40px"><el-input v-model="formKanBan.tag" placeholder="填写标签名称" autocomplete="off" clearable size="medium" style="width:70%;" /></el-form-item>
+                <el-select v-model="formKanBan.status" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="状态">
+                  <el-option v-for="item in processStatusEnumListKanBan" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
+                <el-input v-model="formKanBan.group" placeholder="填写分组名称" autocomplete="off" clearable size="medium" style="width:17.5%;margin-right: 15px;" />
+                <el-input v-model="formKanBan.tag" placeholder="填写标签名称" autocomplete="off" clearable size="medium" style="width:17.5%;margin-right: 15px;" />
+                <el-select v-show="isPlatformShow" v-model="formKanBan.platformType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="平台类型" @change="clickChangeBusiness(formKanBan.platformType)">
+                  <el-option v-for="item in platformTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
+                <el-select v-show="isBusinessShow" v-model="formKanBan.clientType" size="medium" style="width:17.5%;margin-right: 15px;" clearable placeholder="业务模块" @change="clickChangeModule(form.clientType)">
+                  <el-option v-for="item in businessTypeStr" :key="item.code" :label="item.name" :value="item.code" />
+                </el-select>
                 <el-button type="primary" size="medium" style="z-index:999" plain @click="kanBanQuery(formKanBan)">查询</el-button>
               </div>
             </el-form>
@@ -111,16 +119,44 @@
           <div class="collapse">
             <span @click="isCollapsing = !isCollapsing">&lt;&lt; 收起</span>
           </div>
-          <el-tree
-            ref="treeBox"
-            icon-class="el-icon-caret-right"
-            :data="dealWithBusinessDate"
-            node-key="id"
-            highlight-current
-            :props="defaultProps"
-            style="margin-top:20px;min-width:100%;display:inline-block !important;"
-            @node-click="handleNodeClick"
-          />
+          <div class="scroll-navigate">
+            <div v-show="!isEmpty" class="empty-add">
+              <i class="el-icon-circle-plus" @click="addNewNode()" /><span @click="addNewNode()">新建文件夹</span>
+            </div>
+            <el-tree
+              v-show="isEmpty"
+              ref="treeBox"
+              icon-class="el-icon-caret-right"
+              :data="dealWithBusinessDate"
+              node-key="id"
+              highlight-current
+              :default-expanded-keys="defaultExpanded"
+              :props="defaultProps"
+              :expand-on-click-node="false"
+              style="margin-top:10px;min-width:100%;display:inline-block !important;"
+              @node-click="handleNodeClick"
+            >
+              <span slot-scope="{ node, data }" class="custom-tree-node" @mouseenter="mouseenter(data)" @mouseleave="mouseleave(data)">
+                <span v-if="data.spanAbsolute" @dblclick="dblclick(data)">{{ node.label }}</span>
+                <el-input v-if="data.isDbShow" ref="get_Input" v-model="data.pauseContent" autofocus size="mini" @keyup.enter.native="handleInput(node, data)" @blur="handleInput(node, data)" />
+                <el-input v-if="data.isNextDb" ref="get_InputNext" v-model="data.pauseContentNext" autofocus size="mini" @blur="handleInputNext(node, data)" @keyup.enter.native="handleInput(node, data)" />
+                <span>
+                  <el-dropdown v-show="data.del" trigger="hover">
+                    <span class="el-dropdown-link" style="font-weight:bold;z-index:999;">
+                      ···<i class="el-icon--right" />
+                    </span>
+                    <el-dropdown-menu slot="dropdown">
+                      <!-- <el-dropdown-item icon="el-icon-coin" @click.native="addNewNode()">新建节点</el-dropdown-item> -->
+                      <el-dropdown-item icon="el-icon-coin" @click.native="dblclick(data)">修改名称</el-dropdown-item>
+                      <el-dropdown-item icon="el-icon-coin" @click.native="() => append(data)">新建子节点</el-dropdown-item>
+                      <el-dropdown-item icon="el-icon-coin" @click.native="() => deleteNode(data)">删除分组</el-dropdown-item>
+                    </el-dropdown-menu>
+                  </el-dropdown>
+                </span>
+              </span>
+            </el-tree>
+            <el-input v-if="isNewFile" ref="getNewFile" v-model="addFileName" autofocus size="mini" @blur.stop="addFile()" />
+          </div>
         </div>
         <div v-show="!isCollapsing" class="collapse-navigation">
           <div class="expand-collapse">
@@ -153,7 +189,7 @@
                 </div>
                 <draggable v-model="statusAll.taskInfos" :sort="false" group="statusAll.taskInfos" :move="checkMove" @add="targetRecording(statusAll.status)">
                   <div v-for="item in statusAll.taskInfos" :key="item.id" class="inner-drag" :class="{ waitColor: [0, 1, 2, 3, 4, 6, 8, 9].indexOf(statusAll.status) !== -1, 'processColor': [5, 7].indexOf(statusAll.status) !== -1, 'finishColor': [10, 11, 12].indexOf(statusAll.status) !== -1 }">
-                    <div class="span-wrap">
+                    <div class="span-wrap" @click="jumpToReport(item.id)">
                       <div class="set-reverse">
                         <span>ID :&nbsp;{{ item.id }}</span>
                         <div class="center">
@@ -161,15 +197,15 @@
                         </div>
                       </div>
                     </div>
-                    <div class="span-wrap">
+                    <div class="span-wrap" @click="jumpToReport(item.id)">
                       <span>名称 :&nbsp;{{ item.name }}</span>
                     </div>
-                    <div class="span-wrap">
+                    <div class="span-wrap" @click="jumpToReport(item.id)">
                       <div class="priority" :class="{ 'priority-red':item.priorityString === 'p0', 'priority-orange':item.priorityString === 'p1', 'priority-green':item.priorityString === 'p2', 'priority-blue':item.priorityString === 'p3', 'priority-purple':item.priorityString === 'p4', 'priority-yellow':item.priorityString === 'p5', 'priority-grey':item.priorityString === 'p6' }">
                         <span>{{ item.priorityString }}</span>
                       </div>
                     </div>
-                    <div class="span-wrap">
+                    <div class="span-wrap" @click="jumpToReport(item.id)">
                       <div class="set-wrap">
                         <div v-for="(role,index) in item.nameGroup" :key="index" class="role-color" :class="{ 'priority-orange':( index+1 ) % 7 === 1, 'priority-blue':( index+1 ) % 7 === 2, 'priority-green':( index+1 ) % 7 === 3, 'priority-red':( index+1 ) % 7 === 4, 'priority-purple':( index+1 ) % 7 === 5, 'priority-yellow':( index+1 ) % 7 === 6, 'priority-grey':( index+1 ) % 7 === 0 }">
                           <span>
@@ -180,8 +216,31 @@
                     </div>
                     <div class="span-wrap">
                       <div class="only-tag">
-                        <i class="el-icon-price-tag" />
-                        <span>{{ item.tag }}</span>
+                        <!-- <i class="el-icon-price-tag" /> -->
+                        <el-tag
+                          v-for="(tag,index) in item.tagGroup"
+                          :key="index"
+                          type="info"
+                          closable
+                          size="mini"
+                          :disable-transitions="false"
+                          @close.stop="handleClose(tag,item)"
+                        >
+                          <i class="el-icon-price-tag" /> {{ tag }}
+                        </el-tag>
+                        <!-- <el-input v-if="data.isNextDb" ref="get_InputNext" v-model="data.pauseContentNext" autofocus size="mini" @blur="handleInputNext(node, data)" @keyup.enter.native="handleInput(node, data)" /> -->
+                        <el-input
+                          v-if="item.inputVisible"
+                          ref="save_TagInput"
+                          v-model="item.inputValue"
+                          autofocus
+                          class="input-new-tag"
+                          size="mini"
+                          style="width:30%;margin-left:10px;"
+                          @keyup.enter.native="$event.target.blur"
+                          @blur="handleInputConfirm(item)"
+                        />
+                        <el-button v-if="!item.inputVisible" class="button-new-tag" icon="el-icon-plus" size="mini" circle @click="() => showInput(item)" />
                       </div>
                     </div>
                   <!-- <div class="tag-wrap">
@@ -202,10 +261,12 @@
 <script>
 import { taskListGet } from '@/api/defectManage'
 import { bugGetEnum } from '@/api/defectManage' // 下拉菜单data
-import { deleteTaskData, listMap, updateTaskList } from '@/api/projectPage.js'
+import { deleteTaskData, listMap, updateTaskList, projectGetTypeMap } from '@/api/projectPage.js'
 import { updateComment, deleteComment, listComment, createComment } from '@/api/KanBan.js'
 import draggable from 'vuedraggable'
-import axios from 'axios'
+// import axios from 'axios'
+
+// let CONSTANT_ID = 9999
 
 export default {
   components: {
@@ -214,15 +275,24 @@ export default {
   },
   data() {
     return {
+      isPlatformShow: false,
+      isBusinessShow: false,
+      platformTypeStr: [],
+      businessTypeStr: [],
+      defaultExpanded: [],
       labelDrag: [],
+      isNewFile: false,
+      isClosing: 'none',
       tableData: [],
       dealWithBusinessDate: [],
       defaultProps: {
         children: 'child',
-        label: 'commentInfo.content'
+        label: (data, node) => data.commentInfo.content
       },
       form: {},
+      addFileName: '',
       isCollapsing: true,
+      isEmpty: true,
       formKanBan: {},
       dialogVisible: false,
       bizJson: localStorage.getItem('key'),
@@ -239,7 +309,8 @@ export default {
       activeName: 'first',
       pauseId: '',
       processStatusEnumList: [],
-      processStatusEnumListKanBan: []
+      processStatusEnumListKanBan: [],
+      bizOptions: []
     }
   },
   watch: {
@@ -248,13 +319,19 @@ export default {
     },
     isCollapsing(newKanbanWidth) {
       newKanbanWidth === false ? document.getElementsByClassName('content')[0].style.cssText = 'width:93.5%' : document.getElementsByClassName('content')[0].style.cssText = 'width:82.5%'
+    },
+    dealWithBusinessDate(newData, old) {
+      newData.length === 0 ? this.isEmpty = false : this.isEmpty = true
     }
   },
   created() {
     this.bugListSelectBeforeGet()
+    this.forkDown()
   },
   mounted() {
     document.getElementsByClassName('app-main')[0].style.cssText = 'overflow:auto'
+    document.getElementsByClassName('el-tree__empty-block')[0].style.cssText = 'display:none'
+    // document.getElementsByClassName('el-tag__close')[0].style.cssText = 'display:none'
   },
   methods: {
     async bugListSelectBeforeGet() {
@@ -354,6 +431,14 @@ export default {
       })
       this.dialogVisible = false
     },
+    // 显示隐藏删除图标
+    mouseenter(data) {
+      this.$set(data, 'del', true)
+    },
+    mouseleave(data) {
+      this.$set(data, 'del', false)
+    },
+
     // 看板移动更新
     checkMove(evt) {
       this.pauseFromId = evt.draggedContext.element.id
@@ -372,15 +457,114 @@ export default {
         }
       })
     },
+    // 业务线数据获取
+    forkDown() {
+      projectGetTypeMap().then(res => {
+        if (res.code === 200) {
+          this.bizOptions = res.data
+          if (this.bizJson) {
+            this.isPlatformShow = true
+            this.platformTypeStr = this.bizOptions.filter(value => value.code === parseInt(this.bizJson))[0].child
+            this.$set(this.form, 'platformType', '')
+            this.$set(this.form, 'clientType', '')
+          } else {
+            this.isPlatformShow = false
+            this.isBusinessShow = false
+          }
+        } else {
+          this.errorFun('业务线数据获取失败')
+        }
+      })
+    },
+    // 业务线取子数据
+    clickChangeBusiness(e) {
+      if (e && this.platformTypeStr.filter(value => value.code === e)[0].child) {
+        this.isBusinessShow = true
+        this.businessTypeStr = this.platformTypeStr.filter(value => value.code === e)[0].child
+        this.$set(this.form, 'clientType', '')
+      } else {
+        this.isBusinessShow = false
+      }
+    },
+    clickChangeModule(e) {
+      if (!e) {
+        this.isBusinessShow = false
+      }
+    },
     // 看板获取
     kanBanDrag() {
       this.loadingOnlineProcess = true
       const initValue = { bizId: this.bizJson }
-      axios.all([listMap(initValue), listComment({ type: 1 })]).then(axios.spread((res, resNavigation) => {
+      listMap(initValue).then((res) => {
         res.code === 200 ? this.labelDrag = this.bubble(res.data) : this.errorFun(res.msg)
-        resNavigation.code === 200 ? this.dealWithBusinessDate = resNavigation.data : this.errorFun(resNavigation.msg)
         this.loadingOnlineProcess = false
-      }))
+        // HTMLCollection 如何便利呢
+        // console.log(document.getElementsByClassName('el-tag__close'))
+        // document.getElementsByClassName('el-tag__close').map((eachHtml) => {
+        //   eachHtml.style.cssText = 'display:none'
+        // })
+      })
+    },
+    // 标签删除
+    handleClose(tag, item) {
+      const afterDeleteArr = item.tagGroup.filter((eachData) => eachData !== tag)
+      this.$confirm('是否确认删除', '确认信息', {
+        distinguishCancelAndClose: true,
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+      }).then(() => {
+        const sendData = { id: item.id, tag: afterDeleteArr.join(',') }
+        const userData = { id: '', ename: this.userInformation, name: this.userNames }
+        const objData = { taskInfo: sendData, user: userData }
+        updateTaskList(objData).then(res => {
+          this.kanBanDrag()
+        })
+      }).catch(action => {
+        this.$message({ type: 'success', message: '已取消' })
+      })
+    },
+    // 失去焦点执行
+    handleInputConfirm(item) {
+      if (item.inputValue === undefined) {
+        item.inputVisible = false
+        return
+      }
+      item.tagGroup.push(item.inputValue)
+      const sendData = { id: item.id, tag: item.tagGroup.join(',') }
+      const userData = { id: '', ename: this.userInformation, name: this.userNames }
+      const objData = { taskInfo: sendData, user: userData }
+      updateTaskList(objData).then((res) => {
+        this.$set(item, 'inputVisible', false)
+        this.kanBanDrag()
+      })
+    },
+    // 添加标签
+    showInput(item) {
+      this.$set(item, 'inputVisible', true)
+      this.$nextTick(() => {
+        // setTimeout(() => {
+        //   that.$refs.save_TagInput.focus()
+        // })
+        this.$refs.save_TagInput[0].focus() // 真的神奇。。。
+      })
+    },
+    // 导航栏获取
+    navigationGet() {
+      listComment({ bizId: this.bizJson, type: 1 }).then((res) => {
+        const reduceNa = (arr) => { // modules和child
+          arr.forEach((each) => {
+            each.id = each.commentInfo.id
+            each.spanAbsolute = true
+            if (each.child) {
+              each.child = reduceNa(each.child)
+            }
+          })
+          return arr
+        }
+        res.code === 200 ? this.dealWithBusinessDate = reduceNa(res.data) : this.errorFun(res.msg)
+        // this.dealWithBusinessDate === [] ? this.isEmpty = false : this.isEmpty = true
+        // console.log(this.isEmpty)
+      })
     },
     // 冒泡数量从高到低 和 分组
     bubble(arr) {
@@ -401,11 +585,14 @@ export default {
           break
         }
       }
-      // 自己处理数组
+      // 自己处理吧 (^_^)
       res = res.map(eachData => ({
         ...eachData,
         taskInfos: eachData.taskInfos.map(detail => ({
           ...detail,
+          tagGroup: [
+            ...(detail.tag ? detail.tag.split(',').map(str => str.trim()) : [])
+          ],
           nameGroup: [
             ...(detail.pmList ? detail.pmList.split(',').map(str => str.trim()) : []),
             ...(detail.qaList ? detail.qaList.split(',').map(str => str.trim()) : []),
@@ -419,13 +606,106 @@ export default {
     // 标签页研发质量
     handleClick() {
       if (this.activeName === 'second') {
+        this.isBusinessShow = false
         this.kanBanDrag()
+        this.navigationGet()
       } else if (this.activeName === 'first') {
+        this.isBusinessShow = false
         this.bugListSelectBeforeGet()
       } else {
         this.errorFun('获取数据失败')
       }
     },
+    // 新增子节点
+    append(data) {
+      const newChild = { id: data.id, commentInfo: { content: '新建文件夹' }, child: [] }
+      if (!data.child) {
+        this.$set(data, 'child', [])
+      }
+      // this.$nextTick(() => {
+      //   data.child.push(newChild)
+      // })
+      data.child.push(newChild)
+      this.defaultExpanded.push(data.id)
+      this.$set(newChild, 'pauseContentNext', newChild.commentInfo.content)
+      this.$set(newChild, 'isNextDb', true)
+      this.$set(newChild, 'isDbShow', false)
+      this.$set(newChild, 'spanAbsolute', false)
+      this.$nextTick(() => {
+        setTimeout(() => {
+          this.$refs.get_InputNext.focus()
+        })
+        this.$refs.get_InputNext.focus()
+      })
+    },
+    // 创建下级节点
+    handleInputNext(node, data) {
+      if (data.pauseContentNext === '') {
+        this.$set(data, 'isNextDb', false)
+        this.$set(data, 'isDbShow', false)
+        this.$set(data, 'spanAbsolute', true)
+        return
+      }
+      const sendData = { bizId: this.bizJson, type: 1, fatherId: data.id, content: data.pauseContentNext }
+      const userData = { id: '', ename: this.userInformation, name: this.userNames }
+      const objData = { commentInfo: sendData, user: userData }
+      createComment(objData).then((res) => {
+        this.$set(data, 'isNextDb', false)
+        this.$set(data, 'isDbShow', false)
+        this.$set(data, 'spanAbsolute', true)
+        this.navigationGet()
+      })
+    },
+    // 删除节点
+    deleteNode(data) {
+      this.$confirm('是否确认删除', '确认信息', {
+        distinguishCancelAndClose: true,
+        confirmButtonText: '确定',
+        cancelButtonText: '取消'
+      }).then(() => {
+        const userData = { bizId: this.bizJson, id: '', ename: this.userInformation, name: this.userNames }
+        const objData = { user: userData }
+        deleteComment(data.commentInfo.id, objData).then(res => {
+          this.defaultExpanded.push(data.commentInfo.fatherId)
+          this.navigationGet()
+        })
+      }).catch(action => {
+        this.$message({ type: 'success', message: '已取消' })
+      })
+    },
+    // 新建最外级节点
+    addNewNode() {
+      this.isEmpty = true
+      this.isNewFile = true
+      this.$nextTick(() => {
+        this.$refs.getNewFile.focus()
+      })
+    },
+    addFile() {
+      if (this.addFileName === '') {
+        this.isNewFile = false
+        this.isEmpty = false
+        return
+      }
+      const sendData = { bizId: this.bizJson, type: 1, fatherId: 0, content: this.addFileName }
+      const userData = { id: '', ename: this.userInformation, name: this.userNames }
+      const objData = { commentInfo: sendData, user: userData }
+      createComment(objData).then((res) => {
+        this.isNewFile = false
+        this.navigationGet()
+        this.addFileName = ''
+      })
+    },
+    // 双击编辑
+    dblclick(data) {
+      this.$set(data, 'pauseContent', data.commentInfo.content)
+      this.$set(data, 'isDbShow', true)
+      this.$set(data, 'isNextDb', false)
+      this.$set(data, 'spanAbsolute', false)
+      this.$nextTick(() => {
+        this.$refs.get_Input.focus()
+      })
+    },
     // 看板查询
     kanBanQuery(e) {
       for (const key in e) {
@@ -440,9 +720,47 @@ export default {
         this.loadingOnlineProcess = false
       })
     },
+    // 看板跳转
+    jumpToReport(id) {
+      this.$router.push({ name: '任务查看', query: { id: id }})
+    },
     // tree
     handleNodeClick(data) {
-      console.log(data)
+      console.log(data.commentInfo.fatherId)
+      if (data.commentInfo.fatherId === 0) {
+        this.kanBanDrag()
+      } else {
+        this.loadingOnlineProcess = true
+        const initValue = { bizId: this.bizJson, groups: data.commentInfo.id }
+        listMap(initValue).then((res) => {
+          res.code === 200 ? this.labelDrag = this.bubble(res.data) : this.errorFun(res.msg)
+          this.loadingOnlineProcess = false
+        // HTMLCollection 如何便利呢
+        // console.log(document.getElementsByClassName('el-tag__close'))
+        // document.getElementsByClassName('el-tag__close').map((eachHtml) => {
+        //   eachHtml.style.cssText = 'display:none'
+        // })
+        })
+      }
+    },
+    // 双击编辑
+    handleInput(node, data) {
+      if (data.pauseContent === data.commentInfo.content) {
+        this.$set(data, 'isDbShow', false)
+        this.$set(data, 'isNextDb', false)
+        this.$set(data, 'spanAbsolute', true)
+        return
+      }
+      const sendData = { bizId: this.bizJson, type: 1, id: data.commentInfo.id, content: data.pauseContent }
+      const userData = { id: '', ename: this.userInformation, name: this.userNames }
+      const objData = { commentInfo: sendData, user: userData }
+      updateComment(objData).then((res) => {
+        this.defaultExpanded.push(data.commentInfo.fatherId)
+        this.$set(data, 'isDbShow', false)
+        this.$set(data, 'isNextDb', false)
+        this.$set(data, 'spanAbsolute', true)
+        this.navigationGet()
+      })
     },
     handleCurrentChange(curIndex) {
       this.curIndex = curIndex
@@ -493,6 +811,8 @@ export default {
       background-color #F0F2F4 !important
     .set-between
       display flex
+    .set-between:first-child
+      width 80%
     .set-between >>> .el-button
       height 36px
     .set-between >>> .el-form-item
@@ -502,6 +822,8 @@ export default {
       display flex
       align-items center
       margin-bottom 20px
+    .set-between-kanban:first-child
+      width 80%
     .set-between-kanban >>> .el-button
       height 36px
     .set-between-kanban >>> .el-form-item
@@ -531,6 +853,49 @@ export default {
           line-height 35px
           span
             cursor pointer
+        .scroll-navigate
+          overflow-x scroll
+          height calc(100% - 30px)
+          // .span_el
+          //   display block
+          //   overflow hidden
+          //   /* white-space: nowrap; */
+          //   text-overflow ellipsis
+          .empty-add
+            width 100%
+            height calc(100% - 30px)
+            display flex
+            align-items center
+            justify-content center
+            span
+              color rgba(111,124,147,1)
+              font-size 14px
+              padding-left 5px
+              cursor pointer
+            .el-icon-circle-plus
+              opacity 0.4
+              cursor pointer
+          .custom-tree-node
+            width 100%
+            font-size 14px
+            display flex
+            align-items center
+            justify-content space-between
+            font-size 14px
+            // padding-right 25px
+          .el-button--text
+            margin-right 10px
+      .navigation >>> .el-tree-node__content
+        height 30px !important
+      .navigation >>> .el-tree-node__children
+        opacity 0.9
+      .navigation >>> .el-tree-node__expand-icon
+        font-size 14px
+        color black
+        opacity 0.7
+      .navigation >>> .el-tree-node__expand-icon.is-leaf
+        color transparent !important
+        cursor default !important
       .collapse-navigation
         background-color rgba(255,255,255,1)
         box-shadow 0px 0px 11px 0px rgba(238,240,245,1)
@@ -618,7 +983,7 @@ export default {
                 margin 10px auto 0 auto
                 background-color white
                 border-radius 4px
-                padding 10px
+                padding 10px 10px 4px 10px
                 border-left-width 4px
                 border-left-style solid
                 &.waitColor
@@ -693,21 +1058,43 @@ export default {
                         transform scale(0.8)
                         font-size 12px
                   .only-tag
-                    background-color #EDEDED
+                    width 100%
                     display flex
-                    align-items center
-                    justify-content center
+                    flex-wrap wrap
                     margin-top 6px
-                    border-radius 8px
-                    width fit-content
-                    // height 18px
-                    padding 0 6px 0 6px
                     span
-                      color #333B4A
-                      transform scale(0.8)
                       font-size 12px
+                    .el-tag
+                      margin 0px 10px 6px 0px
+                      display flex
+                      // align-items center
+                      // justify-content center
+                      // height 28px
+                    .button-new-tag
+                      // margin-left 10px
+                      padding 3px
+                      height 20px
+                      background-color #f4f4f5
+                      // height 25px
+                      // width 25px
+                      display flex
+                      // align-items center
+                      // justify-content center
+                      // height 32px
+                      // line-height 30px
+                      // padding-top 0
+                      // padding-bottom 0
+                    .input-new-tag
+                      // width 90px
+                      // height 25px
+                      // margin-left 10px
+                      // vertical-align bottom
+                    .input-new-tag >>> .el-input__inner
+                      height 20px
+                      line-height 20px
                     .el-icon-price-tag
-                      margin-right 2px
+                      margin-right 4px
+                      padding-top 3px
                       font-size 12px
                       transform rotate(-45deg)
                   .set-reverse