ソースを参照

任务管理,任务视图页面

ysc 1 年間 前
コミット
2bd254f9ca

+ 2 - 1
package.json

@@ -24,7 +24,8 @@
     "vue": "2.6.10",
     "vue-router": "3.0.6",
     "vuex": "3.1.0",
-    "@riophae/vue-treeselect": "0.4.0"
+    "@riophae/vue-treeselect": "0.4.0",
+    "moment": "^2.29.4"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "4.4.4",

+ 9 - 0
src/api/task/category.js

@@ -43,3 +43,12 @@ export function delCategory(CategoryId) {
     method: 'delete'
   })
 }
+
+// 查询分类列表(无条件)
+export function getCategoryList() {
+  return request({
+    url: '/task/task/getCategoryList',
+    method: 'get'
+  })
+}
+

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

@@ -44,10 +44,10 @@ export function delProject(ProjectId) {
   })
 }
 
-// 查询分类列表
-export function getCategoryList() {
+// 查询项目列表
+export function getProjectList(categoryId) {
   return request({
-    url: '/task/project/getCategoryList',
+    url: '/task/project/getProjectList/' + categoryId,
     method: 'get'
   })
 }

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

@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+// 查询任务列表
+export function listTask(query) {
+  return request({
+    url: '/task/task/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询任务详细
+export function getTask(TaskId) {
+  return request({
+    url: '/task/task/' + TaskId,
+    method: 'get'
+  })
+}
+
+// 新增任务
+export function addTask(data) {
+  return request({
+    url: '/task/task',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改任务
+export function updateTask(data) {
+  return request({
+    url: '/task/task',
+    method: 'put',
+    data: data
+  })
+}
+
+
+// 删除任务
+export function delTask(TaskId) {
+  return request({
+    url: '/task/task/' + TaskId,
+    method: 'delete'
+  })
+}
+
+// 查询任务视图列表
+export function listView(query) {
+  return request({
+    url: '/task/task/viewList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 添加任务反馈
+export function addTaskFeedback(data) {
+  return request({
+    url: '/task/task/addFeedback',
+    method: 'post',
+    data: data
+  })
+}
+
+// 查询任务反馈
+export function getFeedbackList(taskId, date) {
+  return request({
+    url: '/task/task/getFeedbackList?taskId=' + taskId + '&date=' + date,
+    method: 'get'
+  })
+}

+ 10 - 1
src/main.js

@@ -17,7 +17,15 @@ import router from './router'
 import '@/icons' // icon
 import '@/permission' // permission control
 
-import {parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree} from "@/utils/common";
+import {
+  parseTime,
+  resetForm,
+  addDateRange,
+  selectDictLabel,
+  selectDictLabels,
+  handleTree,
+  getMonthDate
+} from "@/utils/common";
 
 Vue.prototype.parseTime = parseTime
 Vue.prototype.resetForm = resetForm
@@ -25,6 +33,7 @@ Vue.prototype.addDateRange = addDateRange
 Vue.prototype.selectDictLabel = selectDictLabel
 Vue.prototype.selectDictLabels = selectDictLabels
 Vue.prototype.handleTree = handleTree
+Vue.prototype.getMonthDate = getMonthDate
 
 // set ElementUI lang to EN
 // Vue.use(ElementUI, { locale })

+ 36 - 8
src/utils/common.js

@@ -1,10 +1,8 @@
-
-
 /**
  * 通用js方法封装处理
- * Copyright (c) 2019 ruoyi
  */
 
+
 // 日期格式化
 export function parseTime(time, pattern) {
   if (arguments.length === 0 || !time) {
@@ -37,7 +35,9 @@ export function parseTime(time, pattern) {
   const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
     let value = formatObj[key]
     // Note: getDay() returns 0 on Sunday
-    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
+    if (key === 'a') {
+      return ['日', '一', '二', '三', '四', '五', '六'][value]
+    }
     if (result.length > 0 && value < 10) {
       value = '0' + value
     }
@@ -88,7 +88,7 @@ export function selectDictLabel(datas, value) {
 
 // 回显数据字典(字符串、数组)
 export function selectDictLabels(datas, value, separator) {
-  if (value === undefined || value.length ===0) {
+  if (value === undefined || value.length === 0) {
     return "";
   }
   if (Array.isArray(value)) {
@@ -203,9 +203,9 @@ export function handleTree(data, id, parentId, children) {
 }
 
 /**
-* 参数处理
-* @param {*} params  参数
-*/
+ * 参数处理
+ * @param {*} params  参数
+ */
 export function tansParams(params) {
   let result = ''
   for (const propName of Object.keys(params)) {
@@ -238,3 +238,31 @@ export async function blobValidate(data) {
     return true;
   }
 }
+
+/**
+ * 获取月份每天日期及对应星期几
+ */
+export function getMonthDate(date) {
+  let d = new Date(date);
+  let year = d.getFullYear();
+  let month = d.getMonth() + 1;
+  let today = new Date();
+  let startDate = new Date(year, d.getMonth(), 1);
+  let endData = new Date(year, d.getMonth() + 1, 1);
+  let days = (endData - startDate) / (1000 * 60 * 60 * 24);
+  let list = []
+  let weeks = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
+  for (let i = 1; i <= days; i++) {
+    const day = i < 10 ? '0' + i : i + '';
+    let weekIndex = new Date(month + '/' + i + '/' + year).getDay();
+    let week = weeks[weekIndex];
+    if (today.getFullYear() === year && today.getMonth() + 1 === month && today.getDate() === i) {
+      week = '今日'
+    }
+    list.push({
+      day,
+      week
+    })
+  }
+  return list;
+}

+ 92 - 0
src/utils/date.js

@@ -0,0 +1,92 @@
+import moment from 'moment'
+
+const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
+const DATE_FORMAT = 'YYYY-MM-DD'
+const MONTH_FORMAT = 'YYYY-MM'
+const YEAR_FORMAT = 'YYYY'
+const TIME_FORMAT = 'HH:mm:ss'
+
+export default {
+  parseDay(date) {
+    if (date) {
+      return date.format(DATE_TIME_FORMAT)
+    }
+    return date.format(DATE_TIME_FORMAT)
+  },
+  date(date, format) {
+    if (date) {
+      return moment(date).format(format || DATE_TIME_FORMAT)
+    }
+    return moment().format(format || DATE_TIME_FORMAT)
+  },
+  day(date) {
+    if (date) {
+      return moment(date).format(DATE_FORMAT)
+    }
+    return moment().format(DATE_FORMAT)
+  },
+  month(date) {
+    if (date) {
+      return moment(date).format(MONTH_FORMAT)
+    }
+    return moment().format(MONTH_FORMAT)
+  },
+  year(date) {
+    if (date) {
+      return moment(date).format(YEAR_FORMAT)
+    }
+    return moment().format(YEAR_FORMAT)
+  },
+  beforeDay(date, num = 1) {
+    if (date) {
+      return moment(date).subtract(num, 'days').format(DATE_FORMAT)
+    }
+    return moment().subtract(num, 'days').format(DATE_FORMAT)
+  },
+  afterDay(date, num = 1) {
+    if (date) {
+      return moment(date).add(num, 'days').format(DATE_FORMAT)
+    }
+    return moment().add(num, 'days').format(DATE_FORMAT)
+  },
+  time(date) {
+    if (date) {
+      return moment(date).format(TIME_FORMAT)
+    }
+    return moment().format(TIME_FORMAT)
+  },
+  unix(date) {
+    if (date) {
+      return moment(date).unix()
+    }
+    return moment().unix()
+  },
+  dayDiff(dateStart, dateEnd) {
+    return moment(dateEnd).diff(moment(dateStart), 'day')
+  },
+  minuteDiff(startDate, endDate, type = 'minute') {
+    return moment(endDate).diff(moment(startDate), type)
+  },
+  getMinutes(date) {
+    let time = moment(date)
+    return time.hours() * 60 + time.minutes()
+  },
+  beforeMonth(date, num = 1) {
+    if (date) {
+      return moment(date).subtract(num, 'months').format(MONTH_FORMAT)
+    }
+    return moment().subtract(num, 'months').format(MONTH_FORMAT)
+  },
+  afterMonth(date, num = 1) {
+    if (date) {
+      return moment(date).add(num, 'months').format(MONTH_FORMAT)
+    }
+    return moment().add(num, 'months').format(MONTH_FORMAT)
+  },
+  lastMonth(date) {
+    return this.beforeMonth(date)
+  },
+  getMonthDays(date) {
+    return moment(date).daysInMonth();
+  }
+}

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

@@ -63,7 +63,7 @@
           <span>{{ parseTime(scope.row.createTime) }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center">
         <template slot-scope="scope">
           <el-button
             size="mini"
@@ -137,9 +137,9 @@ import {
   getProject,
   delProject,
   addProject,
-  updateProject,
-  getCategoryList
+  updateProject
 } from "@/api/task/project";
+import {getCategoryList} from "@/api/task/category";
 
 export default {
   name: "Project",

+ 388 - 0
src/views/task/task.vue

@@ -0,0 +1,388 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+      <el-form-item label="所属分类" prop="categoryId">
+        <el-select
+          v-model="queryParams.categoryId"
+          clearable
+          style="width: 240px">
+          <el-option v-for="item in categoryList" :key="item.id" :label="item.categoryName" :value="item.id"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属项目" prop="projectId">
+        <el-select
+          v-model="queryParams.projectId"
+          clearable
+          style="width: 240px">
+          <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="月份选择">
+        <el-date-picker
+          v-model="queryParams.month"
+          type="month"
+          value-format="yyyy-MM"
+          placeholder="选择月份">
+        </el-date-picker>
+      </el-form-item>
+      <!--      <el-form-item label="状态" prop="status">-->
+      <!--        <el-select-->
+      <!--          v-model="queryParams.status"-->
+      <!--          placeholder="项目状态"-->
+      <!--          clearable-->
+      <!--          style="width: 240px">-->
+      <!--          <el-option :key="0" label="正常" :value="0"/>-->
+      <!--          <el-option :key="1" label="停用" :value="1"/>-->
+      <!--        </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>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['task:Task:add']"
+        >新增
+        </el-button>
+      </el-col>
+      <el-col :span="10" :offset="2">
+        <el-radio-group v-model="queryParams.status" size="mini">
+          <el-radio-button label="0">全部</el-radio-button>
+          <el-radio-button label="1">完成</el-radio-button>
+          <el-radio-button label="2">延期</el-radio-button>
+          <el-radio-button label="3">终止</el-radio-button>
+          <el-radio-button label="4">未开始</el-radio-button>
+          <el-radio-button label="5">进行中</el-radio-button>
+        </el-radio-group>
+      </el-col>
+    </el-row>
+
+    <el-table :data="TaskList">
+      <el-table-column label="任务编号" prop="id" width="100"/>
+      <el-table-column label="任务名称" prop="taskName"/>
+      <el-table-column label="所属项目" prop="projectName"/>
+      <el-table-column label="执行人" prop="executorName"/>
+      <el-table-column label="进度" prop="progressValue">
+        <template slot-scope="scope">
+          <span>{{ scope.row.progressValue ? scope.row.progressValue : 0 + '%' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态">
+        <template slot-scope="scope">
+          <el-tag type="success" size="small" v-if="scope.row.status==0">正常</el-tag>
+          <el-tag type="info" size="small" v-else>停用</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="任务起止时间" width="180">
+        <template slot-scope="scope">
+          <span>{{ scope.row.beginDate + '至' + scope.row.endDate }}</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="创建时间" prop="createTime" width="150">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="240">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:Task:edit']"
+          >审核
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:Task:edit']"
+          >分解
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:Task:edit']"
+          >终止
+          </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:task:delete']"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </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-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="任务名称" prop="taskName">
+          <el-input v-model="form.taskName" placeholder="请输入项目名称"/>
+        </el-form-item>
+        <el-form-item label="任务类型" prop="taskType">
+          <el-radio-group v-model="form.taskType">
+            <el-radio label="1">软件开发</el-radio>
+            <el-radio label="2">硬件开发</el-radio>
+            <el-radio label="3">测试</el-radio>
+            <el-radio label="4">实施</el-radio>
+            <el-radio label="5">日常事务</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="所属项目" prop="projectId">
+          <el-select
+            v-model="form.projectId"
+            clearable
+            style="width: 240px">
+            <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="起止时间">
+          <el-date-picker
+            v-model="form.rangeDate"
+            type="daterange"
+            value-format="yyyy-MM-dd"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="执行人" prop="executor">
+          <el-select
+            v-model="form.executor"
+            clearable
+            style="width: 240px">
+            <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="共同执行人" prop="coExecutor">
+          <el-select
+            v-model="form.coExecutor"
+            clearable
+            style="width: 240px">
+            <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="任务附件">
+          <!--          <el-upload-->
+          <!--            class="upload-demo"-->
+          <!--            action="https://jsonplaceholder.typicode.com/posts/"-->
+          <!--            :on-preview="handlePreview"-->
+          <!--            :on-remove="handleRemove"-->
+          <!--            :before-remove="beforeRemove"-->
+          <!--            multiple-->
+          <!--            :limit="3"-->
+          <!--            :on-exceed="handleExceed"-->
+          <!--            :file-list="fileList">-->
+          <!--            <el-button size="small" type="primary">点击上传</el-button>-->
+          <!--          </el-upload>-->
+        </el-form-item>
+        <el-form-item label="任务描述">
+          <el-input v-model="form.description" type="textarea" placeholder="请输入内容"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {
+  listTask,
+  getTask,
+  delTask,
+  addTask,
+  updateTask
+} from "@/api/task/task";
+import {getCategoryList} from "@/api/task/category";
+import {getProjectList} from "@/api/task/project";
+
+export default {
+  name: "Task",
+  data() {
+    return {
+      categoryList: [],
+      projectList: [],
+      // 总条数
+      total: 0,
+      // 项目表格数据
+      TaskList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        categoryId: undefined,
+        projectId: undefined,
+        month: undefined,
+        status: '0'
+      },
+      // 表单参数
+      form: {},
+
+      // 表单校验
+      rules: {
+        taskName: [
+          {required: true, message: "项目名称不能为空", trigger: "blur"}
+        ],
+        taskType: [
+          {required: true, message: "任务类型不能为空", trigger: "change"}
+        ],
+        projectId: [
+          {required: true, message: "所属项目不能为空", trigger: "change"}
+        ],
+        rangeDate: [
+          {required: true, message: "起止时间不能为空", trigger: "change"}
+        ],
+        executor: [
+          {required: true, message: "执行人不能为空", trigger: "change"}
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询项目列表 */
+    getList() {
+      getCategoryList().then(res => {
+        this.categoryList = res.data;
+      })
+      getProjectList("").then(res => {
+        this.projectList = res.data;
+      })
+      listTask(this.queryParams).then(response => {
+          this.TaskList = response.data.records;
+          this.total = response.data.total;
+        }
+      );
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 取消按钮(数据权限)
+    cancelDataScope() {
+      this.openDataScope = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: undefined,
+        taskName: undefined,
+        categoryId: undefined,
+        description: undefined,
+        status: "0",
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.getList();
+    },
+    handleCurrentChange(val) {
+      this.pageNum = val;
+      this.getList();
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加项目";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      getTask(row.id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改项目";
+      });
+    },
+
+
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          this.form.beginDate = this.form.rangeDate[0]
+          this.form.endDate = this.form.rangeDate[1]
+          if (this.form.id != undefined) {
+            updateTask(this.form).then(response => {
+              this.$message.success("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addTask(this.form).then(response => {
+              this.$message.success("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      this.$confirm('是否确认删除项目编号为"' + row.id + '"的数据项?').then(() => {
+        return delTask(row.id);
+      }).then(() => {
+        this.getList();
+        this.$message.success("删除成功");
+      }).catch(() => {
+      });
+    },
+  }
+};
+</script>

+ 305 - 0
src/views/task/view.vue

@@ -0,0 +1,305 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
+      <el-form-item label="所属项目" prop="projectId">
+        <el-select
+          v-model="queryParams.projectId"
+          @change="getList"
+          clearable
+          style="width: 200px">
+          <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="月份">
+        <el-date-picker
+          v-model="queryParams.month"
+          @change="getList"
+          type="month"
+          value-format="yyyy-MM"
+          style="width: 200px">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-radio-group v-model="queryParams.status" size="mini" @change="getList">
+          <el-radio-button label="0">全部</el-radio-button>
+          <el-radio-button label="1">完成</el-radio-button>
+          <el-radio-button label="2">延期</el-radio-button>
+          <el-radio-button label="3">终止</el-radio-button>
+          <el-radio-button label="4">未开始</el-radio-button>
+          <el-radio-button label="5">进行中</el-radio-button>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+
+    <el-table
+      :data="tableData"
+      :header-cell-style="headerCellStyle"
+      :cell-style="cellStyle"
+      @cell-click="cellClick"
+      @cell-dblclick="cellDbclick"
+      height="calc(100vh - 140px)"
+      border>
+      <el-table-column prop="id" label="编号" align="center" width="50"/>
+      <el-table-column prop="taskName" label="任务名称" align="center" width="180"/>
+      <el-table-column prop="executorName" label="主负责人" align="center" width="80">
+        <template slot-scope="scope">
+          <div>{{ scope.row.executorName }}</div>
+          <el-tag size="mini">{{ scope.row.progressValue + '%' }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="" label="上月延期" width="50">
+        <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="(item,index) in tableHeaders" :key="index" :prop="item.day" width="40">
+        <template slot="header" slot-scope="scope">
+          <div style="width: 20px">{{ item.day }}</div>
+          <div v-if="item.week=='周六'" style="width: 24px;color: #1c84c6">{{ item.week }}</div>
+          <div v-else-if="item.week=='周日'" style="width: 24px;color: #1c84c6">{{ item.week }}</div>
+          <div v-else-if="item.week=='今日'" style="width: 24px;color: #008000">{{ item.week }}</div>
+          <div v-else style="width: 24px">{{ item.week }}</div>
+        </template>
+        <template slot-scope="scope">
+          <el-popover
+            placement="top"
+            width="560"
+            trigger="click">
+            <el-table :data="feedbacks" border style="font-size: 12px">
+              <el-table-column width="70" 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>{{ scope.row.value + '%' }}</div>
+                </template>
+              </el-table-column>
+              <el-table-column width="140" property="createTime" label="反馈时间"></el-table-column>
+              <el-table-column width="200" label="反馈备注"></el-table-column>
+            </el-table>
+            <div slot="reference">{{ scope.row[item.day].value }}</div>
+          </el-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <el-dialog title="反馈任务" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="任务名称">
+          <div>{{ form.taskName }}</div>
+        </el-form-item>
+        <el-form-item label="所属项目">
+          <div>{{ form.projectName }}</div>
+        </el-form-item>
+        <el-form-item label="反馈时间">
+          <div>{{ form.feedbackDate }}</div>
+        </el-form-item>
+        <el-form-item label="反馈类型">
+          <el-radio-group v-model="form.feedbackType">
+            <el-radio label="1">进度反馈</el-radio>
+            <el-radio label="2">完成</el-radio>
+            <el-radio label="3">终止</el-radio>
+            <el-radio label="4">评论</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="进度">
+          <el-input-number v-model="form.value" :min="1" :max="100"></el-input-number>
+        </el-form-item>
+        <el-form-item label="附件"></el-form-item>
+        <el-form-item label="反馈描述" prop="description">
+          <el-input v-model="form.description" type="textarea"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog title="任务详情" :visible.sync="openDetail" width="500px" append-to-body>
+      <el-form :model="detailForm" label-width="100px">
+        <el-form-item label="任务名称:">
+          <div>{{ detailForm.taskName }}</div>
+        </el-form-item>
+        <el-form-item label="所属项目:">
+          <div>{{ detailForm.projectName }}</div>
+        </el-form-item>
+        <el-form-item label="任务描述:">
+          <div>{{ detailForm.description }}</div>
+        </el-form-item>
+        <el-form-item label="起止时间:">
+          <div>{{ detailForm.beginDate + '至' + detailForm.endDate }}</div>
+        </el-form-item>
+        <el-form-item label="主要负责人:">
+          <div>{{ detailForm.executorName }}</div>
+        </el-form-item>
+        <el-form-item label="共同执行人:">
+          <div>{{ detailForm.executorName }}</div>
+        </el-form-item>
+        <el-form-item label="附件:"></el-form-item>
+      </el-form>
+      <el-table :data="detailForm.feedbacks" border style="font-size: 12px">
+        <el-table-column width="70" 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>{{ scope.row.value + '%' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column width="140" property="createTime" label="反馈时间"></el-table-column>
+        <el-table-column width="200" label="反馈备注"></el-table-column>
+      </el-table>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import {addTask, listView, updateTask, addTaskFeedback, getFeedbackList} from "@/api/task/task";
+import {getProjectList} from "@/api/task/project";
+import DateUtil from "@/utils/date"
+
+export default {
+  data() {
+    return {
+      queryParams: {
+        projectId: undefined,
+        month: undefined,
+        status: '5'
+      },
+      projectList: [],
+      tableHeaders: [],
+      tableData: [],
+      open: false,
+      form: {},
+      feedbacks: [],
+      visible: false,
+      rules: {},
+      openDetail: false,
+      detailForm: {}
+    }
+  },
+  created() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.queryParams.month = DateUtil.month(new Date())
+      this.tableHeaders = this.getMonthDate('2023-10');
+      this.getList()
+      getProjectList("").then(res => {
+        this.projectList = res.data;
+      })
+    },
+    getList() {
+      listView(this.queryParams).then(res => {
+        this.tableData = res.data
+      })
+    },
+    headerCellStyle({row, column, rowIndex, columnIndex}) {
+      return {
+        fontSize: '12px',
+        padding: '0',
+        lineHeight: '20px',
+        width: '30px'
+      }
+    },
+    cellStyle({row, column, rowIndex, columnIndex}) {
+      let style = {
+        fontSize: '12px',
+        padding: '2px 0'
+      }
+      if (row[column.property]) {
+        style.background = row[column.property].color
+      }
+      return style
+    },
+
+    cellClick(row, column, cell, event) {
+      if (!row[column.property].color || row[column.property].color === 'white') {
+        return
+      }
+      let date = this.queryParams.month + '-' + column.property
+      getFeedbackList(row.id, date).then(res => {
+        this.feedbacks = res.data
+      })
+    },
+    cellDbclick(row, column, cell, event) {
+      // this.visible = false
+      if (!row[column.property].color || row[column.property].color === 'white') {
+        return
+      }
+      this.form = {
+        id: undefined,
+        taskName: row.taskName,
+        taskId: row.id,
+        projectName: row.projectName,
+        feedbackDate: this.queryParams.month + '-' + column.property,
+        feedbackType: '1',
+        value: undefined,
+        fileUrl: undefined,
+        description: undefined
+      };
+      this.open = true
+
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: undefined,
+        taskName: undefined,
+        taskId: undefined,
+        projectName: undefined,
+        feedbackDate: undefined,
+        feedbackType: undefined,
+        value: undefined,
+        fileUrl: undefined,
+        description: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          addTaskFeedback(this.form).then(response => {
+            this.$message.success("反馈成功");
+            this.open = false;
+            this.getList();
+          });
+        }
+      })
+    },
+
+    getFeedbackTypeName(type) {
+      if (type === '1') {
+        return '进度反馈'
+      } else if (type === '2') {
+        return '完成'
+      } else if (type === '3') {
+        return '终止'
+      }
+      return '评论'
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.header-cell {
+  fontSize: 12px;
+  padding: 2px 0;
+}
+</style>