chenrui
2025-02-28 ff28e6db2f3535812a753a7213cc106ece8f297c
Merge remote-tracking branch 'origin/dev' into dev
已修改13个文件
已添加3个文件
791 ■■■■■ 文件已修改
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/personal/personJobResponsibilities.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/personal/personRewardPunishmentRecord.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/personal/personTrainingRecord.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/personal/personalTraining.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/ruoyi.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Pagination/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/components/Edit.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/components/ViewRecord.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/tabs/job-responsibilities.vue 108 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/tabs/personnel-list.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/tabs/personnelTraining.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/tabs/reward-punishment-record.vue 194 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/personnel/personnelInfo/tabs/training-record.vue 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -54,6 +54,7 @@
    "jsencrypt": "3.0.0-rc.1",
    "jspdf": "^3.0.0",
    "mammoth": "^1.9.0",
    "moment": "^2.30.1",
    "nprogress": "0.2.0",
    "pako": "^2.1.0",
    "print-js": "^1.6.0",
src/api/cnas/personal/personJobResponsibilities.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
import request from "@/utils/request";
// åˆ†é¡µæŸ¥è¯¢å²—位职责
export function personJobResponsibilitiesSelect(query) {
  return request({
    url: "/personJobResponsibilities/personJobResponsibilitiesSelect",
    method: "get",
    params: query
  });
}
// æ–°å¢žå²—位职责
export function personJobResponsibilitiesSave(query) {
  return request({
    url: "/personJobResponsibilities/personJobResponsibilitiesSave",
    method: "post",
    data: query
  });
}
// å¯¼å‡ºå²—位职责
export function exportPersonJobResponsibilities(query) {
  return request({
    url: "/personJobResponsibilities/exportPersonJobResponsibilities",
    method: "post",
    params: query,
    responseType: "blob"
  });
}
// åˆ é™¤å²—位职责
export function personJobResponsibilitiesDelete(query) {
  return request({
    url: "/personJobResponsibilities/personJobResponsibilitiesDelete",
    method: "delete ",
    params: query
  });
}
src/api/cnas/personal/personRewardPunishmentRecord.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
import request from "@/utils/request";
// äººå‘˜ - å¥–惩记录 åˆ†é¡µæŸ¥è¯¢
export function rewardPunishmentPage(query) {
  return request({
    url: "/personRewardPunishmentRecord/rewardPunishmentPage",
    method: "get",
    params: query
  });
}
// äººå‘˜ - å¥–惩记录 å¯¼å‡º
export function rewardPunishmentExport(query) {
  return request({
    url: "/personRewardPunishmentRecord/rewardPunishmentExport",
    method: "get",
    params: query,
    responseType: 'blob'
  });
}
// äººå‘˜ - å¥–惩记录 æ–°å¢ž/更新
export function addOrUpdateRewardPunishment(query) {
  return request({
    url: "/personRewardPunishmentRecord/addOrUpdateRewardPunishment",
    method: "post",
    data: query,
  });
}
// äººå‘˜ - å¥–惩记录 æ–°å¢ž/更新
export function deleteRewardPunishment(query) {
  return request({
    url: "/personRewardPunishmentRecord/deleteRewardPunishment",
    method: "delete",
    params: query,
  });
}
src/api/cnas/personal/personTrainingRecord.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
import request from "@/utils/request";
// å¯¼å‡ºåŸ¹è®­è®°å½•
export function exportTrainingRecord(query) {
  return request({
    url: "/personTrainingRecord/exportTrainingRecord",
    method: "get",
    params: query,
    responseType: 'blob'
  });
}
// æŸ¥è¯¢äººå‘˜ åŸ¹è®­è®°å½•
export function trainingSelectTrainingRecord(query) {
  return request({
    url: "/personTrainingRecord/trainingSelectTrainingRecord",
    method: "get",
    params: query,
  });
}
// æŸ¥è¯¢äººå‘˜æ˜Žç»† åŸ¹è®­è®°å½•
export function queryPersonnelDetails(query) {
  return request({
    url: "/personTrainingRecord/queryPersonnelDetails",
    method: "get",
    params: query,
  });
}
src/api/cnas/personal/personalTraining.js
@@ -3,7 +3,7 @@
// æŸ¥è¯¢äººå‘˜åŸ¹è®­
export function personTraining(query) {
  return request({
    url: "/personTraining/personTraining",
    url: "/personTraining/personTrainingSelect",
    method: "get",
    params: query
  });
src/assets/styles/ruoyi.scss
@@ -121,7 +121,7 @@
  height: 32px;
  margin-bottom: 10px;
  margin-top: 15px;
  padding: 10px 20px !important;
  padding: 0 20px !important;
}
/* tree border */
src/components/Pagination/index.vue
@@ -106,7 +106,8 @@
<style scoped>
.pagination-container {
  background: #fff;
  padding: 32px 16px;
  padding: 28px 16px;
  margin-top: 10px;
}
.pagination-container.hidden {
  display: none;
src/main.js
@@ -49,6 +49,8 @@
import DictData from "@/components/DictData";
import { checkPermi } from "@/utils/permission"; // æƒé™åˆ¤æ–­å‡½æ•°
import { getToken } from "@/utils/auth";
// æ—¶é—´è½¬æ¢
import Moment from 'moment'
// å…¨å±€æ–¹æ³•挂载
Vue.prototype.getDicts = getDicts;
@@ -80,6 +82,8 @@
    });
  }
})
Vue.use(Moment)
Vue.prototype.$moment = Moment
// å…¨å±€ç»„件挂载
Vue.component("DictTag", DictTag);
src/views/CNAS/personnel/personnelInfo/components/Edit.vue
@@ -222,7 +222,6 @@
      },
      addUserTableInfo: {
        name: null,
        departLimsId: '1',
      },
      multipleSelection: [],
      userList: [],
src/views/CNAS/personnel/personnelInfo/components/ViewRecord.vue
@@ -35,6 +35,7 @@
import filePreview from '@/components/Preview/filePreview.vue';
import limsTable from "@/components/Table/lims-table.vue";
import {delTrainingDetailedFileList, getTrainingDetailedFileList} from "@/api/cnas/personal/personalTraining";
import {delCustomById} from "@/api/system/customer";
export default {
  name: 'ViewRecord',
@@ -126,15 +127,21 @@
    },
    // åˆ é™¤
    delete (row) {
      this.tableLoading = true
      delTrainingDetailedFileList({detailedFileId: row.detailedFileId}).then(res => {
        this.tableLoading = false
        this.$message.success('删除成功')
        this.searchTableList()
      }).catch(err => {
        this.tableLoading = false
        console.log('err---', err);
      })
      this.$confirm('是否删除当前数据?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.tableLoading = true
        delTrainingDetailedFileList({detailedFileId: row.detailedFileId}).then(res => {
          this.tableLoading = false
          this.$message.success('删除成功')
          this.searchTableList()
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {})
    },
    // ä¸Šä¼ éªŒè¯
    fileBeforeUpload(file) {
@@ -167,7 +174,7 @@
  },
  computed: {
    fileAction() {
      return this.javaApi + '/personTraining/delTrainingDetailedFileList'
      return this.javaApi + '/personTraining/uploadTrainingDetailedFile'
    }
  },
src/views/CNAS/personnel/personnelInfo/index.vue
@@ -57,24 +57,24 @@
                         @updatePerson="updatePerson"></PersonnelList>
          <personnelInformation v-if="activeName === '人员基本信息' && !isShowAll" :clickNodeVal="clickNodeVal"></personnelInformation>
        </el-tab-pane>
<!--        <el-tab-pane label="培训计划" name="培训计划">-->
<!--          <PersonnelTraining v-if="activeName === '培训计划'" ref="personnelTraining"-->
<!--                             :departId="departId" :isDepartment="isDepartment"></PersonnelTraining>-->
<!--        </el-tab-pane>-->
<!--        <el-tab-pane label="岗位职责" name="岗位职责">-->
<!--          <job-responsibilities v-if="activeName === '岗位职责'" ref="jobResponsibilities"-->
<!--                                :departId="departId"-->
<!--                                :isDepartment="isDepartment"></job-responsibilities>-->
<!--        </el-tab-pane>-->
<!--        <el-tab-pane label="奖惩记录" name="奖惩记录">-->
<!--          <rewardPunishmentRecord v-if="activeName === '奖惩记录'"-->
<!--                                  :departId="departId" :isDepartment="isDepartment"></rewardPunishmentRecord>-->
<!--        </el-tab-pane>-->
<!--        <el-tab-pane label="培训记录" name="培训记录">-->
<!--          <training-record v-if="activeName === '培训记录'" ref="trainingRecord"-->
<!--                           :departId="departId"-->
<!--                           :isDepartment="isDepartment"></training-record>-->
<!--        </el-tab-pane>-->
        <el-tab-pane label="培训计划" name="培训计划">
          <PersonnelTraining v-if="activeName === '培训计划'" ref="personnelTraining"
                             :departId="departId" :isDepartment="isDepartment"></PersonnelTraining>
        </el-tab-pane>
        <el-tab-pane label="岗位职责" name="岗位职责">
          <job-responsibilities v-if="activeName === '岗位职责'" ref="jobResponsibilities"
                                :departId="departId"
                                :isDepartment="isDepartment"></job-responsibilities>
        </el-tab-pane>
        <el-tab-pane label="奖惩记录" name="奖惩记录">
          <rewardPunishmentRecord v-if="activeName === '奖惩记录'"
                                  :departId="departId" :isDepartment="isDepartment"></rewardPunishmentRecord>
        </el-tab-pane>
        <el-tab-pane label="培训记录" name="培训记录">
          <training-record v-if="activeName === '培训记录'" ref="trainingRecord"
                           :departId="departId"
                           :isDepartment="isDepartment"></training-record>
        </el-tab-pane>
<!--        <el-tab-pane label="任职授权记录" name="任职授权记录">-->
<!--          <Mandate v-if="activeName === '任职授权记录'" ref="manDateRef" :departId="departId" :isDepartment="isDepartment"></Mandate>-->
<!--        </el-tab-pane>-->
@@ -274,6 +274,10 @@
  height: 14px;
  /* è®¾ç½®æ»šåŠ¨æ¡å®½åº¦ */
}
.node_i {
  color: orange;
  font-size: 18px;
}
.custom-tree-node {
  width: 80%;
  line-height: 32px;
src/views/CNAS/personnel/personnelInfo/tabs/job-responsibilities.vue
@@ -1,17 +1,22 @@
<!-- å²—位职责 -->
<template>
  <div class="view">
    <div style="text-align: left; margin-bottom: 15px;padding: 0 10px">
      <label>员工:</label>
      <el-input v-model="userName" clearable placeholder="请输入员工" size="small" style="width: 20vh;"></el-input>
      <el-button size="small" type="primary" @click="refreshTable">查询</el-button>
      <div v-if="isDepartment" style="float: right;">
    <div style="display: flex;justify-content: space-between;">
      <el-form ref="page" size="small" :inline="true">
        <el-form-item label="员工">
          <el-input v-model="userName" clearable placeholder="请输入员工" size="small" style="width: 20vh;"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button size="small" type="primary" @click="refreshTable">查询</el-button>
        </el-form-item>
      </el-form>
      <div>
        <el-button size="small" type="primary" @click="addPost">新增</el-button>
        <!--        <el-button size="small" type="primary">导出excel</el-button>-->
      </div>
    </div>
    <div class="table" style="padding: 0 10px">
      <el-table :data="tableData" height="70vh" style="width: 100%">
    <div class="table">
      <el-table :data="tableData" v-loading="tableLoading" height="66.5vh" style="width: 100%">
        <el-table-column label="序号" type="index" width="60"></el-table-column>
        <el-table-column label="员工编号" min-width="120" prop="account"></el-table-column>
        <el-table-column label="岗位名称" min-width="180" prop="postName"></el-table-column>
@@ -22,7 +27,7 @@
        <el-table-column label="任职人审核日期" min-width="180" prop="incumbentDate"></el-table-column>
        <el-table-column label="主管" min-width="180" prop="supervisorName"></el-table-column>
        <el-table-column label="主管审核日期" min-width="180" prop="supervisorDate"></el-table-column>
        <el-table-column fixed="right" label="操作" width="140">
        <el-table-column fixed="right" label="操作" width="140" align="center">
          <template v-slot="scope">
            <el-button v-if="!isDepartment || scope.row.currentState === '关闭'" size="small" type="text"
                       @click="handleViewClick(scope.row, 'view')">查看
@@ -31,12 +36,14 @@
                       @click="handleViewClick(scope.row, 'edit')">编辑
            </el-button>
            <el-button size="small" type="text" @click="downLoadPost(scope.row)">导出</el-button>
            <el-button v-if="isDepartment" size="small" type="text" @click="deletePost(scope.row)">删除</el-button>
            <el-button v-if="isDepartment" size="small" style="color: #f56c6c" type="text" @click="deletePost(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
                     :total="search.total" layout="->,total, sizes, prev, pager, next, jumper"
                     background
                     style="margin-top: 10px"
                     @size-change="handleSizeChange"
                     @current-change="handleCurrentChange">
      </el-pagination>
@@ -123,13 +130,21 @@
</template>
<script>
// import { dateFormat } from '../../../util/date';
import { dateFormat } from '@/utils/date'
import {
  exportPersonJobResponsibilities, personJobResponsibilitiesDelete,
  personJobResponsibilitiesSave,
  personJobResponsibilitiesSelect
} from "@/api/cnas/personal/personJobResponsibilities";
import {selectUserCondition} from "@/api/cnas/resourceDemand/facilitiesEnvironment/facilitiesAndEnvironment";
import {mapGetters} from "vuex";
export default {
  data() {
    return {
      userName: '',
      tableData: [],
      tableLoading: false,
      responsibleOptions: [],
      search: {
        size: 20,
@@ -192,19 +207,32 @@
    // æŸ¥è¯¢åˆ—表信息
    getPostList(userId) {
      this.search.userId = userId;
      const name = this.isDepartment ? 'departmentId' : 'userId';
      this.$axios.get(this.$api.personnel.personJobResponsibilitiesSelect + '?userName=' + this.userName + `&${name}=` + this.search.userId + '&size=' + this.search.size + '&current=' + this.search.current).then(res => {
        if (res.code === 201) return;
      const params = this.isDepartment ? {
        userName: this.userName,
        departmentId: this.search.userId,
        size: this.search.size,
        current: this.search.current,
      }: {
        userName: this.userName,
        userId: this.search.userId,
        size: this.search.size,
        current: this.search.current,
      }
      this.tableLoading = true
      personJobResponsibilitiesSelect(params).then(res => {
        this.tableLoading = false
        this.tableData = res.data.records;
        this.search.total = res.data.total;
      });
      }).catch(err => {
        this.tableLoading = false
      })
    },
    //提交表单
    async submitForm(saveState) {
      this.$refs.form.validate((valid) => {
        if (valid === true || saveState !== '1submit') {
          // ç»™å½“前环节设置创建人与时间
          let user = JSON.parse(localStorage.getItem('user'));
          let user = this.nickName;
          const dateTime = dateFormat(new Date());
          // èŽ·å–å½“å‰çŽ¯èŠ‚æ“ä½œäººä¸Žæ—¥æœŸ
          switch (this.currentStep) {
@@ -254,12 +282,7 @@
          }
          // èŽ·å–å½“å‰çŠ¶æ€
          this.form.currentState = currentStepAction === 3 ? '关闭' : this.steps[currentStepAction];
          this.$axios.post(this.$api.personnel.personJobResponsibilitiesSave, this.form, {
            headers: {
              'Content-Type': 'application/json'
            },
            noQs: true
          }).then(res => {
          personJobResponsibilitiesSave(this.form).then(res => {
            if (res.code == 200) {
              this.$message.success('提交成功');
              this.getPostList(this.departId);
@@ -307,34 +330,10 @@
    },
    // ä¸‹è½½å²—位职责
    downLoadPost(row) {
      this.$axios.post(this.$api.personPostAuthorizationRecord.exportPersonJobResponsibilities,{id:row.id},{responseType: "blob"}).then(res => {
      exportPersonJobResponsibilities({id:row.id}).then(res => {
        const blob = new Blob([res],{ type: 'application/octet-stream' });
        //将Blob å¯¹è±¡è½¬æ¢æˆå­—符串
        let reader = new FileReader();
        reader.readAsText(blob, 'utf-8');
        reader.onload = () => {
          try {
            let result = JSON.parse(reader.result);
            if (result.message) {
              this.$message.error(result.message);
            } else {
              const url = URL.createObjectURL(blob);
              const link = document.createElement('a');
              link.href = url;
              link.download = row.incumbentName+'-岗位职责'+'.docx';
              link.click();
              this.$message.success('导出成功')
            }
          } catch (err) {
            console.log(err);
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.download = row.incumbentName+'-岗位职责'+'.docx';
            link.click();
            this.$message.success('导出成功')
          }
        }
        this.$download.saveAs(blob, row.incumbentName+'-岗位职责'+'.docx');
        this.$message.success('导出成功')
      })
    },
    // åˆ é™¤å²—位职责
@@ -344,7 +343,7 @@
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$axios.delete(this.$api.personnel.personJobResponsibilitiesDelete + '?id=' + row.id).then(res => {
        personJobResponsibilitiesDelete({id: row.id}).then(res => {
          if (res.code == 200) {
            this.$message.success('删除成功');
            this.getPostList(this.departId);
@@ -362,11 +361,11 @@
    },
    // èŽ·å–è´Ÿè´£äººä¿¡æ¯æŽ¥å£
    getUserList() {
      this.$axios.get(this.$api.deviceScope.selectUserList).then(res => {
      selectUserCondition().then(res => {
        if (res.code == 200) {
          this.responsibleOptions = res.data;
          this.responsibleOptions = res.data
        }
      });
      })
    },
    choiceStep(index) {
      this.currentStepClick = index;
@@ -386,7 +385,10 @@
        this.getPostList(newId);
      }
    }
  }
  },
  computed: {
    ...mapGetters(['nickName'])
  },
};
</script>
<style scoped>
src/views/CNAS/personnel/personnelInfo/tabs/personnel-list.vue
@@ -48,7 +48,7 @@
        :total="page.total"
        background
        layout="->,total, sizes, prev, pager, next, jumper"
        style="margin-top: 16px"
        style="margin-top: 10px"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      >
src/views/CNAS/personnel/personnelInfo/tabs/personnelTraining.vue
@@ -2,6 +2,9 @@
<template>
  <div class="flex_column">
    <div v-if="!editPlanShow && isDepartment">
      <div class="title">
        <span style="font-weight: bold">年度计划</span>
      </div>
      <div style="display: flex;justify-content: space-between;">
        <el-form :model="page" ref="page" size="small" :inline="true">
          <el-form-item label="编制人">
@@ -17,11 +20,14 @@
      </div>
      <lims-table :tableData="yearPlanTableData" :column="yearPlanColumn"
                  :currentChange="currentChange"
                  @pagination="pagination" :height="'calc(100vh - 290px)'"
                  @pagination="pagination" height="40vh"
                  :page="page" :tableLoading="yearLoading"></lims-table>
    </div>
    <div v-if="!editPlanShow" class="table">
      <div v-if="!editPlanShow && isDepartment">
      <div>
        <div class="title">
          <span style="font-weight: bold">年度计划明细</span>
        </div>
        <div style="display: flex;justify-content: space-between;">
          <el-form :model="inDetailForm" ref="inDetailForm" size="small" :inline="true">
            <el-form-item label="培训讲师">
@@ -42,10 +48,10 @@
          </div>
        </div>
        <lims-table :tableData="inDetailPlanTableData" :column="inDetailPlanColumn"
                    :currentChange="currentChange" :height="isDepartment ? '45vh' : '68vh' "
                    :height="isDepartment ? '40vh' : '62vh' "
                    :isSelection="true" :handleSelectionChange="handleSelectionChange"
                    @pagination="pagination1"
                    :page="inDetailPagination" :tableLoading="yearLoading"></lims-table>
                    :page="inDetailPagination" :tableLoading="yearDetailLoading"></lims-table>
      </div>
    </div>
    <Add ref="addPlan" :currentChangeRow="currentChangeRow" @search="getInDetailPlan(currentRowId, departId)"></Add>
@@ -167,6 +173,7 @@
        trainingDate: '',
      },
      yearLoading: false,
      yearDetailLoading: false,
      yearPlanTableData: [], // å¹´åº¦è®¡åˆ’表数据
      yearPlanColumn: [
        {
@@ -292,7 +299,7 @@
              name: '批准',
              type: 'text',
              disabled: (row) => {
                if(row.approvalStatus === 1 || this.userId != row.approverId) {
                if(row.approvalStatus === 1 || this.userId != row.approverId || row.reviewerStatus != 1) {
                  return true;
                } else {
                  return false;
@@ -477,6 +484,7 @@
    },
    // æŸ¥è¯¢-年度计划表
    getYearPlanList(userId) {
      this.yearLoading = true
      const params = this.isDepartment ?
      {
        departmentId: userId,
@@ -490,13 +498,16 @@
          compilerName: this.page.compilerName,
        }
      personTraining(params).then(res => {
        this.yearLoading = false
        this.yearPlanTableData = res.data.records;
        this.pagination.total = res.data.total;
        if (this.yearPlanTableData.length > 0) {
          this.currentRowId = this.yearPlanTableData[0].id
          this.currentChange(this.yearPlanTableData[0])
        }
      });
      }).catch(err => {
        this.yearLoading = false
      })
    },
    pagination (page) {
      this.page.size = page.limit
@@ -530,10 +541,14 @@
          trainingLecturerName: this.inDetailForm.trainingLecturerName,
          trainingDate: this.inDetailForm.trainingDate,
        }
      this.yearDetailLoading = true
      queryTheAnnualPlanDetailsTable(params).then(res => {
        this.yearDetailLoading = false
        this.inDetailPlanTableData = res.data.records;
        this.inDetailPagination.total = res.data.total;
      });
      }).catch(err => {
        this.yearDetailLoading = false
      })
    },
    pagination1 (page) {
      this.inDetailPagination.size = page.limit
@@ -639,7 +654,7 @@
      this.uploadDia = false
      this.uploading = false
      if (response.code != 200) {
        this.$message.error(response.message)
        this.$message.error(response.msg)
        return
      }
      this.$message.success('上传成功')
@@ -761,23 +776,27 @@
  overflow: auto;
  justify-content: space-between;
}
.pagination {
  display: flex;
  justify-content: space-between
}
.items_center {
  display: flex;
  align-items: center;
}
.date_box {
  margin: 0 5px;
}
.search {
  width: 150px;
  margin: 0 16px;
}
.title {
  position: relative;
  font-size: 16px;
  color: #333;
  font-weight: 400;
  padding-left: 10px;
  margin-bottom: 10px;
}
.title::before {
  position: absolute;
  left: 0;
  top: 4px;
  content: '';
  width: 4px;
  height: 16px;
  background-color: #3A7BFA;
  border-radius: 2px;
}
</style>
src/views/CNAS/personnel/personnelInfo/tabs/reward-punishment-record.vue
@@ -1,33 +1,41 @@
<!-- å¥–惩记录 -->
<template>
  <div>
    <div style="text-align: left; margin-bottom: 15px;">
      <label>姓名</label>
      <el-input v-model="search.userName" clearable placeholder="请输入关键字" size="small" style="width: 20vh;"></el-input>
      <label style="margin-left: 1em">奖惩日期</label>
      <el-date-picker
        v-model="search.searchTimeList"
        :picker-options="pickerOptions"
        align="right"
        clearable
        end-placeholder="结束日期"
        format="yyyy-MM-dd"
        range-separator="至"
        size="small"
        start-placeholder="开始日期"
        style="width: 20%"
        type="daterange"
        unlink-panels
        value-format="yyyy-MM-dd 00:00:00">
      </el-date-picker>
      <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">查询</el-button>
      <div style="float: right;">
        <el-button :loading="outLoading" size="small" type="primary" @click="handleDown">导出</el-button>
        <el-button size="small" type="primary" @click="addRow">新增</el-button>
    <div class="view">
      <div style="display: flex;justify-content: space-between;">
        <el-form :model="search" ref="page" size="small" :inline="true">
          <el-form-item label="姓名">
            <el-input v-model="search.userName" clearable placeholder="请输入关键字" size="small" style="width: 20vh;"></el-input>
          </el-form-item>
          <el-form-item label="奖惩日期">
            <el-date-picker
              v-model="search.searchTimeList"
              :picker-options="pickerOptions"
              align="right"
              clearable
              end-placeholder="结束日期"
              format="yyyy-MM-dd"
              range-separator="至"
              size="small"
              start-placeholder="开始日期"
              style="width: 100%"
              type="daterange"
              unlink-panels
              value-format="yyyy-MM-dd 00:00:00">
            </el-date-picker>
          </el-form-item>
          <el-form-item>
            <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">查询</el-button>
          </el-form-item>
        </el-form>
        <div>
          <el-button :loading="outLoading" size="small" type="primary" @click="handleDown">导出</el-button>
          <el-button size="small" type="primary" @click="addRow">新增</el-button>
        </div>
      </div>
    </div>
    <div class="table">
      <el-table :data="tableData" height="70vh" style="width: 100%">
      <el-table :data="tableData" v-loading="tableLoading" height="66.5vh" style="width: 100%">
        <el-table-column label="序号" type="index" width="120">
          <template v-slot="scope">
            <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span>
@@ -49,22 +57,25 @@
        </el-table-column>
        <el-table-column label="创建人" min-width="180" prop="createUserName">
        </el-table-column>
        <el-table-column fixed="right" label="操作" width="100">
        <el-table-column fixed="right" label="操作" width="100" align="center">
          <template v-slot="scope">
            <el-button size="small" type="text" @click="editForm(scope.row)">编辑</el-button>
            <el-button size="small" type="text" @click="deleteRow(scope.row)">删除</el-button>
            <el-button size="small" type="text" style="color: #f56c6c" @click="deleteRow(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
      <el-pagination :current-page="1" :page-size="search.size"
                     :page-sizes="[10, 20, 30, 50, 100]"
                     :total="search.total" layout="->,total, sizes, prev, pager, next, jumper"
                     background
                     style="margin-top: 10px"
                     @size-change="handleSizeChange"
                     @current-change="handleCurrentChange">
      </el-pagination>
    </div>
    <el-dialog
      :visible.sync="dialogVisible"
      title="提示"
      title="奖惩记录"
      width="50%"
      @open="getUserList">
      <div style="height: 40vh">
@@ -119,14 +130,22 @@
        </el-form>
      </div>
      <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
    <el-button type="primary" @click="saveOrUpdate">ç¡® å®š</el-button>
  </span>
        <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="saveOrUpdate">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addOrUpdateRewardPunishment, deleteRewardPunishment,
  rewardPunishmentExport,
  rewardPunishmentPage
} from "@/api/cnas/personal/personRewardPunishmentRecord";
import {selectUserCondition} from "@/api/system/user";
import {delCustomById} from "@/api/system/customer";
export default {
  props: {
    departId: {
@@ -143,6 +162,7 @@
  data() {
    return {
      tableData: [],
      tableLoading: false,
      search: {
        size: 20,
        current: 1,
@@ -213,23 +233,23 @@
      this.getPersonnelTraining(this.departId);
    },
    async getPersonnelTraining() {
      const {code, data} = await this.$axios({
        method: 'get',
        url: rewardPunishmentPageApi,
        params: {
          userId: this.isDepartment ? '' : this.departId,
      const params = {
        userId: this.isDepartment ? '' : this.departId,
          departmentId: this.isDepartment ? this.departId : '',
          current: this.search.curent,
          size: this.search.size,
          userName: this.search.userName,
          startTime: this.search.searchTimeList && this.search.searchTimeList[0],
          endTime: this.search.searchTimeList && this.search.searchTimeList[1],
        }
      })
      if (code == 200) {
        this.tableData = data.records
        this.search.total = data.total
      }
      this.tableLoading = true
      rewardPunishmentPage(params).then(res => {
        this.tableLoading = false
        this.tableData = res.data.records
        this.search.total = res.data.total
      }).catch(err => {
        this.tableLoading = false
      })
    },
    addRow () {
      this.dialogVisible = true
@@ -240,60 +260,28 @@
    },
    handleDown(){
      this.outLoading = true
      this.$axios.post(this.$api.deviceCheck.rewardPunishmentExport,{
      rewardPunishmentExport({
        userId: this.isDepartment ? '' : this.departId,
        departmentId: this.isDepartment ? this.departId : '',
        userName: this.search.userName,
        startTime: this.search.searchTimeList && this.search.searchTimeList[0],
        endTime: this.search.searchTimeList && this.search.searchTimeList[1]
      },{responseType: 'blob'}).then(res => {
      }).then(res => {
        this.outLoading = false
        const blob = new Blob([res], {
          type: 'application/force-download'
        })
        //将Blob å¯¹è±¡è½¬æ¢æˆå­—符串
        let reader = new FileReader();
        reader.readAsText(blob, 'utf-8');
        reader.onload = () => {
          try {
            let result = JSON.parse(reader.result);
            if (result.message) {
              this.$message.error(result.message);
            } else {
              // åˆ›å»ºä¸€ä¸ªè¶…链接,将文件流赋进去,然后实现这个超链接的单击事件
              const elink = document.createElement('a')
              elink.download = decodeURI('奖惩记录'+'.xlsx')
              elink.style.display = 'none'
              elink.href = URL.createObjectURL(blob)
              document.body.appendChild(elink)
              elink.click();
              URL.revokeObjectURL(elink.href) // é‡Šæ”¾URL å¯¹è±¡
              document.body.removeChild(elink)
              this.$message.success('导出成功')
            }
          } catch (err) {
            console.log(err);
            // åˆ›å»ºä¸€ä¸ªè¶…链接,将文件流赋进去,然后实现这个超链接的单击事件
            const elink = document.createElement('a')
            elink.download = decodeURI('奖惩记录'+'.xlsx')
            elink.style.display = 'none'
            elink.href = URL.createObjectURL(blob)
            document.body.appendChild(elink)
            elink.click();
            URL.revokeObjectURL(elink.href) // é‡Šæ”¾URL å¯¹è±¡
            document.body.removeChild(elink)
            this.$message.success('导出成功')
          }
        }
        this.$download.saveAs(blob, '奖惩记录.xlsx')
        this.$message.success('导出成功')
      })
    },
    // èŽ·å–è´Ÿè´£äººä¿¡æ¯æŽ¥å£
    getUserList() {
      this.$axios.get(this.$api.deviceScope.selectUserList).then(res => {
      selectUserCondition().then(res => {
        if (res.code == 200) {
          this.responsibleOptions = res.data
        }
      })
      });
    },
    selectUserChange(val) {
      const index = this.responsibleOptions.findIndex(item => item.id === val)
@@ -302,42 +290,40 @@
        this.form.account = this.responsibleOptions[index].account
      }
    },
    // æ‰“开表单弹框
    editForm(row) {
      this.dialogVisible = true
      this.form = {...row};
    },
    // æäº¤è¡¨å•数据
    saveOrUpdate() {
      this.$refs.form.validate(async (valid) => {
        if (valid) {
          this.dialogVisible = false
          const {code, data} = await this.$axios({
            method: 'post',
            url: addOrUpdateRewardPunishmentApi,
            data: this.form,
            headers: {
              'Content-Type': 'application/json'
            },
            noQs: true
          })
          if (code == 200) {
            this.$message.success("操作成功!")
          addOrUpdateRewardPunishment(this.form).then(res => {
            this.dialogVisible = false
            this.$message.success("操作成功")
            this.getPersonnelTraining(this.departId);
          }
          })
        }
      })
    },
    async deleteRow(row) {
      const {code, data} = await this.$axios({
        method: 'delete',
        url: deleteRewardPunishmentApi,
        params: {
          id: row.id
        }
      })
      if (code == 200) {
        this.$message.success("操作成功!")
        this.getPersonnelTraining(this.departId);
      }
    deleteRow(row) {
      this.$confirm('是否删除当前数据?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        deleteRewardPunishment({id: row.id}).then(res => {
          if (res.code === 500) {
            return
          }
          this.$message.success('删除成功')
          this.getPersonnelTraining(this.departId);
        }).catch(e => {
          this.$message.error('删除失败')
        })
      }).catch(() => {})
    }
  },
  watch: {
src/views/CNAS/personnel/personnelInfo/tabs/training-record.vue
@@ -2,82 +2,54 @@
<template>
  <div>
    <div class="flex_table">
      <div v-if="isDepartment" style="width: 50%">
<!--        <TableCard :showTitle="false">-->
<!--          <template v-slot:form>-->
<!--            <div class="items_center">-->
<!--              <span>姓名</span>-->
<!--              <el-input v-model="trainingPagination.userName" class="search" clearable placeholder="请输入" size="small"></el-input>-->
<!--              <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">查询</el-button>-->
<!--            </div>-->
<!--            <div>-->
<!--&lt;!&ndash;              <el-button :loading="outLoading" size="small" type="primary" @click="exportExcel">导出</el-button>&ndash;&gt;-->
<!--            </div>-->
<!--          </template>-->
<!--          <template v-slot:table>-->
<!--            <ZTTable-->
<!--              :column="trainingColumn"-->
<!--              :currentChange="currentChange"-->
<!--              :height="'calc(100vh - 18em)'"-->
<!--              :highlightCurrentRow="true"-->
<!--              :table-data="trainingTableData"-->
<!--              :table-loading="trainingLoading"-->
<!--              style="padding: 0 15px;">-->
<!--            </ZTTable>-->
<!--            <div class="pagination">-->
<!--              <div></div>-->
<!--              <el-pagination-->
<!--                :page-size="trainingPagination.size"-->
<!--                :page-sizes="[10, 20, 30, 40]"-->
<!--                :total="trainingPagination.total"-->
<!--                layout="total, sizes, prev, pager, next, jumper"-->
<!--                @current-change="handleYearCurrentTraining"-->
<!--                @size-change="handleYearSizeChangeTraining">-->
<!--              </el-pagination>-->
<!--            </div>-->
<!--          </template>-->
<!--        </TableCard>-->
<!--      </div>-->
<!--      <div :style="`width: ${isDepartment ? '50%' : '100%'};`">-->
<!--        <TableCard :showTitle="false">-->
<!--          <template v-slot:form>-->
<!--            <div class="items_center">-->
<!--              <span>年份</span>-->
<!--              <el-date-picker-->
<!--                v-model="searchForm.trainingDate"-->
<!--                clearable-->
<!--                format="yyyy"-->
<!--                placeholder="选择年"-->
<!--                size="small"-->
<!--                style="margin: 0 10px"-->
<!--                type="year"-->
<!--                value-format="yyyy">-->
<!--              </el-date-picker>-->
<!--              <el-button size="small" type="primary" @click="queryPersonnelDetailsPage(currentChangeRow.userId)">查询</el-button>-->
<!--              <el-button size="small" type="primary" @click="openDownloadDia(currentChangeRow)">导出</el-button>-->
<!--            </div>-->
<!--          </template>-->
<!--          <template v-slot:table>-->
<!--            <ZTTable-->
<!--              :column="trainingPersonColumn"-->
<!--              :height="'calc(100vh - 18em)'"-->
<!--              :table-data="trainingPersonTableData"-->
<!--              :table-loading="trainingPersonLoading"-->
<!--              style="padding: 0 15px;">-->
<!--            </ZTTable>-->
<!--            <div class="pagination">-->
<!--              <div></div>-->
<!--              <el-pagination-->
<!--                :page-size="trainingPersonPagination.size"-->
<!--                :page-sizes="[10, 20, 30, 40]"-->
<!--                :total="trainingPersonPagination.total"-->
<!--                layout="total, sizes, prev, pager, next, jumper"-->
<!--                @current-change="handleYearCurrentPagination"-->
<!--                @size-change="handleYearSizeChangePagination">-->
<!--              </el-pagination>-->
<!--            </div>-->
<!--          </template>-->
<!--        </TableCard>-->
      <div v-if="isDepartment" style="width: 49%">
        <div class="title">
          <span style="font-weight: bold">年度计划</span>
        </div>
        <div style="display: flex;justify-content: space-between;">
          <el-form :model="trainingPagination" ref="trainingPagination" size="small" :inline="true">
            <el-form-item label="姓名">
              <el-input v-model="trainingPagination.userName" class="search" clearable placeholder="请输入" size="small"></el-input>
            </el-form-item>
            <el-form-item>
              <el-button size="small" type="primary" @click="getPersonnelTraining(departId)">查询</el-button>
            </el-form-item>
          </el-form>
        </div>
        <lims-table :tableData="trainingTableData" :column="trainingColumn"
                    ref="trainingTableData"
                    :currentChange="currentChange" :highlightCurrentRow="true"
                    @pagination="pagination" :height="'calc(100vh - 22em)'"
                    :page="trainingPagination" :tableLoading="trainingLoading"></lims-table>
      </div>
      <div :style="`width: ${isDepartment ? '49%' : '100%'};`">
        <div class="title">
          <span style="font-weight: bold">年度计划明细</span>
        </div>
        <div style="display: flex;justify-content: space-between;">
          <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
            <el-form-item label="年份">
              <el-date-picker
                v-model="searchForm.trainingDate"
                clearable
                format="yyyy"
                placeholder="选择年"
                size="small"
                type="year"
                value-format="yyyy">
              </el-date-picker>
            </el-form-item>
            <el-form-item>
              <el-button size="small" type="primary" @click="queryPersonnelDetailsPage(currentChangeRow.userId)">查询</el-button>
            </el-form-item>
          </el-form>
          <div>
            <el-button size="small" type="primary" @click="openDownloadDia(currentChangeRow)">导出</el-button>
          </div>
        </div>
        <lims-table :tableData="trainingPersonTableData" :column="trainingPersonColumn"
                    :height="'calc(100vh - 22em)'" @pagination="pagination1"
                    :page="trainingPersonPagination" :tableLoading="trainingPersonLoading"></lims-table>
      </div>
    </div>
  </div>
@@ -85,8 +57,15 @@
<script>
import limsTable from "@/components/Table/lims-table.vue";
import {
  exportTrainingRecord,
  queryPersonnelDetails,
  trainingSelectTrainingRecord
} from "@/api/cnas/personal/personTrainingRecord";
export default {
  components: {},
  components: {limsTable},
  props: {
    departId: {
      type: Number,
@@ -215,48 +194,31 @@
      if (!date) {
        date = this.$moment().format('YYYY')
      }
      console.log('date----', date);
      this.$axios.get( this.$api.personnel.exportTrainingRecord+ '?userId=' + row.userId + '&trainingDate=' + date,{responseType: "blob"}).then(res => {
      exportTrainingRecord({userId: row.userId, trainingDate: date}).then(res => {
        this.outLoading = false
        const blob = new Blob([res],{ type: 'application/msword' });
        //将Blob å¯¹è±¡è½¬æ¢æˆå­—符串
        let reader = new FileReader();
        reader.readAsText(blob, 'utf-8');
        reader.onload = () => {
          try {
            let result = JSON.parse(reader.result);
            if (result.message) {
              this.$message.error(result.message);
            } else {
              const url = URL.createObjectURL(blob);
              const link = document.createElement('a');
              link.href = url;
              link.download = '培训记录导出' + '.docx';
              link.click();
              this.$message.success('导出成功')
            }
          } catch (err) {
            console.log(err);
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.download = '培训记录导出' + '.docx';
            link.click();
            this.$message.success('导出成功')
          }
        }
        this.$download.saveAs(blob, '培训记录导出.docx');
      })
    },
    // èŽ·å–å®žéªŒå®¤-培训计划列表信息
    getPersonnelTraining(departId) {
      // const name = this.isDepartment ? 'departmentId' : 'userId';
      this.$axios.get(`${this.$api.personnel.trainingSelectTrainingRecord}?departmentId=${departId}&size=${this.trainingPagination.size}&current=${this.trainingPagination.current}&userName=${this.trainingPagination.userName}`).then(res => {
      const params = {
        departmentId: departId,
        size: this.trainingPagination.size,
        current: this.trainingPagination.current,
        userName: this.trainingPagination.userName,
      }
      this.trainingLoading = true
      trainingSelectTrainingRecord(params).then(res => {
        this.trainingLoading = false
        this.trainingTableData = res.data.records;
        this.trainingPagination.total = res.data.total;
        if (this.trainingTableData.length > 0) {
          this.currentChange(this.trainingTableData[0]);
          this.$refs.trainingTableData.setCurrentRow(this.trainingTableData[0])
        }
      });
      }).catch(err => {
        this.trainingLoading = false
      })
    },
    // èŽ·å–ä¸ªäºº-培训计划列表信息
    currentChange(row) {
@@ -270,29 +232,31 @@
      if (this.searchForm.trainingDate === null) {
        this.searchForm.trainingDate = ''
      }
      this.$axios.get(`${this.$api.personnel.queryPersonnelDetails}?userId=${userId}&size=${this.trainingPersonPagination.size}&current=${this.trainingPersonPagination.current}&trainingDate=${this.searchForm.trainingDate}`).then(res => {
      const params = {
        userId: userId,
        size: this.trainingPersonPagination.size,
        current: this.trainingPersonPagination.current,
        trainingDate: this.searchForm.trainingDate,
      }
      this.trainingPersonLoading = true
      queryPersonnelDetails(params).then(res => {
        this.trainingPersonLoading = false
        this.trainingPersonTableData = res.data.records;
        this.trainingPersonPagination.total = res.data.total;
      });
      }).catch(err => {
        this.trainingPersonLoading = false
      })
    },
    // åˆ†é¡µ
    handleYearCurrentTraining(page) {
      this.trainingPagination.curent = page;
      this.getPersonnelTraining(this.departId);
    },
    handleYearSizeChangeTraining(size) {
      this.trainingPagination.size = size;
    pagination(page) {
      this.trainingPagination.size = page.limit;
      this.getPersonnelTraining(this.departId);
    },
    // åˆ†é¡µ
    handleYearCurrentPagination(page) {
      this.trainingPersonPagination.curent = page;
    pagination1(page) {
      this.trainingPersonPagination.size = page.limit;
      this.queryPersonnelDetailsPage(this.currentChangeRow.userId);
    },
    handleYearSizeChangePagination(size) {
      this.trainingPersonPagination.size = size;
      this.queryPersonnelDetailsPage(this.currentChangeRow.userId);
    }
  },
  watch: {
    departId: {
@@ -308,29 +272,32 @@
};
</script>
<style scoped>
>>> .el-form-item {
  margin-bottom: 13px;
}
.flex_table {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
.pagination {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}
.items_center {
  display: flex;
  align-items: center;
}
.search {
  width: 150px;
  padding: 0 6px;
}
.title {
  position: relative;
  font-size: 16px;
  color: #333;
  font-weight: 400;
  padding-left: 10px;
  margin-bottom: 10px;
}
.title::before {
  position: absolute;
  left: 0;
  top: 4px;
  content: '';
  width: 4px;
  height: 16px;
  background-color: #3A7BFA;
  border-radius: 2px;
}
</style>