Files
UNION_NSI/target/classes/views/platform/meeting/online.html
T
2026-09-08 19:49:21 +08:00

378 lines
15 KiB
HTML

<!--#
layout("/layouts/platform.html"){
#-->
<style>
.qrcode {
min-width: 240px;
text-align: center;
display: flex;
flex-direction: column;
}
.real-data {
display: flex;
flex-wrap: wrap;
}
.real-data .data-card {
border-radius: 10px;
width: calc((100% - 80px) / 4);
min-width: 100px;
/*height: 150px;*/
/*min-height: 100px;*/
/*max-height: 150px;*/
/*background: #3CB371;*/
/*background: #000;*/
background-image: linear-gradient(141deg, #9fb8ad 0%, #1fc8db 51%, #2cb5e8 75%);
margin: 10px 0 10px 20px;
padding: 10px;
color: #ffffff;
display: flex;
flex-direction: column;
position: relative;
}
.real-data .data-card .data-card-title {
font-size: 20px;
max-width: 100%;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
flex: 1;
position: absolute;
}
.real-data .data-card .data-card-num {
font-size: 90px;
flex: auto;
display: flex;
justify-content: center;
align-items: center;
}
.real-data .data-card .flow-border {
position: absolute;
display: block;
}
.timePeriod_card {
border-top: 5px solid #106898;
}
.timePeriod_card .el-form-item {
margin-bottom: 0 !important;
}
img {
height: 100% !important;
width: 100%;
}
.operation {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 1111;
}
</style>
<div id="app" v-cloak>
<guava ref="guava" v-model="guavaIndex">
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
<el-date-picker
placeholder="选择年份"
style="width: 100%" type="year"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</div>
</div>
<div class="search-item">
<div class="search-item-label">会议名称:</div>
<div class="search-item-option">
<el-input clearable
placeholder="可输入会议名称、地点进行查询"
v-model="pageForm.searchKeyword"></el-input>
</div>
</div>
<div class="search-item">
<div class="search-item-label">会议类型:</div>
<div class="search-item-option">
<el-select clearable style="width: 100%" v-model="pageForm.typeId">
<el-option :label="item.meetingTypeName"
:value="item.id"
v-for="item in meetingTypeList"></el-option>
</el-select>
</div>
</div>
<div class="search-query">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
</div>
</div>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="会议信息">
<template #func>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
align="center"
header-align="center" ref="meetingTable">
<el-table-column type="expand">
<template scope="scope">
<el-row :gutter="20" justify="start" style="flex-wrap: wrap" type="flex"
v-if="scope.row.timePeriods && scope.row.timePeriods.length>0">
<el-col :xl="5" v-for="tp in scope.row.timePeriods">
<el-card class="mb10 timePeriod_card" shadow="hover">
<el-form label-width="80px">
<el-form-item label="名称">{{tp.timePeriodName}}</el-form-item>
<el-form-item label="会议时间">{{tp.startTime}}</el-form-item>
<!--<el-form-item label="结束时间">{{tp.endTime}}</el-form-item>-->
</el-form>
<el-row justify="space-around"
style="border-top: 1px solid #ebeef5;padding: 20px 0 0 0"
type="flex">
<el-button @click="exportSignature(tp.id)" size="medium" type="text">
导出签字表
</el-button>
<el-button @click="title = tp.timePeriodName; openOnline(tp.id,scope.row.id)"
size="medium" type="text">
扫描二维码
</el-button>
</el-row>
</el-card>
</el-col>
</el-row>
<el-row v-else>
<el-empty description="没有时间段"></el-empty>
</el-row>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="序号" type="index" width="80">
<template scope="scope">
<span>{{ scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1 }} </span>
</template>
</el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='isCanLeave'">
<span class="text-muted" v-if="row.isCanLeave==null">未设置</span>
<span class="text-success" v-if="row.isCanLeave==true"></span>
<span class="text-danger" v-if="row.isCanLeave==false"></span>
</template>
</el-table-column>
<el-table-column label="操作" width="200px">
<template scope="{row}">
<el-button @click="toggleRowTimePeriod(row)" size="mini" type="primary">展开</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<template #view>
<div style="min-width: 500px;height: 100%;position: relative">
<el-row type="flex">
<el-col :span="4" class="qrcode">
<div @click="downLoadQrCode" title="点击二维码可下载">
<qrcode :value="qrCodeUrl" ref="qrCode"
tag="img"></qrcode>
</div>
</el-col>
<el-col :span="20" class="real-data">
<template v-for="rd of realTimeData">
<div class="data-card">
<div class="data-card-title">
{{rd.label}}
</div>
<div class="data-card-num">
<count-to :end-val="rd.value"
:start-val="getLastValue(rd.key)"></count-to>
</div>
</div>
</template>
</el-col>
</el-row>
<!-- <el-row class="mt20">-->
<el-table :data="userData" :max-height="signTableHeight" class="mt20" ref="signTable">
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="工号" prop="loginname"></el-table-column>
<el-table-column label="性别" prop="sex"></el-table-column>
<el-table-column label="单位" prop="unitname"></el-table-column>
<el-table-column label="签到时间" prop="signInDateTime"></el-table-column>
<el-table-column label="签到名次">
<template scope="scope">
{{userData.length - scope.$index}}
</template>
</el-table-column>
</el-table>
<!-- </el-row>-->
</div>
</template>
</guava>
</div>
<script>
<!--# include("/platform/meeting/includeJs/meetingUtil.js"){} #-->
const meetUtil = new meetingUtil()
let pollingInterval = null
const intervalTime = 3500
window['vue'] = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
title: '',
tableColumns: [
{prop: 'meetingName', label: '会议名称', sortable: true},
{prop: 'meetingTypeName', label: '会议类型', sortable: true},
{prop: 'startTime', label: '会议时间', sortable: true},
/*{prop: 'endTime', label: '结束时间', sortable: true},*/
{prop: 'location', label: '会议地点', sortable: true},
{prop: 'isCanLeave', label: '能否请假', sortable: true},
],
pageForm: {
year: new Date().getFullYear().toString()
},
meetingTypeList: [],
lastTimeData: [],
realTimeData: [],
userData: [],
meetingId: null,
timePeriodId: null,
qrcodeVisible: false,
qrCodeUrl: null,
signTableHeight: 600
}
},
watch: {
guavaIndex(val) {
if (val === 'index') {
this.toggleFullScreen()
}
}
},
methods: {
//导出签字表
exportSignature(timePeriodId) {
window.open(loc() + '/exportSignature/' + timePeriodId)
},
//打开在线
async openOnline(timePeriodId, meetingId) {
this.meetingId = meetingId
this.timePeriodId = timePeriodId
this.$refs.guava.view()
this.toggleFullScreen()
this.calcSignTableHeight()
this.generateQrCodeUrl(timePeriodId, meetingId)
this.stopInterval()
pollingInterval = this.startPolling(this.getRealTimeData)
},
calcSignTableHeight() {
this.$nextTick(() => {
setTimeout(() => {
console.log(window.innerHeight)
const offsetTop = this.$refs.signTable.$el.offsetTop
const th = window.innerHeight - 54 - 40 - offsetTop
console.log(th)
this.$set(this, 'signTableHeight', th)
})
})
},
async generateQrCodeUrl(tpId, meetingId) {
const resp = await $.get(loc() + '/generateQrCodeUrl', {tpId, meetingId})
if (resp.code === 0) {
this.qrCodeUrl = resp.data
} else {
this.notifyError(resp.msg)
}
},
async getRealTimeData() {
this.lastTimeData = clone(this.realTimeData)
const resp = await $.get(loc() + '/getRealTimeData/' + this.timePeriodId)
if (resp.code === 0) {
this.lastTimeData = clone(this.realTimeData)
this.$set(this, 'realTimeData', resp.data.countData)
//去重
let ud = clone(this.userData)
ud.unshift(...resp.data.userData)
let uMap = new Map()
for (let u of ud) {
if (!uMap.has(u.loginname)) {
uMap.set(u.loginname, u)
}
}
this.$set(this, 'userData', [...uMap.values()])
} else {
}
},
startPolling(func) {
this.lastTimeData = []
this.realTimeData = []
this.userData = []
func()
return setInterval(func, intervalTime)
},
stopInterval() {
if (pollingInterval) {
clearInterval(pollingInterval)
}
},
getLastValue(key) {
if (this.lastTimeData && this.lastTimeData.length > 0) {
return this.lastTimeData.find(v => v.key === key).value
} else {
return 0
}
},
downLoadQrCode() {
if (this.$refs['qrCode']) {
const src = this.$refs['qrCode'].$el.currentSrc
const aEle = document.createElement('a')
aEle.setAttribute("download", '签到二维码')
aEle.setAttribute("href", src)
aEle.click()
}
},
toggleRowTimePeriod(row) {
this.$refs['meetingTable'].toggleRowExpansion(row)
}
},
async created() {
this.meetingTypeList = await meetUtil.getAllMeetingType()
this.pageData()
// this.openOnline('2bb2b18a053b4c8ca00e27d30e8f4573')
},
beforeDestroy() {
this.stopInterval()
}
})
</script>
<!--#
}
#-->