Jelajahi Sumber

任务模块修改

yanshichao 1 tahun lalu
induk
melakukan
00618ac781

+ 12 - 3
src/api/task/task.js

@@ -53,6 +53,15 @@ export function listView(data) {
   })
 }
 
+// 查询项目视图列表
+export function listProjectView(data) {
+  return request({
+    url: '/task/task/projectViewList',
+    method: 'post',
+    data: data
+  })
+}
+
 // 添加任务反馈
 export function addTaskFeedback(data) {
   return request({
@@ -99,11 +108,11 @@ export function confirmComment(parmas) {
 }
 
 //查询子任务列表
-export function childrenTask(parmas) {
+export function childrenTask(data) {
   return request({
     url: '/task/task/children',
-    method: 'get',
-    params: parmas
+    method: 'post',
+    data: data
   })
 }
 

+ 22 - 21
src/components/RichTextEditor/index.vue

@@ -1,18 +1,18 @@
 <template>
   <div style="border: 1px solid #ccc;">
     <Toolbar
-        style="border-bottom: 1px solid #ccc"
-        :editor="editor"
-        :defaultConfig="toolbarConfig"
-        :mode="mode"
+      style="border-bottom: 1px solid #ccc"
+      :editor="editor"
+      :defaultConfig="toolbarConfig"
+      :mode="mode"
     />
     <Editor
-        style="height: 300px; overflow-y: hidden;"
-        v-model="html"
-        :defaultConfig="editorConfig"
-        :mode="mode"
-        @onCreated="onCreated"
-        @onChange="onChange"
+      style="height: 200px; overflow-y: hidden;"
+      v-model="html"
+      :defaultConfig="editorConfig"
+      :mode="mode"
+      @onCreated="onCreated"
+      @onChange="onChange"
     />
   </div>
 </template>
@@ -36,7 +36,7 @@ export default {
   data() {
     return {
       editor: null,
-      html: undefined,
+      // html: '',
       toolbarSimpleConfig: {
         toolbarKeys: [
           "bold",
@@ -123,15 +123,14 @@ export default {
   computed: {
     toolbarConfig() {
       return this.isSimple ? this.toolbarSimpleConfig : this.toolbarDefaultConfig
-    }
-  },
-  watch: {
-    value: {
-      handler(newVal, oldVal) {
-        this.html = newVal
+    },
+    html:{
+      get(){
+        return this.value
       },
-      deep: true,
-      immediate: true
+      set(val){
+        this.$emit('input', val);
+      }
     }
   },
   beforeDestroy() {
@@ -144,10 +143,12 @@ export default {
       this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
     },
     onChange(editor) {
-      this.$emit('getHtml', this.html)
+      this.$emit('input', editor.getHtml());
     },
     clear() {
-      this.html = undefined
+      const editor = this.editor
+      if (editor == null) return
+      editor.setHtml('')
     },
 
   }

+ 9 - 8
src/views/material/myReceive.vue

@@ -64,21 +64,22 @@
       </el-table-column>
       <el-table-column label="操作" width="160">
         <template slot-scope="scope">
-<!--          <el-button-->
-<!--            icon="el-icon-edit"-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            @click="handleTransfer(scope.row)"-->
-<!--          >流转记录-->
-<!--          </el-button>-->
+          <!--          <el-button-->
+          <!--            icon="el-icon-edit"-->
+          <!--            size="mini"-->
+          <!--            type="text"-->
+          <!--            @click="handleTransfer(scope.row)"-->
+          <!--          >流转记录-->
+          <!--          </el-button>-->
           <el-button
             icon="el-icon-coordinate"
             size="mini"
             type="text"
-            :disabled="scope.row.receiveConfirm==='1'"
+            v-if="scope.row.receiveConfirm!='1'"
             @click="handleConfirm(scope.row)"
           >领用确认
           </el-button>
+          <el-tag type="success" v-if="scope.row.receiveConfirm==='1'"><i class="el-icon-coordinate"></i>已确认</el-tag>
         </template>
       </el-table-column>
     </el-table>

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

@@ -1,143 +0,0 @@
-<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>

+ 2 - 3
src/views/task/components/project.vue

@@ -76,8 +76,7 @@
           <dept-user-tree ref="dut" :userList="userList" :multiple="true" @selected="selectCoExecutor"/>
         </el-form-item>
         <el-form-item label="描述" prop="description">
-          <rich-text-editor ref="rtEditor" :value="form.description"
-                            @getHtml="(val)=>form.description=val"></rich-text-editor>
+          <rich-text-editor ref="rtEditor" v-model="form.description"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -104,7 +103,7 @@
           </el-radio-group>
         </el-form-item>
         <el-form-item label="可查看人员" prop="viewable">
-          <div></div>
+          <div>{{ form.viewUserNames }}</div>
         </el-form-item>
         <el-form-item label="描述" prop="description">
           <div v-html="form.description"></div>

+ 99 - 0
src/views/task/components/taskAudit.vue

@@ -0,0 +1,99 @@
+<template>
+  <div>
+    <task-detail :detail-form="detailForm"></task-detail>
+
+    <el-form ref="form" :model="form" :rules="auditRules" size="mini" label-width="100px">
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="审核意见" prop="auditResult">
+            <el-radio-group v-model="form.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="form.auditResult==='0'" label="进度(%)" prop="value">
+            <el-input-number v-model="form.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="form.auditOpinion" type="textarea"/>
+      </el-form-item>
+    </el-form>
+
+    <div class="footer-btn">
+      <el-button type="primary" size="mini" @click="submitAudit">确 定</el-button>
+      <el-button size="mini" @click="auditCancel">取 消</el-button>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import TaskDetail from './taskDetail'
+import {auditTask} from "@/api/task/task";
+
+export default {
+  name: "taskAudit",
+  components: {TaskDetail},
+  props: {
+    detailForm: {
+      type: Object,
+      default: {}
+    },
+    auditForm: {
+      type: Object,
+      default: {}
+    }
+  },
+  watch: {
+    auditForm(val) {
+      this.form = val
+    }
+  },
+  data() {
+    return {
+      form: {},
+      auditRules: {
+        auditResult: [
+          {required: true, message: "审核意见不能为空", trigger: "change"}
+        ],
+        value: [
+          {required: true, message: "进度不能为空", trigger: "blur"}
+        ]
+      },
+    }
+  },
+  methods: {
+    /** 审核提交按钮 */
+    submitAudit() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          auditTask(this.form).then(res => {
+            this.resetForm("form");
+            this.auditCancel()
+            this.$message.success("操作成功");
+          })
+        }
+      });
+    },
+    auditCancel() {
+      this.form = {}
+      this.resetForm('form')
+      this.$emit('auditCancel')
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
+  margin-bottom: 10px;
+}
+
+.footer-btn {
+  margin-left: 720px;
+}
+</style>

+ 1 - 1
src/views/task/components/taskDetail.vue

@@ -97,7 +97,7 @@
           </span>
               </template>
             </el-table-column>
-            <el-table-column label="反馈详情" width="80px">
+            <el-table-column label="当前达成进度" width="100px">
               <template slot-scope="scope">
                 <el-popover
                   v-if="scope.row.descriptionDetail&&scope.row.descriptionDetail.length>0"

+ 336 - 0
src/views/task/components/taskSplit.vue

@@ -0,0 +1,336 @@
+<template>
+  <div>
+    <div class="header">
+      <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>
+
+    <el-tabs v-model="activeName" @tab-remove="delChild">
+      <el-tab-pane name="child0">
+        <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="附件:">
+            <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
+        v-for="(child, index) in form.children"
+        :key="index"
+        :label="'子任务'+(index+1)"
+        :name="'child'+(index+1)"
+        closable>
+        <el-form ref="splitChild" :model="child" :rules="rules" size="mini">
+          <el-form-item label="任务名称" prop="taskName" label-width="80px">
+            <el-input v-model="child.taskName"/>
+          </el-form-item>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="开始时间" prop="beginDate" label-width="80px">
+                <el-date-picker
+                  v-model="child.beginDate"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  @change="checkDates(child.beginDate,child.endDate)"
+                  :picker-options="startPickerOptions"
+                  start-placeholder="开始日期"
+                  style="width: 160px">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="结束时间" prop="endDate">
+                <el-date-picker
+                  v-model="child.endDate"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  @change="checkDates(child.beginDate,child.endDate)"
+                  :picker-options="pickerOptions"
+                  start-placeholder="结束日期"
+                  style="width: 160px">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="执行人" prop="executor" label-width="80px">
+                <dept-user-tree ref="dutSplit" :userList="userList"
+                                @selected="(val)=>selectExecutor(child,val)"/>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-form-item label="任务附件" label-width="80px">
+            <file-upload @getFileUrl="(val)=>getChildFileUrl(child,val)"
+                         @removeFile="(val)=>removeChildFile(child,val)"></file-upload>
+          </el-form-item>
+          <el-form-item label="任务描述" prop="description" label-width="80px">
+            <rich-text-editor v-model="child.description"></rich-text-editor>
+          </el-form-item>
+        </el-form>
+      </el-tab-pane>
+
+      <el-tab-pane disabled>
+        <slot slot="label">
+          <el-button type="success" plain icon="el-icon-plus"
+                     @click="addChild">子任务
+          </el-button>
+        </slot>
+      </el-tab-pane>
+    </el-tabs>
+
+
+  </div>
+</template>
+
+<script>
+import task from "@/views/mixins/task";
+import DeptUserTree from "@/components/DeptUserTree"
+import FileUpload from "@/components/FileUpload"
+import RichTextEditor from '@/components/RichTextEditor'
+import DateUtil from "@/utils/date";
+
+export default {
+  name: "taskSplit",
+  mixins: [task],
+  dicts: ['task_status', 'task_priority'],
+  components: {DeptUserTree, FileUpload, RichTextEditor},
+  props: {
+    splitForm: {
+      type: Object,
+      default: {}
+
+    },
+    userList: {
+      type: Array,
+      default: []
+    }
+  },
+  watch: {
+    splitForm(val) {
+      if (!val) {
+        return
+      }
+      this.activeName = 'child1'
+      this.form = val
+    }
+  },
+  data() {
+    return {
+      form: {},
+      activeName: 'child1',
+      rules: {
+        taskName: [
+          {required: true, message: "任务名称不能为空", trigger: "blur"}
+        ],
+        projectId: [
+          {required: true, message: "所属项目不能为空", trigger: "blur"}
+        ],
+        beginDate: [
+          {required: true, message: "开始时间不能为空", trigger: "change"}
+        ],
+        endDate: [
+          {required: true, message: "结束时间不能为空", trigger: "change"}
+        ],
+        planHours: [
+          {required: true, message: "计划工时不能为空", trigger: "blur"}
+        ],
+        executor: [
+          {required: true, message: "执行人不能为空", trigger: 'change'}
+        ]
+      },
+
+    }
+  },
+  computed: {
+    startPickerOptions(){
+      let self = this
+      return {
+        disabledDate(time) {
+          return time.getTime() < DateUtil.unix(self.form.beginDate) * 1000
+        }
+      }
+    },
+    pickerOptions() {
+      let self = this
+      return {
+        disabledDate(time) {
+          return time.getTime() > DateUtil.unix(self.form.endDate) * 1000
+        }
+      }
+    }
+  },
+  created() {
+    this.form = this.splitForm
+  },
+  methods: {
+    addChild() {
+      let child = {
+        taskName: undefined,
+        executor: undefined,
+        beginDate: this.form.beginDate,
+        endDate: this.form.endDate,
+        planHours: undefined,
+        description: undefined
+      }
+      this.form.children.push(child)
+      this.activeName = 'child' + this.form.children.length
+    },
+    delChild(targetName) {
+      let index = parseInt(targetName.replace('child', ''));
+      this.form.children.splice(index - 1, 1)
+      this.activeName = 'child' + this.form.children.length
+    },
+    selectExecutor(child, val) {
+      this.$set(child, 'executor', val)
+    },
+    getChildFileUrl(child, val) {
+      child['files'] = val
+    },
+    removeChildFile(child, val) {
+      child['files'] = val
+    },
+    submit() {
+      let validResult = true
+      let splitChild = this.$refs.splitChild;
+      for (let key in splitChild) {
+        splitChild[key].validate(valid => {
+          if (!valid) {
+            this.activeName = "child" + (parseInt(key) + 1)
+            validResult = valid
+          }
+        })
+      }
+      if (!validResult) {
+        return
+      }
+      this.form.children.forEach(c => {
+        if (c.files) {
+          let files = c.files.map(item => item.name);
+          c.fileUrl = JSON.stringify(files)
+        }
+      })
+      return this.form
+    },
+    reset() {
+      let splitChild = this.$refs.splitChild;
+      for (let key in splitChild) {
+        splitChild[key].clearValidate()
+      }
+      let dutSplit = this.$refs.dutSplit;
+      for (let key in dutSplit) {
+        dutSplit[key].clearText()
+      }
+    }
+  }
+}
+</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;
+  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: 260px;
+  overflow: auto;
+}
+
+.footer {
+  margin-top: 20px;
+  margin-left: 20px;
+  display: flex;
+  justify-content: start;
+  color: #aaaaaa;
+}
+
+.el-tag--dark {
+  border-color: white;
+}
+
+
+</style>

+ 33 - 7
src/views/task/projectView.vue

@@ -79,8 +79,13 @@
       @cell-dblclick="cellDbClick"
       @row-click="rowClick"
       height="calc(100vh - 110px)"
+      row-key="id"
+      lazy
+      :indent="10"
+      :load="loadChildren"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
       border>
-      <el-table-column fixed prop="id" label="编号" align="center" width="50"/>
+      <el-table-column fixed prop="id" header-align="center" label="编号"/>
       <el-table-column fixed prop="taskName" label="任务名称" align="center" class="task-name-cell" width="180"/>
       <el-table-column fixed prop="executorName" label="主负责人" align="center" width="90">
         <template slot-scope="scope">
@@ -148,7 +153,7 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column label="反馈详情" width="80px">
+        <el-table-column label="当前达成进度" width="100px">
           <template slot-scope="temp">
             <el-popover
               v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
@@ -190,7 +195,7 @@
           <el-input v-model="form.description" type="textarea" autosize/>
         </el-form-item>
         <el-form-item label="描述详情" prop="descriptionDetail">
-          <rich-text-editor ref="rtEditor" @getHtml="(val)=>form.descriptionDetail=val"></rich-text-editor>
+          <rich-text-editor v-model="form.descriptionDetail"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -199,7 +204,7 @@
       </div>
     </el-dialog>
 
-    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" :close-on-click-modal="true"
+    <el-dialog :visible.sync="openDetail" width="900px" class="feed-dialog" :close-on-click-modal="true"
                append-to-body>
       <task-detail :detailForm="detailForm"></task-detail>
     </el-dialog>
@@ -208,7 +213,15 @@
 </template>
 
 <script>
-import {getTask, listView, addTaskFeedback, getFeedbackList, confirmComment} from "@/api/task/task";
+import {
+  getTask,
+  listView,
+  addTaskFeedback,
+  getFeedbackList,
+  confirmComment,
+  listProjectView,
+  childrenTask
+} from "@/api/task/task";
 import {getProjectList, getProjectTree} from "@/api/task/project";
 import DateUtil from "@/utils/date"
 import TaskDetail from "./components/taskDetail"
@@ -302,7 +315,7 @@ export default {
         return
       }
       this.loading = true
-      listView(this.queryParams).then(res => {
+      listProjectView(this.queryParams).then(res => {
         this.tableData = []
         this.page = 0
         this.disabled = false
@@ -402,7 +415,6 @@ export default {
     },
     // 取消按钮
     cancel() {
-      this.$refs.rtEditor.clear()
       this.$refs.fu.clear()
       this.reset();
       this.open = false;
@@ -469,6 +481,20 @@ export default {
           this.getList()
         }
       })
+    },
+
+    loadChildren(tree, treeNode, resolve) {
+      let params = {
+        projectId: this.queryParams.projectId,
+        startDate: this.queryParams.startDate,
+        endDate: this.queryParams.endDate,
+        status: this.queryParams.status,
+        priority: undefined,
+        parentTaskId: tree.id
+      }
+      childrenTask(params).then(res => {
+        resolve(res.data)
+      })
     }
   }
 }

+ 52 - 204
src/views/task/task.vue

@@ -126,12 +126,6 @@
           </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">-->
-          <!--              <span>{{ parseTime(scope.row.createTime) }}</span>-->
-          <!--            </template>-->
-          <!--          </el-table-column>-->
           <el-table-column label="操作" width="120">
             <template slot-scope="scope">
               <el-button size="mini"
@@ -205,7 +199,7 @@
             <el-form-item label="执行(负责)人" prop="executor">
               <dept-user-tree ref="dut2" :userList="userList"
                               style="width: 220px"
-                              @selected="(val)=>selectExecutor(val,'form')"/>
+                              @selected="selectExecutor"/>
             </el-form-item>
           </el-col>
         </el-row>
@@ -262,8 +256,7 @@
           </el-col>
         </el-row>
         <el-form-item label="任务描述" prop="description">
-          <rich-text-editor ref="rtEditor" :value="form.description"
-                            @getHtml="(val)=>form.description=val"></rich-text-editor>
+          <rich-text-editor ref="rtEditor" v-model="form.description" v-if="open"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -272,114 +265,23 @@
       </div>
     </el-dialog>
 
+    <!-- 任务详情对话框 -->
     <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>
     </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 :visible.sync="auditOpen" width="900px" class="add-dialog" append-to-body @close="auditCancel">
+      <task-audit :detail-form="detailForm" :audit-form="auditForm" @auditCancel="auditCancel"></task-audit>
+    </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">
-        <el-form-item label="任务名称:">
-          <div>{{ splitForm.taskName }}</div>
-        </el-form-item>
-        <el-form-item label="所属项目:">
-          <span>{{ splitForm.projectName }}</span>
-          <div style="float: right; padding: -1px 3px">
-            <el-button type="primary" plain circle icon="el-icon-plus"
-                       @click="addChild"></el-button>
-          </div>
-
-        </el-form-item>
-        <div style="display: flex;justify-content: flex-start;flex-wrap:wrap">
-          <el-card shadow="always" v-for="(child,index) in splitForm.children" :key="index" class="split-card">
-            <div slot="header" class="clearfix">
-              <div class="card-header">
-                <div style="margin-top: 5px">子任务{{ index + 1 }}</div>
-                <el-button type="danger" circle @click="delChild(index)" icon="el-icon-delete"
-                           style="float: right;">
-                </el-button>
-              </div>
-            </div>
-            <el-form ref="splitChild" :model="child" :rules="rules" size="mini">
-              <el-form-item label="任务名称" prop="taskName" label-width="80px">
-                <el-input v-model="child.taskName"/>
-              </el-form-item>
-              <el-row :gutter="20">
-                <el-col :span="12">
-                  <el-form-item label="开始时间" prop="beginDate" label-width="80px">
-                    <el-date-picker
-                      v-model="child.beginDate"
-                      type="date"
-                      value-format="yyyy-MM-dd"
-                      @change="checkDates(child.beginDate,child.endDate)"
-                      start-placeholder="开始日期">
-                    </el-date-picker>
-                  </el-form-item>
-                </el-col>
-                <el-col :span="12">
-                  <el-form-item label="结束时间" prop="endDate">
-                    <el-date-picker
-                      v-model="child.endDate"
-                      type="date"
-                      value-format="yyyy-MM-dd"
-                      @change="checkDates(child.beginDate,child.endDate)"
-                      start-placeholder="结束日期">
-                    </el-date-picker>
-                  </el-form-item>
-                </el-col>
-              </el-row>
-              <el-form-item label="执行人" prop="executor" label-width="80px">
-                <dept-user-tree ref="dutSplit" :userList="userList"
-                                @selected="(val)=>selectExecutor(val,'splitForm',index)"/>
-              </el-form-item>
-              <el-form-item label="任务附件" label-width="80px">
-                <file-upload @getFileUrl="(val)=>getChildFileUrl(child,val)"
-                             @removeFile="(val)=>removeChildFile(child,val)"></file-upload>
-              </el-form-item>
-              <el-form-item label="任务描述" prop="description" label-width="80px">
-                <rich-text-editor ref="crtEditor"
-                                  @getHtml="(val)=>child.description=val"></rich-text-editor>
-              </el-form-item>
-            </el-form>
-          </el-card>
-        </div>
-      </el-form>
-      <div v-if="splitForm.children&&splitForm.children.length>0" style=" position: fixed; bottom: 10px;left: 49%">
-        <el-button type="primary" size="mini" @click="submitSplit">保存</el-button>
-        <!--        <el-button size="mini" @click="splitCancel">取消</el-button>-->
+    <el-dialog :visible.sync="splitOpen" width="900px" class="add-dialog" append-to-body @close="splitCancel">
+      <task-split ref="split" :split-form="splitForm" :user-list="userList"></task-split>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="mini" @click="splitCancel">取 消</el-button>
+        <el-button type="primary" size="mini" @click="submitSplit">确 定</el-button>
       </div>
     </el-dialog>
 
@@ -410,16 +312,19 @@ import {
   addTask,
   updateTask,
   auditTask,
-  splitTask, childrenTask
+  splitTask
 } from "@/api/task/task";
 import {listProject} from "@/api/task/project";
 import {getDeptUserTree} from "@/api/system/user";
-import TaskDetail from "./components/taskDetail"
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import DeptUserTree from "@/components/DeptUserTree"
 import FileUpload from "@/components/FileUpload"
 import Project from "@/views/task/components/project";
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import TaskDetail from "@/views/task/components/taskDetail"
+import TaskSplit from "@/views/task/components/taskSplit"
+import TaskAudit from "@/views/task/components/taskAudit"
+
 import RichTextEditor from '@/components/RichTextEditor'
 import {mapGetters} from "vuex";
 import task from "@/views/mixins/task";
@@ -427,7 +332,7 @@ import DateUtil from "@/utils/date";
 
 export default {
   name: "Task",
-  components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect, RichTextEditor},
+  components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect, RichTextEditor, TaskSplit, TaskAudit},
   dicts: ['task_status', 'task_priority'],
   mixins: [task],
   computed: {
@@ -449,7 +354,7 @@ export default {
       // 查询参数
       queryParams: {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 20,
         executors: [],
         projectId: undefined,
         startDate: undefined,
@@ -464,6 +369,7 @@ export default {
       detailTitle: "",
       detailOpen: false,
       detailForm: {},
+      auditOpen: false,
       auditForm: {},
       splitOpen: false,
       splitForm: {},
@@ -488,14 +394,7 @@ export default {
           {required: true, message: "执行人不能为空", trigger: 'change'}
         ]
       },
-      auditRules: {
-        auditResult: [
-          {required: true, message: "审核意见不能为空", trigger: "change"}
-        ],
-        value: [
-          {required: true, message: "进度不能为空", trigger: "blur"}
-        ]
-      },
+
       confirmOpen: false,
       conflictTasks: []
     };
@@ -553,7 +452,7 @@ export default {
     // 取消按钮
     cancel() {
       this.$refs.dut2.clearText()
-      this.$refs.rtEditor.clear()
+      // this.$refs.rtEditor.clear()
       this.$refs.fu.clear()
       this.reset()
       this.open = false;
@@ -571,18 +470,18 @@ export default {
       };
       this.resetForm("form");
     },
-    // 取消按钮(详情/审核)
-    detailCancel() {
-      this.detailOpen = false;
+    // 审核取消按钮
+    auditCancel() {
+      this.auditOpen = false;
       this.detailForm = {};
       this.auditForm = {}
       this.resetForm("auditForm");
     },
     // 取消按钮(分解任务)
-    splitCancel() {
+    async splitCancel() {
+      await this.$refs.split.reset();
+      // this.splitForm = {}
       this.splitOpen = false;
-      this.splitForm = {}
-      this.resetForm("splitForm");
     },
 
     /** 查看任务详情*/
@@ -598,6 +497,9 @@ export default {
     },
 
     sortChange({column, prop, order}) {
+      if (!order) {
+        return
+      }
       this.queryParams.sortField = prop
       this.queryParams.order = order.replace('ending', '')
       this.getList()
@@ -622,7 +524,7 @@ export default {
       this.reset();
       this.open = true;
       this.title = "添加任务";
-      listProject().then(response => {
+      listProject('1').then(response => {
         this.projectOptions = this.handleTree(response.data, "id");
         if (this.selectProjectId && this.projectOptions.length > 0) {
           let ids = this.projectOptions.map(item => item.id);
@@ -655,14 +557,8 @@ export default {
       this.$set(this.form, 'rangeDate', [row.beginDate, row.endDate])
       this.$refs.dut2.setCheckedNode(this.form.executor)
     },
-    selectExecutor(val, form, index) {
-      if (form === 'splitForm') {
-        let child = this.splitForm.children[index];
-        this.$set(child, 'executor', val)
-      }
-      if (form === 'form') {
-        this.$set(this.form, 'executor', val)
-      }
+    selectExecutor(val) {
+      this.$set(this.form, 'executor', val)
     },
     getFileUrl(val) {
       this.form.files = val
@@ -670,12 +566,7 @@ export default {
     removeFile(val) {
       this.form.files = val
     },
-    getChildFileUrl(child, val) {
-      child['files'] = val
-    },
-    removeChildFile(child, val) {
-      child['files'] = val
-    },
+
     /** 更多操作触发 */
     handleCommand(command, row) {
       switch (command) {
@@ -706,26 +597,26 @@ export default {
           value: undefined,
           auditOpinion: undefined
         }
-        this.detailOpen = true;
-        this.detailTitle = "审核任务";
+        this.auditOpen = true;
       })
     },
     /** 分解按钮操作 */
     handleSplit(row) {
-      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.splitForm['children'] = []
+        let child = {
+          taskName: undefined,
+          executor: undefined,
+          beginDate: row.beginDate,
+          endDate: row.endDate,
+          planHours: undefined,
+          description: undefined
+        }
+        this.splitForm.children.push(child)
         this.splitOpen = true
       })
-
     },
 
     /** 提交按钮 */
@@ -807,44 +698,15 @@ export default {
       // this.resetForm("splitForm");
     },
 
-    /** 审核提交按钮 */
-    submitAudit() {
-      this.$refs["auditForm"].validate(valid => {
-        if (valid) {
-          auditTask(this.auditForm).then(res => {
-            this.resetForm("auditForm");
-            this.getList()
-            this.detailOpen = false
-            this.$message.success("操作成功");
-          })
-        }
-      });
-    },
 
     /** 分解任务提交按钮 */
     submitSplit() {
-      if (this.splitForm.children.length === 0) {
-        return;
-      }
-      let validResult = true
-      let splitChild = this.$refs.splitChild;
-      for (let key in splitChild) {
-        splitChild[key].validate(valid => {
-          if (!valid) {
-            validResult = valid
-          }
-        })
-      }
-      if (!validResult) {
+      let data = this.$refs.split.submit();
+      if (!data) {
         return
       }
-      this.splitForm.children.forEach(c => {
-        if (c.files) {
-          let files = c.files.map(item => item.name);
-          c.fileUrl = JSON.stringify(files)
-        }
-      })
-      this.splitForm.checkTaskConflict = true;
+      this.splitForm = data;
+      this.$set(this.splitForm, 'checkTaskConflict', true)
       splitTask(this.splitForm).then(res => {
         if (res.code === 'S.F-2001') {
           this.conflictTasks = res.data
@@ -877,20 +739,6 @@ export default {
         this.$message.success("删除成功");
       }).catch(() => {
       });
-    },
-
-    addChild() {
-      let child = {
-        taskName: undefined,
-        executor: undefined,
-        rangeDate: [],
-        planHours: undefined,
-        description: undefined
-      }
-      this.splitForm.children.push(child)
-    },
-    delChild(index) {
-      this.splitForm.children.splice(index, 1)
     }
 
   }

+ 87 - 72
src/views/task/view.vue

@@ -2,68 +2,68 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="mini" :inline="true">
       <el-row type="flex" justify="space-between">
-        <el-col :span="22">
-          <el-form-item label="日期" prop="startDate">
-            <el-date-picker
-              v-model="queryParams.startDate"
-              type="date"
-              value-format="yyyy-MM-dd"
-              @change="getList"
-              placeholder="开始日期"
-              :clearable="false"
-              style="width: 130px">
-            </el-date-picker>
-          </el-form-item>
-          <el-form-item label="至" prop="endDate">
-            <el-date-picker
-              v-model="queryParams.endDate"
-              type="date"
-              value-format="yyyy-MM-dd"
-              @change="getList"
-              placeholder="结束日期"
-              :clearable="false"
-              style="width: 130px">
-            </el-date-picker>
-          </el-form-item>
-          <el-form-item prop="status">
-            <el-radio-group v-model="queryParams.status" size="mini" @change="getList">
-              <el-radio-button
-                v-for="dict in dict.type.task_status"
-                :key="dict.value"
-                :label="dict.value"
-              >{{ dict.label }}
-              </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
-            type="primary"
-            plain
-            icon="el-icon-plus"
-            size="mini"
-            @click="handleAdd"
-          >日常任务
-          </el-button>
-        </el-col>
+        <!--        <el-col :span="22">-->
+        <el-form-item label="日期" prop="startDate">
+          <el-date-picker
+            v-model="queryParams.startDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            @change="getList"
+            placeholder="开始日期"
+            :clearable="false"
+            style="width: 130px">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="至" prop="endDate">
+          <el-date-picker
+            v-model="queryParams.endDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            @change="getList"
+            placeholder="结束日期"
+            :clearable="false"
+            style="width: 130px">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item prop="status">
+          <el-radio-group v-model="queryParams.status" size="mini" @change="getList">
+            <el-radio-button
+              v-for="dict in dict.type.task_status"
+              :key="dict.value"
+              :label="dict.value"
+            >{{ dict.label }}
+            </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-->
+        <!--            type="primary"-->
+        <!--            plain-->
+        <!--            icon="el-icon-plus"-->
+        <!--            size="mini"-->
+        <!--            @click="handleAdd"-->
+        <!--          >日常任务-->
+        <!--          </el-button>-->
+        <!--        </el-col>-->
       </el-row>
 
     </el-form>
@@ -150,7 +150,7 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column label="反馈详情" width="80px">
+        <el-table-column label="当前达成进度" width="100px">
           <template slot-scope="temp">
             <el-popover
               v-if="temp.row.descriptionDetail&&temp.row.descriptionDetail.length>0"
@@ -162,13 +162,19 @@
                          type="text">详情
               </el-button>
             </el-popover>
+            <span
+              v-if="(temp.row.feedbackType === '4'||temp.row.feedbackType === '5')&& temp.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>
     </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 ref="form" :model="form" :rules="rules" size="mini" label-width="106px">
         <el-form-item label="任务名称">
           <div>{{ form.taskName }}</div>
         </el-form-item>
@@ -205,7 +211,6 @@
             <el-form-item label="工作时长" prop="hours">
               <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>
           </el-col>
@@ -232,8 +237,8 @@
         <el-form-item label="反馈描述" prop="description">
           <el-input v-model="form.description" type="textarea" autosize/>
         </el-form-item>
-        <el-form-item label="反馈详情" prop="descriptionDetail">
-          <rich-text-editor ref="rtEditor" @getHtml="(val)=>form.descriptionDetail=val"></rich-text-editor>
+        <el-form-item label="当前达成进度" prop="descriptionDetail">
+          <rich-text-editor v-model="form.descriptionDetail"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -242,7 +247,7 @@
       </div>
     </el-dialog>
 
-    <el-dialog title="任务详情" :visible.sync="openDetail" width="70%" class="feed-dialog" :close-on-click-modal="true"
+    <el-dialog :visible.sync="openDetail" width="900px" class="feed-dialog" :close-on-click-modal="true"
                append-to-body>
       <task-detail :detailForm="detailForm"></task-detail>
     </el-dialog>
@@ -308,8 +313,7 @@
           </el-col>
         </el-row>
         <el-form-item label="任务描述" prop="description">
-          <rich-text-editor ref="artEditor" :value="addForm.description"
-                            @getHtml="(val)=>addForm.description=val"></rich-text-editor>
+          <rich-text-editor v-model="addForm.description"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -377,6 +381,16 @@ export default {
       }
       return callback();
     };
+    let validateDescriptionDetail = (rule, value, callback) => {
+      if (!value) {
+        return callback(new Error('当前达成进度不能为空'));
+      }
+      let text = value.replaceAll('<p>', '').replaceAll('</p>', '').replaceAll('<br>', '').replaceAll('&nbsp;', '').trim();
+      if (text.length === 0) {
+        return callback(new Error('当前达成进度不能为空'));
+      }
+      return callback();
+    };
 
     return {
       queryParams: {
@@ -411,6 +425,9 @@ export default {
         ],
         description: [
           {required: true, validator: validateDescription, trigger: "blur"},
+        ],
+        descriptionDetail: [
+          {required: true, validator: validateDescriptionDetail, trigger: "change"},
         ]
       },
       openDetail: false,
@@ -540,7 +557,6 @@ export default {
     },
     // 取消按钮
     cancel() {
-      this.$refs.rtEditor.clear();
       this.$refs.fu.clear();
       this.open = false;
       this.reset();
@@ -661,7 +677,6 @@ export default {
       });
     },
     cancelAddForm() {
-      this.$refs.artEditor.clear()
       this.$refs.afu.clear()
       this.resetAdd()
       this.openAdd = false;