Browse Source

任务详情重写,查看某天反馈详情时,点击单元格就弹出

ysc 1 năm trước cách đây
mục cha
commit
40ba2c4f6f

+ 43 - 1
src/views/mixins/task.js

@@ -9,6 +9,20 @@ const statusMap = {
   '5': {name: '终止', type: 'warning'},
   '6': {name: '待审核', type: 'warning'}
 }
+
+const fieldMap = {
+  'taskName': '任务名称',
+  'projectId': '所属项目',
+  'beginDate': '开始日期',
+  'endDate': '结束日期',
+  'executor': '执行人',
+  'fileUrl': '附件',
+  'description': '描述',
+  'priority': '优先级',
+  'status': '状态',
+}
+
+
 export default {
 
   data() {
@@ -21,7 +35,15 @@ export default {
         '4': '#67c23a',
         '5': '#e6a23c',
         '6': '#e1b111'
-      }
+      },
+      priorityColorMap: {
+        '1': '#fa8888',
+        '2': '#fb7fb7',
+        '3': '#f4d66d',
+        '4': '#40e0c3',
+        '5': '#5dcfff',
+      },
+      clickTimer: undefined,
     }
   },
 
@@ -50,5 +72,25 @@ export default {
       })
       return label
     },
+
+    cellMouseEnter(row, column, cell, event) {
+      if (column.property != 'taskName') {
+        return
+      }
+      cell.style.color = '#306FB1';
+      cell.style.cursor = 'pointer';
+      cell.style.textDecoration = 'underline';
+    },
+    cellMouseLeave(row, column, cell, event) {
+      if (column.property != 'taskName') {
+        return
+      }
+      cell.style.color = '#606266';
+      cell.style.textDecoration = 'none';
+    },
+
+    getFieldName(field) {
+      return fieldMap[field]
+    }
   }
 }

+ 143 - 0
src/views/task/components/auditTask.vue

@@ -0,0 +1,143 @@
+<template>
+  <div>
+    <el-form :model="form" size="mini" label-width="100px">
+      <el-form-item label="任务名称:">
+        <div>{{ form.taskName }}</div>
+      </el-form-item>
+      <el-form-item label="父任务:" v-if="form.parentTaskId">
+        <div class="p-task" @click="getParentTask(form.parentTaskId)">{{ form.parentTaskName }}</div>
+      </el-form-item>
+
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <el-form-item label="所属项目:">
+            <div>{{ form.projectName }}</div>
+          </el-form-item>
+        </el-col>
+        <el-col :span="10">
+          <el-form-item label="起止时间:">
+            <div>{{ form.beginDate + ' 至 ' + form.endDate }}</div>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="执行(负责)人:" label-width="110px">
+            <div>{{ form.executorName }}</div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-form-item label="任务描述:">
+        <div v-html="form.description"></div>
+      </el-form-item>
+      <el-form-item label="附件:">
+        <div v-if="form.fileList.length>0">
+          <div v-for="(file,index) in form.fileList">
+            <a :href="file.url" style="color: darkgreen">
+              <span style="margin-left: 5px">{{ file.name }}</span>
+            </a>
+          </div>
+        </div>
+        <div v-else>
+          无
+        </div>
+      </el-form-item>
+    </el-form>
+    <el-table :data="form.feedbacks" size="mini" border>
+      <el-table-column width="75" label="反馈状态">
+        <template slot-scope="scope">
+          <div>{{ getFeedbackTypeName(scope.row.feedbackType) }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
+      <el-table-column width="60" label="完成度">
+        <template slot-scope="scope">
+          <div v-if="scope.row.value!==undefined">{{ scope.row.value + '%' }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column width="120" property="createTime" label="反馈时间">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column width="70" property="hours" label="工时(h)"></el-table-column>
+      <el-table-column label="反馈备注">
+        <template slot-scope="scope">
+          <span>{{ scope.row.description }}</span>
+          <span v-for="(file,index) in scope.row.fileList">
+              <a :href="file.url" style="color: darkgreen">
+                <span style="margin-left: 5px">{{ file.name }}</span>
+              </a>
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column label="反馈详情" width="80px">
+        <template slot-scope="scope">
+          <el-popover
+            v-if="scope.row.descriptionDetail&&scope.row.descriptionDetail.length>0"
+            placement="top"
+            width="600"
+            trigger="hover">
+            <div v-html="scope.row.descriptionDetail"></div>
+            <el-button slot="reference" type="text">详情</el-button>
+          </el-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import {getTask} from "@/api/task/task";
+
+export default {
+  name: "taskDetail",
+  props: {
+    detailForm: {
+      type: Object,
+      default: {}
+    }
+  },
+  watch: {
+    detailForm(val) {
+      this.form = val
+    }
+  },
+  data() {
+    return {
+      form: {}
+    }
+  },
+  created() {
+    this.form = this.detailForm
+  },
+  methods: {
+    getFeedbackTypeName(type) {
+      if (type === '1') {
+        return '进度反馈'
+      } else if (type === '2') {
+        return '完成'
+      } else if (type === '3') {
+        return '终止'
+      } else if (type === '4') {
+        return '评论'
+      }
+      return '审批'
+    },
+    getParentTask(id) {
+      getTask(id).then(res => {
+        this.form = res.data;
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
+  margin-bottom: 10px;
+}
+
+.p-task {
+  color: #1c84c6;
+  text-decoration: underLine
+}
+</style>

+ 52 - 7
src/views/task/components/project.vue

@@ -20,12 +20,14 @@
         :expand-on-click-node="false"
         :check-on-click-node="true"
         :filter-node-method="filterNode"
-        default-expand-all
         :indent="10"
+        accordion
         ref="projectTree"
         class="custom-tree"
         node-key="id"
         :highlight-current="true"
+        :default-expanded-keys="expandedKeys"
+        @node-expand="nodeExpand"
         @node-click="handleNodeClick">
             <span class="custom-tree-node" slot-scope="{ node, data }">
               <el-tooltip class="item" effect="dark" :content="node.label" :disabled="node.label&&node.label.length<11"
@@ -42,7 +44,9 @@
                 <el-button size="mini" @click="handleUpdate(data)" v-hasPermi="['task:project:edit']">修改</el-button>
                 <el-button size="mini" type="danger" @click="handleDelete(data)"
                            v-hasPermi="['task:project:delete']">删除</el-button>
-                <el-button size="mini" @click="handleDetail(data)" v-if="data.type==='项目'"
+                <el-button size="mini" @click="handleTable(data)" v-if="data.type==='项目'"
+                           v-hasPermi="['task:project:table']">统计</el-button>
+                <el-button size="mini" @click="handleDetail(data)"
                            v-hasPermi="['task:project:table']">详情</el-button>
                 <i class="el-icon-share" slot="reference"
                    v-hasPermi="['task:project:add','task:project:edit','task:project:delete','task:project:table']"></i>
@@ -59,7 +63,8 @@
         </el-form-item>
         <el-form-item label="上级结构" prop="parentId">
           <treeselect v-model="form.parentId" :options="projectOptions" :normalizer="normalizer"
-                      @select="treeSelectChange" placeholder="请选择"/>
+                      @select="treeSelectChange" :disabled="!form.parentId&&title==='修改项目'"
+                      :placeholder="title==='修改项目'?'无':'请选择'"/>
         </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-radio-group v-model="form.status">
@@ -81,6 +86,32 @@
       </div>
     </el-dialog>
 
+    <!-- 查看项目配置详情对话框 -->
+    <el-dialog title="详情" :visible.sync="detailOpen" @close="cancel" width="700px" class="add-dialog" append-to-body>
+      <el-form ref="form" :model="form" size="mini" label-width="100px">
+        <el-form-item label="名称" prop="projectName">
+          <div>{{ form.projectName }}</div>
+        </el-form-item>
+        <el-form-item label="上级结构" prop="parentId">
+          <treeselect v-model="form.parentId" :options="projectOptions" :normalizer="normalizer"
+                      @select="treeSelectChange" :disabled="true"
+                      placeholder="无"/>
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-radio-group v-model="form.status" :disabled="true">
+            <el-radio label="0">正常</el-radio>
+            <el-radio label="1">停用</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="可查看人员" prop="viewable">
+          <div></div>
+        </el-form-item>
+        <el-form-item label="描述" prop="description">
+          <div v-html="form.description"></div>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
   </div>
 </template>
 
@@ -132,7 +163,10 @@ export default {
           {required: true, message: "状态不能为空", trigger: "change"}
         ]
       },
-      userList: []
+      userList: [],
+      expandedKeys: [],
+      detailOpen: false,
+
     };
   },
   watch: {
@@ -167,6 +201,9 @@ export default {
       if (!value) return true;
       return data.name.indexOf(value) !== -1;
     },
+    nodeExpand(data, node, self) {
+      this.expandedKeys = [data.id]
+    },
     /** 节点单击事件 */
     handleNodeClick(data) {
       this.$emit('selectProject', data.id)
@@ -296,12 +333,20 @@ export default {
       }).catch(() => {
       });
     },
-    /** 详情按钮操作 */
-    handleDetail(row) {
+    /** 统计按钮操作 */
+    handleTable(row) {
       this.$router.push({path: '/task/projectTable', query: {projectId: row.id}});
     },
+    /** 详情按钮操作 */
+    async handleDetail(row) {
+      getProject(row.id).then(res => {
+        this.form = res.data;
+        this.form.id = this.form.id
+        this.detailOpen = true;
+      })
+    },
+
     clear() {
-      let currentKey = this.$refs.projectTree.getCurrentKey();
       this.$refs.projectTree.setCurrentKey(null)
       this.$emit('selectProject', null)
     }

+ 253 - 76
src/views/task/components/taskDetail.vue

@@ -1,90 +1,205 @@
 <template>
-  <div>
-    <el-form :model="form" size="mini" label-width="100px">
-      <el-form-item label="任务名称:">
-        <div>{{ form.taskName }}</div>
-      </el-form-item>
-      <el-form-item label="父任务:" v-if="form.parentTaskId">
-        <div class="p-task" @click="getParentTask(form.parentTaskId)">{{ form.parentTaskName }}</div>
-      </el-form-item>
-
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="所属项目:">
-            <div>{{ form.projectName }}</div>
-          </el-form-item>
-        </el-col>
-        <el-col :span="10">
-          <el-form-item label="起止时间:">
-            <div>{{ form.beginDate + ' 至 ' + form.endDate }}</div>
-          </el-form-item>
-        </el-col>
-        <el-col :span="6">
-          <el-form-item label="执行(负责)人:" label-width="110px">
-            <div>{{ form.executorName }}</div>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-form-item label="任务描述:">
-        <div v-html="form.description"></div>
-      </el-form-item>
-      <el-form-item label="附件:">
-        <div v-for="(file,index) in form.fileList">
-          <a :href="file.url" style="color: darkgreen">
-            <span style="margin-left: 5px">{{ file.name }}</span>
-          </a>
-        </div>
-      </el-form-item>
-    </el-form>
-    <el-table :data="form.feedbacks" size="mini" border>
-      <el-table-column width="75" label="反馈状态">
-        <template slot-scope="scope">
-          <div>{{ getFeedbackTypeName(scope.row.feedbackType) }}</div>
-        </template>
-      </el-table-column>
-      <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
-      <el-table-column width="60" label="完成度">
-        <template slot-scope="scope">
-          <div v-if="scope.row.value!==undefined">{{ scope.row.value + '%' }}</div>
-        </template>
-      </el-table-column>
-      <el-table-column width="120" property="createTime" label="反馈时间">
-        <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.createTime) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column width="70" property="hours" label="工时(h)"></el-table-column>
-      <el-table-column label="反馈备注">
-        <template slot-scope="scope">
-          <span>{{ scope.row.description }}</span>
-          <span v-for="(file,index) in scope.row.fileList">
+  <div style="height: 560px">
+    <div class="header">
+      <!--      <el-button plain icon="el-icon-back">返回</el-button>-->
+      <div class="task-name">{{ form.taskName }}</div>
+    </div>
+    <el-descriptions class="margin-top" :column="5" direction="vertical">
+      <el-descriptions-item label="负责人">
+        <div class="desc-item-content">{{ form.executorName }}</div>
+      </el-descriptions-item>
+      <el-descriptions-item label="当前状态">
+        <el-tag size="mini" :type="statusMap[form.status].type">
+          {{ statusMap[form.status].name }}
+        </el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="优先级">
+        <el-tag :color="priorityColorMap[form.priority]" effect="dark" :hit="false">
+          {{ getTaskPriority(form.priority) }}
+        </el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="开始时间">
+        <div class="desc-item-content">{{ form.beginDate }}</div>
+      </el-descriptions-item>
+      <el-descriptions-item label="结束时间">
+        <div class="desc-item-content">{{ form.endDate }}</div>
+      </el-descriptions-item>
+    </el-descriptions>
+    <template>
+      <el-tabs v-model="activeName">
+        <el-tab-pane name="first">
+          <span slot="label"><i class="el-icon-info"></i><span style="margin-left: 5px">任务信息</span></span>
+
+          <el-form :model="form" size="mini" label-width="100px">
+            <el-form-item label="所属项目:">
+              <div>{{ form.projectName }}</div>
+            </el-form-item>
+            <el-form-item label="父任务:" v-if="form.parentTaskId">
+              <div class="p-task" @click="getParentTask(form.parentTaskId)">{{ form.parentTaskName }}</div>
+            </el-form-item>
+            <el-form-item label="附件:">
+              <div v-if="form.fileList.length>0">
+                <div v-for="(file,index) in form.fileList">
+                  <a :href="file.url">
+                    <span class="file">{{ file.name }}</span>
+                  </a>
+                </div>
+              </div>
+              <div v-else>无</div>
+            </el-form-item>
+            <el-form-item label="任务描述:">
+              <div v-if="form.description" v-html="form.description" class="description"></div>
+              <div v-else>无</div>
+            </el-form-item>
+          </el-form>
+
+          <div class="footer">
+            <div>
+              <span>{{ form.createUserName }}</span>
+              <span style="margin-left: 5px;margin-right: 5px">创建于</span>
+              <span>{{ form.createTime }}</span>
+            </div>
+            <el-divider direction="vertical" v-if="form.updateUserName"></el-divider>
+            <div v-if="form.updateUserName">
+              <span>{{ form.updateUserName }}</span>
+              <span style="margin-left: 5px;margin-right: 5px">更新于</span>
+              <span>{{ form.updateTime }}</span>
+            </div>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane name="second">
+          <span slot="label"><i class="el-icon-document"></i><span style="margin-left: 5px">反馈信息</span></span>
+          <el-table :data="form.feedbacks" size="mini" max-height="300" border>
+            <el-table-column width="75" label="反馈状态">
+              <template slot-scope="scope">
+                <div>{{ getFeedbackTypeName(scope.row.feedbackType) }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
+            <el-table-column width="60" label="完成度">
+              <template slot-scope="scope">
+                <div v-if="scope.row.value!==undefined">{{ scope.row.value + '%' }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column width="120" property="createTime" label="反馈时间">
+              <template slot-scope="scope">
+                <span>{{ parseTime(scope.row.createTime) }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column width="70" property="hours" label="工时(h)"></el-table-column>
+            <el-table-column label="反馈备注">
+              <template slot-scope="scope">
+                <span>{{ scope.row.description }}</span>
+                <span v-for="(file,index) in scope.row.fileList">
               <a :href="file.url" style="color: darkgreen">
                 <span style="margin-left: 5px">{{ file.name }}</span>
               </a>
           </span>
-        </template>
-      </el-table-column>
-      <el-table-column label="反馈详情" width="80px">
-        <template slot-scope="scope">
-          <el-popover
-            v-if="scope.row.descriptionDetail&&scope.row.descriptionDetail.length>0"
-            placement="top"
-            width="600"
-            trigger="hover">
-            <div v-html="scope.row.descriptionDetail"></div>
-            <el-button slot="reference" type="text">详情</el-button>
-          </el-popover>
-        </template>
-      </el-table-column>
-    </el-table>
+              </template>
+            </el-table-column>
+            <el-table-column label="反馈详情" width="80px">
+              <template slot-scope="scope">
+                <el-popover
+                  v-if="scope.row.descriptionDetail&&scope.row.descriptionDetail.length>0"
+                  placement="top"
+                  width="600"
+                  trigger="hover">
+                  <div v-html="scope.row.descriptionDetail"></div>
+                  <el-button slot="reference" type="text">详情</el-button>
+                </el-popover>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane label="子任务" name="third">
+          <span slot="label"><i class="el-icon-more"></i><span
+            style="margin-left: 5px">子任务({{ form.children.length }})</span></span>
+          <el-table :data="form.children"
+                    max-height="400"
+                    size="mini"
+                    @cell-mouse-enter="cellMouseEnter"
+                    @cell-mouse-leave="cellMouseLeave"
+                    @cell-click="cellClick">
+            <el-table-column width="70" prop="id" label="编号"></el-table-column>
+            <el-table-column label="任务名称" prop="taskName" min-width="150" :show-overflow-tooltip="true"/>
+            <el-table-column label="执行(负责)人" prop="executorName" width="100"/>
+            <el-table-column label="进度" prop="progressValue" width="70">
+              <template slot-scope="scope">
+                <span>{{ (scope.row.progressValue ? scope.row.progressValue : 0) + '%' }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="状态" align="center" width="80">
+              <template slot-scope="scope">
+                <el-tag size="mini" :type="statusMap[scope.row.status].type">{{
+                    statusMap[scope.row.status].name
+                  }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="优先级" prop="priority" align="center" width="80">
+              <template slot-scope="scope">
+                <el-tag v-if="scope.row.priority==='1'" color="#fa8888" effect="dark" :hit="false">
+                  {{ getTaskPriority(scope.row.priority) }}
+                </el-tag>
+                <el-tag v-else-if="scope.row.priority==='2'" color="#fb7fb7" effect="dark" :hit="false">
+                  {{ getTaskPriority(scope.row.priority) }}
+                </el-tag>
+                <el-tag v-else-if="scope.row.priority==='3'" color="#40e0c3" effect="dark" :hit="false">
+                  {{ getTaskPriority(scope.row.priority) }}
+                </el-tag>
+                <el-tag v-else color="#5dcfff" effect="dark" :hit="false">{{
+                    getTaskPriority(scope.row.priority)
+                  }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="开始时间" prop="beginDate" width="100"/>
+            <el-table-column label="结束时间" prop="endDate" width="100"/>
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane label="修改日志" name="four">
+          <span slot="label"><i class="el-icon-edit"></i><span style="margin-left: 5px">修改日志</span></span>
+          <el-table :data="form.updateLogs"
+                    max-height="400"
+                    size="mini">
+            <el-table-column label="修改项" prop="fieldName" width="90">
+              <template slot-scope="scope">
+                <span>{{ getFieldName(scope.row.field) }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="旧值" prop="oldValue" min-width="150" :show-overflow-tooltip="true">
+              <template slot-scope="scope">
+                <div v-html="scope.row.oldValue"></div>
+              </template>
+            </el-table-column>
+            <el-table-column label="新值" prop="newValue" min-width="150" :show-overflow-tooltip="true">
+              <template slot-scope="scope">
+                <div v-html="scope.row.newValue"></div>
+              </template>
+            </el-table-column>
+            <el-table-column label="修改人" prop="operatorName" width="90"/>
+            <el-table-column label="修改时间" prop="createTime" width="120">
+              <template slot-scope="scope">
+                <span>{{ parseTime(scope.row.createTime) }}</span>
+              </template>
+            </el-table-column>
+          </el-table>
+
+        </el-tab-pane>
+      </el-tabs>
+    </template>
+
   </div>
 </template>
 
 <script>
 import {getTask} from "@/api/task/task";
+import task from "@/views/mixins/task";
 
 export default {
   name: "taskDetail",
+  mixins: [task],
+  dicts: ['task_status', 'task_priority'],
   props: {
     detailForm: {
       type: Object,
@@ -93,12 +208,14 @@ export default {
   },
   watch: {
     detailForm(val) {
+      this.activeName = 'first'
       this.form = val
     }
   },
   data() {
     return {
-      form: {}
+      form: {},
+      activeName: 'first'
     }
   },
   created() {
@@ -120,6 +237,16 @@ export default {
     getParentTask(id) {
       getTask(id).then(res => {
         this.form = res.data;
+        this.activeName = 'first'
+      })
+    },
+    cellClick(row, column, cell, event) {
+      if (column.property != 'taskName') {
+        return
+      }
+      getTask(row.id).then(res => {
+        this.form = res.data;
+        this.activeName = 'first'
       })
     }
   }
@@ -127,12 +254,62 @@ export default {
 </script>
 
 <style scoped lang="scss">
+.header {
+  display: flex;
+  justify-content: start;
+  margin-top: -10px;
+  margin-bottom: 15px
+}
+
+.task-name {
+  font-size: 16px;
+  width: 800px;
+}
+
+.desc-item-content {
+  font-size: 14px;
+  font-weight: bold;
+}
+
 .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
   margin-bottom: 10px;
 }
 
 .p-task {
   color: #1c84c6;
-  text-decoration: underLine
+  cursor: pointer;
+}
+
+.p-task:hover {
+  text-decoration-line: underline;
+  text-decoration-color: #1c84c6;
+}
+
+.file {
+  margin-right: 10px;
+  color: darkgreen;
+}
+
+.file:hover {
+  text-decoration-line: underline;
+  text-decoration-color: darkgreen;
+}
+
+.description {
+  margin-top: -13px;
+  max-height: 300px;
+  overflow: auto;
+}
+
+.footer {
+  margin-top: 20px;
+  margin-left: 20px;
+  display: flex;
+  justify-content: start;
+  color: #aaaaaa;
+}
+
+.el-tag--dark {
+  border-color: white;
 }
 </style>

+ 119 - 107
src/views/task/projectView.vue

@@ -45,6 +45,24 @@
           </el-radio-button>
         </el-radio-group>
       </el-form-item>
+      <el-form-item prop="priority">
+        <el-select
+          v-model="queryParams.priority"
+          @change="getList"
+          clearable
+          placeholder="优先级"
+          style="width: 85px">
+          <el-option
+            v-for="dict in dict.type.task_priority"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value">
+            <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
+              {{ dict.label }}
+            </el-tag>
+          </el-option>
+        </el-select>
+      </el-form-item>
     </el-form>
 
     <el-table
@@ -72,25 +90,13 @@
           </el-tag>
         </template>
       </el-table-column>
-      <el-table-column fixed prop="" label="优先级" align="center" width="100">
+      <el-table-column fixed prop="" label="优先级" align="center" width="60">
         <template slot-scope="scope">
-          <el-tag v-if="scope.row.priority==='1'" color="#fa8888" effect="dark" :hit="false">
-            {{ getTaskPriority(scope.row.priority) }}
-          </el-tag>
-          <el-tag v-else-if="scope.row.priority==='2'" color="#fb7fb7" effect="dark" :hit="false">
+          <el-tag :color="priorityColorMap[scope.row.priority]" effect="dark" :hit="false">
             {{ getTaskPriority(scope.row.priority) }}
           </el-tag>
-          <el-tag v-else-if="scope.row.priority==='3'" color="#40e0c3" effect="dark" :hit="false">
-            {{ getTaskPriority(scope.row.priority) }}
-          </el-tag>
-          <el-tag v-else color="#5dcfff" effect="dark" :hit="false">{{ getTaskPriority(scope.row.priority) }}</el-tag>
         </template>
       </el-table-column>
-      <!--      <el-table-column fixed prop="" label="上月延期" width="40">-->
-      <!--        <template slot-scope="scope">-->
-      <!--          <span v-if="scope.row.formLastMonth" style="color: red">是</span>-->
-      <!--        </template>-->
-      <!--      </el-table-column>-->
       <el-table-column align="center" v-for="header in tableHeaders" :key="header.day" :prop="header.day" width="42">
         <template slot="header">
           <div style="width:32px;font-size: 10px;text-align: center">{{ header.day }}</div>
@@ -101,60 +107,64 @@
         </template>
         <template slot-scope="scope">
           <span v-if="scope.row[header.day].comment" class="comment-badge"></span>
-          <el-popover
-            v-if="scope.row[header.day].value!=''"
-            placement="top"
-            width="680"
-            trigger="click">
-            <el-table :data="feedbacks" border size="mini">
-              <el-table-column width="75" label="反馈状态">
-                <template slot-scope="temp">
-                  <div>{{ getFeedbackTypeName(temp.row.feedbackType) }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
-              <el-table-column width="55" label="完成度">
-                <template slot-scope="temp">
-                  <div>{{ temp.row.feedbackType === '4' ? '' : temp.row.value + '%' }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column width="110" property="createTime" label="反馈时间">
-                <template slot-scope="temp">
-                  <div>{{ parseTime(temp.row.createTime) }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column label="反馈备注">
-                <template slot-scope="temp">
-                  <div>
-                    <span style="margin-right: 5px">{{ temp.row.description }}</span>
-                    <span v-for="(file,index) in temp.row.fileList">
+          <div v-popover:popover style="font-size: 10px;cursor: pointer">{{ scope.row[header.day].value }}</div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-popover
+      ref="popover"
+      placement="top"
+      width="700"
+      v-model="popoverVisible"
+      trigger="manual">
+      <el-table :data="feedbacks" border size="mini">
+        <el-table-column width="75" label="反馈状态">
+          <template slot-scope="temp">
+            <div>{{ getFeedbackTypeName(temp.row.feedbackType) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
+        <el-table-column width="55" label="完成度">
+          <template slot-scope="temp">
+            <div>{{ temp.row.feedbackType === '4' ? '' : temp.row.value + '%' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column width="60" prop="hours" label="工时(h)"></el-table-column>
+        <el-table-column width="110" property="createTime" label="反馈时间">
+          <template slot-scope="temp">
+            <div>{{ parseTime(temp.row.createTime) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="反馈备注">
+          <template slot-scope="temp">
+            <div>
+              <span style="margin-right: 5px">{{ temp.row.description }}</span>
+              <span v-for="(file,index) in temp.row.fileList">
                       <a :href="file.url" style="color: darkgreen">
                                   <span style="margin-left: 5px">{{ file.name }}</span>
                       </a>
                     </span>
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column label="反馈详情" width="80px">
-                <template slot-scope="temp">
-                  <el-popover
-                    v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
-                    placement="top"
-                    width="600"
-                    trigger="hover">
-                    <div v-html="temp.row.descriptionDetail"></div>
-                    <el-button slot="reference"
-                               type="text">详情
-                    </el-button>
-                  </el-popover>
-                </template>
-              </el-table-column>
-            </el-table>
-            <div slot="reference" style="font-size: 10px;cursor: pointer">{{ scope.row[header.day].value }}</div>
-          </el-popover>
-        </template>
-      </el-table-column>
-    </el-table>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="反馈详情" width="80px">
+          <template slot-scope="temp">
+            <el-popover
+              v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
+              placement="top"
+              width="600"
+              trigger="hover">
+              <div v-html="temp.row.descriptionDetail"></div>
+              <el-button slot="reference"
+                         type="text">详情
+              </el-button>
+            </el-popover>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-popover>
+
 
     <el-dialog title="添加评论" :visible.sync="open" width="680px" class="feed-dialog" append-to-body @close="cancel">
       <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="100px">
@@ -189,7 +199,8 @@
       </div>
     </el-dialog>
 
-    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" append-to-body>
+    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" :close-on-click-modal="true"
+               append-to-body>
       <task-detail :detailForm="detailForm"></task-detail>
     </el-dialog>
 
@@ -208,16 +219,6 @@ import {getDeptUserTree} from "@/api/system/user";
 import task from "@/views/mixins/task";
 import elTableInfiniteScroll from 'el-table-infinite-scroll'
 
-const statusMap = {
-  '0': {name: '待查看', type: 'info'},
-  '1': {name: '未开始', type: 'info'},
-  '2': {name: '进行中', type: ''},
-  '3': {name: '延期', type: 'danger'},
-  '4': {name: '完成', type: 'success'},
-  '5': {name: '终止', type: 'warning'},
-  '6': {name: '待审核', type: 'warning'}
-}
-
 export default {
   components: {TaskDetail, FileUpload, DeptUserTree, RichTextEditor},
   dicts: ['task_status', 'task_priority'],
@@ -231,7 +232,8 @@ export default {
         projectId: undefined,
         startDate: undefined,
         endDate: undefined,
-        status: '0'
+        status: '0',
+        priority: undefined
       },
       loading: true,
       projectTree: [],
@@ -242,7 +244,7 @@ export default {
       tableData: [],
       page: 0,
       total: 0,
-
+      popoverVisible: false,
       open: false,
       form: {},
       feedbacks: [],
@@ -256,6 +258,15 @@ export default {
       detailForm: {},
     }
   },
+  watch: {
+    totalData: {
+      handler(newVal, oldVal) {
+        this.loadData()
+      },
+      deep: true,
+      immediate: true
+    }
+  },
   created() {
     this.initData();
   },
@@ -267,7 +278,7 @@ export default {
       getProjectTree().then(res => {
         this.projectTree = res.data
       })
-      getDeptUserTree('').then(res => {
+      getDeptUserTree('1').then(res => {
         this.userList = res.data
       })
     },
@@ -296,13 +307,14 @@ export default {
         this.page = 0
         this.disabled = false
         this.tableHeaders = res.data.headers
-        this.totalData = res.data.data
-        this.total = Number.parseInt(this.totalData.length / 15) + 1
+        this.totalData = res.data.data || []
+        this.total = this.totalData.length > 0 ? Number.parseInt(this.totalData.length / 15) + 1 : 0
         this.loading = false
       })
     },
     loadData() {
       if (this.disabled) return;
+      if (this.totalData.length === 0) return;
       if (this.page < this.total) {
         let temp = this.totalData.slice(this.page * 15, (this.page + 1) * 15)
         this.tableData = this.tableData.concat(temp);
@@ -313,21 +325,6 @@ export default {
       }
     },
 
-    cellMouseEnter(row, column, cell, event) {
-      if (column.property != 'taskName') {
-        return
-      }
-      cell.style.color = '#306FB1';
-      cell.style.cursor = 'pointer';
-      cell.style.textDecoration = 'underline';
-    },
-    cellMouseLeave(row, column, cell, event) {
-      if (column.property != 'taskName') {
-        return
-      }
-      cell.style.color = '#606266';
-      cell.style.textDecoration = 'none';
-    },
     cellStyle({row, column, rowIndex, columnIndex}) {
       let style = {
         fontSize: '12px',
@@ -340,21 +337,36 @@ export default {
     },
 
     cellClick(row, column, cell, event) {
-      if (!row[column.property].value || row[column.property].value === '') {
-        return;
-      }
-      let date = row[column.property].date
-      if (DateUtil.unix(date) > DateUtil.unix()) {
-        return;
-      }
-      getFeedbackList(row.id, date).then(res => {
-        this.feedbacks = res.data.map(item => {
-          item['executor'] = row.executor
-          return item
+      this.popoverVisible = false;
+      clearTimeout(this.clickTimer);
+      this.clickTimer = setTimeout(() => {
+        if (!row[column.property].value || row[column.property].value === '') {
+          return;
+        }
+        let date = row[column.property].date
+        if (DateUtil.unix(date) > DateUtil.unix()) {
+          return;
+        }
+        getFeedbackList(row.id, date).then(res => {
+          this.feedbacks = res.data.map(item => {
+            item['executor'] = row.executor
+            return item
+          })
         })
-      })
+        this.$refs.popover.doDestroy(true);
+        this.$nextTick(() => {
+          this.$refs.popover.referenceElm = event.target;
+          this.popoverVisible = true;
+        });
+      }, 300)
+
     },
     cellDbClick(row, column, cell, event) {
+      clearTimeout(this.clickTimer);
+      this.popoverVisible = false;
+      if (row.status === '4' || row.status === '5') {
+        return;
+      }
       let feedbackDate = DateUtil.getFeedBackDate(this.queryParams.startDate, this.queryParams.endDate, column.property)
       if (DateUtil.unix(feedbackDate) > DateUtil.unix()) {
         this.$message.warning("评论时间不能超过:" + DateUtil.day())

+ 90 - 57
src/views/task/task.vue

@@ -44,6 +44,22 @@
                 />
               </el-select>
             </el-form-item>
+            <el-form-item prop="priority">
+              <el-select
+                v-model="queryParams.priority"
+                placeholder="优先级"
+                style="width: 85px">
+                <el-option
+                  v-for="dict in dict.type.task_priority"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value">
+                  <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
+                    {{ dict.label }}
+                  </el-tag>
+                </el-option>
+              </el-select>
+            </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
               <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -68,7 +84,10 @@
         <el-table :data="taskList"
                   ref="taskList"
                   height="calc(100vh - 150px)"
-                  @row-click="rowClick"
+                  @cell-mouse-enter="cellMouseEnter"
+                  @cell-mouse-leave="cellMouseLeave"
+                  @cell-click="cellClick"
+                  @sort-change="sortChange"
                   row-key="id"
                   :indent="10"
                   :tree-props="{children: 'children'}">
@@ -88,7 +107,7 @@
               </el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="优先级" prop="priority" align="center" width="110">
+          <el-table-column label="优先级" prop="priority" align="center" width="80">
             <template slot-scope="scope">
               <el-tag v-if="scope.row.priority==='1'" color="#fa8888" effect="dark" :hit="false">
                 {{ getTaskPriority(scope.row.priority) }}
@@ -105,11 +124,8 @@
               </el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="任务起止时间" width="170">
-            <template slot-scope="scope">
-              <span>{{ scope.row.beginDate + ' 至 ' + scope.row.endDate }}</span>
-            </template>
-          </el-table-column>
+          <el-table-column label="开始时间" prop="beginDate" sortable="custom" width="100"/>
+          <el-table-column label="结束时间" prop="endDate" sortable="custom" width="100"/>
 
           <!--          <el-table-column label="创建时间" prop="createTime" width="120">-->
           <!--            <template slot-scope="scope">-->
@@ -231,11 +247,9 @@
                   :key="dict.value"
                   :label="dict.label"
                   :value="dict.value">
-                  <span v-if="dict.value==='1'" style="color: #fa8888;margin-right: 5px">!!!</span>
-                  <span v-else-if="dict.value==='2'" style="color: #fb7fb7;margin-right: 5px">!!</span>
-                  <span v-else-if="dict.value==='3'" style="color: #40e0c3;margin-right: 5px">!</span>
-                  <span v-else style="color: #5dcfff;margin-right: 5px">!</span>
-                  <span>{{ dict.label }}</span>
+                  <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
+                    {{ dict.label }}
+                  </el-tag>
                 </el-option>
               </el-select>
             </el-form-item>
@@ -258,38 +272,43 @@
       </div>
     </el-dialog>
 
-    <!-- 详情/审核任务对话框 -->
-    <el-dialog :title="detailTitle" :visible.sync="detailOpen" width="800px" class="add-dialog" append-to-body
-               :close-on-click-modal="false">
+    <el-dialog :visible.sync="detailOpen" width="900px" class="add-dialog" append-to-body
+               :close-on-click-modal="true">
       <task-detail :detail-form="detailForm"></task-detail>
-      <div v-if="detailTitle=='审核任务'" style="margin-top: 10px">
-        <el-form ref="auditForm" :model="auditForm" :rules="auditRules" size="mini" label-width="100px">
-          <el-row>
-            <el-col :span="12">
-              <el-form-item label="审核意见" prop="auditResult">
-                <el-radio-group v-model="auditForm.auditResult">
-                  <el-radio label="1">确认完成</el-radio>
-                  <el-radio label="0">驳回</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item v-if="auditForm.auditResult==='0'" label="进度(%)" prop="value">
-                <el-input-number v-model="auditForm.value" :min="1" :max="99"></el-input-number>
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-form-item label="审核备注" prop="auditOpinion">
-            <el-input v-model="auditForm.auditOpinion" type="textarea"/>
-          </el-form-item>
-        </el-form>
-      </div>
-      <div v-if="detailTitle=='审核任务'" slot="footer" class="dialog-footer">
-        <el-button type="primary" size="mini" @click="submitAudit">确 定</el-button>
-        <el-button size="mini" @click="detailCancel">取 消</el-button>
-      </div>
     </el-dialog>
 
+    <!-- 详情/审核任务对话框 -->
+    <!--    <el-dialog :title="detailTitle" :visible.sync="detailOpen" width="800px" class="add-dialog" append-to-body-->
+    <!--               :close-on-click-modal="detailTitle==='审核任务'?false:true">-->
+    <!--&lt;!&ndash;      <task-detail :detail-form="detailForm"></task-detail>&ndash;&gt;-->
+    <!--      <div v-if="detailTitle=='审核任务'" style="margin-top: 10px">-->
+    <!--        <el-form ref="auditForm" :model="auditForm" :rules="auditRules" size="mini" label-width="100px">-->
+    <!--          <el-row>-->
+    <!--            <el-col :span="12">-->
+    <!--              <el-form-item label="审核意见" prop="auditResult">-->
+    <!--                <el-radio-group v-model="auditForm.auditResult">-->
+    <!--                  <el-radio label="1">确认完成</el-radio>-->
+    <!--                  <el-radio label="0">驳回</el-radio>-->
+    <!--                </el-radio-group>-->
+    <!--              </el-form-item>-->
+    <!--            </el-col>-->
+    <!--            <el-col :span="12">-->
+    <!--              <el-form-item v-if="auditForm.auditResult==='0'" label="进度(%)" prop="value">-->
+    <!--                <el-input-number v-model="auditForm.value" :min="1" :max="99"></el-input-number>-->
+    <!--              </el-form-item>-->
+    <!--            </el-col>-->
+    <!--          </el-row>-->
+    <!--          <el-form-item label="审核备注" prop="auditOpinion">-->
+    <!--            <el-input v-model="auditForm.auditOpinion" type="textarea"/>-->
+    <!--          </el-form-item>-->
+    <!--        </el-form>-->
+    <!--      </div>-->
+    <!--      <div v-if="detailTitle=='审核任务'" slot="footer" class="dialog-footer">-->
+    <!--        <el-button type="primary" size="mini" @click="submitAudit">确 定</el-button>-->
+    <!--        <el-button size="mini" @click="detailCancel">取 消</el-button>-->
+    <!--      </div>-->
+    <!--    </el-dialog>-->
+
     <!-- 分解任务对话框 -->
     <el-dialog title="分解任务" :visible.sync="splitOpen" width="90%" class="add-dialog" append-to-body>
       <el-form ref="splitForm" class="split-form" size="mini">
@@ -435,7 +454,10 @@ export default {
         projectId: undefined,
         startDate: undefined,
         endDate: undefined,
-        status: '0'
+        status: '0',
+        priority: undefined,
+        sortField: undefined,
+        order: undefined
       },
       // 表单参数
       form: {},
@@ -513,6 +535,9 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.$refs.taskList.clearSort();
+      this.queryParams.sortField = undefined
+      this.queryParams.order = undefined
       this.$refs.pjTree.clear()
       this.$refs.dut.clearText()
       this.handleQuery();
@@ -561,8 +586,8 @@ export default {
     },
 
     /** 查看任务详情*/
-    rowClick(row, column, event) {
-      if (!column.property || column.property === 'id') {
+    cellClick(row, column, event) {
+      if (!column.property || column.property != 'taskName') {
         return
       }
       getTask(row.id).then(res => {
@@ -571,11 +596,13 @@ export default {
         this.detailTitle = "任务详情";
       })
     },
-    load(row, treeNode, resolve) {
-      childrenTask({taskId: row.id}).then(res => {
-        resolve(res.data)
-      })
+
+    sortChange({column, prop, order}) {
+      this.queryParams.sortField = prop
+      this.queryParams.order = order.replace('ending', '')
+      this.getList()
     },
+
     /** 转换项目数据结构 */
     normalizer(node) {
       if (node.children && !node.children.length) {
@@ -587,7 +614,6 @@ export default {
         children: node.children,
         isDisabled: node.type === '1'
       };
-      console.log(node);
       return newVar;
     },
 
@@ -686,13 +712,20 @@ export default {
     },
     /** 分解按钮操作 */
     handleSplit(row) {
-      this.splitForm = {
-        parentId: row.id,
-        taskName: row.taskName,
-        projectName: row.projectName,
-        children: []
-      }
-      this.splitOpen = true
+      console.log(row);
+      getTask(row.id).then(res => {
+        console.log(res);
+        this.splitForm = res.data
+        // this.splitForm = {
+        //   parentId: row.id,
+        //   taskName: row.taskName,
+        //   projectName: row.projectName,
+        //   children: []
+        // }
+        this.splitForm['parentId'] = row.id
+        this.splitOpen = true
+      })
+
     },
 
     /** 提交按钮 */
@@ -710,7 +743,7 @@ export default {
       }
       this.$refs["form"].validate(valid => {
         if (valid) {
-          if (this.form.files) {
+          if (this.form.files && this.form.files.length > 0) {
             let tempFiles = this.form.files.map(item => item.name);
             this.form.fileUrl = JSON.stringify(tempFiles)
           }

+ 114 - 112
src/views/task/view.vue

@@ -35,6 +35,24 @@
               </el-radio-button>
             </el-radio-group>
           </el-form-item>
+          <el-form-item prop="priority">
+            <el-select
+              v-model="queryParams.priority"
+              @change="getList"
+              clearable
+              placeholder="优先级"
+              style="width: 85px">
+              <el-option
+                v-for="dict in dict.type.task_priority"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value">
+                <el-tag :color="priorityColorMap[dict.value]" effect="dark" :hit="false">
+                  {{ dict.label }}
+                </el-tag>
+              </el-option>
+            </el-select>
+          </el-form-item>
         </el-col>
         <el-col :span="2">
           <el-button
@@ -52,6 +70,7 @@
 
     <el-table
       class="view-table"
+      v-loading="loading"
       :data="tableData"
       size="mini"
       @cell-mouse-enter="cellMouseEnter"
@@ -72,18 +91,11 @@
           </el-tag>
         </template>
       </el-table-column>
-      <el-table-column fixed prop="" label="优先级" align="center" width="100">
+      <el-table-column fixed prop="" label="优先级" align="center" width="60">
         <template slot-scope="scope">
-          <el-tag v-if="scope.row.priority==='1'" color="#fa8888" effect="dark" :hit="false">
-            {{ getTaskPriority(scope.row.priority) }}
-          </el-tag>
-          <el-tag v-else-if="scope.row.priority==='2'" color="#fb7fb7" effect="dark" :hit="false">
-            {{ getTaskPriority(scope.row.priority) }}
-          </el-tag>
-          <el-tag v-else-if="scope.row.priority==='3'" color="#40e0c3" effect="dark" :hit="false">
+          <el-tag :color="priorityColorMap[scope.row.priority]" effect="dark" :hit="false">
             {{ getTaskPriority(scope.row.priority) }}
           </el-tag>
-          <el-tag v-else color="#5dcfff" effect="dark" :hit="false">{{ getTaskPriority(scope.row.priority) }}</el-tag>
         </template>
       </el-table-column>
       <el-table-column align="center" v-for="header in tableHeaders" :key="header.day" :prop="header.day" width="42">
@@ -97,65 +109,64 @@
         <template slot-scope="scope">
           <span v-if="scope.row[header.day].comment" class="comment-badge"></span>
           <span v-if="scope.row[header.day].audit" class="audit-badge"></span>
-          <el-popover
-            v-if="scope.row[header.day].value!=''"
-            placement="top"
-            width="680"
-            trigger="click">
-            <el-table :data="feedbacks" border size="mini">
-              <el-table-column width="75" label="反馈状态">
-                <template slot-scope="temp">
-                  <div>{{ getFeedbackTypeName(temp.row.feedbackType) }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
-              <el-table-column width="55" label="完成度">
-                <template slot-scope="temp">
-                  <div>{{ temp.row.feedbackType === '4' ? '' : temp.row.value + '%' }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column width="110" property="createTime" label="反馈时间">
-                <template slot-scope="temp">
-                  <div>{{ parseTime(temp.row.createTime) }}</div>
-                </template>
-              </el-table-column>
-              <el-table-column label="反馈备注">
-                <template slot-scope="temp">
-                  <div>
-                    <span>{{ temp.row.description }}</span>
-                    <span v-for="(file,index) in temp.row.fileList">
-                                <a :href="file.url" style="color: darkgreen">
-                                  <span style="margin-left: 5px">{{ file.name }}</span>
-                                </a>
-                    </span>
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column label="反馈详情" width="90px">
-                <template slot-scope="temp">
-                  <el-popover
-                    v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
-                    placement="top"
-                    width="600"
-                    trigger="hover">
-                    <div v-html="temp.row.descriptionDetail"></div>
-                    <el-button slot="reference" type="text">详情</el-button>
-                  </el-popover>
-                  <span
-                    v-if="(temp.row.feedbackType === '4'||temp.row.feedbackType === '5')&& scope.row.executor===userId && temp.row.commentConfirm!='1'"
-                    style="margin-left: 10px">
-                  <el-button type="text" icon="el-icon-thumb" size="mini"
-                             @click="confirmComment(temp.row)">确认</el-button>
-                  </span>
-                </template>
-              </el-table-column>
-            </el-table>
-            <div slot="reference" style="font-size: 10px;cursor: pointer">{{ scope.row[header.day].value }}</div>
-          </el-popover>
+          <div v-popover:popover style="font-size: 10px;cursor: pointer">{{ scope.row[header.day].value }}</div>
         </template>
       </el-table-column>
     </el-table>
 
+    <el-popover
+      ref="popover"
+      placement="top"
+      width="700"
+      v-model="popoverVisible"
+      trigger="manual">
+      <el-table :data="feedbacks" border size="mini">
+        <el-table-column width="75" label="反馈状态">
+          <template slot-scope="temp">
+            <div>{{ getFeedbackTypeName(temp.row.feedbackType) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column width="60" property="userName" label="反馈人"></el-table-column>
+        <el-table-column width="55" label="完成度">
+          <template slot-scope="temp">
+            <div>{{ temp.row.feedbackType === '4' ? '' : temp.row.value + '%' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column width="60" prop="hours" label="工时(h)"></el-table-column>
+        <el-table-column width="110" property="createTime" label="反馈时间">
+          <template slot-scope="temp">
+            <div>{{ parseTime(temp.row.createTime) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="反馈备注">
+          <template slot-scope="temp">
+            <div>
+              <span style="margin-right: 5px">{{ temp.row.description }}</span>
+              <span v-for="(file,index) in temp.row.fileList">
+                      <a :href="file.url" style="color: darkgreen">
+                                  <span style="margin-left: 5px">{{ file.name }}</span>
+                      </a>
+                    </span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="反馈详情" width="80px">
+          <template slot-scope="temp">
+            <el-popover
+              v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
+              placement="top"
+              width="600"
+              trigger="hover">
+              <div v-html="temp.row.descriptionDetail"></div>
+              <el-button slot="reference"
+                         type="text">详情
+              </el-button>
+            </el-popover>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-popover>
+
     <el-dialog title="反馈任务" :visible.sync="open" width="680px" class="feed-dialog" append-to-body @close="cancel">
       <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="100px">
         <el-form-item label="任务名称">
@@ -176,7 +187,8 @@
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="计划工时" prop="planHours">
-              <el-input-number v-model="form.planHours" @change="hoursChange" :min="1" :step-strictly="true"
+              <el-input-number v-model="form.planHours" @change="hoursChange" :min="0.1" :step="0.1"
+                               :step-strictly="true"
                                :controls="false"></el-input-number>
               <span style="margin-left: 5px">小时</span>
             </el-form-item>
@@ -189,23 +201,10 @@
           </el-col>
         </el-row>
         <el-row :gutter="20">
-          <!--          <el-col :span="12">-->
-          <!--            <el-form-item label="反馈类型" prop="feedbackType">-->
-          <!--              <el-radio-group v-model="form.feedbackType" @input="feedbackTypeChange">-->
-          <!--                <el-radio-->
-          <!--                  v-for="dict in dict.type.feedback_type"-->
-          <!--                  :key="dict.value"-->
-          <!--                  :label="dict.value"-->
-          <!--                  v-if="dict.value<3"-->
-          <!--                >{{ dict.label }}-->
-          <!--                </el-radio>-->
-          <!--              </el-radio-group>-->
-          <!--            </el-form-item>-->
-          <!--          </el-col>-->
           <el-col :span="12">
             <el-form-item label="工作时长" prop="hours">
-              <el-input-number v-model="form.hours" @change="hoursChange" :min="0.5" :step="0.5" :step-strictly="true"
-                               :controls="false"></el-input-number>
+              <el-input-number v-model="form.hours" @change="hoursChange" :min="0.1" :max="24" :step="0.1"
+                               :step-strictly="true" :controls="false"></el-input-number>
               <!--              <el-input v-model="form.hours" style="width: 130px"></el-input>-->
               <span style="margin-left: 5px">小时</span>
             </el-form-item>
@@ -243,7 +242,8 @@
       </div>
     </el-dialog>
 
-    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" append-to-body>
+    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" :close-on-click-modal="true"
+               append-to-body>
       <task-detail :detailForm="detailForm"></task-detail>
     </el-dialog>
 
@@ -359,9 +359,9 @@ export default {
       return callback();
     };
     let validateHours = (rule, value, callback) => {
-      const regex = /^(?:[0-1]?\d|2[0-4])(\.5)?$/;
-      if (!regex.test(value) || value < 0 || value > 24) {
-        return callback(new Error('工时必须为0到24的数,最小维度为0.5小时'));
+      // const regex = /^(?:[0-1]?\d|2[0-4])(\.\d)?$/;
+      if (value < 0 || value > 24) {
+        return callback(new Error('工时必须为0到24的数,最小维度为0.1小时'));
       }
       if (!value) {
         return callback(new Error('工时不能为空'));
@@ -384,11 +384,15 @@ export default {
         startDate: undefined,
         endDate: undefined,
         status: '0',
+        priority: undefined,
         userId: undefined
       },
+      loading: true,
       projectTree: [],
       tableHeaders: [],
       tableData: [],
+      popoverVisible: false,
+
       open: false,
       form: {},
       feedbacks: [],
@@ -453,24 +457,10 @@ export default {
       listView(this.queryParams).then(res => {
         this.tableHeaders = res.data.headers
         this.tableData = res.data.data
+        this.loading = false
       })
     },
 
-    cellMouseEnter(row, column, cell, event) {
-      if (column.property != 'taskName') {
-        return
-      }
-      cell.style.color = '#306FB1';
-      cell.style.cursor = 'pointer';
-      cell.style.textDecoration = 'underline';
-    },
-    cellMouseLeave(row, column, cell, event) {
-      if (column.property != 'taskName') {
-        return
-      }
-      cell.style.color = '#606266';
-      cell.style.textDecoration = 'none';
-    },
     cellStyle({row, column, rowIndex, columnIndex}) {
       let style = {
         // fontSize: '12px',
@@ -483,21 +473,33 @@ export default {
     },
 
     cellClick(row, column, cell, event) {
-      if (!row[column.property].value || row[column.property].value === '') {
-        return;
-      }
-      let date = row[column.property].date
-      if (DateUtil.unix(date) > DateUtil.unix()) {
-        return;
-      }
-      getFeedbackList(row.id, date).then(res => {
-        this.feedbacks = res.data.map(item => {
-          item['executor'] = row.executor
-          return item
+      this.popoverVisible = false;
+      clearTimeout(this.clickTimer);
+      this.clickTimer = setTimeout(() => {
+        if (!row[column.property].value || row[column.property].value === '') {
+          return;
+        }
+        let date = row[column.property].date
+        if (DateUtil.unix(date) > DateUtil.unix()) {
+          return;
+        }
+        getFeedbackList(row.id, date).then(res => {
+          this.feedbacks = res.data.map(item => {
+            item['executor'] = row.executor
+            return item
+          })
         })
-      })
+        this.$refs.popover.doDestroy(true);
+        this.$nextTick(() => {
+          this.$refs.popover.referenceElm = event.target;
+          this.popoverVisible = true;
+        });
+      }, 300)
     },
     cellDbClick(row, column, cell, event) {
+      clearTimeout(this.clickTimer);
+      this.popoverVisible = false;
+      this.$refs.popover.doDestroy(true);
       let feedbackDate = DateUtil.getFeedBackDate(this.queryParams.startDate, this.queryParams.endDate, column.property)
       if (DateUtil.unix(feedbackDate) > DateUtil.unix()) {
         this.$message.warning("反馈时间不能超过:" + DateUtil.day())
@@ -617,7 +619,7 @@ export default {
     },
 
     hoursChange() {
-      let planHours = Number.parseInt(this.form.planHours)
+      let planHours = Number.parseFloat(this.form.planHours)
       let hours = Number.parseFloat(this.form.hours)
       if (planHours && hours) {
         let feedbackHours = Number.parseFloat(this.form.feedbackHours)