<template>
|
<div>
|
<div class="bg-white border-bottom pt-2 pb-4 px-4">
|
<h5 class="font-weight-bold py-2 mt-2">
|
<i class="ion ion-ios-arrow-dropleft f20 text-light pr5"></i>
|
<!-- <router-link to="/">
|
<span class="text-muted font-weight-light">考勤管理 /</span>
|
</router-link>-->
|
考勤管理
|
</h5>
|
<el-row :gutter="10" style="margin-top:15px">
|
<el-col class="mb-2" :lg="2" :md="6" :sm="6" :xs="12">
|
<Select
|
class="mr10"
|
v-model="searchFrome.identity"
|
@change="search"
|
placeholder="身份"
|
style="width:100%"
|
>
|
<Option
|
v-for="item in identity"
|
:key="item.value"
|
:label="item.lable"
|
:value="item.value"
|
></Option>
|
</Select>
|
</el-col>
|
<el-col class="mb-2" :lg="3" :md="6" :sm="6" :xs="12">
|
<select-org-tree
|
ref="tree"
|
:data="treeList"
|
:isOpenAll="false"
|
:highlightCurrent="false"
|
:showCheckbox="true"
|
@hide-change="({ids})=>{checkIds=ids;search()}"
|
/>
|
<!-- <Select
|
class="mr10"
|
v-model="searchFrome.gradeValue"
|
@change="selectClass()"
|
placeholder="年级"
|
style="width:100%"
|
>
|
<Option v-for="item in grades" :key="item.value" :label="item.name" :value="item.id"></Option>
|
</Select>-->
|
<!-- </el-col>
|
<el-col class="mb-2" :lg="2" :md="3" :sm="4" :xs="8">-->
|
<!-- <Select
|
class="mr10 float-left"
|
v-model="searchFrome.classValue"
|
:disabled="!searchFrome.gradeValue"
|
placeholder="班级"
|
style="max-width: 8rem;width:100%"
|
>
|
<Option v-for="item in classes" :key="item.value" :label="item.name" :value="item.id"></Option>
|
</Select>-->
|
</el-col>
|
<el-col class="mb-2" :lg="3" :md="6" :sm="6" :xs="12">
|
<el-input
|
v-model="searchFrome.contentValue"
|
placeholder="请输入姓名/身份证号/学号"
|
autocomplete="off"
|
style="max-width: 15rem;width:100%"
|
class="mr10 float-left"
|
@keyup.enter="search"
|
clearable
|
/>
|
</el-col>
|
<el-col class="mb-2" :lg="2" :md="6" :sm="6" :xs="12">
|
<el-input
|
v-model="searchFrome.location"
|
placeholder="请输入进出位置"
|
autocomplete="off"
|
style="max-width: 15rem;width:100%"
|
class="mr10 float-left"
|
@keyup.enter="search"
|
clearable
|
/>
|
</el-col>
|
<el-col class="mb-2" :lg="5" :md="12" :sm="12" :xs="24">
|
<el-date-picker
|
:clearable="false"
|
v-model="searchTime"
|
type="datetimerange"
|
range-separator="至"
|
style="width:100%"
|
format="yyyy-MM-dd HH:mm:ss"
|
value-format="yyyy/MM/dd HH:mm:ss"
|
:default-time="['00:00:00', '23:59:59']"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
></el-date-picker>
|
</el-col>
|
<el-col class="mb-2 d-flex" :lg="4" :md="12" :sm="12" :xs="24">
|
<div>
|
<b-btn
|
variant="primary"
|
class="mr10 float-left"
|
v-on:click="search()"
|
style="width:150px"
|
>
|
<span class="fs fas-search"></span>搜索
|
</b-btn>
|
</div>
|
<div class="pt10">
|
<b-form-checkbox v-model="delFlag" @change="(val)=>{delFlag = val;search()}">已删除人员</b-form-checkbox>
|
</div>
|
</el-col>
|
<!-- <el-col :lg="2" :md="3" :sm="6" :xs="8">
|
<fButton
|
type="default"
|
style="width:100%"
|
@click.native="()=>{$router.push({path:'/export',query:{isShow:'false',identity:'teacher'}})}"
|
authority="sys:attendance:teacher"
|
class="mr10 float-left"
|
>教师考勤报表</fButton>
|
</el-col>-->
|
<!-- <el-col :lg="2" :md="3" :sm="6" :xs="8"> -->
|
<!-- <b-btn @click="()=>{$router.push({path:'/export',query:{isShow:'true',identity:'student'}})}" variant="default" class="mr10 float-left" style="width:100%">
|
<span class="fs ">学生考勤报表</span>
|
</b-btn>-->
|
<!-- <fButton
|
type="default"
|
style="width:100%"
|
@click.native="()=>{$router.push({path:'/export',query:{isShow:'true',identity:'student'}})}"
|
authority="sys:attendance:student"
|
class="mr10 float-left"
|
>学生考勤报表</fButton>-->
|
<el-col :lg="2" :md="6" :sm="12" :xs="12" class="float-right">
|
<div style="width:100%">
|
<fButton
|
style="width:100%"
|
type="outline-primary"
|
@click.native="()=>{$router.push({path:'/ruler'})}"
|
authority="sys:attendance:rule"
|
>考勤规则</fButton>
|
</div>
|
</el-col>
|
<el-col :lg="2" :md="6" :sm="12" :xs="12" class="float-right">
|
<fButton
|
type="outline-primary"
|
style="width:100%"
|
@click.native="()=>{$router.push({path:'/export',query:{isShow:'true'}})}"
|
authority="sys:attendance:report"
|
class="mr10 float-left"
|
>考勤报表</fButton>
|
</el-col>
|
</el-row>
|
</div>
|
|
<!-- 设备列表 -->
|
<b-card class="mx-4 mt-4" style="height: 70vh;">
|
<div class="mt10 ml20 mr20 flex-row-between">
|
<h5>
|
进出记录:
|
<span class="text-primary">{{total?total:tableList.length}}</span> 条
|
</h5>
|
<!-- <b-btn variant="primary" class="pl30 pr30" @click="exportFile">导出记录</b-btn> -->
|
<!-- <fButton
|
type="outline-primary"
|
@click.native="exportFile"
|
authority="sys:attendance:export"
|
class="pl30 pr30"
|
>
|
<i class="ion ion-md-open pr5"></i>
|
导出记录
|
</fButton>-->
|
<fTemplate authority="sys:attendance:export">
|
<span class="text-primary cursor-pointer font-weight-bolder" @click="exportFile">
|
<i class="ion ion-md-open pr5"></i>
|
导出
|
</span>
|
</fTemplate>
|
</div>
|
<div class="pl20 pr20 pt10 pb30">
|
<Table
|
:data="newtableList"
|
:border="true"
|
fit
|
style="text-align:center!important;min-width:1200px;"
|
height="55vh"
|
@sort-change="sortChange"
|
@row-click="checkUserInfo"
|
>
|
<TableColumn
|
type="index"
|
prop="index"
|
label="序号"
|
:index="snMethod"
|
:fit="true"
|
width="80px"
|
align="center"
|
/>
|
<TableColumn type="poto" prop="poto" label="图片" width="60">
|
<template slot-scope="scope">
|
<div class="headImgUrl flex-center" @click="checkUserInfo(scope.row)" title="当月考勤">
|
<httpImg :src="scope.row.photo" width="50px" height="50px" alt/>
|
</div>
|
</template>
|
</TableColumn>
|
<TableColumn label="姓名" prop="pname" :span="1">
|
<template slot-scope="scope">
|
<div class="media d-flex align-items-center" @click.stop>
|
<div class="media-body line-height-condenced ml-3">
|
<div class="text-dark">{{scope.row.pname}}</div>
|
</div>
|
</div>
|
</template>
|
</TableColumn>
|
<TableColumn label="身份" prop="identity" :span="3">
|
<template slot-scope="scope">
|
<div @click.stop>{{scope.row.identity}}</div>
|
</template>
|
</TableColumn>
|
<TableColumn label="时间" prop="onlinetime" sortable="custom" :span="4">
|
<template slot-scope="scope">
|
<div @click.stop>{{scope.row.onlinetime}}</div>
|
</template>
|
</TableColumn>
|
<TableColumn label="位置" prop="indevicename" sortable="custom" :span="4">
|
<template slot-scope="scope">
|
<div @click.stop>{{scope.row.indevicename}}</div>
|
</template>
|
</TableColumn>
|
<TableColumn label="操作" :span="4">
|
<template slot-scope="scope">
|
<div @click.stop>
|
<fButton
|
type="link"
|
style="padding:2px;"
|
class="text-primary"
|
@click.native="checkImage(scope.row)"
|
authority="sys:attendce:catchImg"
|
>抓拍图片</fButton>
|
<b-button
|
variant="link"
|
style="padding:2px;"
|
class="text-primary"
|
@click="checkUserInfo(scope.row)"
|
authority="sys:attendce:catchImg"
|
>当月考勤</b-button>
|
</div>
|
</template>
|
</TableColumn>
|
</Table>
|
|
<div class="pt15 pb20">
|
<b-pagination
|
class="justify-content-center justify-content-sm-end m-0"
|
v-if="total"
|
v-model="activePage"
|
:total-rows="total"
|
:per-page="pageSize"
|
/>
|
</div>
|
</div>
|
</b-card>
|
<!-- / 设备列表 -->
|
<calendar-attendance-modal ref="calendarModal"/>
|
<check-image-modal ref="checkImageModal"/>
|
</div>
|
</template>
|
<style >
|
.el-table .success-row {
|
background: #f0f9eb;
|
}
|
.el-date-editor .el-range-separator {
|
padding: 0 5px;
|
line-height: 32px;
|
width: 7%;
|
color: #35bde5;
|
}
|
</style>
|
|
<script>
|
import { mapState, mapActions } from 'vuex'
|
// import { getApplicationList } from '@/server/common.js'
|
import {
|
Table,
|
TableColumn,
|
DatePicker,
|
Select,
|
Option,
|
Row,
|
Col,
|
Checkbox,
|
Input
|
} from 'element-ui'
|
import calendarAttendanceModal from './components/CalendarAttendanceModal'
|
import checkImageModal from './components/CheckImageModal'
|
import { getAttendList } from '@/server/attend.js'
|
import CommonModel from '@/server/models/CommonModel'
|
import selectOrgTree from './components/SelectOrgTree'
|
|
export default {
|
name: 'home',
|
metaInfo: {
|
title: '首页'
|
},
|
data() {
|
return {
|
userInfo: this.$store.getters.basicUserInfo,
|
/** 查询班级年级的参数变量 */
|
typeG: 600,
|
typeC: 700,
|
orgid: this.$store.getters.basicUserInfo.orgId,
|
currentId: this.$store.getters.basicUserInfo.officeId,
|
/* webSocket声明 */
|
PersonStateWS: new CommonModel(),
|
infoDataCountWsClient: null,
|
/* 字典 */
|
modules: '',
|
num: '20',
|
// identity: [{ lable: '全部', value: 'all' }],
|
grades: [
|
{
|
id: 'all',
|
name: '全部'
|
}
|
],
|
classes: [
|
{
|
id: 'all',
|
name: '全部'
|
}
|
],
|
|
searchFrome: {
|
contentValue: '',
|
identity: 'all',
|
gradeValue: '',
|
classValue: '',
|
location: ''
|
},
|
searchTime: [
|
this.$moment().format('YYYY/MM/DD 00:00:00'),
|
this.$moment().format('YYYY/MM/DD HH:mm:ss')
|
],
|
/* 表格数据 */
|
tableList: [],
|
total: 0,
|
pageSize: 10,
|
activePage: 1,
|
/** 记录排序规则 */
|
order: '',
|
delFlag: true, // true是包含已删除人员
|
// treeList: [],
|
checkIds: []
|
}
|
},
|
computed: {
|
...mapState({
|
treeList: 'dictOrgTree',
|
dictIdentity: 'dictIdentity'
|
}),
|
identity() {
|
return [{ lable: '全部', value: 'all' }, ...this.dictIdentity]
|
},
|
orgId() {
|
return this.$store.getters.basicUserInfo.orgId
|
},
|
newtableList() {
|
let list = JSON.parse(JSON.stringify(this.tableList))
|
if (list && list.length > 200) {
|
list.length = 200
|
}
|
return list
|
}
|
},
|
methods: {
|
...mapActions(['_initTreeData', '_initIdentityDict']),
|
snMethod(index) {
|
return this.activePage > 1
|
? this.pageSize * (this.activePage - 1) + index + 1
|
: index + 1
|
},
|
getDateInit() {
|
// 要求 默认一个月
|
const end = new Date()
|
const start = new Date()
|
const nowDate = new Date()
|
nowDate.setHours(0)
|
nowDate.setMinutes(0)
|
nowDate.setSeconds(0)
|
nowDate.setMilliseconds(0)
|
start.setTime(nowDate.getTime() - 3600 * 1000 * 24 * 30)
|
end.setTime(nowDate.getTime() + 3600 * 1000 * 24 - 1)
|
return [
|
this.$moment(start).format('YYYY/MM/DD HH:mm:ss'),
|
this.$moment(end).format('YYYY/MM/DD HH:mm:ss')
|
]
|
},
|
/** 选择年级,同时让班级根据年级获取数据 */
|
/* selectGrad() {
|
let json = {
|
orgid: this.orgid,
|
type: this.typeG,
|
currentId: this.currentId
|
}
|
this.queryGrads(json)
|
},
|
async queryGrads(json) {
|
let res = await queryGrads(json)
|
this.grades = this.grades.concat(res)
|
// console.log(this.grades, '年级')
|
},
|
selectClass() {
|
let json = {
|
type: this.typeC,
|
orgid: this.orgid,
|
currentId: this.searchFrome.gradeValue
|
}
|
this.queryClass(json)
|
},
|
async queryClass(json) {
|
this.classes = [
|
{
|
id: 'all',
|
name: '全部'
|
}
|
]
|
this.searchFrome.classValue = ''
|
let res = await queryGrads(json)
|
// console.log(res)
|
this.classes = this.classes.concat(res)
|
}, */
|
/* 人员查看日历详情 */
|
checkUserInfo(data) {
|
console.log(data, 'data')
|
// this.$refs.calendarModal.showModal(data)
|
this.$router.push({
|
path: 'calendar',
|
query: {
|
personId: data.pid ? data.pid : '',
|
date: data.onlinetime ? data.onlinetime : ''
|
}
|
})
|
},
|
// 请求列表数据
|
async search() {
|
if (!this.searchTime || this.searchTime.length === 0) {
|
this.$toast({
|
type: 'warning',
|
message: '日期不允许为空'
|
})
|
return false
|
}
|
let data = {
|
...this.searchFrome,
|
startTime: this.searchTime[0],
|
endTime: this.searchTime[1],
|
page: this.activePage,
|
size: this.pageSize,
|
order: this.order.order,
|
orderName: this.order.prop,
|
delFlag: this.delFlag,
|
orgIds: this.checkIds.join(',')
|
}
|
sessionStorage.setItem('attendance_search', JSON.stringify(data))
|
|
let res = await getAttendList(data)
|
if (res && res.success && res.data) {
|
console.log(res, 'home res')
|
if (res.data.total > -1 && res.data.esAttList) {
|
this.total = res.data.total
|
this.tableList = res.data.esAttList
|
}
|
} else {
|
this.$toast({
|
message: res.msg ? res.msg : '报错了',
|
type: 'error'
|
})
|
}
|
},
|
checkImage(data) {
|
console.log(data, '查看图片')
|
this.$refs.checkImageModal.showModal(data)
|
},
|
|
/* webcocket */
|
InitWebSocket() {
|
try {
|
this.PersonStateWS.getAttendancePersonnelNum(
|
null,
|
this.infoDataCountMsg,
|
err => {
|
console.log(err, '获取进出记录--出错')
|
},
|
close => {
|
console.log(close, '获取进出记录--关闭')
|
},
|
e => {
|
this.infoDataCountWsClient = e
|
}
|
)
|
} catch (error) {}
|
},
|
infoDataCountMsg(res) {
|
if (res) {
|
this.tableList = [...res, ...this.tableList]
|
}
|
console.log(res, '获取进出记录--接收数据')
|
},
|
exportFile() {
|
let access = JSON.parse(
|
sessionStorage.getItem('loginedInfo')
|
).access_token.replace('bearer ', '')
|
/* 创建form对象 */
|
let oA = document.createElement('A')
|
// oA.setAttribute('method', 'get')
|
oA.setAttribute(
|
'href',
|
'data/api-a/att/searchExcel?access_token=' + access
|
)
|
console.log(oA, 'oA')
|
document.body.append(oA)
|
oA.click()
|
// window.location.href = 'data/api-a/att/excel?access_token=' + access
|
// window.open('data/api-a/att/excel?access_token=' + access, '_blank')
|
},
|
sortChange(column, prop, order) {
|
console.log(column, 'column')
|
if (column) {
|
this.order = { ...column }
|
this.search()
|
}
|
}
|
},
|
created() {
|
this.$store.dispatch('_initTreeData', {
|
orgById: this.orgId
|
})
|
this.$store.dispatch('_initIdentityDict', {
|
orgId: this.orgId
|
}) // 日期插件赋值
|
/** 查询列表:WebSocket 临时注释
|
this.infoDataCountWsClient && this.infoDataCountWsClient.close()
|
this.InitWebSocket()
|
*/
|
/* eslint-disable */ const json = JSON.parse(
|
sessionStorage.getItem('attendance_search')
|
)
|
this.searchTime =
|
json && json.startTime && json.endTime
|
? [json.startTime, json.endTime]
|
: this.getDateInit()
|
this.activePage = json && json.page ? json.page : 1
|
this.pageSize = json && json.size ? json.size : 10
|
this.delFlag = json && json.delFlag ? json.delFlag : true
|
|
this.searchFrome.identity = json && json.identity ? json.identity : ''
|
this.searchFrome.contentValue =
|
json && json.contentValue ? json.contentValue : ''
|
this.searchFrome.location = json && json.location ? json.location : ''
|
this.checkIds = json && json.orgIds ? json.orgIds.split(',') : []
|
|
console.log(json, 'json---created')
|
// setTimeout(() => {
|
// this.$refs.tree.initVal(this.checkIds)
|
// }, 500)
|
},
|
mounted() {
|
this.search()
|
},
|
destroyed() {},
|
watch: {
|
activePage(newVal, oldVal) {
|
if (newVal !== oldVal) {
|
this.search(this.order)
|
}
|
}
|
},
|
components: {
|
Table,
|
TableColumn,
|
Select,
|
Option,
|
elRow: Row,
|
elCol: Col,
|
elCheckbox: Checkbox,
|
calendarAttendanceModal,
|
checkImageModal,
|
elDatePicker: DatePicker,
|
selectOrgTree,
|
elInput: Input
|
}
|
}
|
</script>
|
<style lang="scss">
|
.headImgUrl {
|
height: 38px;
|
width: 38px;
|
overflow: hidden;
|
border-radius: 25px;
|
}
|
.has-gutter th {
|
background: #f4fcff;
|
}
|
</style>
|