Преглед изворни кода

王子文 专项培养 月度反馈
1) 月度培养计划列表查询
2) 培养计划详情查询
3) 导师反馈内容修改、查询

wangggziwen пре 3 година
родитељ
комит
77430250e8

+ 16 - 0
master/src/main/java/com/ruoyi/project/training/spec/controller/TStPlanController.java

@@ -52,6 +52,22 @@ public class TStPlanController extends BaseController
     @Autowired
     private ITStYearplanService tStYearplanService;
 
+    /**
+     * 查询月度反馈培养计划列表
+     */
+    @PreAuthorize("@ss.hasPermi('spec:plan:list')")
+    @GetMapping("/listMonthly")
+    public TableDataInfo listMonthly(TStFeedback feedback)
+    {
+        Long userId = getUserId();
+        SysUser sysUser = sysUserService.selectUserById(userId);
+        String staffId = sysUser.getStaffId();
+        feedback.setMentorId(staffId);
+        startPage();
+        List<TStPlan> list = tStPlanService.selectMonthlyTStPlanList(feedback);
+        return getDataTable(list);
+    }
+
     /**
      * 查询季度汇报培养计划列表
      */

+ 18 - 9
ui/src/api/training/spec/plan.js

@@ -1,5 +1,23 @@
 import request from '@/utils/request'
 
+// 查询月度反馈培养计划列表
+export function listPlanMonthly(query) {
+  return request({
+    url: '/spec/plan/listMonthly',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询季度汇报培养计划列表
+export function listPlanSeasonal(query) {
+  return request({
+    url: '/spec/plan/listSeasonal',
+    method: 'get',
+    params: query
+  })
+}
+
 // 根据导师ID查询学员列表
 export function getSuccessorListByMentorId(data) {
   return request({
@@ -44,15 +62,6 @@ export function listSuccessorsByMentorId(query) {
   })
 }
 
-// 查询季度汇报培养计划列表
-export function listPlanSeasonal(query) {
-  return request({
-    url: '/spec/plan/listSeasonal',
-    method: 'get',
-    params: query
-  })
-}
-
 // 查询培训计划列表
 export function listPlan(query) {
   return request({

+ 661 - 0
ui/src/views/training/spec/monthlyfeedback/index.vue

@@ -0,0 +1,661 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
+      <el-form-item label="学员" prop="successorId">
+        <el-select
+          size="small"
+          v-model="queryParams.successorId" 
+          placeholder="请选择学员"
+          style="width:200px"
+        >
+          <el-option
+            v-for="successor in this.successorOptions"
+            :key="successor.key"
+            :label="successor.value"
+            :value="successor.key"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="年" prop="feedbackYear">
+        <el-date-picker
+          v-model="queryParams.feedbackYearTemp"
+          placeholder="请选择年"
+          clearable
+          type="year"
+          size="small"
+          @keyup.enter.native="handleQuery"
+          style="width:200px"
+        />
+      </el-form-item>
+      <el-form-item label="月" prop="feedbackMonth">
+        <el-select 
+          v-model="queryParams.feedbackMonth" 
+          placeholder="请选择月" 
+          clearable 
+          size="small" 
+          @keyup.enter.native="handleQuery" 
+          style="width:200px"
+        >
+          <el-option label="1月" value="1"></el-option>
+          <el-option label="2月" value="2"></el-option>
+          <el-option label="3月" value="3"></el-option>
+          <el-option label="4月" value="4"></el-option>
+          <el-option label="5月" value="5"></el-option>
+          <el-option label="6月" value="6"></el-option>
+          <el-option label="7月" value="7"></el-option>
+          <el-option label="8月" value="8"></el-option>
+          <el-option label="9月" value="9"></el-option>
+          <el-option label="10月" value="10"></el-option>
+          <el-option label="11月" value="11"></el-option>
+          <el-option label="12月" value="12"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" 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-table
+      v-loading="loading"
+      :data="dataList"
+      @selection-change="handleSelectionChange"
+      ref="feedbackListSeasonalTable"
+      border
+      :cell-style="tableCellStyle"
+    >
+      <el-table-column label="培养内容" align="center" prop="plantName" width="600px"/>
+      <el-table-column label="开始日期" align="center" prop="startDate"/>
+      <el-table-column label="结束日期" align="center" prop="endDate"/>
+      <el-table-column label="实际完成日期" align="center" prop="dateOfCompletion"/>
+      <el-table-column label="学习状态" align="center" prop="studyState" :formatter="studyStateFormat"/>
+      <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-chat-dot-round"
+            v-hasPermi="['spec:plan:edit']"
+            @click="handleFeedback(scope.row)"
+          >详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 导师反馈 -->
+    <div>
+      <h3>导师反馈</h3>
+      <editor :min-height="300" v-model="mentorFeedback"/>
+    </div>
+    <!-- 保存按钮 -->
+    <div style="text-align:center;margin: 20px auto;">
+      <el-button 
+        size="medium" 
+        type="success" 
+        @click="handleSave"
+      >
+        保存
+      </el-button>
+    </div>
+    <!-- 详情对话框 -->
+    <el-dialog v-dialogDrag :title="feedbackDialog.title" :visible.sync="feedbackDialog.open" width="800px" append-to-body>
+      <div style="width:700px; margin:0px auto;">
+        <h3 style="margin-bottom:20px;">学员心得</h3>
+        <el-table :data="tableData" border style="width: 100%">
+          <el-table-column prop="id" label="编号" width="50"></el-table-column>
+          <el-table-column prop="question" label="问题" width="250"></el-table-column>
+          <el-table-column prop="answer" label="答案"></el-table-column>
+        </el-table>
+        <el-table :data="docFeedback.commonfileList" border>
+          <el-table-column :label="$t('文件名')" align="center" prop="fileName" :show-overflow-tooltip="true">
+            <template slot-scope="scope">
+              <a  class="link-type"  @click="handleDownload(scope.row)">
+                <span>{{ scope.row.fileName }}</span>
+              </a>
+            </template>
+          </el-table-column>
+          <el-table-column :label="$t('大小(Kb)')" align="center" prop="fileSize" :show-overflow-tooltip="true" width="80" />
+          <el-table-column :label="$t('上传人')" align="center" prop="creator" :show-overflow-tooltip="true" width="120"/>
+          <el-table-column :label="$t('操作')" align="center" width="120" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button
+                v-if="scope.row.fileName.endsWith('pdf')"
+                size="mini"
+                type="text"
+                icon="el-icon-view"
+                @click="handleSee(scope.row)"
+              >{{ $t('预览') }}</el-button>
+              <el-button
+                size="mini"
+                type="text"
+                icon="el-icon-download"
+                @click="handleDownload(scope.row)"
+              >{{ $t('下载') }}</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-form v-if="detailFeedback != null">
+          <h3 style="margin-top:30px;margin-bottom:20px;">导师反馈</h3>
+          <el-form-item>
+            <p v-html="detailFeedback" style="border:1px solid #DFE6EC;"/>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getAnswer, addAnswer, updateAnswer, listAnswer } from "@/api/training/spec/answer";
+import { allFileList, delCommonfile } from "@/api/common/commonfile";
+import { addFeedback, getFeedbackByParams, listInvitedSuccessor, updateFeedback, listFeedback, getFeedbackByPlanId } from "@/api/training/spec/feedback";
+import { listMentors } from "@/api/training/spec/successor";
+import { listSuccessorsByMentorId, listPlanMonthly } from "@/api/training/spec/plan";
+import { getToken } from "@/utils/auth";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import Editor from '@/components/Editor';
+
+export default {
+  name: "MonthlyFeedback",
+  components: { Treeselect, Editor },
+  data() {
+    return {
+      // 导师标签
+      mentorTabs: [],
+      // 详情对话框表格数据
+      tableData: [],
+      // 反馈id
+      feedbackId: null,
+      // 父级反馈id
+      parentId: null,
+      // 会议日期快捷选项
+      pickerOptions: {
+        shortcuts: [{
+          text: '今天',
+          onClick(picker) {
+            picker.$emit('pick', new Date());
+          }
+        }, {
+          text: '昨天',
+          onClick(picker) {
+            const date = new Date();
+            date.setTime(date.getTime() - 3600 * 1000 * 24);
+            picker.$emit('pick', date);
+          }
+        }, {
+          text: '一周前',
+          onClick(picker) {
+            const date = new Date();
+            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
+            picker.$emit('pick', date);
+          }
+        }, {
+          text: '一周后',
+          onClick(picker) {
+            const date = new Date();
+            date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);
+            picker.$emit('pick', date);
+          }
+        }]
+      },
+      // 会议日期
+      meetingDate: null,
+      // 学习状态字典
+      studyStateOptions: [],
+      // 汇报展示附件参数
+      doc: {  // 反馈附件
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'docSeasonal'
+        },
+        pType: 'docSeasonal',
+        pId: null
+      },
+      // 培养计划总表数据
+      dataList: [],
+      // 首选标签页
+      activeName: null,
+      // 学员下拉列表
+      successorOptions: [],
+      // 导师下拉列表
+      mentorOptions: [],
+      // 导师数组
+      mentorOptionsArray: [],
+      // 包含导师id的查询对象
+      queryObject: {
+        mentorStaffId: ""
+      },
+      // 导师反馈内容
+      mentorFeedback: null, // 季度反馈内容
+      detailFeedback: null, // 计划详情反馈内容
+      // 反馈对话框参数
+      feedbackDialog: {
+        id: 0,
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: ""
+      },
+      // 问卷单选框
+      radio1: '',
+      radio2: '',
+      radio3: '',
+      radio4: '',
+      radio5: '',
+      radio6: '',
+      radio7: '',
+      radio8: '',
+      radio9: '',
+      radio10: '',
+      radio11: '',
+      radio12: '',
+      radio13: '',
+      radio14: '',
+      // 报告附件参数
+      doc: {  // 季度汇报附件
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'plan'
+        },
+        pType: 'plan',
+        pId: null
+      },
+      docFeedback: {  // 反馈附件
+        file: "",
+        // 是否显示弹出层(报告附件)
+        open: false,
+        // 弹出层标题(报告附件)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的用户数据
+        updateSupport: 0,
+        // 报告附件上传位置编号
+        ids: 0,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/common/commonfile/uploadFile",
+        commonfileList: null,
+        queryParams: {
+          pId: null,
+          pType: 'docFeedback'
+        },
+        pType: 'docFeedback',
+        pId: null
+      },
+      // 标签页选中项
+      activeName: 'zhu',
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 专项培训反馈表格数据
+      feedbackList: [],
+      // 弹出层标题
+      title: "",
+      // 部门树选项
+      deptOptions: undefined,
+      clientHeight:300,
+      // 是否显示弹出层
+      open: false,
+        // 用户导入参数
+        upload: {
+            // 是否显示弹出层(用户导入)
+            open: false,
+            // 弹出层标题(用户导入)
+            title: "",
+            // 是否禁用上传
+            isUploading: false,
+            // 是否更新已经存在的用户数据
+            updateSupport: 0,
+            // 设置上传的请求头部
+            headers: { Authorization: "Bearer " + getToken() },
+            // 上传的地址
+            url: process.env.VUE_APP_BASE_API + "/spec/feedback/importData"
+        },
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 100,
+        feedbackType: null,
+        mentorId: null,
+        successorId: null,
+        successorName: null,
+        parentId: null,
+        planId: null,
+        feedbackYear: null,
+        feedbackYearTemp: null,
+        feedbackSeason: null,
+        feedbackMonth: null,
+        successorFeedback: null,
+        mentorFeedback: null,
+        feedbackScore: null,
+        feedbackStatus: null,
+        meetingDate: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  watch: {
+  },
+  created() {
+    //设置表格高度对应屏幕高度
+    this.$nextTick(() => {
+      this.clientHeight = document.body.clientHeight -250
+    })
+    // 获取学习状态字典
+    this.getDicts("st_study_state").then(response => {
+      this.studyStateOptions = response.data;
+    });
+    // 初始化页面数据
+    this.initPageData();
+  },
+  methods: {
+    /** 初始化页面数据 */
+    initPageData() {
+      // 获取当前日期
+      let date = new Date();
+      // 搜索条件默认为当年、当月
+      this.queryParams.feedbackYear = date.getFullYear().toString();
+      this.queryParams.feedbackYearTemp = date.getFullYear().toString();
+      this.queryParams.feedbackMonth = ( date.getMonth() + 1 ).toString();
+      // 获取当前导师的学员列表
+      listSuccessorsByMentorId(this.queryObject).then(response => {
+        let data = response.data;
+        for (let i = 0; i < data.length; i++) {
+          if (i == 0) {
+            // 默认选中列表中第一个学员
+            this.queryParams.successorId = data[i].staffId;
+            this.getList();
+          }
+          this.successorOptions.push( { key: data[i].staffId, value: data[i].staffName } );
+        }
+        // 获取当前学员当年当月反馈id
+        getFeedbackByParams({
+          successorId: this.queryParams.successorId,
+          feedbackYear: this.queryParams.feedbackYear,
+          feedbackMonth: this.queryParams.feedbackMonth
+        }).then(response => {
+          let data = response.data;
+          this.feedbackId = data.id;
+          this.mentorFeedback = data.mentorFeedback;
+        });
+      });
+    },
+    /** 保存导师反馈内容 */
+    saveMentorFeedback() {
+      let feedback = {};
+      feedback.id = this.feedbackId;
+      feedback.mentorFeedback = this.mentorFeedback;
+      updateFeedback(feedback);
+    },
+    /** 保存按钮处理 */
+    handleSave() {
+      // 保存导师反馈内容
+      this.saveMentorFeedback();
+      this.msgSuccess("保存成功");
+    },
+    /** 培养计划详情处理 */
+    handleFeedback(row) {
+      // 加载反馈附件
+      this.docFeedback.id = row.id;
+      this.docFeedback.queryParams.pId = row.id
+      this.docFeedback.pId = row.id
+      this.getFileListFeedback();
+      // 清空导师反馈内容
+      this.detailFeedback = null;
+      // 清空表格数据
+      this.tableData = [];
+      let feedback1 = {};
+      feedback1.planId = row.id;
+      feedback1.questionId = 1;
+      let feedback2 = {};
+      feedback2.planId = row.id;
+      feedback2.questionId = 2;
+      let feedback3 = {};
+      feedback3.planId = row.id;
+      feedback3.questionId = 3;
+      let answerObj1 = {};
+      let answerObj2 = {};
+      let answerObj3 = {};
+      // 获取问题和答案
+      getAnswer(feedback1).then(response => {
+        let data = response.data;
+        if (data != null) {
+          answerObj1 = { id: 1, question: data.question, answer: data.answer};
+        }
+        return getAnswer(feedback2);
+      }).then(response => {
+        let data = response.data;
+        if (data != null) {
+          answerObj2 = { id: 2, question: data.question, answer: data.answer};
+        }
+        return getAnswer(feedback3);
+      }).then(response => {
+        let data = response.data;
+        if (data != null) {
+          answerObj3 = { id: 3, question: data.question, answer: data.answer};
+          this.tableData.push(answerObj1);
+          this.tableData.push(answerObj2);
+          this.tableData.push(answerObj3);
+        }
+        // 获取导师反馈内容
+        return getFeedbackByPlanId(row.id);
+      }).then(response => {
+        if (response.data != null) {
+          let data = response.data;
+          this.detailFeedback = data.mentorFeedback;
+        }
+        this.feedbackDialog.title = row.staffName + row.plantName + "学习情况详情";
+        this.feedbackDialog.planId = row.id;
+        this.feedbackDialog.studyState = row.studyState;
+        this.feedbackDialog.open = true;
+      });
+    },
+    /** 单元格样式 */
+    tableCellStyle(row, column, rowIndex, columnIndex) {
+      if (row.column.label === "实际完成日期" && row.row.dateOfCompletion > row.row.endDate) {
+        return "background: #FFEEEE"
+      }
+    },
+    /** 学习状态字典翻译 */
+    studyStateFormat(row, column) {
+      return this.selectDictLabel(this.studyStateOptions, row.studyState);
+    },
+    /** 文件下载处理 */
+    handleDownload(row) {
+      var name = row.fileName;
+      var url = row.fileUrl;
+      var suffix = url.substring(url.lastIndexOf("."), url.length);
+      const a = document.createElement('a');
+      a.setAttribute('download', name);
+      a.setAttribute('target', '_blank');
+      a.setAttribute('href', process.env.VUE_APP_BASE_API + url);
+      a.click();
+    },
+    openPdf() {
+      window.open(this.pdf.pdfUrl);//path是文件的全路径地址
+    },
+    handleSee(row) {
+      this.pdf.open = true;
+      this.pdf.title = row.fileName;
+      this.pdf.pdfUrl = process.env.VUE_APP_BASE_API +'/pdf/web/viewer.html?file=' + process.env.VUE_APP_BASE_API + row.fileUrl;
+    },
+    /** 汇报附件参数初始化 */
+    initFileList(id) {
+      this.doc.queryParams.pId = id
+      this.doc.pId = id
+      this.getFileList()
+      // this.$nextTick(() => {
+      //   this.$refs.doc.clearFiles()
+      // })
+    },
+    getFileList() {
+      allFileList(this.doc.queryParams).then(response => {
+        this.doc.commonfileList = response;
+      });
+    },
+    getFileListFeedback() {
+      allFileList(this.docFeedback.queryParams).then(response => {
+        this.docFeedback.commonfileList = response;
+      });
+    },
+    /** 附件上传中处理 */
+    handleFileDocProgress(event, file, fileList) {
+      this.doc.file = file;
+      this.doc.isUploading = true;
+    },
+    handleFileDocProgressFeedback(event, file, fileList) {
+      this.docFeedback.file = file;
+      this.docFeedback.isUploading = true;
+    },
+    /** 附件上传成功处理 */
+    handleFileDocSuccess(response, file, fileList) {
+      this.doc.isUploading = false;
+      this.$alert(response.msg, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      this.getFileList()
+    },
+    handleFileDocSuccessFeedback(response, file, fileList) {
+      this.docMentorFeedback.isUploading = false;
+      this.$alert(response.msg, this.$t('导入结果'), { dangerouslyUseHTMLString: true });
+      this.getFileListFeedback()
+    },
+    /** 删除按钮操作 */
+    handleDeleteDoc(row) {
+      const ids = row.id || this.ids;
+      this.$confirm(this.$t('是否确认删除?'), this.$t('警告'), {
+        confirmButtonText: this.$t('确定'),
+        cancelButtonText: this.$t('取消'),
+        type: "warning"
+      }).then(function() {
+        return delCommonfile(ids);
+      }).then(() => {
+        this.getFileList()
+        this.msgSuccess(this.$t('删除成功'));
+      })
+    },
+    /** 查询专项培训反馈列表 */
+    getList() {
+      this.loading = true;
+      listPlanMonthly(this.queryParams).then(response => {
+        this.dataList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        feedbackType: null,
+        mentorId: null,
+        successorId: null,
+        successorName: null,
+        parentId: null,
+        planId: null,
+        feedbackYear: null,
+        feedbackSeason: null,
+        feedbackMonth: null,
+        successorFeedback: null,
+        mentorFeedback: null,
+        feedbackScore: null,
+        feedbackStatus: 0,
+        meetingDate: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+      // 清空导师反馈内容
+      this.mentorFeedback = null;
+      getFeedbackByParams({
+        successorId: this.queryParams.successorId,
+        feedbackYear: this.queryParams.feedbackYear,
+        feedbackMonth: this.queryParams.feedbackMonth,
+      }).then(response => {
+        let data = response.data;
+        this.feedbackId = data.id;
+        this.mentorFeedback = data.mentorFeedback;
+      });
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+  }
+};
+</script>
+
+<style scoped>
+  .question{
+    margin: 20px 0px;
+    padding-left: 20px;
+  }
+  .answer{
+    padding-bottom: 10px;
+    padding-left: 40px;
+  }
+  h3{
+    margin: 20px 0px;
+  }
+</style>