浏览代码

Merge remote-tracking branch 'origin/master'

humingbo 1 年之前
父节点
当前提交
144fc888db

+ 12 - 2
src/api/task/project.js

@@ -44,11 +44,21 @@ export function delProject(ProjectId) {
   })
 }
 
+// 归档项目
+export function archiveProject(data) {
+  return request({
+    url: '/task/project/archive',
+    method: 'post',
+    data: data
+  })
+}
+
 // 查询项目列表
-export function getProjectTree() {
+export function getProjectTree(query) {
   return request({
     url: '/task/project/projectTree',
-    method: 'get'
+    method: 'get',
+    params: query
   })
 }
 

+ 8 - 0
src/api/task/task.js

@@ -149,3 +149,11 @@ export function taskAuditConfigs(parmas) {
     params: parmas
   })
 }
+
+export function getDeleteTasks(data) {
+  return request({
+    url: '/task/task/getDeleteTasks',
+    method: 'post',
+    data: data
+  })
+}

+ 417 - 0
src/views/task/archive.vue

@@ -0,0 +1,417 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="10">
+      <el-col :span="5" style="position:relative;z-index: 20">
+        <el-radio-group v-model="typeRadio" @input="initData">
+          <el-radio-button label="归档项目"></el-radio-button>
+          <el-radio-button label="垃圾桶"></el-radio-button>
+        </el-radio-group>
+        <div style="height:calc(100vh - 148px);margin-top:10px;overflow: auto">
+          <el-tree
+            :data="projectData"
+            :props="defaultProps"
+            :expand-on-click-node="false"
+            :check-on-click-node="true"
+            :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"
+                          placement="top-end">
+                  <div>{{ node.label | ellipsis }}</div>
+              </el-tooltip>
+
+              <div v-if="data.type!='模块'" style="font-size: 12px;color: #1c84c6">({{ data.type }})</div>
+            </span>
+          </el-tree>
+        </div>
+      </el-col>
+      <el-col :span="19">
+        <div class="query-container">
+          <el-form :model="queryParams" ref="queryForm" size="mini" :inline="true">
+            <el-form-item prop="startDate">
+              <el-date-picker
+                v-model="queryParams.startDate"
+                type="date"
+                value-format="yyyy-MM-dd"
+                placeholder="开始日期"
+                clearable
+                style="width: 135px">
+              </el-date-picker>
+            </el-form-item>
+            <el-form-item prop="endDate">
+              <el-date-picker
+                v-model="queryParams.endDate"
+                type="date"
+                value-format="yyyy-MM-dd"
+                placeholder="结束日期"
+                clearable
+                style="width: 135px">
+              </el-date-picker>
+            </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>
+            </el-form-item>
+          </el-form>
+
+        </div>
+
+        <el-table :data="taskList"
+                  ref="taskList"
+                  height="calc(100vh - 150px)"
+                  @cell-mouse-enter="cellMouseEnter"
+                  @cell-mouse-leave="cellMouseLeave"
+                  @cell-click="cellClick"
+                  @sort-change="sortChange"
+                  row-key="id"
+                  :indent="10"
+                  :tree-props="{children: 'children'}">
+          <el-table-column label="任务编号" prop="id" width="120"/>
+          <el-table-column label="任务名称" prop="taskName" min-width="150" :show-overflow-tooltip="true"/>
+          <el-table-column label="执行(负责)人" prop="executorName" width="95"/>
+          <!--          <el-table-column label="进度" prop="progressValue" width="60">-->
+          <!--            <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="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">
+                {{ 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-column v-if="typeRadio==='归档项目'" label="完成时间" prop="finishDate" width="100"/>
+          <el-table-column v-if="typeRadio==='垃圾桶'" label="删除人" prop="operatorUserName" width="60"/>
+          <el-table-column v-if="typeRadio==='垃圾桶'" label="删除时间" prop="updateTime" width="120">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.updateTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column v-if="typeRadio==='垃圾桶'" label="删除原因" prop="remark" :show-overflow-tooltip="true"/>
+        </el-table>
+
+        <div style="margin-top: 10px;text-align: center">
+          <el-pagination
+            background
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+            :current-page="queryParams.pageNum"
+            :page-sizes="[10, 20, 50]"
+            :page-size="queryParams.pageSize"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total">
+          </el-pagination>
+        </div>
+      </el-col>
+    </el-row>
+
+    <!-- 任务详情对话框 -->
+    <el-dialog :title="detailForm.id+'、'+detailForm.taskName" :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>
+
+  </div>
+</template>
+
+<script>
+import {
+  listTask,
+  getTask,
+  delTask,
+  addTask,
+  updateTask,
+  auditTask,
+  splitTask,
+  projectAuditConfigs, taskAuditConfigs, addTaskFeedback, delTaskWithReason, getDeleteTasks
+} from "@/api/task/task";
+import {getProjectTree, listProject} from "@/api/task/project";
+import {getDeptUserTree, getAuditUsers, resetUserPwd} from "@/api/system/user";
+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 TaskDetail from "@/views/task/components/taskDetail"
+import TaskSplit from "@/views/task/components/taskSplit"
+
+import RichTextEditor from '@/components/RichTextEditor'
+import {mapGetters} from "vuex";
+import task from "@/views/mixins/task";
+import DateUtil from "@/utils/date";
+
+import AuditModule from '@/views/task/components/auditModule';
+
+export default {
+  name: "Task",
+  components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect, RichTextEditor, TaskSplit, AuditModule},
+  dicts: ['task_status', 'task_priority'],
+  mixins: [task],
+  computed: {
+    ...mapGetters(['userId'])
+  },
+  data() {
+    return {
+      typeRadio: '归档项目',
+      projectData: [],
+      defaultProps: {
+        children: "children",
+        label: "name"
+      },
+      expandedKeys: [],
+
+      // 总条数
+      total: 0,
+      // 列表数据
+      taskList: [],
+
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        projectId: undefined,
+        projectIds: [],
+        startDate: undefined,
+        endDate: undefined,
+        priority: undefined,
+        sortField: undefined,
+        order: undefined
+      },
+      detailTitle: "",
+      detailOpen: false,
+      detailForm: {},
+
+    };
+  },
+  filters: {
+    ellipsis(val) {
+      if (!val) {
+        return ''
+      }
+      if (val.length > 10) {
+        return val.slice(0, 10) + '...'
+      }
+      return val
+    }
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.getProjectTree();
+      this.getList();
+      // getDeptUserTree('1').then(res => {
+      //   this.userList = res.data
+      // })
+    },
+    getProjectTree() {
+      this.projectData = []
+      if (this.typeRadio === '归档项目') {
+        getProjectTree({status: '1'}).then(response => {
+          this.projectData = response.data
+        })
+      }
+      if (this.typeRadio === '垃圾桶') {
+        getProjectTree({status: '0'}).then(res => {
+          this.projectData = res.data
+        })
+      }
+
+    },
+    /** 查询项目列表 */
+    getList() {
+      if (DateUtil.unix(this.queryParams.startDate) > DateUtil.unix(this.queryParams.endDate)) {
+        this.$message.warning("开始时间不能超过结束时间")
+        return
+      }
+      if (this.typeRadio === '归档项目') {
+        if (!this.queryParams.projectId && this.projectData.length === 0) {
+          this.taskList = [];
+          this.total = 0;
+          return;
+        }
+        if (!this.queryParams.projectId) {
+          let tempProjectIds = []
+          this.projectData.forEach(item => {
+            item.children.forEach(p => {
+              tempProjectIds.push(p.id)
+            })
+          })
+          this.queryParams.projectIds = tempProjectIds
+        }
+
+        listTask(this.queryParams).then(res => {
+          this.taskList = res.data.records;
+          this.total = res.data.total;
+        });
+      }
+      if (this.typeRadio === '垃圾桶') {
+        getDeleteTasks(this.queryParams).then(res => {
+          this.taskList = res.data.records;
+          this.total = res.data.total;
+        })
+      }
+
+
+    },
+
+    nodeExpand(data, node, self) {
+      this.expandedKeys = [data.id]
+    },
+    /** 节点单击事件 */
+    handleNodeClick(data) {
+      this.queryParams.projectId = data.id;
+      this.queryParams.projectIds = []
+      this.handleQuery()
+    },
+
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.queryParams.projectId = undefined;
+      this.queryParams.projectIds = []
+      this.$refs.taskList.clearSort();
+      this.queryParams.sortField = undefined
+      this.queryParams.order = undefined
+      // this.$refs.pjTree.clear()
+      // this.$refs.dut.clearText()
+      this.handleQuery();
+    },
+    handleSizeChange(val) {
+      this.queryParams.pageSize = val;
+      this.getList();
+    },
+    handleCurrentChange(val) {
+      this.queryParams.pageNum = val;
+      this.getList();
+    },
+
+
+    /** 查看任务详情*/
+    cellClick(row, column, event) {
+      if (!column.property || column.property != 'taskName') {
+        return
+      }
+      getTask(row.id).then(res => {
+        this.detailForm = res.data;
+        this.detailOpen = true;
+        this.detailTitle = "任务详情";
+      })
+    },
+
+    sortChange({column, prop, order}) {
+      this.queryParams.sortField = prop
+      if (order) {
+        this.queryParams.order = order.replace('ending', '')
+      }
+      this.getList()
+    },
+
+    /** 转换项目数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      let newVar = {
+        id: node.id,
+        label: node.projectName || node.name,
+        children: node.children,
+        isDisabled: node.type === '分类'
+      };
+      return newVar;
+    },
+
+
+    selectExecutor(val) {
+      this.$set(this.form, 'executor', val)
+    },
+    getFileUrl(val) {
+      this.form.files = val
+    },
+    removeFile(val) {
+      this.form.files = val
+    },
+
+
+  }
+};
+</script>
+<style scoped lang="scss">
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  padding-right: 8px;
+}
+
+.el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
+  margin-bottom: 10px;
+}
+
+
+.card-header {
+  display: flex;
+  justify-content: space-between
+}
+
+.add-dialog ::v-deep .el-dialog__body {
+  padding: 0 20px 10px 20px;
+}
+
+.el-tag--dark {
+  border-color: white;
+}
+
+</style>

+ 73 - 28
src/views/task/components/project.vue

@@ -36,19 +36,22 @@
               </el-tooltip>
 
               <div v-if="data.type!='模块'" style="font-size: 12px;color: #1c84c6">({{ data.type }})</div>
-              <el-popover
-                placement="right"
-                trigger="hover">
-                <el-button size="mini" type="primary" @click="handleAdd(data)" v-if="data.type==='分类'"
-                           v-hasPermi="['task:project:add']">新增</el-button>
-                <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="handleTable(data)" v-if="data.type==='项目'"
-                           v-hasPermi="['task:project:table']">统计</el-button>
-                <el-button size="mini" @click="handleDetail(data)">详情</el-button>
-                <i class="el-icon-share" slot="reference"></i>
-               </el-popover>
+              <el-dropdown size="mini" placement="bottom-start" @command="(command) => handleCommand(command, data)">
+                <i class="el-icon-share"/>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item command="handleAdd" icon="el-icon-plus" v-if="data.type==='分类'"
+                                    v-hasPermi="['task:project:add']">新增</el-dropdown-item>
+                  <el-dropdown-item command="handleUpdate" icon="el-icon-edit"
+                                    v-hasPermi="['task:project:edit']">修改</el-dropdown-item>
+                  <el-dropdown-item command="handleUpdate" icon="el-icon-delete"
+                                    v-hasPermi="['task:project:delete']">删除</el-dropdown-item>
+                  <el-dropdown-item command="handleTable" icon="el-icon-document" v-if="data.type==='项目'"
+                                    v-hasPermi="['task:project:table']">统计</el-dropdown-item>
+                  <el-dropdown-item command="handleDetail" icon="el-icon-view">详情</el-dropdown-item>
+                  <el-dropdown-item command="handleArchive" icon="el-icon-folder" v-if="data.type==='项目'"
+                                    v-hasPermi="['task:project:archive']">归档</el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
             </span>
       </el-tree>
     </div>
@@ -64,12 +67,12 @@
                       @select="treeSelectChange" :disabled="!form.parentId&&title==='修改项目'"
                       :placeholder="title==='修改项目'?'无':'请选择'"/>
         </el-form-item>
-        <el-form-item label="状态" prop="status">
-          <el-radio-group v-model="form.status">
-            <el-radio label="0">正常</el-radio>
-            <el-radio label="1">停用</el-radio>
-          </el-radio-group>
-        </el-form-item>
+        <!--        <el-form-item label="状态" prop="status">-->
+        <!--          <el-radio-group v-model="form.status">-->
+        <!--            <el-radio label="0">正常</el-radio>-->
+        <!--            <el-radio label="1">停用</el-radio>-->
+        <!--          </el-radio-group>-->
+        <!--        </el-form-item>-->
         <el-form-item label="可查看人员" prop="viewable" v-if="form.type==='2'&&form.parentId">
           <dept-user-tree ref="dut" :userList="userList" :multiple="true" @selected="selectCoExecutor"/>
         </el-form-item>
@@ -96,12 +99,12 @@
         <el-form-item label="上级结构" prop="parentId">
           <div>{{ form.parentName || '无' }}</div>
         </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="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" v-if="form.type==='2'">
           <div>{{ form.viewUserNames }}</div>
         </el-form-item>
@@ -126,7 +129,9 @@ import {
   getProject,
   delProject,
   addProject,
-  updateProject, getProjectTree
+  updateProject,
+  archiveProject,
+  getProjectTree
 } from "@/api/task/project";
 import {getAuditUsers, getDeptUserTree} from "@/api/system/user";
 
@@ -199,7 +204,7 @@ export default {
   methods: {
     /** 查询项目树数据 */
     getProjectTree() {
-      getProjectTree().then(res => {
+      getProjectTree({status: '0'}).then(res => {
         this.projectData = res.data
       })
 
@@ -260,6 +265,32 @@ export default {
         this.form.type = '3'
       }
     },
+    /** 更多操作触发 */
+    handleCommand(command, data) {
+      switch (command) {
+        case 'handleAdd':
+          this.handleAdd(data)
+          break
+        case 'handleUpdate':
+          this.handleUpdate(data)
+          break
+        case 'handleEdit':
+          this.handleEdit(data)
+          break
+        case 'handleDelete':
+          this.handleDelete(data)
+          break
+        case 'handleDetail':
+          this.handleDetail(data)
+          break
+        case 'handleArchive':
+          this.handleArchive(data)
+          break
+        default:
+          break
+      }
+    },
+
     /** 新增按钮操作 */
     handleAdd(row) {
       this.reset();
@@ -280,7 +311,7 @@ export default {
         this.projectOptions = this.handleTree(response.data, "id");
       });
       getDeptUserTree('1').then(res => {
-        this.userList = res.data
+        this.userList = res.datas
       })
       getAuditUsers().then(res => {
         this.auditUsers = res.data
@@ -374,6 +405,20 @@ export default {
       })
       this.detailOpen = true;
     },
+    handleArchive(row) {
+      this.$confirm('是否将' + row.type + '【' + row.name + '】归档?', '', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        let data = {id: row.id, status: '1'}
+        archiveProject(data).then(res => {
+          this.$message.success('归档成功!');
+          this.getProjectTree();
+        })
+      }).catch(() => {
+      });
+    },
 
     clear() {
       this.$refs.projectTree.setCurrentKey(null)

+ 17 - 7
src/views/task/components/taskDetail.vue

@@ -69,6 +69,14 @@
             <div v-if="form.description" v-html="form.description" class="description"></div>
             <div v-else>无</div>
           </el-form-item>
+          <el-form-item label="审批情况:" v-if="form.status==='6'">
+            <template v-for="(info,index) in form.auditInfoList">
+              <el-tag>{{ info.auditUserName }}</el-tag>
+              <span v-if="info.auditResult==='1'" style="font-size: 10px">(已同意)</span>
+              <span v-else style="font-size: 10px">(待审核)</span>
+              <i class="el-icon-right" v-if="index!=form.auditInfoList.length-1"></i>
+            </template>
+          </el-form-item>
         </el-form>
 
         <div class="footer">
@@ -101,12 +109,8 @@
               <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 width="90" property="feedbackDate" label="反馈日期"></el-table-column>
+          <el-table-column width="65" property="hours" label="工时(h)"></el-table-column>
           <el-table-column label="反馈备注">
             <template slot-scope="scope">
               <span>{{ scope.row.description }}</span>
@@ -288,7 +292,7 @@ export default {
 
 <style scoped lang="scss">
 .task-detail {
-  height: 500px;
+  height: 520px;
 }
 
 .desc-item-content {
@@ -347,4 +351,10 @@ export default {
 .el-tag--dark {
   border-color: white;
 }
+
+.el-icon-right {
+  font-weight: bold;
+  margin-right: 5px;
+  margin-left: 5px;
+}
 </style>

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

@@ -622,7 +622,7 @@ export default {
           }
         }
       ))
-      arr.push(getProjectTree().then(response => {
+      arr.push(getProjectTree({status: '0'}).then(response => {
         this.projectOptions = response.data
       }))
       await Promise.all(arr)