1204 lines
37 KiB
Vue
1204 lines
37 KiB
Vue
<template>
|
||
<div class="personManage">
|
||
<div class="left">
|
||
<el-input placeholder="请输入关键字" prefix-icon="el-icon-search" v-model="filterText" maxlength="30"
|
||
style="margin: 10px 0;"></el-input>
|
||
<div class="content tree">
|
||
<el-tree :data="treeData" icon="el-icon-search" node-key="id" :default-expanded-keys="idArr"
|
||
@node-click="handleNodeClick" :render-content="renderContent" style="font-size: 15px;letter-spacing: 1px;"
|
||
ref="tree" :filter-node-method="filterNode" :highlight-current="true" :expand-on-click-node="false" />
|
||
</div>
|
||
</div>
|
||
<div class="center">
|
||
<div class="layout btn-box">
|
||
<el-button type="primary" plain icon="el-icon-search" @click="facialSampling">手环人脸验证抽检</el-button>
|
||
<el-button type="primary" plain icon="el-icon-setting" @click="getCheckConfigDetail">自动验证配置</el-button>
|
||
</div>
|
||
<div class="content">
|
||
<div id="searchBox" class="layout" v-if="isShowHistoryGj">
|
||
<el-button type="primary" plain @click="closeHistoryGj" style="margin-right: 10px;">返回</el-button>
|
||
<el-date-picker v-model="chooseDate" @change="loadHistoryGj" :editable="false" :clearable="false" type="date"
|
||
format="yyyy-MM-dd" value-format="yyyy-MM-dd" placeholder="选择日期">
|
||
</el-date-picker>
|
||
</div>
|
||
<baidu-map map-style-v2="light" class="map" :zoom="zoom" :center="center" @ready="handler"></baidu-map>
|
||
</div>
|
||
</div>
|
||
<div class="right">
|
||
<!-- 杆塔 -->
|
||
<div id="tower-box" class="layout" v-if="isTower">
|
||
<div>今日施工班组 <span>{{ person.workTeamNum }}</span> 个</div>
|
||
<div>今日施工人数 <span>{{ person.workPersonNum }}</span> 人</div>
|
||
</div>
|
||
<!-- 班组 -->
|
||
<div id="team-box" v-if="isTeam">
|
||
<!-- <h4>智能安全帽</h4>
|
||
<el-table :data="hatTable" style="width: 100%" max-height="400">
|
||
<el-table-column prop="name" label="姓名" align="center">
|
||
</el-table-column>
|
||
<el-table-column prop="devName" label="设备名称" align="center">
|
||
</el-table-column>
|
||
<el-table-column label="操作" align="center">
|
||
<template slot-scope="scope">
|
||
<img style="cursor: pointer;margin-right: 10px;" title="对讲" src="../../../../assets/person_img/talk.png">
|
||
<img style="cursor: pointer;" title="视频" src="../../../../assets/person_img/video.png">
|
||
</template>
|
||
</el-table-column>
|
||
</el-table> -->
|
||
</div>
|
||
<!-- 人员 -->
|
||
<div id="person-box" v-if="isPerson">
|
||
<div id="person-info" class="layout">
|
||
<div class="layout">
|
||
<div class="layout"><img src="../../../../assets/person_img/person.png">{{ person.name }}</div>
|
||
<div><el-tag :type="person.warnType">{{ person.warnName }}</el-tag></div>
|
||
</div>
|
||
<div class="layout"><img src="../../../../assets/person_img/team2.png">{{ person.teamName }}</div>
|
||
<div class="layout"><img src="../../../../assets/person_img/phone.png">{{ person.phone }}</div>
|
||
<div class="layout"><img src="../../../../assets/person_img/idCard.png">{{ person.idCard }}</div>
|
||
</div>
|
||
<div id="sh-info" class="layout">
|
||
<div class="layout">
|
||
<div class="layout"><img src="../../../../assets/person_img/sh.png">{{ person.sh.name }}</div>
|
||
<div class="layout info" v-if="person.sh.elec == 100">
|
||
<img width="30px" height="16px" src="../../../../assets/person_img/elec.png">
|
||
{{ person.sh.elec }}%
|
||
</div>
|
||
<div class="layout info" v-if="person.sh.elec >= 20 && person.sh.elec < 100">
|
||
<img width="30px" height="16px" src="../../../../assets/images/battery2.png">
|
||
{{ person.sh.elec }}%
|
||
</div>
|
||
<div class="layout info" v-if="person.sh.elec < 20"><img width="30px" height="16px"
|
||
src="../../../../assets/person_img/elec_warn.png">{{ person.sh.elec }}%</div>
|
||
<div class="layout info2"><img @click="openHistoryGj(person.sh.devId)"
|
||
src="../../../../assets/person_img/dw.png" title="历史轨迹"></div>
|
||
</div>
|
||
<div class="layout">
|
||
<div class="layout" v-if="person.sh.isWarn == 0"><img
|
||
src="../../../../assets/person_img/position_nowarn.png">正常
|
||
</div>
|
||
<div class="layout" v-if="person.sh.isWarn == 1"><img
|
||
src="../../../../assets/person_img/position_warn.png"><span style="color: red;">异常</span>
|
||
</div>
|
||
<div class="layout info"><img src="../../../../assets/person_img/temp.png">{{ person.sh.temp }}</div>
|
||
</div>
|
||
<div class="layout">
|
||
<div class="layout"><img src="../../../../assets/person_img/heartRate.png">{{ person.sh.heartRate }}
|
||
</div>
|
||
<div class="layout info"><img src="../../../../assets/person_img/bloodPressure.png">{{
|
||
person.sh.bloodPressure }}</div>
|
||
</div>
|
||
<!-- <div class="layout" v-if="person.hasSafetyHat">
|
||
<div class="layout"><img src="../../../../assets/person_img/hat.png">{{ person.hat.name }}
|
||
</div>
|
||
<div class="layout info2"><img src="../../../../assets/person_img/talk.png" title="对讲"></div>
|
||
<div class="layout info2"><img src="../../../../assets/person_img/video.png" title="播放"></div>
|
||
</div> -->
|
||
<div class="layout">
|
||
<div class="layout"><img src="../../../../assets/person_img/mj.png">{{ person.sh.mjCode }}</div>
|
||
</div>
|
||
</div>
|
||
<div id="warn-info">
|
||
<h4>违章记录</h4>
|
||
<el-table :data="warnTable" style="width: 100%" max-height="400">
|
||
<el-table-column prop="warnTime" label="违章时间" align="center">
|
||
</el-table-column>
|
||
<el-table-column prop="warnContent" label="违章内容" align="center">
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<el-dialog title="选择抽检范围" :visible.sync="dialogVisible1" :append-to-body="true" width="500px"
|
||
@close="dialogVisible1 = false">
|
||
<el-input placeholder="请输入关键字" prefix-icon="el-icon-search" v-model="filterText2" maxlength="30"
|
||
style="margin-bottom: 10px;"></el-input>
|
||
<el-tree :data="teamTreeData" class="tree-container tree" icon="el-icon-search" show-checkbox node-key="id"
|
||
:default-expanded-keys="idArr2" @node-click="teamTreeNodeClick" :filter-node-method="filterNode2"
|
||
style="letter-spacing: 1px;" @check-change="teamTreeCheckChange" ref="teamTree" />
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="startSpotCheck">发起抽检</el-button>
|
||
<el-button @click="dialogVisible1 = false">取消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
|
||
<el-dialog title="自动验证人脸配置" :visible.sync="dialogVisible2" :append-to-body="true" width="500px"
|
||
@close="closeTimeConfig">
|
||
<el-form ref="form" :model="form" :label-position="labelPosition" :rules="rules">
|
||
<el-form-item label="模式选择">
|
||
<el-radio-group v-model="form.configType">
|
||
<el-radio label="1">固定时间验证</el-radio>
|
||
<el-radio label="2">间隔时间验证</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<!--固定时间验证 -->
|
||
<div v-if="form.configType == 1">
|
||
<el-form-item>
|
||
<el-button @click="addTimes"><i class="el-icon-plus"></i> 添加时间</el-button>
|
||
</el-form-item>
|
||
</div>
|
||
<div v-if="form.configType == 1" class="item-arr">
|
||
<el-form-item v-for="(time, index) in form.times" :key="time.key" :prop="'times.' + index + '.value'" :rules="{
|
||
required: true, message: '时间不能为空', trigger: 'blur'
|
||
}">
|
||
<el-col :span="12">
|
||
<el-time-select v-model="time.value" :picker-options="{
|
||
start: '00:00',
|
||
step: '00:15',
|
||
end: '23:45'
|
||
}" placeholder="请选择时间">
|
||
</el-time-select>
|
||
</el-col>
|
||
<el-col :span="5" style="margin-left: 10px;">
|
||
<el-button type="danger" plain @click.prevent="removeTime(time)"><i
|
||
class="el-icon-delete"></i></el-button>
|
||
</el-col>
|
||
</el-form-item>
|
||
</div>
|
||
<!-- 间隔时间验证 -->
|
||
<div v-if="form.configType == 2" class="time">
|
||
<el-col :span="24">
|
||
每隔 <el-input-number v-model="form.timeNum" controls-position="right" @change="handleChange" :min="1"
|
||
:max="10"></el-input-number> 小时自动验证人脸
|
||
</el-col>
|
||
</div>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||
<el-button @click="closeTimeConfig">取消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
|
||
</template>
|
||
|
||
<script>
|
||
import { personsTree, teamPersonByTower, spotCheck, getCheckConfig, checkConfig, getPersonsInfo, getPersonDetail, getHistoryGj, getWorkInfo } from "@/api/construction/manage/personManage.js";
|
||
import no_warn from "@/assets/svg/no_warn.svg";
|
||
import no_warn2 from "@/assets/svg/no_warn2.svg";
|
||
import warn from "@/assets/svg/warn.svg";
|
||
import start from "@/assets/person_img/start.png";
|
||
import end from "@/assets/person_img/end.png";
|
||
import { number } from "echarts";
|
||
export default {
|
||
name: 'personManage',
|
||
/* 人员树前端筛选 */
|
||
watch: {
|
||
filterText(val) {
|
||
this.$refs.tree.filter(val);
|
||
},
|
||
filterText2(val) {
|
||
this.$refs.teamTree.filter(val);
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
// 人员树过滤
|
||
filterText: '',
|
||
// 在施班组及人员过滤
|
||
filterText2: '',
|
||
// 选中的杆塔
|
||
towerId: undefined,
|
||
// 人员树默认展示的节点
|
||
idArr: [],
|
||
// 在施班组及人员默认展示节点
|
||
idArr2: [],
|
||
//树的配置
|
||
defaultProp: {
|
||
children: 'children',
|
||
label: 'label',
|
||
disabled: 'disabled',
|
||
},
|
||
/* 表单对齐样式 */
|
||
labelPosition: 'top',
|
||
// 表单参数
|
||
form: {
|
||
configType: '1',
|
||
times: [],
|
||
timeNum: 1
|
||
},
|
||
// 表单校验
|
||
rules: {},
|
||
map: null,
|
||
BMap: null,
|
||
// 作业杆塔
|
||
circleRange: {
|
||
//中心点
|
||
center: {
|
||
lng: 117.287800,
|
||
lat: 31.255550
|
||
},
|
||
//半径 米
|
||
radius: 50
|
||
},
|
||
//记录信息窗口数据
|
||
infoWindow: {
|
||
//窗体是否展示
|
||
show: false,
|
||
},
|
||
//设置地图中心点
|
||
center: { lng: 117.287800, lat: 31.255550 },
|
||
//设置缩放
|
||
zoom: 20,
|
||
//搜索框数据
|
||
keyword: '',
|
||
//保存树的数据
|
||
treeData: [],
|
||
// 日期
|
||
chooseDate: this.getTodayDate(),
|
||
// 班组ID
|
||
teamId: null,
|
||
// 杆塔ID
|
||
id: null,
|
||
// 人员树选中是否是杆塔
|
||
isTower: false,
|
||
// 人员树选中是否是班组
|
||
isTeam: false,
|
||
// 人员树选中是否是班组人员
|
||
isPerson: false,
|
||
isShowHistoryGj: false,
|
||
// 轨迹定位数组
|
||
gjArr: [],
|
||
person: {
|
||
name: null,
|
||
phone: null,
|
||
teamName: null,
|
||
idCard: null,
|
||
warnName: null,
|
||
warnType: 'success',
|
||
hasSafetyHat: false,
|
||
sh: {
|
||
devId: null,
|
||
name: null,
|
||
elec: 0,
|
||
isWarn: 1,
|
||
temp: null,
|
||
heartRate: null,
|
||
bloodPressure: null,
|
||
mjCode: null,
|
||
},
|
||
hat: {
|
||
name: null,
|
||
},
|
||
workTeamNum: 0,
|
||
workPersonNum: 0
|
||
},
|
||
// 预警表格
|
||
warnTable: [],
|
||
//保存表格数据
|
||
hatTable: [
|
||
{
|
||
name: '张三',
|
||
devName: '1号智能安全帽'
|
||
},
|
||
{
|
||
name: '张三',
|
||
devName: '1号智能安全帽'
|
||
}
|
||
],
|
||
|
||
//保存对话框隐藏展示
|
||
dialogVisible1: false,
|
||
dialogVisible2: false,
|
||
//抽检搜索框数据
|
||
keyword2: "",
|
||
//保存抽检树形数据
|
||
teamTreeData: [],
|
||
// 查看班组施工定位前,是否选中了班组
|
||
checkTeamId: null,
|
||
// 定时刷新
|
||
intervalId: null,
|
||
// 选中树节点ID
|
||
checkNodeId: null,
|
||
// 选中树节点层级
|
||
checkNodeLevel: null,
|
||
// 选中树节点父节点的ID
|
||
checkNodeTowerId: null,
|
||
// 选中班组人员存的数据
|
||
checkPersonObj: {}
|
||
};
|
||
},
|
||
created() {
|
||
this.getPersonsTree();
|
||
},
|
||
mounted() {
|
||
this.startRefresh();
|
||
},
|
||
destroyed() {
|
||
this.stopRefresh();
|
||
},
|
||
methods: {
|
||
startRefresh() {
|
||
// 每3分钟刷新一次
|
||
this.intervalId = setInterval(this.refreshData, 1000 * 60 * 3);
|
||
},
|
||
stopRefresh() {
|
||
if (this.intervalId) {
|
||
clearInterval(this.intervalId);
|
||
this.intervalId = null;
|
||
}
|
||
},
|
||
async refreshData() {
|
||
// this.$message('页面刷新了');
|
||
// 定时刷新球机树数据
|
||
this.treeData.splice(0);
|
||
this.idArr.splice(0);
|
||
await this.getPersonsTree();
|
||
if (this.filterText) {
|
||
this.$refs.tree.filter(this.filterText);
|
||
}
|
||
if (this.checkNodeId) {
|
||
this.$refs.tree.setCurrentKey(this.checkNodeId);
|
||
if (this.checkNodeLevel === 4) {
|
||
this.idArr.push(this.checkNodeId);
|
||
}
|
||
if (this.checkNodeLevel === 2) { // 杆塔
|
||
// this.$message('刷新杆塔选中的数据');
|
||
this.loadWorkInfo();
|
||
} else if (this.checkNodeLevel === 3) { // 班组
|
||
// this.$message('刷新班组选中的数据');
|
||
this.removeOverlay();
|
||
const obj = {
|
||
'id': this.checkNodeTowerId,
|
||
'teamId': this.checkTeamId
|
||
}
|
||
this.loadPersonsInfo(obj, null);
|
||
} else if (this.checkNodeLevel === 4) { // 班组人员
|
||
// this.$message('刷新班组人员选中的数据');
|
||
if (!this.isShowHistoryGj) {
|
||
this.removeOverlay();
|
||
const obj = {
|
||
'id': this.checkNodeTowerId,
|
||
'teamId': this.checkTeamId
|
||
}
|
||
this.loadPersonsInfo(obj, this.checkPersonObj);
|
||
} else {
|
||
this.removeOverlay();
|
||
this.loadHistoryGj();
|
||
}
|
||
}
|
||
}
|
||
},
|
||
// 当前日期
|
||
getTodayDate() {
|
||
const today = new Date();
|
||
let date = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2);
|
||
return date;
|
||
},
|
||
/* 今日施工班组/施工人数/安全帽信息 */
|
||
loadWorkInfo() {
|
||
const query = {
|
||
id: this.towerId
|
||
}
|
||
getWorkInfo(query).then((res) => {
|
||
const data = res.data;
|
||
this.person.workTeamNum = data.workTeamNum;
|
||
this.person.workPersonNum = data.workPersonNum;;
|
||
}).catch((res) => { })
|
||
},
|
||
/* 加载人员树 */
|
||
async getPersonsTree() {
|
||
await personsTree().then(res => {
|
||
const treeData = res.data;
|
||
if (treeData && treeData.length > 0) {
|
||
this.treeData = treeData
|
||
// 设置默认展示杆塔层级
|
||
treeData.forEach(item => {
|
||
const children = item.children;
|
||
children.forEach(child => {
|
||
// 设置默认展示杆塔层级
|
||
this.idArr.push(child.id);
|
||
})
|
||
})
|
||
}
|
||
}).catch(res => {
|
||
|
||
});
|
||
},
|
||
/* 人员树过滤 */
|
||
filterNode(value, data, node) {
|
||
/* if (!value) {
|
||
if (node.level == 1 || node.level == 2) {
|
||
node.expanded = true
|
||
} else {
|
||
node.expanded = false
|
||
}
|
||
return true
|
||
} */
|
||
// 查询列表是否有匹配数据
|
||
let val = value.toLowerCase()
|
||
return this.chooseNode(val, data, node)
|
||
},
|
||
filterNode2(value, data, node) {
|
||
if (!value) {
|
||
if (node.level == 1) {
|
||
node.expanded = true
|
||
} else {
|
||
node.expanded = false
|
||
}
|
||
return true
|
||
}
|
||
// 查询列表是否有匹配数据
|
||
let val = value.toLowerCase()
|
||
return this.chooseNode(val, data, node)
|
||
},
|
||
// 过滤父节点 子节点:如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。
|
||
chooseNode(value, data, node) {
|
||
if (data.label.indexOf(value) !== -1) {
|
||
return true
|
||
}
|
||
const level = node.level
|
||
// 如果传入的节点本身就是一级节点就不用校验了
|
||
if (level === 1) {
|
||
return false
|
||
}
|
||
// 先取当前节点的父节点
|
||
let parentData = node.parent
|
||
// 遍历当前节点的父节点
|
||
let index = 0
|
||
while (index < level - 1) {
|
||
// 如果匹配到直接返回
|
||
if (parentData.data.label.indexOf(value) !== -1) {
|
||
return true
|
||
}
|
||
// 否则的话再往上一层做匹配
|
||
parentData = parentData.parent
|
||
index++
|
||
}
|
||
// 没匹配到返回false
|
||
return false
|
||
},
|
||
|
||
/* 加载抽检班组人员树 */
|
||
getTeamPersonByTower(params) {
|
||
teamPersonByTower(params).then(res => {
|
||
const teamTreeData = res.data;
|
||
if (teamTreeData && teamTreeData.length > 0) {
|
||
this.teamTreeData = teamTreeData
|
||
// 设置默认展示班组层级
|
||
teamTreeData.forEach(item => {
|
||
this.idArr2.push(item.id);
|
||
})
|
||
}
|
||
this.dialogVisible1 = true;
|
||
}).catch(res => {
|
||
|
||
});
|
||
},
|
||
/* 手环人脸验证抽检 */
|
||
facialSampling() {
|
||
if (!this.towerId) {
|
||
return this.$message({
|
||
message: '请选择杆塔',
|
||
type: 'warning'
|
||
});
|
||
} else {
|
||
this.filterText2 = '';
|
||
this.getTeamPersonByTower({ 'id': this.towerId });
|
||
}
|
||
},
|
||
// 自动验证配置详情
|
||
async getCheckConfigDetail() {
|
||
let loading = this.$loading({
|
||
lock: true,
|
||
text: "数据加载中,请稍候...",
|
||
background: 'rgba(0,0,0,0.2)'
|
||
})
|
||
await getCheckConfig().then((res) => {
|
||
if (res.data && res.data.length > 0) {
|
||
const data = res.data;
|
||
const configType = data[0].configType + '';
|
||
if (configType === '1') {
|
||
data.forEach((item, index) => {
|
||
this.form.times.push({ value: item.time, key: Date.now() + index })
|
||
})
|
||
} else if (configType === '2') {
|
||
this.form.timeNum = parseInt(res.data[0].time);
|
||
}
|
||
this.form.configType = configType;
|
||
} else {
|
||
this.form.configType = '1';
|
||
}
|
||
|
||
}).catch((res) => {
|
||
|
||
})
|
||
loading.close();
|
||
this.dialogVisible2 = true;
|
||
},
|
||
// 模式选择为固定时间-添加多个时间
|
||
addTimes() {
|
||
const tiemsArr = this.form.times;
|
||
if (tiemsArr && tiemsArr.length >= 10) {
|
||
return this.$message({
|
||
message: '固定时间验证不能超过10个',
|
||
type: 'warning'
|
||
});
|
||
}
|
||
this.form.times.push({
|
||
value: '',
|
||
key: Date.now()
|
||
});
|
||
},
|
||
// 删除时间
|
||
removeTime(item) {
|
||
var index = this.form.times.indexOf(item)
|
||
if (index !== -1) {
|
||
this.form.times.splice(index, 1)
|
||
}
|
||
},
|
||
// 判断固定时间数组是否存在相同数据
|
||
isTimeRepeated(arr) {
|
||
const newArr = arr.map((item) => item.value);
|
||
const isRepeat = newArr.some((item, index, arr) => arr.indexOf(item) != index);
|
||
return isRepeat;
|
||
},
|
||
// 间隔时间验证空值赋值
|
||
handleChange(value) {
|
||
if (!value) {
|
||
this.form.timeNum = 1;
|
||
}
|
||
},
|
||
// 关闭自动验证配置
|
||
closeTimeConfig() {
|
||
this.form.times = [];
|
||
this.form.timeNum = 1;
|
||
this.dialogVisible2 = false
|
||
},
|
||
// 获取班组下的人员定位及杆塔坐标
|
||
loadPersonsInfo(params, personData) {
|
||
getPersonsInfo(params).then((res) => {
|
||
const data = res.data;
|
||
if (data) {
|
||
const lon = data.towerInfo.lon;
|
||
const lat = data.towerInfo.lat;
|
||
this.circleRange.center.lng = lon;
|
||
this.circleRange.center.lat = lat;
|
||
this.circleRange.radius = data.towerInfo.distance
|
||
// 根据杆塔坐标 重新定义中心点 并绘制施工半径
|
||
const point = new BMap.Point(lon, lat);
|
||
this.map.centerAndZoom(point, this.zoom);
|
||
const circle = new BMap.Circle(point, this.circleRange.radius, {
|
||
strokeColor: "red",
|
||
strokeWeight: 2,
|
||
strokeOpacity: 1,
|
||
fillOpacity: 0.1
|
||
});
|
||
circle.id = "circle";
|
||
this.map.addOverlay(circle);
|
||
// 添加施工人员覆盖物
|
||
const personList = data.personList;
|
||
if (personList && personList.length > 0) {
|
||
for (let index = 0; index < personList.length; index++) {
|
||
let item = personList[index];
|
||
if (item.lon && item.lat) {
|
||
this.addPersonMarker(item);
|
||
}
|
||
}
|
||
if (personData) {
|
||
this.clickMarker(personData);
|
||
}
|
||
}
|
||
}
|
||
}).catch((res) => { })
|
||
},
|
||
// 人员树选中人员加载的数据
|
||
loadPersonDetail(params) {
|
||
getPersonDetail(params).then((res) => {
|
||
const data = res.data;
|
||
if (data && data.vo) {
|
||
const obj = data.vo;
|
||
this.warnTable = obj.warnInfoList;
|
||
this.person.name = obj.name;
|
||
this.person.phone = obj.phone;
|
||
this.person.teamName = obj.teamName;
|
||
this.person.idCard = obj.idCard;
|
||
this.person.warnName = obj.warnName;
|
||
this.person.warnType = obj.warnType;
|
||
this.person.hasSafetyHat = obj.hasSafetyHat;
|
||
this.person.sh.devId = obj.bracelet.devId;
|
||
this.person.sh.name = obj.bracelet.name;
|
||
this.person.sh.elec = obj.bracelet.elec;
|
||
this.person.sh.isWarn = obj.bracelet.isWarn;
|
||
this.person.sh.temp = this.handleData(obj.bracelet.temp);
|
||
this.person.sh.heartRate = this.handleData(obj.bracelet.heartRate);
|
||
this.person.sh.bloodPressure = this.handleData(obj.bracelet.bloodPressure);
|
||
this.person.sh.mjCode = this.handleData(obj.mjCode);
|
||
this.person.hat.name = obj.safetyHat.name;
|
||
}
|
||
}).catch((res) => { })
|
||
},
|
||
// 人员历史轨迹
|
||
loadHistoryGj() {
|
||
// 手环设备ID和开始时间
|
||
let obj = {
|
||
'id': this.person.sh.devId,
|
||
'startTime': this.chooseDate
|
||
};
|
||
getHistoryGj(obj).then((res) => {
|
||
const data = res.data;
|
||
if (data && data.length > 0) {
|
||
this.gjArr = data;
|
||
} else {
|
||
this.gjArr = [];
|
||
}
|
||
this.loadGj();
|
||
}).catch((res) => { })
|
||
},
|
||
handleData(value) {
|
||
if (!value) {
|
||
return '--';
|
||
}
|
||
return value;
|
||
},
|
||
handler({ BMap, map }) {
|
||
this.BMap = BMap;
|
||
this.map = map;
|
||
// 缩放
|
||
map.enableScrollWheelZoom(true);
|
||
//设置地图风格
|
||
map.setMapType(BMAP_NORMAL_MAP); //普通地图
|
||
},
|
||
//人员树组件节点点击
|
||
handleNodeClick(data, node, item) {
|
||
this.checkNodeId = data.id;
|
||
this.checkNodeLevel = data.level;
|
||
this.towerId = undefined;
|
||
this.checkTeamId = null;
|
||
this.checkNodeTowerId = null;
|
||
this.checkPersonObj = {};
|
||
if (node.level === 2) {
|
||
this.removeOverlay();
|
||
// 选中杆塔赋值towerId,用于手环人员验证抽检
|
||
this.towerId = parseInt(data.id.replace('tower-', ''));
|
||
this.isTower = true;
|
||
this.isTeam = false;
|
||
this.isPerson = false;
|
||
this.loadWorkInfo();
|
||
} else if ((node.level === 3)) {
|
||
// 选中班组层级 触发事件 id:杆塔ID teamId:班组ID
|
||
this.isTower = false;
|
||
this.isTeam = true;
|
||
this.isPerson = false;
|
||
this.removeOverlay();
|
||
const teamId = parseInt(data.id.replace('team-', ''));
|
||
const towerId = parseInt(data.parentId.replace('tower-', ''));
|
||
this.teamId = teamId;
|
||
this.id = towerId;
|
||
const obj = {
|
||
'id': towerId,
|
||
'teamId': teamId
|
||
}
|
||
this.checkTeamId = teamId;
|
||
this.checkNodeTowerId = towerId;
|
||
this.loadPersonsInfo(obj, null);
|
||
} else if (node.level === 4) {
|
||
this.isTower = false;
|
||
this.isTeam = false;
|
||
this.isPerson = true;
|
||
const teamId = parseInt(data.parentId.replace('team-', ''));
|
||
const towerId = data.gtId;
|
||
if (!this.checkTeamId || this.checkTeamId !== teamId) {
|
||
this.removeOverlay();
|
||
const obj = {
|
||
'id': towerId,
|
||
'teamId': teamId
|
||
}
|
||
this.checkTeamId = teamId;
|
||
this.checkNodeTowerId = towerId;
|
||
this.checkPersonObj = _.cloneDeep(data);
|
||
this.loadPersonsInfo(obj, data);
|
||
} else {
|
||
// 选中班组人员 触发事件
|
||
this.clickMarker(data);
|
||
}
|
||
} else {
|
||
this.isTower = false;
|
||
this.isTeam = false;
|
||
this.isPerson = false;
|
||
this.removeOverlay();
|
||
}
|
||
},
|
||
// 清除百度地图覆盖物
|
||
removeOverlay() {
|
||
this.map.clearOverlays();
|
||
},
|
||
// 检查overlay是否是Marker的实例
|
||
isOverlayPoint(overlay) {
|
||
return overlay instanceof BMap.Marker;
|
||
},
|
||
// 点击地图人员覆盖物触发的事件
|
||
clickMarker(item) {
|
||
this.checkNodeLevel = 4;
|
||
this.checkPersonObj = item;
|
||
let userId = null;
|
||
if (new RegExp(/^[0-9]*$/).test(item.id)) {
|
||
userId = item.id;
|
||
this.$refs.tree.setCurrentKey(item.type === 0 ? 'zs-' + item.id : 'ls-' + item.id);
|
||
this.checkNodeId = item.type === 0 ? 'zs-' + item.id : 'ls-' + item.id;
|
||
} else {
|
||
userId = item.type === 0 ? parseInt(item.id.replace('zs-', '')) : parseInt(item.id.replace('ls-', ''))
|
||
this.checkNodeId = item.id;
|
||
}
|
||
const allOverlay = this.map.getOverlays();
|
||
for (let index = 0; index < allOverlay.length; index++) {
|
||
let overlay = allOverlay[index];
|
||
const flag = this.isOverlayPoint(overlay);
|
||
// 清除点选中的样式
|
||
if (flag && overlay.isWarn === 0) {
|
||
let myIcon = new BMap.Icon(no_warn, new BMap.Size(11, 11))
|
||
myIcon.setImageSize(new BMap.Size(11, 11));
|
||
overlay.setIcon(myIcon);
|
||
}
|
||
}
|
||
let isExist = false;
|
||
for (let index = 0; index < allOverlay.length; index++) {
|
||
let overlay = allOverlay[index];
|
||
// 判断是否是点的覆盖物
|
||
const flag = this.isOverlayPoint(overlay);
|
||
if (flag && ("marker-" + item.type + '-' + userId === overlay.id)) {
|
||
if (item.isWarn === 0) {
|
||
let myIcon = new BMap.Icon(no_warn2, new BMap.Size(50, 50))
|
||
myIcon.setImageSize(new BMap.Size(50, 50));
|
||
overlay.setIcon(myIcon);
|
||
}
|
||
isExist = true;
|
||
}
|
||
}
|
||
this.isTower = false;
|
||
this.isTeam = false;
|
||
this.isPerson = true;
|
||
// id:人员ID type: 0 班组成员 1 临时人员
|
||
const obj = {
|
||
'id': userId,
|
||
'type': item.type
|
||
}
|
||
this.loadPersonDetail(obj);
|
||
if (!isExist) {
|
||
return this.$message({
|
||
message: item.label + '无定位坐标',
|
||
type: 'error'
|
||
});
|
||
}
|
||
},
|
||
/* 添加人员定位的覆盖物 */
|
||
addPersonMarker(item) {
|
||
let point = new BMap.Point(item.lon, item.lat)
|
||
let marker = "", myIcon = "";
|
||
if (item.isWarn === 0) {
|
||
// 无告警
|
||
myIcon = new BMap.Icon(no_warn, new BMap.Size(11, 11))
|
||
myIcon.setImageSize(new BMap.Size(11, 11));
|
||
} else {
|
||
// 告警
|
||
myIcon = new BMap.Icon(warn, new BMap.Size(50, 50))
|
||
myIcon.setImageSize(new BMap.Size(50, 50));
|
||
}
|
||
marker = new BMap.Marker(point, { icon: myIcon });
|
||
// 设置点的唯一标识 人员类型 + 人员ID / 是否告警
|
||
marker.id = "marker-" + item.type + '-' + item.id;
|
||
marker.isWarn = item.isWarn;
|
||
this.map.addOverlay(marker);
|
||
// 添加监听事件
|
||
|
||
marker.addEventListener("click", () => { this.clickMarker(item) });
|
||
},
|
||
// 人员绑定手环历史轨迹
|
||
openHistoryGj() {
|
||
if (!this.isShowHistoryGj) {
|
||
this.removeOverlay();
|
||
this.loadHistoryGj();
|
||
this.isShowHistoryGj = true;
|
||
}
|
||
},
|
||
// 关闭历史轨迹
|
||
closeHistoryGj() {
|
||
this.removeOverlay();
|
||
this.isShowHistoryGj = false;
|
||
const obj = {
|
||
'id': this.checkNodeTowerId,
|
||
'teamId': this.checkTeamId
|
||
}
|
||
if (Object.keys(this.checkPersonObj).length === 0) {
|
||
this.loadPersonsInfo(obj, null);
|
||
} else {
|
||
this.loadPersonsInfo(obj, this.checkPersonObj);
|
||
}
|
||
},
|
||
// 获取人员运动轨迹
|
||
loadGj() {
|
||
this.removeOverlay();
|
||
const list = this.gjArr;
|
||
if (list.length >= 2) { // 轨迹数组大于2个才会展示轨迹
|
||
// 已轨迹的起点作为中心点
|
||
let startMarker = "", endMarker = "", startIcon = "", endIcon = "";
|
||
const startPoint = new BMap.Point(list[0].lon, list[0].lat);
|
||
this.map.centerAndZoom(startPoint, this.zoom);
|
||
startIcon = new BMap.Icon(start, new BMap.Size(32, 40))
|
||
startIcon.setImageSize(new BMap.Size(32, 40));
|
||
startMarker = new BMap.Marker(startPoint, { icon: startIcon });
|
||
this.map.addOverlay(startMarker);
|
||
// 中间的点
|
||
let array = [];
|
||
list.forEach((item, index) => {
|
||
array.push(new BMap.Point(item.lon, item.lat))
|
||
})
|
||
let polyline = new BMap.Polyline(array,
|
||
{ strokeColor: "red", strokeWeight: 5, strokeOpacity: 0.5 });
|
||
this.map.addOverlay(polyline);
|
||
// 终点
|
||
const endPoint = new BMap.Point(list[list.length - 1].lon, list[list.length - 1].lat);
|
||
endIcon = new BMap.Icon(end, new BMap.Size(32, 40))
|
||
endIcon.setImageSize(new BMap.Size(32, 40));
|
||
endMarker = new BMap.Marker(endPoint, { icon: endIcon });
|
||
this.map.addOverlay(endMarker);
|
||
}
|
||
},
|
||
//给人员树不同层级设置不同的icon
|
||
renderContent(h, { node, data }) {
|
||
let isTeamLeader = data.isTeamLeader, type = data.type, isWarn = data.isWarn, style = '';
|
||
if (isWarn === 1) {
|
||
style = 'warnColor'
|
||
}
|
||
// 根据层级使用不同的图标
|
||
let icon, span = <span class={style}>{node.label}</span>;
|
||
if (node.level === 1) {
|
||
icon = 'pro_icon';
|
||
} else if (node.level === 2) {
|
||
icon = 'tower_nocheck_icon';
|
||
} else if (node.level === 3) {
|
||
icon = 'team_nocheck_icon';
|
||
} else if (node.level === 4 && isTeamLeader === 1) {
|
||
icon = '';
|
||
span = <span class={style}>{node.label}<el-tag size="mini">班组长</el-tag></span>;
|
||
} else if (node.level === 4 && type === 1) {
|
||
icon = '';
|
||
span = <span class={style}>{node.label} <el-tag size="mini">临时人员</el-tag></span>;
|
||
} else if (node.level === 4 && isTeamLeader === 0 && type === 0) {
|
||
icon = '';
|
||
span = <span class={style}>{node.label}</span>;
|
||
}
|
||
return (
|
||
<span class="custom-tree-node">
|
||
<i class={icon}></i>{span}
|
||
</span>
|
||
);
|
||
},
|
||
//抽检弹框搜索
|
||
searchClick2() {
|
||
alert(this.keyword2)
|
||
},
|
||
//抽检树组件节点点击
|
||
teamTreeNodeClick(data) {
|
||
console.log(data.id)
|
||
},
|
||
//抽检树节点多选框值改变监听
|
||
teamTreeCheckChange(data, checked, indeterminate) {
|
||
console.log(data, checked, indeterminate)
|
||
},
|
||
//取消
|
||
spotCheckDialogClose() {
|
||
//清空搜索框
|
||
this.keyword2 = "";
|
||
//关闭对话框
|
||
this.dialogVisible1 = false
|
||
},
|
||
|
||
//取消
|
||
spotCheckDialogClose() {
|
||
//关闭对话框
|
||
this.dialogVisible2 = false
|
||
},
|
||
//发起抽检
|
||
startSpotCheck() {
|
||
//获取多选框勾选的值
|
||
const checkedNodes = this.$refs.teamTree.getCheckedNodes();
|
||
if (!checkedNodes || checkedNodes.length == 0) {
|
||
return this.$message({
|
||
message: '请选择抽检班组人员',
|
||
type: 'warning'
|
||
});
|
||
}
|
||
let checkArr = [];
|
||
checkedNodes.forEach(item => {
|
||
console.error(item.parentId);
|
||
if (item.parentId !== -1 && item.parentId !== 0) {
|
||
checkArr.push({ "userId": parseInt(item.id.replace('team-', '')), "userType": item.userType, "devCode": item.devCode, "shCode": item.shCode })
|
||
}
|
||
});
|
||
if (checkArr.length == 0) {
|
||
return this.$message({
|
||
message: '请选择抽检班组人员!',
|
||
type: 'warning'
|
||
});
|
||
}
|
||
const obj = {
|
||
'spotCheckList': checkArr
|
||
}
|
||
console.log(obj);
|
||
|
||
spotCheck(obj).then((res) => {
|
||
this.$modal.msgSuccess(res.msg);
|
||
this.dialogVisible1 = false;
|
||
}).catch((res) => { })
|
||
},
|
||
//验证人脸配置单选按钮值改变监听
|
||
provingTypeRadioChange(value) {
|
||
console.log(value)
|
||
},
|
||
//验证对话框关闭
|
||
provingDialogClose() {
|
||
this.dialogVisible2 = false;
|
||
},
|
||
//验证对话框确认按钮
|
||
submitForm: function () {
|
||
this.$refs["form"].validate(valid => {
|
||
if (valid) {
|
||
let obj = {};
|
||
if (this.form.configType === '1') {
|
||
// 固定时间
|
||
const timesArr = this.form.times;
|
||
if (!timesArr || timesArr.length == 0) {
|
||
return this.$message({
|
||
message: '未添加固定时间',
|
||
type: 'warning'
|
||
});
|
||
}
|
||
const isRepeat = this.isTimeRepeated(timesArr);
|
||
if (isRepeat) {
|
||
return this.$message({
|
||
message: '请勿添加相同的固定时间',
|
||
type: 'warning'
|
||
});
|
||
}
|
||
let timeArr = [];
|
||
this.form.times.forEach(item => {
|
||
timeArr.push(item.value);
|
||
})
|
||
obj.time = timeArr.toString();
|
||
} else {
|
||
// 间隔时间验证
|
||
obj.time = this.form.timeNum + '';
|
||
}
|
||
obj.configType = this.form.configType;
|
||
checkConfig(obj).then((res) => {
|
||
this.$modal.msgSuccess(res.msg);
|
||
this.closeTimeConfig();
|
||
}).catch((res) => { });
|
||
}
|
||
});
|
||
},
|
||
}
|
||
};
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.personManage {
|
||
width: 100%;
|
||
height: 80vh;
|
||
background-color: #ffffff;
|
||
box-shadow: 10px 10px 5px #000000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.layout {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: start;
|
||
}
|
||
|
||
.map {
|
||
display: inline-block;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.personManage .bm-view {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
|
||
.personManage .left {
|
||
width: 22%;
|
||
height: 100%;
|
||
padding: 0 0.5%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.personManage .left>.content {
|
||
width: 100%;
|
||
height: calc(100% - 70px);
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.personManage .center {
|
||
width: 54%;
|
||
height: 100%;
|
||
}
|
||
|
||
|
||
.btn-box {
|
||
width: 100%;
|
||
height: 56px
|
||
}
|
||
|
||
.personManage .center>.content {
|
||
width: 100%;
|
||
height: calc(100% - 56px);
|
||
padding: 0.5% 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.personManage .right {
|
||
width: 22%;
|
||
height: 100%;
|
||
}
|
||
|
||
#person-box {
|
||
width: 100%;
|
||
height: 100%;
|
||
padding: 3% 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
#person-info,
|
||
#sh-info {
|
||
width: 96%;
|
||
margin: 0 2% 4% 0;
|
||
padding: 0 4% 0 4%;
|
||
min-height: 150px;
|
||
border: 1px solid #cccccc;
|
||
border-radius: 6px;
|
||
font-size: 15px;
|
||
flex-direction: column;
|
||
justify-content: space-evenly;
|
||
align-items: start;
|
||
letter-spacing: 1px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
#person-info>div:nth-of-type(1) {
|
||
width: 100%;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
#person-info img,
|
||
#sh-info img {
|
||
margin-right: 5px;
|
||
}
|
||
|
||
.info {
|
||
margin-left: 20px;
|
||
}
|
||
|
||
.info2 {
|
||
margin-left: 20px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
#warn-info,
|
||
#team-box {
|
||
width: 96%;
|
||
margin: 0 2% 4% 0;
|
||
}
|
||
|
||
#tower-box {
|
||
width: 96%;
|
||
margin: 0 2% 4% 0;
|
||
min-height: 100px;
|
||
padding: 0 4% 0 4%;
|
||
min-height: 100px;
|
||
letter-spacing: 1px;
|
||
box-sizing: border-box;
|
||
flex-direction: column;
|
||
justify-content: space-evenly;
|
||
align-items: start;
|
||
}
|
||
|
||
#tower-box span {
|
||
font-weight: bold;
|
||
}
|
||
|
||
#searchBox {
|
||
width: 58%;
|
||
height: 50px;
|
||
justify-content: center;
|
||
position: absolute;
|
||
top: 8%;
|
||
z-index: 999;
|
||
}
|
||
|
||
/* tree节点过长换行处理 */
|
||
.tree {
|
||
width: 100%;
|
||
|
||
::v-deep .el-tree-node {
|
||
white-space: normal;
|
||
|
||
.el-tree-node__content {
|
||
height: 100%;
|
||
align-items: center;
|
||
margin: 4px 0;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-tree-node__label {
|
||
font-size: 15px;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
|
||
color: #1890ff;
|
||
}
|
||
|
||
.tree-container {
|
||
max-height: 50vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.item-arr,
|
||
.time {
|
||
min-height: 12vh;
|
||
max-height: 30vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
::v-deep .anchorBL {
|
||
display: none !important;
|
||
|
||
}
|
||
|
||
::v-deep .pro_icon,
|
||
::v-deep .tower_nocheck_icon,
|
||
::v-deep .team_nocheck_icon {
|
||
vertical-align: top;
|
||
background-size: cover;
|
||
background-position: center;
|
||
display: inline-block;
|
||
margin-right: 4px;
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
::v-deep .pro_icon {
|
||
background-image: url("../../../../assets/images/pro_icon.png") !important;
|
||
}
|
||
|
||
::v-deep .tower_nocheck_icon {
|
||
background-image: url("../../../../assets/images/tower_nocheck_icon.png") !important;
|
||
}
|
||
|
||
::v-deep .team_nocheck_icon {
|
||
background-image: url("../../../../assets/images/team_nocheck_icon.png") !important;
|
||
}
|
||
|
||
::v-deep .warnColor {
|
||
color: red;
|
||
}
|
||
</style>
|