Răsfoiți Sursa

解决培训管理页面报错

cyy 1 an în urmă
părinte
comite
62d4c7c4e1

+ 86 - 0
src/views/component/trainingManage/barcodeDialog.vue

@@ -0,0 +1,86 @@
+<!--
+ * @Descripttion: 培训管理-培训信息里扫码枪签到使用,扫码获取条码信息并通过表单脚本传过来的方法,重新返回给表单脚本
+ * @version: 1.0
+ * @Author: Liu_jiaYin
+ * @Date: 2024-04-11 14:43:46
+ * @LastEditors: Do not edit
+ * @LastEditTime: 2024-04-11 17:56:07
+-->
+<template>
+    <div class="sample-scan">
+        <!-- 扫码接收的输入框-->
+        <el-input
+            ref="redarInput"
+            v-model="scanDetail"
+            style="z-index: -999;"
+            @change="change(scanDetail)"
+        />
+        <!-- 扫码操作组件-->
+        <div v-if="visible" class="popContainer" @click="TipsClick">
+            <dv-decoration-12 style="width:150px;height:150px;margin:0 auto;top: 35%;">
+                <span style=" color: #66D9EF;">开始扫描</span>
+            </dv-decoration-12>
+        </div>
+
+    </div>
+</template>
+
+<script>
+export default {
+    components: {
+
+    },
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        },
+        func: {
+            type: Function,
+            required: false
+        }
+    },
+    data () {
+        return {
+            redar: false,
+            scanDetail: ''
+        }
+    },
+    watch: {
+        visible: {
+            handler (val, oldName) {
+                if (val) {
+                    this.$nextTick(() => {
+                        this.$refs.redarInput.focus() // 聚焦input
+                    })
+                }
+            },
+            deep: true,
+            immediate: true
+        }
+    },
+    methods: {
+        change (page) {
+            if (page) {
+                this.func(page)
+                this.scanDetail = ''
+            }
+        },
+        TipsClick () {
+            this.$refs.redarInput.focus() // 聚焦input
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.sample-scan .popContainer {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 9999999;
+    background: rgba(0, 0, 0, 0.7);
+}
+</style>

+ 310 - 0
src/views/component/trainingManage/index.vue

@@ -0,0 +1,310 @@
+<template>
+    <div class="main-container">
+        <ibps-container
+            class="page"
+        >
+            <template>
+                <ibps-crud
+                    key="istree"
+                    ref="crud"
+                    :data="listData"
+                    :toolbars="listConfig.toolbars"
+                    :search-form="listConfig.searchForm"
+                    :pk-key="pkKey"
+                    :columns="listConfig.columns"
+                    :loading="loading"
+                    :pagination="pagination"
+                    :display-field="tableTitle"
+                    :index-row="false"
+                    @sort-change="handleSortChange"
+                    @action-event="handleAction"
+                    @pagination-change="handlePaginationChange"
+                >
+
+                    <template
+                        slot="userIdSlot"
+                        slot-scope="{row}"
+                    >
+                        <ibps-user-selector
+                            type="user"
+                            :value="row.id_"
+                            readonly-text="text"
+                            :disabled="true"
+                            :multiple="true"
+                        />
+
+                    </template>
+                    <template
+                        slot="positionIdSlot"
+                        slot-scope="{row}"
+                    >
+                        <ibps-user-selector
+                            type="position"
+                            :value="row.positions_"
+                            readonly-text="text"
+                            :disabled="true"
+                            :multiple="true"
+                        />
+                    </template>
+
+                    <template
+                        slot="customButton"
+                        slot-scope="{row}"
+                    >
+                        <el-button type="text" icon="el-icon-view" @click="goLook(row)">查阅</el-button>
+
+                    </template>
+
+                    <template slot="user">
+                        <ibps-user-selector
+                            v-model="user"
+                            type="user"
+                            readonly-text="text"
+                            :multiple="true"
+                        />
+                    </template>
+                    <template slot="position">
+                        <ibps-user-selector
+                            v-model="pos"
+                            type="position"
+                            readonly-text="text"
+                            :multiple="false"
+                        />
+                    </template>
+                    <template slot="time">
+                        <el-date-picker
+                            v-model="selectItem"
+                            size="mini"
+                            type="daterange"
+                            :picker-options="pickerOptions"
+                            range-separator="至"
+                            start-placeholder="开始日期"
+                            end-placeholder="结束日期"
+                            align="right"
+                            value-format="yyyy-MM-dd"
+                        />
+                    </template>
+                </ibps-crud>
+            </template>
+        </ibps-container>
+        <TrainingStatic v-if="dialogVisible" :params="params" @close="close" />
+
+    </div>
+</template>
+<script>
+import ActionUtils from '@/utils/action'
+import FixHeight from '@/mixins/height'
+import ibpsUserSelector from '@/business/platform/org/selector'
+
+import { getUserStatisticList } from '@/api/platform/org/employee'
+import TrainingStatic from './trainingStatic.vue'
+
+export default {
+    components: {
+        ibpsUserSelector, TrainingStatic
+    },
+    mixins: [FixHeight],
+    data () {
+        const { level, userList } = this.$store.getters
+        return {
+            level: level.second || level.first,
+            userList: userList,
+            dialogVisible: false,
+            params: {},
+            loading: false,
+            selectItem: '',
+            pickerOptions: {
+                shortcuts: [{
+                    text: '最近一周',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+                        picker.$emit('pick', [start, end])
+                    }
+                }, {
+                    text: '最近一个月',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+                        picker.$emit('pick', [start, end])
+                    }
+                }, {
+                    text: '最近三个月',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+                        picker.$emit('pick', [start, end])
+                    }
+                }]
+            },
+            allData: [],
+
+            pkKey: 'id', // 主键  如果主键不是pk需要传主键
+            pkValue: '',
+            templateKey: '',
+            visible: false,
+            categoryKey: '',
+            tableTitle: '内部培训统计',
+            listData: [],
+            selectListData: [],
+            bianlistData: {
+                dataResult: [],
+                pageResult: {
+                    limit: 0,
+                    page: 0,
+                    totalCount: 0,
+                    totalPages: 0
+                }
+            },
+            //   listTreeData: [],
+            listConfig: {
+                // 工具栏
+                toolbars: [
+                    { key: 'search' }
+                ],
+                // 查询条件
+                searchForm: {
+                    forms: [
+                        { prop: '', label: '姓名', fieldType: 'slot', slotName: 'user' },
+                        { prop: '', label: '部门', fieldType: 'slot', slotName: 'position' },
+                        { prop: '', label: '统计时段', fieldType: 'slot', slotName: 'time' }
+                    ]
+                },
+                // 表格字段配置
+                columns: [
+                    { prop: 'id_', label: '姓名', width: 100, slotName: 'userIdSlot' },
+                    { prop: 'positions_', label: '部门', width: 120, slotName: 'positionIdSlot' },
+                    { prop: 'jian_ding_zi_ge_z', label: '工号', width: 140 },
+                    { prop: 'planedjoin', label: '应参训次数', width: 120 },
+                    { prop: 'truejoin', label: '实参训次数', width: 120 },
+                    { prop: 'participationRate', label: '参训率', width: 120 },
+                    { label: '操作', width: 120, slotName: 'customButton' }
+                ]
+            },
+            pagination: {
+                limit: 20, page: 1
+            },
+            sorts: {},
+            sqlWhere: {},
+            searchWhere: {},
+            user: '',
+            pos: ''
+        }
+    },
+    mounted () {
+        this.getDatas()
+    },
+
+    methods: {
+        close () {
+            this.dialogVisible = false
+            this.getDatas()
+        },
+        goLook (row) {
+            this.params.peixunrenyuan = row.id_
+            if (this.selectItem && this.selectItem.length > 0) {
+                this.params.time = [this.selectItem[0], this.selectItem[1]]
+            } else {
+                delete this.params.time
+            }
+            this.dialogVisible = true
+        },
+        async getDatas () {
+            this.loading = true
+            const params = {
+                diDian: this.level
+            }
+            if (this.user) {
+                params.userId = this.user
+            }
+            if (this.pos) {
+                params.deptId = this.pos
+            }
+            if (this.selectItem && this.selectItem.length > 0) {
+                const [start, end] = this.selectItem
+                params.startTime = start
+                params.endTime = end
+            }
+            console.log('params', params)
+            try {
+                const { data: tempList } = await getUserStatisticList(params)
+                console.log('接口数据', tempList)
+                tempList.forEach(item => { item.jian_ding_zi_ge_z = item.jian_ding_zi_ge_z ? item.jian_ding_zi_ge_z : '/' })
+
+                // 默认参训率排序
+                tempList.sort((a, b) => {
+                    return b.participationRate.split('%')[0] - a.participationRate.split('%')[0]
+                })
+
+                this.selectListData = JSON.parse(JSON.stringify(tempList))
+
+                this.bianlistData.pageResult.totalCount = tempList.length
+                this.bianlistData.pageResult.totalPages = Math.ceil(tempList.length / this.pagination.limit)
+                this.bianlistData.pageResult.limit = this.pagination.limit
+                this.bianlistData.pageResult.page = 1
+                let filterDatas = []
+                if (this.pagination.limit > tempList.length) {
+                    filterDatas = JSON.parse(JSON.stringify(tempList))
+                } else {
+                    for (let index = 0; index < this.bianlistData.pageResult.limit; index++) {
+                        filterDatas.push(tempList[index])
+                    }
+                }
+                this.bianlistData.dataResult = filterDatas
+                ActionUtils.handleListData(this, this.bianlistData)
+                this.loading = false
+            } catch (error) {
+                if (error.message === '服务器君开小差了,请稍后再试') {
+                    this.$message.error('找不到接口,请切换服务环境')
+                }
+                this.loading = false
+            }
+        },
+        refreshData () {
+            this.listData = []
+            this.getDatas()
+        },
+        /**
+ * 处理按钮事件
+ */
+        handleAction (command, position, selection, data, index, button) {
+            switch (command) {
+                case 'search':// 查询
+                    this.refreshData()
+                    break
+                default:
+                    break
+            }
+        },
+        /**
+    * 处理排序
+    */
+        handleSortChange (sort) {
+            this.getDatas()
+        },
+        // 处理分页事件
+        handlePaginationChange (page) {
+            ActionUtils.setPagination(this.pagination, page)
+            this.bianlistData.pageResult.limit = page.limit
+            this.bianlistData.pageResult.page = page.page
+            const filterDatas = []
+            if (this.selectListData.length >= (page.limit * page.page)) {
+                for (let index = (page.limit * page.page) - page.limit; index < (page.limit * page.page); index++) {
+                    filterDatas.push(this.selectListData[index])
+                }
+                this.bianlistData.dataResult = JSON.parse(JSON.stringify(filterDatas))
+            } else {
+                for (let index = (page.limit * page.page) - page.limit; index < this.selectListData.length; index++) {
+                    filterDatas.push(this.selectListData[index])
+                }
+                this.bianlistData.dataResult = JSON.parse(JSON.stringify(filterDatas))
+            }
+            ActionUtils.handleListData(this, this.bianlistData)
+        }
+    }
+}
+</script>
+

+ 364 - 0
src/views/component/trainingManage/registerInfoDialog.vue

@@ -0,0 +1,364 @@
+<template>
+    <div>
+        <el-dialog
+            title="签到信息"
+            center
+            :visible.sync="dialogVisible"
+            width="70%"
+            append-to-body
+            top
+            style="margin-top:100px"
+            :close-on-click-modal="false"
+            :show-close="true"
+            :close-on-press-escape="false"
+        >
+            <div class="contain">
+                <div class="selector">
+                    <div>
+                        签到状态:
+                        <el-select v-model="selectItem" placeholder="请选择" @change="onSelectorChange">
+                            <el-option
+                                v-for="item in ['全部','已签到','未签到','已补签']"
+                                :key="item"
+                                :label="item"
+                                :value="item"
+                            />
+                        </el-select>
+                    </div>
+                    <div class="rate">
+                        <div>
+                            <el-popover
+                                placement="top-start"
+                                width="300"
+                                trigger="hover"
+                                :content="`应到:${calRate.mustPeople}人,应到人员中实际签到:${calRate.mustSignIn}人(总计签到人数:${calRate.signIn}人,其他签到人数:${calRate.signIn-calRate.mustSignIn}人)`"
+                            >
+                                <div slot="reference" style="cursor: pointer;">出勤率:{{ calRate.signInRate }}%</div>
+                            </el-popover>
+                        </div>
+                        <div>
+                            <el-popover
+                                placement="top-start"
+                                width="300"
+                                trigger="hover"
+                                :content="`应到:${calRate.mustPeople}人,未到:${calRate.noSignIn}人`"
+                            >
+                                <div slot="reference" style="cursor: pointer;">缺勤率:{{ calRate.noSignInRate }}%</div>
+                            </el-popover>
+                        </div>
+                        <div>
+                            <el-popover
+                                placement="top-start"
+                                width="300"
+                                trigger="hover"
+                                :content="`应到:${calRate.mustPeople}人,补签:${calRate.laterSignIn}人`"
+                            >
+                                <div slot="reference" style="cursor: pointer;">补签率:{{ calRate.laterSignInRate }}%</div>
+                            </el-popover>
+                        </div>
+                    </div>
+
+                </div>
+                <div class="table">
+                    <el-table :data="showPaperList" row-key="ren_yuan_id_">
+                        <el-table-column
+                            prop=""
+                            label="序号"
+                            type="index"
+                            width="100"
+                            :index="showIndex"
+                        />
+                        <el-table-column
+                            prop="ren_yuan_id_"
+                            label="应参训人员"
+                            width="150"
+                        >
+                            <template slot-scope="{row}">
+                                <ibps-user-selector
+                                    type="user"
+                                    :value="row.ren_yuan_id_"
+                                    readonly-text="text"
+                                    :disabled="true"
+                                    :multiple="true"
+                                />
+                            </template>
+                        </el-table-column>
+                        <el-table-column
+                            prop="status"
+                            label="签到状态"
+                            width="150"
+                        >
+                            <template slot-scope="{row}">
+                                <el-tag :type="showType(row)">{{ row.status }}</el-tag>
+                            </template>
+                        </el-table-column>
+                        <el-table-column
+                            prop="qian_dao_shi_jian"
+                            label="签到时间"
+                            align="center"
+                        />
+                    </el-table>
+                </div>
+
+                <el-pagination
+                    style="margin-top: 5px; padding-bottom: 10px"
+                    :current-page="pagination.currentPage"
+                    :page-sizes="[10, 20,30, 50]"
+                    :page-size="pagination.pageSize"
+                    layout="prev,pager,next,jumper,sizes,->,total"
+                    :total="categoryList.length"
+                    @size-change="handleSizeChange"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="close">关 闭</el-button>
+            </span>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import ibpsUserSelector from '@/business/platform/org/selector'
+export default {
+    components: {
+        ibpsUserSelector
+    },
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        },
+        params: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    data () {
+        return {
+            pagination: {
+                pageSize: 10,
+                currentPage: 1
+            },
+
+            dialogVisible: true,
+            tableList: [],
+            selectItem: '全部'
+        }
+    },
+    computed: {
+        // 计算各种统计率
+        calRate () {
+            const total = this.tableList.length
+            let mustPeople = this.tableList.filter(i => i.flag).length
+            let noSignIn = 0
+            let signIn = 0
+            let mustSignIn = 0 // 应参人数中签到的人数
+            let laterSignIn = 0
+            this.tableList.forEach(item => {
+                if (item.status === '已签到') {
+                    signIn++
+                    if (item.flag) mustSignIn++
+                }
+                if (item.status === '未签到') noSignIn++
+                if (item.status === '已补签') laterSignIn++
+            })
+            if (mustPeople === 0) { // 没有确定参会人员的情况
+                mustPeople = total
+                mustSignIn = signIn
+            }
+            const signInRate = mustPeople === 0 ? 0 : mustSignIn / mustPeople * 100
+            const noSignInRate = mustPeople === 0 ? 0 : noSignIn / mustPeople * 100
+            const laterSignInRate = mustPeople === 0 ? 0 : laterSignIn / mustPeople * 100
+            return {
+                mustSignIn,
+                mustPeople,
+                total,
+                signIn,
+                noSignIn,
+                laterSignIn,
+                signInRate: signInRate.toFixed(2),
+                noSignInRate: noSignInRate.toFixed(2),
+                laterSignInRate: laterSignInRate.toFixed(2)
+            }
+        },
+        categoryList () {
+            const list = { '已签到': 1, '已补签': 2, '未签到': 3 }
+            const tempList = this.selectItem === '全部' ? this.tableList : this.tableList.filter(item => item.status === this.selectItem)
+            // 默认排序显示
+            tempList.sort((a, b) => {
+                if (list[a.status] && list[b.status]) { return list[a.status] - list[b.status] }
+            })
+            return tempList
+        },
+        showPaperList () {
+            const start = (this.pagination.currentPage - 1) * this.pagination.pageSize
+            const end = start + this.pagination.pageSize
+            return this.categoryList.slice(start, end)
+        }
+    },
+    async mounted () {
+        console.log(this.params)
+        await this.getAllPeople()
+    },
+    methods: {
+        // 选择器切换
+        onSelectorChange () {
+            this.pagination = {
+                pageSize: 10,
+                currentPage: 1
+            }
+        },
+        // tag 类型
+        showType (row) {
+            let type = ''
+            switch (row.status) {
+                case '已签到':
+                    type = 'success'
+                    break
+                case '未签到':
+                    type = 'danger'
+                    break
+                case '已补签':
+                    type = 'warning'
+                    break
+                default:
+                    break
+            }
+            return type
+        },
+        // 手动签到的
+        addPeople () {
+            if (!this.params.addPeople) return
+            this.params.addPeople.split(',').forEach(person => {
+                const p = this.tableList.find(item => item.ren_yuan_id_ === person)
+                if (!p) {
+                    this.tableList.push({
+                        ren_yuan_id_: person,
+                        status: '已签到'
+                    })
+                } else {
+                    p.status = '已签到'
+                }
+            })
+        },
+        // 获取全部培训人员  7.15通用性调整
+        async getAllPeople () {
+            const sql = `select * from ${this.params.tableName} where id_='${this.params.guan_lian_id_}'`
+            const { variables: { data }} = await this.$common.request('sql', sql)
+            if (data.length <= 0) {
+                return this.$message.warning('数据异常!')
+            }
+            // console.log('全部人员', data)
+            let peopleList = []
+            switch (this.params.tableName) {
+                case 't_fwxyhyqdb':
+                    peopleList = data[0].bian_zhi_can_hui_?.split(',')
+                    break
+                case 't_rypxcjb':
+                    peopleList = data[0].pei_xun_ren_yuan_?.split(',')
+                    break
+                default:
+                    break
+            }
+            peopleList.forEach(person => {
+                if (person) {
+                    this.tableList.push({
+                        ren_yuan_id_: person,
+                        status: '未签到',
+                        qian_dao_shi_jian: '',
+                        flag: true // 原本应参人员的标记
+                    })
+                }
+            })
+            await this.getRegisterPeople()
+            if (this.params.tableName === 't_rypxcjb') {
+                if (data[0].shi_fou_guo_shen_ === '进行中') {
+                    this.addPeople()
+                }
+                if (data[0].shi_fou_guo_shen_ === '已结束' && data[0].bu_qian_ren_yuan_) {
+                    data[0].bu_qian_ren_yuan_.split(',').forEach(person => {
+                        const p = this.tableList.find(item => item.ren_yuan_id_ === person)
+                        if (p) {
+                            p.status = '已补签'
+                        } else {
+                            this.tableList.push({
+                                ren_yuan_id_: person,
+                                status: '已补签',
+                                qian_dao_shi_jian: ''
+                            })
+                        }
+                    })
+                }
+            } else if (this.params.tableName === 't_fwxyhyqdb' || this.params.tableName === 't_nshyjyb' || this.params.tableName === 't_gshyjyb' || this.params.tableName === 't_jykzjbdjb') {
+                if (data[0].shi_fou_guo_shen_ !== '已完成') {
+                    this.addPeople()
+                }
+            }
+        },
+
+        // 获取已签到人员
+        async getRegisterPeople () {
+            const sql = `select * from t_qdxxb where guan_lian_id_='${this.params.guan_lian_id_}'`
+            const { variables: { data }} = await this.$common.request('sql', sql)
+            // console.log('已签到', data)
+            data.forEach(person => {
+                const p = this.tableList.find(item => item.ren_yuan_id_ === person.ren_yuan_id_)
+                if (!p) {
+                    this.tableList.push({
+                        ren_yuan_id_: person.ren_yuan_id_,
+                        status: '已签到',
+                        qian_dao_shi_jian: person.qian_dao_shi_jian
+                    })
+                } else {
+                    p.status = '已签到'
+                    p.qian_dao_shi_jian = person.qian_dao_shi_jian
+                }
+            })
+        },
+        // 当前页码改变
+        handleCurrentChange (val) {
+            this.pagination.currentPage = val
+        },
+        // 页码选择器改变
+        handleSizeChange (val) {
+            this.pagination.pageSize = val
+            this.pagination.currentPage = 1
+        },
+        // 分页连续序号
+        showIndex (index) {
+            return index + 1 + (this.pagination.currentPage - 1) * this.pagination.pageSize
+        },
+        close () {
+            this.dialogVisible = false
+        }
+    }
+
+}
+</script>
+
+<style lang="scss" scoped>
+.contain{
+    padding: 20px;
+    .table{
+        height:440px;
+        overflow: auto;
+        margin-top: 20px;
+    }
+    .selector{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .rate{
+            display: flex;
+            div{
+                margin: 0 8px;
+                font-size: 16px;
+            }
+        }
+    }
+}
+</style>

+ 454 - 0
src/views/component/trainingManage/trainingStatic.vue

@@ -0,0 +1,454 @@
+<template>
+    <div>
+        <el-dialog
+            :title="title"
+            center
+            :visible.sync="dialogVisible"
+            width="70%"
+            append-to-body
+            top
+            style="margin-top:5vh"
+            :close-on-click-modal="false"
+            :show-close="false"
+            :close-on-press-escape="false"
+        >
+            <div v-if="refresh" v-loading="loading" class="contain">
+                <div class="selector">
+                    <div>
+                        签到状态:
+                        <el-select v-model="selectItem2" placeholder="请选择" size="mini" style="width:100px" @change="onSelectorChange">
+                            <el-option
+                                v-for="item in ['全部','已签到','未签到','已补签']"
+                                :key="item"
+                                :label="item"
+                                :value="item"
+                            />
+                        </el-select>
+                    </div>
+                    <div>
+                        培训时间:
+                        <el-date-picker
+                            v-model="selectItem3"
+                            size="mini"
+                            type="daterange"
+                            :picker-options="pickerOptions"
+                            range-separator="至"
+                            start-placeholder="开始日期"
+                            end-placeholder="结束日期"
+                            align="right"
+                            value-format="yyyy-MM-dd"
+                            style="width:240px"
+                        />
+                    </div>
+                    <div>
+                        <span style="width:110px">培训主题:</span>
+                        <el-input v-model="selectItem1" placeholder="请输入培训主题" size="mini" />
+                    </div>
+                </div>
+                <div class="table">
+                    <el-table :data="showPaperList" row-key="id_" border>
+                        <el-table-column
+                            prop=""
+                            label="序号"
+                            type="index"
+                            width="100"
+                            :index="showIndex"
+                        />
+                        <el-table-column
+                            prop="pei_xun_nei_rong_"
+                            label="培训主题"
+                            show-overflow-tooltip
+                        />
+                        <el-table-column
+                            prop="bian_zhi_ren_"
+                            label="培训负责人"
+                            width="150"
+                        >
+                            <template slot-scope="{row}">
+                                <ibps-user-selector
+                                    type="user"
+                                    :value="row.bian_zhi_ren_"
+                                    readonly-text="text"
+                                    :disabled="true"
+                                    :multiple="true"
+                                />
+                            </template>
+                        </el-table-column>
+
+                        <el-table-column
+                            prop="pei_xun_shi_jian_"
+                            label="培训时间"
+                            width="150"
+                        />
+                        <el-table-column
+                            prop="pei_xun_lei_bie_"
+                            label="培训类型"
+                            width="100"
+                        />
+                        <el-table-column
+                            prop="shi_fou_guo_shen_"
+                            label="培训状态"
+                            width="100"
+                        />
+                        <el-table-column
+                            prop="status"
+                            label="签到状态"
+                            width="100"
+                        >
+                            <template slot-scope="{row}">
+                                <el-tag :type="showType(row)">{{ row.status }}</el-tag>
+                            </template>
+                        </el-table-column>
+
+                        <el-table-column
+                            label="操作"
+                            width="100"
+                        >
+                            <template slot-scope="{row}">
+                                <el-button type="primary" size="mini" :disabled="row.status!=='未签到'" :title="showTitle(row)" icon="el-icon-finished" @click="onRegister(row)">补签</el-button>
+                            </template>
+                        </el-table-column>
+
+                    </el-table>
+                </div>
+
+                <el-pagination
+                    style="margin-top: 5px; padding-bottom: 10px"
+                    :current-page="pagination.currentPage"
+                    :page-sizes="[10, 20,30, 50]"
+                    :page-size="pagination.pageSize"
+                    layout="prev,pager,next,jumper,sizes,->,total"
+                    :total="categoryList.length"
+                    @size-change="handleSizeChange"
+                    @current-change="handleCurrentChange"
+                />
+            </div>
+
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="close">关 闭</el-button>
+            </span>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import ibpsUserSelector from '@/business/platform/org/selector'
+export default {
+    components: {
+        ibpsUserSelector
+    },
+    props: {
+        visible: {
+            type: Boolean,
+            default: false
+        },
+        params: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        }
+    },
+    data () {
+        return {
+            refresh: true,
+            loading: false,
+            title: '',
+            pagination: {
+                pageSize: 10,
+                currentPage: 1
+            },
+
+            dialogVisible: true,
+            tableList: [],
+            selectItem1: '',
+            selectItem2: '全部',
+            selectItem3: '',
+            pickerOptions: {
+                shortcuts: [{
+                    text: '最近一周',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+                        picker.$emit('pick', [start, end])
+                    }
+                }, {
+                    text: '最近一个月',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+                        picker.$emit('pick', [start, end])
+                    }
+                }, {
+                    text: '最近三个月',
+                    onClick (picker) {
+                        const end = new Date()
+                        const start = new Date()
+                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+                        picker.$emit('pick', [start, end])
+                    }
+                }]
+            }
+        }
+    },
+    computed: {
+        categoryList () {
+            const list = { '已签到': 1, '已补签': 2, '未签到': 3 }
+            let tempList = this.tableList
+            // 第一次过滤
+            if (this.selectItem1) {
+                tempList = tempList.filter(item => item.pei_xun_nei_rong_.indexOf(this.selectItem1) >= 0)
+            }
+            // 第二次过滤
+            if (this.selectItem2 !== '全部') {
+                tempList = tempList.filter(item => item.status === this.selectItem2)
+            }
+            // 第三次过滤
+            if (this.selectItem3 && this.selectItem3.length > 0) {
+                tempList = tempList.filter(item => {
+                    let [start, end] = this.selectItem3
+                    const now = new Date(item.pei_xun_shi_jian_).getTime()
+                    start = new Date(start)
+                    end = new Date(end)
+                    return start <= now && now <= end
+                })
+            }
+
+            // 按培训时间排序
+            tempList.sort((a, b) => {
+                return new Date(b.pei_xun_shi_jian_).getTime() - new Date(a.pei_xun_shi_jian_).getTime()
+            })
+
+            return tempList
+        },
+        showPaperList () {
+            const start = (this.pagination.currentPage - 1) * this.pagination.pageSize
+            const end = start + this.pagination.pageSize
+            return this.categoryList.slice(start, end)
+        }
+    },
+    async mounted () {
+        this.loading = true
+        if (this.params.time && this.params.time.length) {
+            this.selectItem3 = this.params.time
+        }
+        this.getTitle()
+        await this.fetchPaperList()
+        await this.fetchRegisterList()
+        this.loading = false
+    },
+    methods: {
+        showTitle (row) {
+            if (row.shi_fou_guo_shen_ !== '已结束') {
+                return '未结束的培训不允许补签'
+            }
+            if (row.status !== '未签到') {
+                return '只有未签到才能补签'
+            }
+            return ''
+        },
+        getTitle () {
+            const { userList } = this.$store.getters
+            const user = userList.find(item => item.userId === this.params.peixunrenyuan)
+            if (user) {
+                this.title = `${user.userName} 的培训记录`
+            }
+        },
+
+        async onRegister (row) {
+            const sql = `select * from t_qdxxb where ren_yuan_id_='${this.params.peixunrenyuan}' and guan_lian_id_='${row.id_}'`
+            const { variables: { data }} = await this.$common.request('sql', sql)
+            if (data.length > 0) {
+                return this.$message.warning('已签到,请不要重复签到!')
+            }
+
+            const peiXunRen = row.pei_xun_ren_yuan_
+            const buQianRen = row.bu_qian_ren_yuan_
+            // 1.签到表补签操作
+            // 2.培训记录表更新操作
+            const paramWhere = [{
+                guan_lian_id_: row.id_,
+                ren_yuan_id_: this.params.peixunrenyuan,
+                qian_dao_shi_jian: this.$common.getDateNow(19)
+            }]
+
+            const addParams = {
+                tableName: 't_qdxxb',
+                paramWhere
+            }
+
+            const params = {
+                tableName: 't_rypxcjb',
+                updList: [{
+                    where: {
+                        id_: row.id_
+                    },
+                    param: {
+                        bu_qian_ren_yuan_: buQianRen === '' ? this.params.peixunrenyuan : buQianRen + ',' + this.params.peixunrenyuan
+                    }
+                }]
+            }
+
+            // 合并请求
+            Promise.all([
+                this.$common.request('add', addParams),
+                this.$common.request('update', params)
+            ]).then(async ([addRes, updateRes]) => {
+                console.log('补签签到数据成功', addRes)
+                console.log('更新补签考试人员', updateRes)
+                this.$message.success('补签成功!')
+                this.loading = true
+                await this.fetchPaperList()
+                await this.fetchRegisterList()
+                this.loading = false
+            }).catch(error => {
+                console.error('补签签到或更新失败', error)
+                this.$message.error('补签失败,请重试!')
+                this.loading = false
+            })
+
+            // 为补签的人发考试与消息 更新试卷人员信息  1.17 考试与培训取消关联
+            // if (row.ti_ku_ming_cheng_) {
+            //     // todo 1.给考试参加人员替换掉2.结束培训判断谁没签到提示补签
+
+            //     const sql1 = `select qb.id_ as tkid,qb.ti_ku_ming_cheng_ as bankName, qb.ti_shu_ as questionCount, qb.zong_fen_ as totalScore, ex.kao_shi_ming_chen as examName, ex.xian_kao_ci_shu_ as limitCount, ex.xian_kao_shi_jian as limitDate, ex.kao_shi_shi_chang as duration, ex.can_kao_ren_yuan_ as examinee, ex.da_biao_zhan_bi_ as qualifiedRadio, ex.ji_fen_fang_shi_ as scoringType, ex.yun_xu_bao_ming_ as allowRegist, ex.sui_ji_chou_ti_ as isRand, ex.sui_ji_ti_shu_ as randNumber,ex.chou_ti_zong_fen_ as randScore,ex.ti_mu_zong_shu_ as randTotal  from t_exams ex, t_question_bank qb where ex.ti_ku_id_ = qb.id_ and ex.id_ = '${row.ti_ku_ming_cheng_}'`
+            //     this.$common.request('sql', sql1).then(res => {
+            //         const { data = [] } = res.variables || {}
+            //         if (!data.length) {
+            //             return
+            //         } else {
+            //             if (data[0].isRand === '1') {
+            //                 data[0].questionCount = data[0].randTotal
+            //                 data[0].totalScore = data[0].randScore
+            //             }
+            //             console.log('data对象', data)
+            //             const { first, second } = this.$store.getters.level || {}
+            //             const { tkid, examName, questionCount, totalScore, duration, qualifiedRadio, limitDate, limitCount } = data[0] || {}
+            //             const paramWhere = [{
+            //                 exam_id_: row.ti_ku_ming_cheng_,
+            //                 ti_ku_id_: tkid,
+            //                 di_dian_: second || first,
+            //                 kao_shi_ren_: this.params.peixunrenyuan,
+            //                 bu_men_: '',
+            //                 bao_ming_shi_jian: this.$common.getDateNow(19),
+            //                 ti_ku_zong_fen_: totalScore,
+            //                 zhuang_tai_: '未开始',
+            //                 sheng_yu_shi_chan: duration,
+            //                 da_biao_zhan_bi_: qualifiedRadio
+            //             }]
+            //             const addParams = {
+            //                 tableName: 't_examination',
+            //                 paramWhere
+            //             }
+            //             console.log('添加考试信息', addParams)
+            //             this.$common.request('add', addParams).then(res => {
+            //                 // 发送通知
+            //                 const limitTime = duration === '不限' || !duration ? '不限' : this.transformTime(duration)
+            //                 const msgContent = `您参加的考试【${examName}】已发布,该考试限考时间【${limitDate}】,限考次数【${limitCount}】,考试时长【${limitTime}】,题数【${questionCount}】,总分【${totalScore}】,请及时完成考试!`
+            //                 console.log('消息msgContent', msgContent)
+            //                 this.$common.sendMsg({
+            //                     subject: '考试信息提醒',
+            //                     content: msgContent,
+            //                     receiverId: this.params.peixunrenyuan,
+            //                     canreplay: '0'
+            //                 })
+            //             }).then(res => {
+            //                 this.$message.success('补签报名考试成功,参与人员可到考试中心考试!')
+            //             })
+            //         }
+            //     })
+            // }
+            // 补签更新培训记录表"参加人员"字段与"参加人数字段" 更新操作
+            // 更新培训记录表 todo
+        },
+        // tag 类型
+        showType (row) {
+            let type = ''
+            switch (row.status) {
+                case '已签到':
+                    type = 'success'
+                    break
+                case '未签到':
+                    type = 'danger'
+                    break
+                case '已补签':
+                    type = 'warning'
+                    break
+                default:
+                    break
+            }
+            return type
+        },
+        // 查询指定人员的培训记录
+        async fetchPaperList () {
+            const sql = `select * from t_rypxcjb where FIND_IN_SET('${this.params.peixunrenyuan}', pei_xun_ren_yuan_) > 0 and shi_fou_guo_shen_='已结束'`
+            const { variables: { data }} = await this.$common.request('sql', sql)
+            this.tableList = data
+        },
+        // 获取签到状态
+        async fetchRegisterList () {
+            const sql = `select guan_lian_id_,ren_yuan_id_ from t_qdxxb where ren_yuan_id_='${this.params.peixunrenyuan}'`
+            const { variables: { data }} = await this.$common.request('sql', sql)
+            this.tableList.forEach(item => {
+                const id_ = item.id_
+                const index = data.findIndex(i => i.guan_lian_id_ === id_)
+                this.$set(item, 'status', index >= 0 ? '已签到' : '未签到')
+                if (item.bu_qian_ren_yuan_) {
+                    const person = item.bu_qian_ren_yuan_.split(',').find(i => i === this.params.peixunrenyuan)
+                    if (person) {
+                        item.status = '已补签'
+                    }
+                }
+            })
+        },
+        // 选择器切换
+        onSelectorChange () {
+            this.pagination = {
+                pageSize: 10,
+                currentPage: 1
+            }
+        },
+
+        // 当前页码改变
+        handleCurrentChange (val) {
+            this.pagination.currentPage = val
+        },
+        // 页码选择器改变
+        handleSizeChange (val) {
+            this.pagination.pageSize = val
+            this.pagination.currentPage = 1
+        },
+        // 分页连续序号
+        showIndex (index) {
+            return index + 1 + (this.pagination.currentPage - 1) * this.pagination.pageSize
+        },
+        close () {
+            this.dialogVisible = false
+            this.$emit('close')
+        }
+    }
+
+}
+</script>
+
+<style lang="scss" scoped>
+.contain{
+    padding: 20px;
+    .table{
+        height:436px;
+        overflow: auto;
+        margin-top: 20px;
+    }
+    .selector{
+        display: flex;
+        align-items: center;
+        div{
+            display: flex;
+            align-items: center;
+            margin: 0 10px;
+        }
+    }
+}
+</style>