Browse Source

预案演练计划代码提交

jingyuanchao 2 years ago
parent
commit
e4ff3e792b

+ 0 - 0
src/api/drill/drillDictionary.js → src/api/core/drill/drillDictionary.js


+ 68 - 0
src/api/core/drill/drillPlan.js

@@ -0,0 +1,68 @@
+import request from '@/utils/request'
+
+export function listPlan(query) {
+  return request({
+    url: '/core/drillPlan/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getPlan(id) {
+  return request({
+    url: '/core/drillPlan/' + id,
+    method: 'get'
+  })
+}
+
+export function addPlan(data) {
+  return request({
+    url: '/core/drillPlan',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePlan(data) {
+  return request({
+    url: '/core/drillPlan',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delPlan(id) {
+  return request({
+    url: '/core/drillPlan/' + id,
+    method: 'delete'
+  })
+}
+
+//获取教育培训计划角色列表
+export function listPlanRole(query) {
+  return request({
+    url: '/core/drillPlan/role/list',
+    method: 'get',
+    params: query
+  })
+}
+
+//获取教育培训计划角色列表
+export function roleList(query) {
+  return request({
+    url: '/system/drillPlan/all',
+    method: 'get',
+    params: {
+      orgType: query
+    }
+  })
+}
+
+//下发计划
+export function publishPlan(id) {
+  return request({
+    url: '/core/drillPlan/publish/' + id,
+    method: 'get'
+  })
+}
+

+ 47 - 0
src/api/core/drill/drillTask.js

@@ -0,0 +1,47 @@
+import request from '@/utils/request'
+
+export function listEduTask(query) {
+  return request({
+    url: '/core/eduTask/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getEduTask(id) {
+  return request({
+    url: '/core/eduTask/' + id,
+    method: 'get'
+  })
+}
+
+export function addEduTask(data) {
+  return request({
+    url: '/core/eduTask',
+    method: 'post',
+    data: data
+  })
+}
+
+export function recordEduTask(data) {
+  return request({
+    url: '/core/eduTask',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delEduTask(id) {
+  return request({
+    url: '/core/eduTask/' + id,
+    method: 'delete'
+  })
+}
+
+// 查询详细教育任务
+// export function recordEduTask(id) {
+//   return request({
+//     url: '/core/eduTask/' + id,
+//     method: 'get'
+//   })
+// }

+ 134 - 0
src/views/core/drill/plan/dialog.select.file.vue

@@ -0,0 +1,134 @@
+<template>
+  <el-dialog
+    title="选择学习附件"
+    :visible.sync="isShow"
+    class="g-dialog-select-safe-check"
+    :close-on-click-modal="false"
+    width="55%"
+    top="10vh"
+    append-to-body
+  >
+    <div class="el-dialog-div">
+      <g-search-table
+        ref="st"
+        url="/core/materials/fileList"
+        method="post"
+        :search-data="search"
+        :manual="true"
+        :pageable="true"
+        :select="true"
+        :select-default="selectList"
+        :drag="false"
+        @select="onSelect"
+      >
+        <!-- 搜索 -->
+        <template slot="searchs">
+          <el-form-item prop="title" label="资料标题">
+            <el-input v-model="search.title"></el-input>
+          </el-form-item>
+          <el-form-item prop="fileName" label="附件名称">
+            <el-input v-model="search.fileName"></el-input>
+          </el-form-item>
+        </template>
+
+        <!-- 表格 -->
+        <template slot="columns">
+          <el-table-column
+            prop="orgName"
+            label="资料上传机构"
+           min-width="40%"
+          ></el-table-column>
+          <el-table-column label="资料标题" prop="title" min-width="40%"> </el-table-column>
+          <el-table-column
+            label="资料附件"
+            min-width="20%"
+          >
+          <template slot-scope="scope">
+            <template v-if="scope.row.fileList">
+              <el-tag size="mini" type="success" v-for="(item, index) in scope.row.fileList"
+                      :key="index">
+                {{ JSON.parse(item).name }}
+              </el-tag>
+            </template>
+          </template>
+        </el-table-column>
+          <!--          <el-table-column prop="nfcName"
+                           label="采集点"
+                           width="120"></el-table-column>-->
+        </template>
+      </g-search-table>
+    </div>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="onHide">关闭</el-button>
+      <el-button type="primary" @click="onSubmit">确定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import GSearchTable from "@/components/table/gx.search.table.vue";
+// import { ruleListForOrg } from "@/api/resumption/rule.js";
+export default {
+  components: { GSearchTable },
+  data() {
+    return {
+      isShow: false,
+      selectList: [],
+      // ruleList: [],
+      search: this.emptySearch(),
+    };
+  },
+  computed: {},
+  watch: {
+    orgId(newval) {
+      console.log("orgId",newval);
+      this.search.orgId=newval;
+    },
+  },
+  props: {
+    defaultSelect:{
+      type:Array
+    },
+    orgId:{
+
+    },
+  },
+  methods: {
+    show() {
+      this.search= this.emptySearch();
+      console.log("this.search",this.search)
+      this.isShow = true;
+      this.selectList =this.defaultSelect;
+      // TODO: 处理第一次进入弹窗时,表格数据不加载
+    },
+    onHide() {
+      this.isShow = false;
+      this.search=this.emptySearch();
+    },
+    onSelect(item) {
+      this.selectList = item;
+    },
+    onSubmit() {
+      let s=this.selectList
+      this.$emit("select", this.selectList);
+      this.onHide();
+    },
+    emptySearch() {
+      return {
+        title: null,
+        fileName: null,
+        orgId:this.$store.getters.orgId,
+        t:new Date(),
+      };
+    },
+  },
+  mounted() {
+
+  },
+};
+</script>
+<style lang="scss" scoped>
+.el-dialog-div {
+  overflow: auto;
+}
+</style>

+ 587 - 0
src/views/core/drill/plan/index.vue

@@ -0,0 +1,587 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="20">
+      <!--机构数据-->
+      <el-col :span="4" :xs="24">
+        <org-tree v-model="queryParams.belongOrgId" @defaultKey="getDefaultKey" @checkChange="checkChange"
+                  @click="clickTreeNode" hangsheTree></org-tree>
+      </el-col>
+      <!--搜索栏-->
+      <el-col :span="20" :xs="24">
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
+                 label-width="68px">
+
+          <el-form-item label="机构类型" prop="execOrgType">
+            <el-select v-model="queryParams.execOrgType" placeholder="请选择执行机构类型" clearable>
+              <el-option v-for="dict in dict.type.sys_org_type" :key="dict.value" :label="dict.label"
+                         :value="dict.value"/>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="计划周期" prop="planCycle">
+            <el-select v-model="queryParams.planCycle" placeholder="请选择计划周期" clearable>
+              <el-option v-for="dict in dict.type.edu_plan_cycle" :key="dict.value" :label="dict.label"
+                         :value="dict.value"/>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="计划状态" prop="planStatus">
+            <el-select v-model="queryParams.planStatus" placeholder="请选择计划状态" clearable>
+              <el-option v-for="dict in dict.type.plan_status" :key="dict.value" :label="dict.label"
+                         :value="dict.value"/>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="培训角色" prop="planRoleId">
+            <el-select v-model="queryParams.planRoleId" placeholder="请选择培训角色" clearable>
+              <el-option v-for="item in planRoleList" :key="item.roleId" :label="item.roleName"
+                         :value="item.roleId"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="计划名称" prop="planName">
+            <el-input v-model="queryParams.planName" placeholder="请输入计划名称" clearable
+                      @keyup.enter.native="handleQuery"/>
+          </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="['core:plan:add']">新增
+            </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
+                       v-hasPermi="['core:plan:edit']">修改
+            </el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+                       v-hasPermi="['core:plan:remove']">删除
+            </el-button>
+          </el-col>
+          <!--        <el-col :span="1.5">
+                  <el-button
+                    type="warning"
+                    plain
+                    icon="el-icon-download"
+                    size="mini"
+                    @click="handleExport"
+                    v-hasPermi="['core:plan:export']"
+                  >导出
+                  </el-button>
+                </el-col>-->
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
+
+        <el-table max-height="550px" :data="planList" @selection-change="handleSelectionChange" row-key="id"
+                  :tree-props="{ children: 'children' }">
+          <el-table-column label="序号" align="center" prop="no"/>
+          <el-table-column label="计划名称" align="center" prop="planName"/>
+          <el-table-column label="计划创建机构" align="center" prop="createOrgName"/>
+          <el-table-column label="计划所属机构" align="center" prop="belongOrgName"/>
+          <el-table-column label="培训机构类型" align="center" prop="execOrgType">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.sys_org_type" :value="scope.row.execOrgType"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="计划周期" align="center" prop="planCycle">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.edu_plan_cycle" :value="scope.row.planCycle"/>
+            </template>
+          </el-table-column>
+          <el-table-column prop="planRoleNameList" label="培训角色">
+            <template slot-scope="scope">
+              <template v-if="scope.row.planRoleNameList">
+                <el-tag size="mini" type="success"
+                        v-for="(item, index) in (scope.row.planRoleNameList || '').split(',')"
+                        :key="index">
+                  {{ item }}
+                </el-tag>
+              </template>
+              <template v-else>
+                <el-tag size="mini">{{ scope.row.checkOrgTypeText }}</el-tag>
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column label="培训次数" align="center" prop="execTimes"/>
+          <el-table-column label="备注" align="center" prop="remark"/>
+          <el-table-column label="修改人" align="center" prop="updateBy"/>
+          <el-table-column label="计划状态" align="center" prop="planStatus">
+            <template slot-scope="scope">
+              <dict-tag :options="dict.type.plan_status" :value="scope.row.planStatus"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button v-if="checkCanPublish(scope.row)" size="mini" type="text" icon="el-icon-edit"
+                         @click="handlePublish(scope.row)" v-hasPermi="['core:plan:publish']">下发
+              </el-button>
+              <el-button v-if="checkCanEdit(scope.row)" size="mini" type="text" icon="el-icon-edit"
+                         @click="handleUpdate(scope.row)" v-hasPermi="['core:plan:edit']">修改
+              </el-button>
+              <el-button v-if="checkCanDel(scope.row)" size="mini" type="text" icon="el-icon-delete"
+                         @click="handleDelete(scope.row)" v-hasPermi="['core:plan:remove']">删除
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+                    :limit.sync="queryParams.pageSize"
+                    @pagination="getList"/>
+      </el-col>
+    </el-row>
+    <!-- 添加或修改教育培训计划对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="800px" height="800px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="计划名称" prop="planName">
+              <el-input v-model="form.planName" placeholder="请输入计划名称"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="计划周期" prop="planCycle">
+              <el-select v-model="form.planCycle" placeholder="请选择计划周期">
+                <el-option v-for="dict in dict.type.edu_plan_cycle" :key="dict.value" :label="dict.label"
+                           :value="parseInt(dict.value)"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12" v-show="form.planCycle == 0">
+            <el-form-item prop="startDate" label="开始日期">
+              <el-date-picker v-model="form.startDate" @change="startDateChanged"
+                              :picker-options="startDatepickerOptions"
+                              align="right" type="date" placeholder="选择开始日期">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" v-show="form.planCycle == 0">
+            <el-form-item prop="endDate" label="结束日期">
+              <el-date-picker v-model="form.endDate" :picker-options="endDatepickerOptions" align="right" type="date"
+                              placeholder="选择结束日期">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="培训次数" prop="execTimes">
+              <template>
+                <el-input-number v-model="form.execTimes" :min="1" :max="10"></el-input-number>
+              </template>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="计划状态" prop="planStatus">
+              <el-select v-model="form.planStatus" placeholder="请选择计划状态">
+                <el-option v-for="dict in dict.type.plan_status" :key="dict.value" :label="dict.label"
+                           :value="parseInt(dict.value)"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12" v-show="form.planCycle != 0">
+            <el-form-item label="立即生效" prop="buildTaskNow">
+              <el-checkbox v-model="form.buildTaskNow">
+                勾选后在当前周期开始生效
+              </el-checkbox>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="培训机构类型" prop="execOrgType">
+              <el-select v-model="form.execOrgType" placeholder="请选择执行机构类型" @change="execOrgTypeChanged()">
+                <el-option v-for="dict in dict.type.sys_org_type" :key="dict.value" :label="dict.label"
+                           :value="parseInt(dict.value)"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="培训角色" prop="planRoleId">
+              <el-select v-model="form.planRoleId" placeholder="请选择" multiple>
+                <el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="培训机构" prop="planExecOrgIdList">
+              <tree-select v-model="form.planExecOrgIdList" :options="deptOptions" :show-count="true"
+                           :normalizer="tenantIdnormalizer" :props="{ checkStrictly: true, label: 'name' }"
+                           placeholder="请选择培训机构"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="备注" prop="remark">
+              <el-input v-model="form.remark" placeholder="请输入备注"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="上传文件" prop="fileList">
+              <K-file-upload ref="upload" v-model="form.fileList" @input="getKUploadFileList"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="">
+              <el-button type="primary" @click="showSelectFile">从学习资料中选择</el-button>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </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>
+    <DialogSelectFile
+      ref="DialogSelectFile"
+      :defaultSelect=defaultSelect
+      @select="fileSelected"
+      :orgId="orgId"
+    ></DialogSelectFile>
+
+  </div>
+</template>
+
+<script>
+import {
+  addPlan,
+  delPlan,
+  getPlan,
+  listPlan,
+  listPlanRole,
+  publishPlan,
+  roleList,
+  updatePlan
+} from "@/api/core/drill/drillPlan";
+import tableList from "@/mixins/tableList";
+import OrgTree from "@/components/orgTree";
+import {deptTreeSelect} from "@/api/system/public";
+import KFileUpload from "@/components/K-FileUpload/index.vue";
+import DialogSelectFile from "./dialog.select.file.vue";
+
+export default {
+  name: "Plan",
+  dicts: ['plan_cycle', 'sys_org_type', 'plan_status', 'edu_plan_cycle'],
+  components: {OrgTree, KFileUpload, DialogSelectFile},
+  mixins: [tableList],
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 教育培训计划表格数据
+      planList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      isUnfold: false,
+      defaultSelect: [],
+      orgId: null,
+      // 查询参数
+      queryParams: {
+        execOrgType: null,
+        planCycle: null,
+        planStatus: null,
+        planRoleId: null,
+        planName: null,
+        pageNum: 1,
+        pageSize: 10,
+        belongOrgId: null
+
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        planName: [
+          {required: true, message: "计划名称不能为空", trigger: "blur"}
+        ],
+        planCycle: [
+          {required: true, message: "计划周期不能为空", trigger: "blur"}
+        ],
+        execTimes: [
+          {required: true, message: "培训次数不能为空", trigger: "blur"}
+        ],
+        planStatus: [
+          {required: true, message: "计划状态不能为空", trigger: "blur"}
+        ],
+        execOrgType: [
+          {required: true, message: "培训机构类型不能为空", trigger: "blur"}
+        ],
+        planRoleId: [
+          {required: true, message: "培训角色不能为空", trigger: "blur"}
+        ],
+      },
+      planRoleList: [],
+      roleList: [],
+      //修改新增中的机构树
+      deptOptions: [],
+      startDatepickerOptions: {
+        disabledDate(time) {
+          const date = new Date();
+          date.setTime(date.getTime() - 3600 * 1000 * 24);
+          return time.getTime() < date;
+        },
+      },
+      endDatepickerOptions: {
+        disabledDate: this.disabledDate,
+      },
+    };
+  },
+  created() {
+    this.getList();
+    this.initPlanRoleList();
+    this.orgId = this.$store.getters.orgId;
+  },
+  methods: {
+    /** 查询教育培训计划列表 */
+    getList() {
+      this.loading = true;
+      listPlan(this.queryParams).then(response => {
+        this.planList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    //初始化与计划相关的角色信息
+    initPlanRoleList() {
+      listPlanRole({}).then(response => {
+        this.planRoleList = response.data;
+      });
+    },
+    //初始化所有角色数据
+    initRoleList(query) {
+      this.form.planRoleId = [];
+      roleList(query).then(response => {
+        this.roleList = response.data;
+      });
+    },
+    startDateChanged(time) {
+      if (this.form.startDate > this.form.endDate) {
+        this.form.endDate = this.form.startDate;
+      }
+    },
+    disabledDate(time) {
+      //小于开始日期禁止选择
+      let startDate = new Date();
+      startDate.setTime(startDate.getTime() - 3600 * 1000 * 24);
+      if (this.form.startDate) {
+        startDate = new Date(this.formatTime(this.form.startDate, 'YYYY-MM-DD'));
+        startDate.setTime(startDate.getTime() - 3600 * 1000 * 24);
+      }
+      return time.getTime() < new Date(startDate).getTime()
+    },
+    //已完成下发的计划不显示下发按钮
+    checkCanPublish(row) {
+      if (row.issue === 0 && row.standard === 1) {
+        return true
+      }
+      return false;
+    },
+    //所属机构为当前用户登录机构时才显示 “编辑、删除”按钮
+    checkCanEdit(row) {
+      return row.belongOrgId === this.$store.getters.orgId
+    },
+    checkCanDel(row) {
+      //计划创建机构为当前机构且不是顶级机构创建的计划才显示“删除”按钮
+      return row.belongOrgId == this.$store.getters.orgId && row.createByTopOrg == 1 && row.issue == 0
+    },
+    //省联社下发的计划不显示“删除”按钮
+    checkCreateByTopOrg(row) {
+      return row.createByTopOrg !== 1
+    },
+    execOrgTypeChanged(row) {
+      this.initRoleList(this.form.execOrgType);
+      // this.form.planExecOrgIdList = [];
+    },
+    /** 查询机构树数据 */
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        planName: null,
+        planCycle: null,
+        execTimes: null,
+        planStatus: null,
+        execOrgType: null,
+        planExecOrgIdList: null,
+        startDate: null,
+        endDate: null,
+        buildTaskNow: null,
+        remark: null,
+        planRoleId: null,
+        fileList: null
+
+      };
+      this.resetForm("form");
+    },
+
+    getDefaultKey(key) {
+      this.queryParams.belongOrgId = key;
+      this.getList();
+    },
+    //单选框状态改变
+    checkChange(state) {
+      this.queryParams.checkSub = state;
+      this.handleQuery();
+    },
+    // 节点单击事件
+    clickTreeNode(data) {
+      this.initPlanRoleList();
+      this.queryParams.belongOrgId = data.id;
+      this.handleQuery();
+    },
+    /** treeSelect组件自定义数据*/
+    tenantIdnormalizer(node, instanceId) {
+      if (node.children && !node.children.length) {
+        delete node.children
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      }
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.initRoleList();
+      this.getDeptTree()
+      this.reset();
+      this.open = true;
+      this.title = "添加教育培训计划";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.initRoleList();
+      this.getDeptTree()
+      this.reset();
+      const id = row.id || this.ids
+      getPlan(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改教育培训计划";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          let request={...this.form};
+          if(this.form.planExecOrgIdList){
+            const list = Array.isArray(this.form.planExecOrgIdList) ? this.form.planExecOrgIdList : [this.form.planExecOrgIdList];
+          request.planExecOrgIdList = list;
+        }
+          else{
+            request.planExecOrgIdList = [];
+          }
+          if (request.id != null) {
+            updatePlan(request).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addPlan(request).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除教育培训计划编号为"' + ids + '"的数据项?').then(function () {
+        return delPlan(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {
+      });
+    },
+    /** 下发计划 */
+    handlePublish(row) {
+      if (row.id != null) {
+        this.$modal.confirm('是否确认下发该计划?').then(function () {
+          return publishPlan(row.id);
+        }).then(() => {
+          this.$modal.msgSuccess("计划下发成功");
+          this.getList();
+        }).catch(() => {
+        });
+      }
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('system/plan/export', {
+        ...this.queryParams
+      }, `plan_${new Date().getTime()}.xlsx`)
+    },
+    showSelectFile() {
+      // this.$refs.DialogSelectFile.show();
+      this.$refs["DialogSelectFile"].show();
+    },
+    fileSelected(list) {
+      console.log("fileSelected", list);
+      if (!list) return;
+      list.forEach(x => {
+        this.form.fileList = this.form.fileList.concat(x.fileList);
+      })
+
+    },
+  }
+};
+</script>

+ 251 - 0
src/views/core/drill/task/dialog.info.vue

@@ -0,0 +1,251 @@
+<template>
+    <div class="edu-training-edit">
+        <el-dialog title="教育培训详情" :visible.sync="isShow" width="960px">
+            <div class="page-body">
+                <el-form :model="formData" size="small" ref="form" label-position="right" label-width="120px"
+                    label-suffix=":">
+                    <el-row>
+
+                        <!-- 培训主题 -->
+                        <el-col :span="12">
+                            <el-form-item prop="type" label="培训主题">{{
+                                formData.title
+                            }}</el-form-item>
+                        </el-col>
+
+                        <!-- 机构 -->
+                        <el-col :span="12">
+                            <el-form-item label="培训机构">{{
+                                formData.orgName
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 执行角色 -->
+                        <!-- <el-col :span="12">
+                            <el-form-item prop="eduJobId" label="执行角色">{{
+                                formData.eduJobNames
+                            }}</el-form-item>
+                        </el-col> -->
+                        <!-- 类型 -->
+                        <el-col :span="12">
+                            <el-form-item label="类型">
+                                <template>
+                                    <dict-tag :options="dict.type.edu_type" :value="formData.type" />
+                                </template>
+                            </el-form-item>
+                        </el-col>
+                        <!-- 主持人 -->
+                        <el-col :span="12">
+                            <el-form-item prop="hostId" label="主持人">{{
+                                formData.hostName
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 记录人 -->
+                        <el-col :span="24">
+                            <el-form-item prop="recorderId" label="记录人">{{
+                                formData.recorderName
+                            }}</el-form-item>
+                        </el-col>
+
+                        <!-- 培训开始时间 -->
+                        <el-col :span="12">
+                            <el-form-item prop="trainingStartDateTime" label="培训开始时间">{{
+                                formData.trainingStartDateTime
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 培训截止时间 -->
+                        <el-col :span="12">
+                            <el-form-item prop="trainingEndDateTime" label="培训截止时间">{{
+                                formData.trainingEndDateTime
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 开始日期 -->
+                        <!-- <el-col :span="12">
+                            <el-form-item prop="dateTime" label="开始日期">{{
+                                formData.startDate
+                            }}</el-form-item>
+                        </el-col> -->
+                        <!-- 截止日期 -->
+                        <!-- <el-col :span="12">
+                            <el-form-item prop="dateTime" label="截止日期">{{
+                                formData.endDate
+                            }}</el-form-item>
+                        </el-col> -->
+                        <!-- 内容 -->
+                        <el-col :span="24">
+                            <el-form-item prop="content" label="培训内容">{{
+                                formData.content
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 总结 -->
+                        <el-col :span="24">
+                            <el-form-item prop="note" label="总结">{{
+                                formData.note
+                            }}</el-form-item>
+                        </el-col>
+
+
+                        <!-- 参与人数 -->
+                        <el-col :span="12">
+                            <el-form-item prop="dueCount" label="参与人员">{{
+                                formData.taskUserList ? formData.taskUserList.filter((x) => x.type === 1)
+                                    .map((v) => v.userName).join(",") : ""
+                            }}</el-form-item>
+                        </el-col>
+                        <el-col :span="12">
+                            <el-form-item prop="dueCount" label="缺陷人员">{{
+                                formData.taskUserList ? formData.taskUserList.filter((x) => x.type === 2)
+                                    .map((v) => v.userName).join(",") : ""
+                            }}</el-form-item>
+                        </el-col>
+                        <!-- 图片 -->
+                        <el-col :span="24">
+                            <el-form-item prop="imageList" label="培训图片">
+                                <ImageListPreview v-model="formData.imageList"></ImageListPreview>
+                                <!-- <k-multi-upload :disabled="!!id" v-model="formData.imageList" limit="4" byModule
+                                    moduleName="edu-training" v-if="isShow" /> -->
+                            </el-form-item>
+                        </el-col>
+                        <!-- 图片 -->
+                        <el-col :span="24">
+                            <el-form-item prop="imageList" label="签名图片">
+                                <ImageListPreview v-model="formData.signImageList"></ImageListPreview>
+                                <!-- <k-multi-upload :disabled="!!id" v-model="formData.imageList" limit="4" byModule
+                                    moduleName="edu-training" v-if="isShow" /> -->
+                            </el-form-item>
+                        </el-col>
+
+                        <!-- 文件 -->
+                        <el-col :span="24">
+                            <el-form-item prop="fileList" label="文件" :disabled="true">
+                                <div v-for="(v, i) in formData.fileList" :key="i">
+                                    <a class="downloadLink" @click="onDownload(JSON.parse(v).url, JSON.parse(v).name)">
+                                        {{ JSON.parse(v).name }}
+                                    </a>
+                                </div>
+
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </el-form>
+            </div>
+
+            <div slot="footer" class="dialog-footer">
+                <el-button @click="onHide">关闭</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { getEduTask } from "@/api/core/edu/eduTask";
+
+export default {
+    components: {},
+    dicts: ['edu_type', 'edu_task_status'],
+    data() {
+        const params = this.$route.params;
+        return {
+            id: params ? params.id : null,
+            isShow: false,
+            formData: this.reset(),
+        };
+    },
+    props: {},
+    watch: {},
+    computed: {
+        ...mapState(["loginUser"]),
+    },
+    methods: {
+        ...mapMutations([]),
+        reset(other = {}) {
+            return {
+                id: null,
+                type: null,
+                host: {},
+                recorder: {},
+                dateTime: null,
+                dueCount: null,
+                actualCount: null,
+                content: null,
+                imageList: null,
+                signImageList:null,
+                org: {},
+                ...other,
+            };
+        },
+        async refresh(id, other) {
+            if (!id) {
+                this.reset(other);
+            }
+            else {
+                getEduTask(id).then(response => {
+                    this.formData = response.data;
+                    this.formData.signImageList=this.getSingImageList();
+                    this.loading = false;
+                })
+            }
+        },
+        async show(id, other = {}) {
+            this.id = id;
+            await this.refresh(id, other);
+            this.isShow = true;
+        },
+        // 事件
+        onHide() {
+            this.isShow = false;
+        },
+        onDownload(url, filename) {
+            let this_ = this;
+            this.getBlob(url, function (blob) {
+                this_.saveAs(blob, filename);
+            });
+        },
+        getSingImageList() {
+            let res = this.formData.taskUserList ? this.formData.taskUserList.filter((x) => x.type === 1 && x.sign == 1)
+                .map((v) => v.signImage).join(",") : null;
+            console.log("getSingImage",res)
+            return res;
+        },
+        getBlob(url, cb) {
+            var xhr = new XMLHttpRequest();
+            xhr.open("GET", url, true);
+            xhr.responseType = "blob";
+            xhr.onload = function () {
+                if (xhr.status === 200) {
+                    cb(xhr.response);
+                }
+            };
+            xhr.send();
+        },
+       saveAs(blob, filename) {
+            if (window.navigator.msSaveOrOpenBlob) {
+                navigator.msSaveBlob(blob, filename);
+            } else {
+              /* var link = document.createElement("a");
+                var body = document.querySelector("body");
+
+                link.href = window.URL.createObjectURL(blob);
+                link.download = filename;
+
+                // fix Firefox
+                link.style.display = "none";
+                body.appendChild(link);
+
+                link.click();
+                body.removeChild(link);
+
+               window.URL.revokeObjectURL(link.href);*/
+           }
+        },
+        // 事件
+        //apimark//
+    },
+    mounted() { },
+};
+</script>
+
+<!-- <style lang="less">
+.edu-training-edit {
+}
+</style> -->

+ 405 - 0
src/views/core/drill/task/dialog.perform.vue

@@ -0,0 +1,405 @@
+<template>
+  <div class="edu-training-edit">
+    <el-dialog :title="'培训登记'" :visible.sync="isShow" width="960px">
+      <div class="page-body">
+        <el-form :model="formData" :rules="formDataRules" size="small" ref="form" label-position="right"
+          label-width="120px" label-prefix=":">
+          <el-row>
+            <!-- 培训主题 -->
+            <el-col :span="12">
+              <el-form-item prop="title" label="培训主题">
+                <!-- <el-input
+                        v-model="formData.title"
+                        :maxlength="32"
+                        placeholder="请输入培训主题"
+                        clearable
+                        readonly
+                        disabled
+                    /> -->
+                {{ formData.title }}
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item prop="orgName" label="培训机构">
+                {{ formData.orgName }}
+              </el-form-item>
+            </el-col>
+            <!-- 类型 -->
+            <el-col :span="24">
+              <el-form-item prop="type" label="类型">
+                <el-select v-model="formData.type" placeholder="请选择执行机构类型" clearable>
+                  <el-option v-for="dict in dict.type.edu_type" :key="dict.value" :label="dict.label"
+                    :value="parseInt(dict.value)" />
+                </el-select>
+                <!-- <k-select-constant
+                        name="EduTrainingType"
+                        v-model="formData.type"
+                        placeholder="请选择类型"
+                    ></k-select-constant> -->
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item v-if="formData.id" prop="dateTime" label="培训开始时间">
+                <el-date-picker v-model="formData.trainingStartDateTime" :picker-options="startDatepickerOptions"     
+                  type="datetime" placeholder="选择日期"  @change="startDateChanged">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item v-if="formData.id" prop="dateTime" label="培训结束时间">
+                <el-date-picker v-model="formData.trainingEndDateTime" :picker-options="endDatepickerOptions"
+                  type="datetime" placeholder="选择日期">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <!-- 内容 -->
+            <el-col :span="24">
+              <el-form-item prop="content" label="内容">
+                <k-textarea v-model="formData.content" placeholder="请输入内容" :length="2000" />
+              </el-form-item>
+            </el-col>
+
+            <!-- 主持人 -->
+            <!-- <el-col :span="24">
+              <el-form-item v-if="formData.id" prop="hostId" label="主持人">
+                <k-select
+                  v-model="formData.hostId"
+                  url="/user/find/all"
+                  :params="{ orgId: formData.orgId }"
+                  placeholder="请选择主持人"
+                ></k-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item v-if="formData.id" prop="recorderId" label="记录人">
+                <k-select
+                  v-model="formData.recorderId"
+                  url="/user/find/all"
+                  :params="{ orgId: formData.orgId }"
+                  placeholder="请选择记录人"
+                ></k-select>
+              </el-form-item>
+            </el-col> -->
+            <!-- 截止日期 -->
+            <!-- <el-col :span="24">
+              <el-form-item v-if="formData.id" prop="dateTime" label="培训时间">
+                <el-date-picker
+                  v-model="formData.dateTime"
+                  type="datetime"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </el-col> -->
+            <!-- 总结 -->
+            <el-col :span="24">
+              <el-form-item v-if="formData.id" prop="note" label="总结">
+                <k-textarea v-model="formData.note" placeholder="请输入总结" :length="1000" />
+              </el-form-item>
+            </el-col>
+            <!-- 应到人数 -->
+            <!-- <el-col :span="24">
+              <el-form-item v-if="formData.id" prop="dueCount" label="应到人数">
+                <el-input-number
+                  v-model="formData.dueCount"
+                  :min="0"
+                  placeholder="请输入应到人数"
+                ></el-input-number>
+              </el-form-item>
+            </el-col> -->
+            <!-- 实到人数 -->
+            <!-- <el-col :span="24">
+              <el-form-item
+                v-if="formData.id"
+                prop="actualCount"
+                label="实到人数"
+              >
+                <el-input-number
+                  v-model="formData.actualCount"
+                  :min="0"
+                  placeholder="请输入实到人数"
+                ></el-input-number>
+              </el-form-item>
+            </el-col> -->
+            <el-col :span="24">
+              <el-form-item v-if="formData.id" label="参与人员">
+                <k-select :multiple="true" v-model="formData.absenceList" url="/user/find/all"
+                  :params="{ orgId: formData.orgId }" placeholder="请选择缺席人员" @select="absenceUserSelectChanged"></k-select>
+                <!-- <k-select :multiple="true" v-model="formData.absenceList" url="/user/find/all"
+                  :params="{ orgId: formData.orgId }" placeholder="请选择参与人员"></k-select> -->
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item v-if="formData.id" label="缺席人员">
+                <k-select :multiple="true" v-model="formData.absentList" url="/user/find/all"
+                  :params="{ orgId: formData.orgId }" @select="absentUserSelectChanged" placeholder="请选择缺席人员">
+                </k-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item prop="imageList" label="上传图片">
+                <imgUpload type="more" :value="formData.imageList" @input="imageListChanged"></imgUpload>
+                <!-- <k-multi-upload v-model="formData.imageList" limit="4" byModule moduleName="edu-training" /> -->
+              </el-form-item>
+            </el-col>
+            <!-- 上传文件 -->
+            <!-- <el-col :span="24">
+              <el-form-item prop="fileList" label="上传文件">
+                <k-upload-file-multiple :disabled="!!id" v-model="formData.fileList" max="4"
+                  @uploadTriggerEvent="uploadTriggerEvent" byModule
+                  moduleName="edu-traning-perform"></k-upload-file-multiple>
+              </el-form-item>
+            </el-col> -->
+          </el-row>
+        </el-form>
+      </div>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="onHide">取消</el-button>
+        <el-button type="primary" @click="onSave">暂存</el-button>
+        <el-button type="primary" @click="onSubmit">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { getEduTask, recordEduTask } from "@/api/core/edu/eduTask";
+import dayjs from "dayjs";
+import KTextarea from "@/components/common/textarea.vue";
+import KSelect from "@/components/common/userselect.vue";
+import imgUpload from "@/components/ImageUpload/index.vue";
+export default {
+  components: { KTextarea, KSelect, imgUpload },
+  data() {
+    const params = this.$route.params;
+    return {
+      id: params ? params.id : null,
+      isShow: false,
+      formData: this.reset(),
+      formDataRules: {
+        type: [{ required: true, message: "请选择类型" }],
+        content: [{ required: true, message: "请输入内容" }],
+        // hostId: [{ required: true, message: "请输入主持人" }],
+        // recorderId: [{ required: true, message: "请输入记录人" }],
+
+        trainingStartDateTime: [{ required: true, message: "请输入培训时间" }],
+        trainingEndDateTime: [{ required: true, message: "请输入培训时间" }],
+        note: [{ required: true, message: "请输入总结" }],
+        // dueCount: [{ required: true, message: "请输入应到人数" }],
+        // actualCount: [{ required: true, message: "请输入实到人数" }],
+      },
+      startDatepickerOptions: {
+        disabledDate(time) {
+          return false;
+        },
+      },
+      endDatepickerOptions: {
+        disabledDate: this.endDisabledDate,
+      },
+    };
+  },
+  dicts: ['edu_type', 'edu_task_status'],
+  props: {},
+  watch: {},
+  computed: {
+    ...mapState(["loginUser", "org"]),
+  },
+  methods: {
+    ...mapMutations([]),
+    reset(other = {}) {
+      return {
+        // hostId: null,
+        // recorderId: null,
+        trainingStartDateTime: null,
+        trainingEndDateTime: null,
+        // dueCount: null,
+        // actualCount: null,
+        content: null,
+        title: null,
+        eduJobId: null,
+        imageList: "",
+        absenceList: [],
+        absentList: [],
+        orgList: [],
+        fileList: [],
+        ...other,
+      };
+    },
+    async refresh(id, other) {
+      // this.formData = id
+      //   ? await this.$api.eduTraining.one(id)
+      //   : this.reset(other);
+
+      if (!id) {
+        this.reset(other);
+        return;
+      }
+      getEduTask(id).then(response => {
+        this.formData = response.data;
+        this.loading = false;
+        if (this.formData.imageList == null) {
+          this.formData.imageList = "";
+        }
+        if (this.formData.fileList == null) {
+          this.formData.fileList = [];
+        }
+        if (this.formData.taskUserList) {
+          let list1 = this.formData.taskUserList.filter((element) =>
+            element.type === 1
+          );
+          console.log("list1", list1)
+          this.formData.absenceList = list1 ? list1.map((a) => { return a.userId; })
+            : [];
+
+          let list2 = this.formData.taskUserList.filter((element) =>
+            element.type === 2
+          );
+          console.log("list2", list2)
+          this.formData.absentList = list2 ? list2.map((a) => { return a.userId; })
+            : [];
+        }
+        else {
+          this.formData.absenceList = [];
+          this.formData.absentList = [];
+        }
+      })
+      console.log("getEduTask", this.formData);
+    },
+    async show(id, other = {}) {
+      this.id = id;
+      await this.refresh(id, other);
+      this.isShow = true;
+    },
+    imageListChanged(list) {
+      this.formData.imageList = list;
+      console.log("imageListChanged", this.formData.imageList);
+    },
+    absentUserSelectChanged(list) {
+      // 将类型为2的数据删除
+      if (this.formData.taskUserList) {
+        this.formData.taskUserList = this.formData.taskUserList.filter(x => x.type == 1);
+      }
+      else {
+        this.formData.taskUserList = [];
+      }
+      let tempList = list.map(x => {
+        return {
+          userId: x.id,
+          userName: x.name,
+          type: 2
+        }
+      })
+      if (!tempList) return;
+      this.formData.taskUserList = this.formData.taskUserList.concat(tempList);
+      console.log("absentUserSelectChanged", list, this.formData.taskUserList);
+    },
+    absenceUserSelectChanged(list) {
+      // 将类型为1的数据删除
+      if (this.formData.taskUserList) {
+        this.formData.taskUserList = this.formData.taskUserList.filter(x => x.type == 2);
+      }
+      else {
+        this.formData.taskUserList = [];
+      }
+      let tempList = list.map(x => {
+        return {
+          userId: x.id,
+          userName: x.name,
+          type: 1
+        }
+      });
+      if (!tempList) return;
+      this.formData.taskUserList = this.formData.taskUserList.concat(tempList);
+      console.log("absenceUserSelectChanged", list, this.formData.taskUserList);
+    },
+    // 事件
+    onHide() {
+      this.isShow = false;
+      this.formData = this.reset();
+    },
+    async onSave() {
+      if (!this.validatePerson()) {
+        this.$message.error("参与人员与缺席人员重复,请重新选择!");
+        return;
+      }
+      let request = { submitType: 1, ...this.formData };
+      if (request.trainingStartDateTime)
+        request.trainingStartDateTime = dayjs(request.trainingStartDateTime).format('YYYY-MM-DD HH:mm:ss')
+
+      if (request.trainingEndDateTime)
+        request.trainingEndDateTime = dayjs(request.trainingEndDateTime).format('YYYY-MM-DD HH:mm:ss')
+      // if(request.imageList)
+      //   request.imageList=request.imageList.split(',').map(x=>{return x;});
+
+      recordEduTask(request).then((v) => {
+        this.$emit("success", this.formData);
+        this.onHide();
+        this.$modal.msgSuccess("培训登记暂存成功");
+      });
+    },
+    async onSubmit() {
+      await this.$refs.form.validate();
+      console.log("onSubmit this.formData", this.formData)
+      let due = this.formData.dueCount;
+      let actual = this.formData.actualCount;
+      if (actual > due) {
+        this.$message.error("实到人数不能大于应到人数!");
+      } else if (!this.validatePerson()) {
+        this.$message.error("参与人员与缺席人员重复,请重新选择!");
+      } else {
+        let request = { submitType: 2, ...this.formData };
+        if (request.trainingStartDateTime)
+        request.trainingStartDateTime = dayjs(request.trainingStartDateTime).format('YYYY-MM-DD HH:mm:ss')
+
+      if (request.trainingEndDateTime)
+        request.trainingEndDateTime = dayjs(request.trainingEndDateTime).format('YYYY-MM-DD HH:mm:ss')
+      
+        recordEduTask(request).then((v) => {
+          this.$emit("success", this.formData);
+          this.onHide();
+          this.$modal.msgSuccess("培训登记提交成功");
+        });
+        // this.$emit("success");
+        // this.onHide();
+      }
+    },
+    validatePerson() {
+      for (let i = 0; i < this.formData.absenceList.length; i++) {
+        let absence = this.formData.absenceList[i];
+        if (this.formData.absentList.indexOf(absence) >= 0) {
+          return false;
+        }
+      }
+      return true;
+    },
+    uploadTriggerEvent(value) { },
+
+    endDisabledDate(time) {
+      //小于开始日期禁止选择
+      let startDate = new Date();
+      startDate.setTime(startDate.getTime() - 3600 * 1000 * 24);
+      if (this.formData.trainingStartDateTime) {
+        startDate = new Date(dayjs(this.formData.trainingStartDateTime).format('YYYY-MM-DD'));
+        startDate.setTime(startDate.getTime() - 3600 * 1000 * 24);
+      }
+      return time.getTime() < new Date(startDate).getTime()
+
+    },
+    startDateChanged(time) {
+      console.log("startDateChanged",time,this.formData.trainingStartDateTime ,this.formData.trainingEndDateTime)
+      if (dayjs(this.formData.trainingStartDateTime).isAfter(dayjs(this.formData.trainingEndDateTime))) {
+        this.formData.trainingEndDateTime = this.formData.trainingStartDateTime;
+        console.log("trainingEndDateTime",this.formData.trainingEndDateTime)
+      }
+    },
+  },
+  mounted() { },
+};
+</script>
+
+<!-- <style lang="less">
+.edu-training-edit {
+}
+</style> -->

+ 422 - 0
src/views/core/drill/task/index.vue

@@ -0,0 +1,422 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="20">
+    <el-col :span="4" :xs="24">
+      <org-tree v-model="queryParams.orgId" @defaultKey="getDefaultKey" @checkChange="checkChange"
+                @click="clickTreeNode"></org-tree>
+    </el-col>
+    <el-col :span="20" :xs="24">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
+
+      <el-form-item label="培训主题" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入培训岗位"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="任务时间" prop="rangen">
+        <el-date-picker
+          v-model="queryParams.range"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          placeholder="请选择开始日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="培训类型" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择执行机构类型" clearable>
+            <el-option
+              v-for="dict in dict.type.edu_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+      </el-form-item>
+      <el-form-item label="培训状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择培训状态" clearable>
+            <el-option
+              v-for="dict in dict.type.edu_task_status"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </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-table height="550px" v-loading="loading" :data="eduTaskList" @selection-change="handleSelectionChange">
+      <el-table-column label="培训机构" align="center" prop="orgName" />
+      <el-table-column label="培训角色" align="center" >
+        <template slot-scope="scope">
+            <template v-if="scope.row.taskRoleNameList  ">
+              <el-tag size="mini" type="success" v-for="(item, index) in (scope.row.taskRoleNameList || '').split(',')"
+                      :key="index">
+                {{ item }}
+              </el-tag>
+            </template>
+          </template>
+      </el-table-column>
+      <el-table-column label="培训主题" align="center" prop="title" />
+      <el-table-column label="类型" align="center"  >
+        <template slot-scope="scope">
+            <dict-tag :options="dict.type.edu_type" :value="scope.row.type"/>
+          </template>
+      </el-table-column>
+
+      <el-table-column label="主持人" align="center" prop="hostName" />
+      <el-table-column label="开始日期" align="center" prop="startDate" width="180">
+      </el-table-column>
+      <el-table-column label="截止日期" align="center" prop="endDate" width="180">
+
+      </el-table-column>
+      <el-table-column label="培训时间" align="center" prop="trainingStartDateTime" width="180">
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status" >
+        <template slot-scope="scope">
+            <dict-tag :options="dict.type.edu_task_status" :value="scope.row.status"/>
+          </template>
+      </el-table-column>
+      <el-table-column label="操作" width="120px" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleDetail(scope.row.id)"
+            v-hasPermi="['system:eduTask:detail']"
+          >详情</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-document-add"
+            v-if="canPerform(scope.row)"
+            @click="handleRecorded(scope.row.id)"
+            v-hasPermi="['system:eduTask:remove']"
+          >培训登记</el-button>
+          <el-button type="text" v-if="scope.row.pdfUrl" @click="onDown(scope.row.pdfUrl)"
+            >培训登记簿
+          </el-button>
+          <!-- <el-button type="text" @click="onEdit(scope.row)">查看</el-button>
+          <el-button
+              type="text"
+              v-if="
+              r.row.auditFlag == 'PASS' &&
+                (isExecute || loginOrgId == r.row.orgId) && canPerform(r.row.eduJobIds)&&isOverOrUnStart(r.row)
+            "
+              @click="onPerform(r.row.id, r.row.eduJobIds, r.row.endDate)"
+          >执行
+          </el-button> -->
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </el-col>
+  </el-row>
+    <!-- 添加或修改教育任务对话框 -->
+    <!-- <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="教育培训计划Id" prop="planId">
+          <el-input v-model="form.planId" placeholder="请输入教育培训计划Id" />
+        </el-form-item>
+        <el-form-item label="培训岗位" prop="roleId">
+          <el-input v-model="form.roleId" placeholder="请输入培训岗位" />
+        </el-form-item>
+        <el-form-item label="开始日期" prop="startDate">
+          <el-date-picker clearable
+            v-model="form.startDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="截止日期" prop="endDate">
+          <el-date-picker clearable
+            v-model="form.endDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择截止日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="实到人数" prop="actualCount">
+          <el-input v-model="form.actualCount" placeholder="请输入实到人数" />
+        </el-form-item>
+        <el-form-item label="内容">
+          <editor v-model="form.content" :min-height="192"/>
+        </el-form-item>
+        <el-form-item label="培训岗位名称" prop="roleName">
+          <el-input v-model="form.roleName" placeholder="请输入培训岗位名称" />
+        </el-form-item>
+        <el-form-item label="岗位id集合" prop="roleIds">
+          <el-input v-model="form.roleIds" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="岗位名集合" prop="roleNames">
+          <el-input v-model="form.roleNames" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="学习主题" prop="title">
+          <el-input v-model="form.title" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="总结" prop="note">
+          <el-input v-model="form.note" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="时间" prop="dateTime">
+          <el-date-picker clearable
+            v-model="form.dateTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="应到人数" prop="dueCount">
+          <el-input v-model="form.dueCount" placeholder="请输入应到人数" />
+        </el-form-item>
+        <el-form-item label="主持人" prop="hostId">
+          <el-input v-model="form.hostId" placeholder="请输入主持人" />
+        </el-form-item>
+        <el-form-item label="附件" prop="fileList">
+          <file-upload v-model="form.fileList"/>
+        </el-form-item>
+        <el-form-item label="图片" prop="imageList">
+          <image-upload v-model="form.imageList"/>
+        </el-form-item>
+        <el-form-item label="机构" prop="orgId">
+          <el-input v-model="form.orgId" placeholder="请输入机构" />
+        </el-form-item>
+        <el-form-item label="记录人" prop="recorderId">
+          <el-input v-model="form.recorderId" placeholder="请输入记录人" />
+        </el-form-item>
+        <el-form-item label="机构名称" prop="orgName">
+          <el-input v-model="form.orgName" placeholder="请输入机构名称" />
+        </el-form-item>
+        <el-form-item label="机构" prop="orgPath">
+          <el-input v-model="form.orgPath" placeholder="请输入机构" />
+        </el-form-item>
+        <el-form-item label="pdf下载地址" prop="pdfUrl">
+          <el-input v-model="form.pdfUrl" placeholder="请输入pdf下载地址" />
+        </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> -->
+
+    <dialog-info ref="infoDialog" @success="handleQuery(true)"></dialog-info>
+    <dialog-perform ref="performDialog" @success="handleQuery(true)"></dialog-perform>
+  </div>
+</template>
+
+<script>
+import { listEduTask, getEduTask, delEduTask, addEduTask, updateEduTask } from "@/api/core/edu/eduTask";
+import OrgTree from "@/components/orgTree";
+import DialogInfo from "./dialog.info";
+import DialogPerform from "./dialog.perform";
+import dayjs from "dayjs";
+export default {
+  name: "EduTask",
+  dicts: ['edu_task_status', 'edu_type'],
+  components: {
+    DialogInfo,
+    DialogPerform,
+    OrgTree
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 教育任务表格数据
+      eduTaskList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        checkSub:false,
+        title: null,
+        orgId: this.$store.getters.orgId,
+        type: null,
+        status: null,
+        range: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        orgId: [
+          { required: true, message: "机构不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+
+  methods: {
+    /** 查询教育任务列表 */
+    getList() {
+      this.loading = true;
+      listEduTask(this.queryParams).then(response => {
+        this.eduTaskList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        range:[],
+        title: null,
+        type: null,
+        status : null,
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    //单选框状态改变
+    checkChange(state) {
+      this.queryParams.checkSub = state;
+      this.handleQuery();
+    },
+    getDefaultKey(key) {
+      this.queryParams.orgId = key;
+      this.getList();
+    },
+    // 节点单击事件
+    clickTreeNode(data) {
+      this.queryParams.orgId = data.id;
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加教育任务";
+    },
+    /** 修改按钮操作 */
+    handleDetail(id) {
+      console.log("this.$refs",this.$refs["infoDialog"])
+      this.$refs["infoDialog"].show(id,{});
+      // this.reset();
+      // const id = row.id || this.ids
+      // getEduTask(id).then(response => {
+      //   this.form = response.data;
+      //   this.open = true;
+      //   this.title = "修改教育任务";
+      // });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateEduTask(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addEduTask(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 培训登记按钮操作 */
+    handleRecorded(id) {
+      this.$refs["performDialog"].show(id,{});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('system/eduTask/export', {
+        ...this.queryParams
+      }, `eduTask_${new Date().getTime()}.xlsx`)
+    },
+    canPerform(row) {
+      // debugger
+      let flag = 0;
+      if(row.status>0) return false;
+      if(!row.taskRoleList)   return false;
+      let isOver =this.isNotOverOrUnStart(row);
+      console.log("isNotOverOrUnStart",isOver);
+      row.taskRoleList.forEach((taskRole) => {
+        this.$store.getters.roleList.forEach((role) => {
+          if (taskRole.roleId == role.roleId) {
+            flag = 1;
+          }
+        });
+      });
+      return (flag == 1) && isOver;
+    },
+    isNotOverOrUnStart(row) {
+      const currentTime = dayjs().startOf('day'); // 获取当前时间,并将时分秒部分设置为00时00分00秒
+      const startDate = dayjs(row.startDate).startOf('day'); // 转换开始时间为 Moment.js 对象,并将时分秒部分设置为00时00分00秒
+
+      const endDate = dayjs(row.endDate).startOf('day'); // 转换结束时间为 Moment.js 对象,并将时分秒部分设置为00时00分00秒
+      // 判断开始时间和结束时间是否是同一天
+      const isSameDay = startDate.isSame(endDate, 'day');
+      console.log("isOverOrUnStart",currentTime,startDate,endDate);
+      // 如果是同一天,则判断当前时间是否在开始时间和结束时间之间(包括开始和结束时间)
+      // if (isSameDay) {
+      //   return dayjs(currentTime).isBetween(startDate, endDate, null, '[]');
+      // }
+
+      // 如果不是同一天,则判断当前时间是否早于开始时间或晚于结束时间
+      return !(currentTime < startDate || currentTime > endDate);
+    },
+    async onDown(pdfUrl) {
+      // const data = await this.$api.eduTraining.predown(id);
+      window.open(pdfUrl);
+    },
+  }
+};
+</script>

+ 1 - 1
src/views/drill/drillDictionary/index.vue

@@ -133,7 +133,7 @@ import {
   delDrillDictionary,
   addDrillDictionary,
   updateDrillDictionary
-} from "@/api/drill/drillDictionary";
+} from "@/api/core/drill/drillDictionary";
 import OrgTree from "@/components/orgTree/index.vue";
 import kOrgTree from "@/components/k-orgTree/index.vue";
 import KFileUpload from "@/components/K-FileUpload/index.vue";