<template>
|
<!-- 安全管理 ==> 智能安全帽 => 报警记录 -->
|
<div class="main">
|
<!-- main_left -->
|
<div class="main_left" v-show="!isRenderDetail">
|
<div class="main_left_search">
|
<div class="search_item">
|
<span>姓名:</span>
|
<el-input size="mini" v-model="queryInfo.userName" placeholder="请输入姓名" clearable></el-input>
|
</div>
|
<div class="search_item">
|
<span>设备编号:</span>
|
<el-input size="mini" v-model="queryInfo.deviceNum" placeholder="请输入设备编号" clearable></el-input>
|
<el-button icon="el-icon-search" @click="queryTable">查询</el-button>
|
</div>
|
</div>
|
<div class="main_left_table">
|
<cpnTable :table-loading="loading" :table-data="dataList" :table-columns="tableColumns">
|
</cpnTable>
|
</div>
|
</div>
|
<!-- main_right -->
|
<div class="main_right" v-show="!isRenderDetail">
|
<div class="echart_options">
|
<el-radio-group v-model="chart.radioGroupVal" @change="loadChart">
|
<el-radio-button label="7">近7天报警数</el-radio-button>
|
<el-radio-button label="31">近31天报警数</el-radio-button>
|
</el-radio-group>
|
</div>
|
<div ref="echart_bar" class="echart_bar"></div>
|
<div class="echart_drop">
|
<div ref="echart_drop_1" :class="{ show: chart.isShowDrop1, hide: !chart.isShowDrop1 }"></div>
|
<div ref="echart_drop_2" :class="{ show: chart.isShowDrop2, hide: !chart.isShowDrop2 }"></div>
|
</div>
|
</div>
|
<!-- detail -->
|
<div class="detail" v-if="isRenderDetail">
|
<div class="detail_option">
|
<div class="search_item">
|
<span>日期:</span>
|
<el-date-picker class="elDatePicker" type="daterange" v-model="detail.date" value-format="yyyy-MM-dd"
|
start-placeholder="开始日期" end-placeholder="结束日期" clearable></el-date-picker>
|
</div>
|
<el-button icon="el-icon-search" @click="queryDetail">查询</el-button>
|
<el-button style="float:right" @click="hideDetail">返回</el-button>
|
</div>
|
<div class="detail_botbox">
|
<div class="detail_table">
|
<cpnTable :table-data="detail.dataList" :table-columns="detail.tableColumns">
|
</cpnTable>
|
</div>
|
<div class="detail_map">
|
<div id="container"></div>
|
<div class="detail_map_info_l" v-show="detail.isShowInfo">
|
<h2>静默报警</h2>
|
<p>原因: <span>{{ detail.info.cause }}</span></p>
|
<p>姓名: <span>{{ detail.info.name }}</span></p>
|
<p>设备: <span>{{ detail.info.device }}</span></p>
|
<p>位置: <span>{{ detail.info.position }}</span></p>
|
<p>时间: <span>{{ detail.info.time }}</span></p>
|
<el-button style="float: right;" @click="() => { detail.isShowInfo = false }">确定</el-button>
|
</div>
|
<div class="detail_map_info_r" v-show="detail.isShowInfo">
|
<h2>报警设备信息</h2>
|
<p>姓名: <span>{{ detail.info.name }}</span></p>
|
<p>时间: <span>{{ detail.info.time }}</span></p>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import AMapLoader from '@amap/amap-jsapi-loader';
|
import cpnTable from '@/components/element/Table'
|
import 'echarts-liquidfill' // 水滴图形
|
export default {
|
data() {
|
return {
|
loading: false,
|
isRenderDetail: false, // 是否查看轨迹地图
|
queryInfo: {
|
pageNum: 1,
|
pageSize: 9999,
|
userName: '',
|
deviceNum: '',
|
},
|
dataList: [],
|
tableColumns: [],
|
userId: '', // 用户id
|
userName: '', // 用户名称
|
deviceNum: '', // 设备编号
|
// 图表数据
|
chart: {
|
date: '',
|
radioGroupVal: '7', // (7 31)默认近7天
|
isShowDrop1: false,
|
isShowDrop2: false,
|
chartInstanceLine: null, // 柱状图实例
|
chartInstanceDrop1: null, // 水滴图实例
|
chartInstanceDrop2: null,
|
},
|
detail: { // 详情
|
date: [], // 日期查询
|
dataList: [],
|
tableColumns: [],
|
isShowInfo: false,
|
// 报警信息
|
info: {
|
cause: '',
|
name: '',
|
device: '',
|
position: '',
|
time: '',
|
},
|
// 报警类型原因
|
sosTypes: {
|
1: '长时间静止'
|
},
|
},
|
$http: '', // 接口api路径
|
}
|
},
|
components: {
|
cpnTable
|
},
|
created() {
|
// 添加密钥,获取高德地址使用
|
window._AMapSecurityConfig = {
|
securityJsCode: "aa90b00e27025d1f57286675cc8b232e",
|
}
|
this.$http = this.$api.Safety.SmartHelmet.warning
|
this.setTableColumn()
|
this.getLists()
|
},
|
mounted() {
|
this.initChart()
|
window.addEventListener("resize", this.screenAdapter)
|
},
|
beforeDestroy() {
|
this.clearMap()
|
this.clearChart()
|
window.removeEventListener("resize", this.screenAdapter)
|
},
|
methods: {
|
setTableColumn() {
|
this.tableColumns = [
|
{name: "用户ID", key: "userId"},
|
{name: "姓名", key: "userName"},
|
{name: "设备编号", key: "deviceNum"},
|
{
|
operation: true, name: "操作", width: 140, value: [
|
{name: "查看", class: "table_btn", handleRow: this.warchRow},
|
{name: "详情", class: "table_btn", handleRow: this.detailRow},
|
]
|
},
|
]
|
},
|
// 获取报警信息
|
async getWarning() {
|
let out = {}
|
const params = {
|
userId: this.userId,
|
strTime: this.chart.date?.[0],
|
endTime: this.chart.date?.[1],
|
}
|
const {data, statusMsg} = await this.$http.getWarning(params)
|
if (statusMsg === 'ok') {
|
out = data
|
}
|
return out
|
},
|
// 获取table数据
|
getLists() {
|
this.loading = true
|
this.$api.Safety.SmartHelmet.getLists(this.queryInfo).then(res => {
|
if (res.statusMsg === 'ok') {
|
this.dataList = res.data.list
|
}
|
this.loading = false
|
})
|
},
|
// table-详情按钮
|
detailRow(row) {
|
this.userId = row.userId
|
this.deviceNum = row.deviceNum
|
this.renderDetail()
|
},
|
// table-查看按钮
|
warchRow(row) {
|
if (this.userId === row.userId) return
|
this.userId = row.userId
|
this.userName = row.userName
|
console.log(row)
|
this.chart.isShowDrop1 = false
|
this.chart.isShowDrop2 = false
|
this.loadChart()
|
},
|
// 加载图表
|
loadChart() {
|
this.changeDay()
|
this.showDrop()
|
this.renderChart()
|
},
|
// 水滴图表根据 7/31 切换显示
|
showDrop() {
|
if (this.chart.radioGroupVal === '7') {
|
this.chart.isShowDrop1 = true
|
} else if (this.chart.radioGroupVal === '31') {
|
this.chart.isShowDrop2 = true
|
}
|
},
|
// 近 7/31 天切换
|
changeDay() {
|
const nowDate = new Date().format()
|
const beforeDate7 = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).format()
|
const beforeDate31 = new Date(Date.now() - 31 * 24 * 60 * 60 * 1000).format()
|
const beforeDate = this.chart.radioGroupVal === '7' ? beforeDate7 : (this.chart.radioGroupVal === '31' ? beforeDate31 : '')
|
|
this.chart.date = [beforeDate, nowDate]
|
},
|
// 初始化图表
|
initChart() {
|
this.chart.chartInstanceLine = this.$echarts.init(this.$refs.echart_bar)
|
this.chart.chartInstanceDrop1 = this.$echarts.init(this.$refs.echart_drop_1)
|
this.chart.chartInstanceDrop2 = this.$echarts.init(this.$refs.echart_drop_2)
|
this.renderBaseChart()
|
},
|
// 渲染chart基础配置
|
renderBaseChart() {
|
const baseBarOptions = {
|
animationDuration: 1500,
|
tooltip: {
|
trigger: "axis",
|
formatter: "日期: {b} <div></div> 在线时长: {c}分",
|
},
|
grid: {
|
top: "10%",
|
right: "0",
|
left: "2%",
|
bottom: "14",
|
containLabel: true,
|
},
|
xAxis: [{
|
type: 'category',
|
axisLine: {
|
lineStyle: {
|
width: 2,
|
color: "#B7E4F7",
|
},
|
},
|
axisTick: {
|
show: false,
|
},
|
}],
|
yAxis: [{
|
type: 'value',
|
axisLabel: {
|
formatter: "{value}",
|
color: "#CAD3E0",
|
},
|
splitLine: {
|
lineStyle: {
|
width: 2,
|
type: "dashed",
|
color: "#5A7E9D",
|
},
|
},
|
}],
|
series: [{
|
type: 'line',
|
smooth: true,
|
barWidth: 14,
|
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{offset: 0, color: "#C15B3C"},
|
{offset: 1, color: "#FACD91"},
|
]),
|
}],
|
}
|
const baseDropOptions1 = {
|
title: {
|
text: '近一周报警天数',
|
left: '32%',
|
top: 30,
|
textStyle: {
|
color: "#fff",
|
},
|
},
|
series: [{
|
type: 'liquidFill',
|
data: [0],
|
radius: '60%', //图表的大小 值是圆的直径
|
shape: 'circle', //水填充图的形状 circle默认圆形 rect圆角矩形 triangle三角形 diamond菱形 pin水滴状 arrow箭头状 还可以是svg的path
|
center: ['50%', '50%'], //图表相对于盒子的位置
|
outline: {
|
show: false
|
},
|
backgroundStyle: { // 背景配置
|
color: 'transparent', //背景颜色
|
borderWidth: '2',//边框大小
|
borderColor: 'rgba(17, 94, 176, 0.4)', // 边框颜色
|
},
|
itemStyle: {
|
color: new this.$echarts.graphic.LinearGradient(
|
0, 0, 0, 1, //4个参数用于配置渐变色的起止位置, 这4个参数依次对应右/下/左/上四个方位. 而0 0 0 1则代表渐变色从正上方开始
|
[
|
{offset: 0, color: '#2790F4'},
|
{offset: 1, color: '#165190'}
|
] //数组, 用于配置颜色的渐变过程. 每一项为一个对象, 包含offset和color两个参数. offset的范围是0 ~ 1, 用于表示位置
|
)
|
},
|
}]
|
}
|
const baseDropOptions2 = {
|
title: {
|
text: '近一个月(31天)报警天数',
|
right: '24%',
|
top: 30,
|
textStyle: {
|
color: "#fff",
|
},
|
},
|
series: [{
|
type: 'liquidFill',
|
data: [0],
|
radius: '60%', //图表的大小 值是圆的直径
|
shape: 'circle', //水填充图的形状 circle默认圆形 rect圆角矩形 triangle三角形 diamond菱形 pin水滴状 arrow箭头状 还可以是svg的path
|
center: ['50%', '50%'], //图表相对于盒子的位置
|
outline: {
|
show: false
|
},
|
backgroundStyle: { // 背景配置
|
color: 'transparent', //背景颜色
|
borderWidth: '2',//边框大小
|
borderColor: 'rgba(17, 94, 176, 0.4)', // 边框颜色
|
},
|
itemStyle: {
|
color: new this.$echarts.graphic.LinearGradient(
|
0, 0, 0, 1, //4个参数用于配置渐变色的起止位置, 这4个参数依次对应右/下/左/上四个方位. 而0 0 0 1则代表渐变色从正上方开始
|
[
|
{offset: 0, color: '#2790F4'},
|
{offset: 1, color: '#165190'}
|
] //数组, 用于配置颜色的渐变过程. 每一项为一个对象, 包含offset和color两个参数. offset的范围是0 ~ 1, 用于表示位置
|
)
|
},
|
}]
|
}
|
this.chart.chartInstanceLine.setOption(baseBarOptions)
|
this.chart.chartInstanceDrop1.setOption(baseDropOptions1)
|
this.chart.chartInstanceDrop2.setOption(baseDropOptions2)
|
},
|
// 渲染chart内容数据(x,y,series)
|
async renderChart() {
|
const obj = await this.getWarning()
|
const day = obj.day // 报警天数
|
const percentDay = (day / this.chart.radioGroupVal).toFixed(2) //百分比
|
const x = [] // x轴数据
|
const y = [] // y轴数据
|
obj.reportNumDtos.forEach(item => {
|
x.push(item.smTime)
|
y.push(item.num)
|
})
|
const lineOptions = {
|
title: {
|
text: `${this.userName} 近${this.chart.radioGroupVal}天报警天数`,
|
left: '42%',
|
textStyle: {
|
color: "#E2E5EA",
|
fontSize: 12,
|
},
|
},
|
xAxis: {
|
index: 0,
|
data: x
|
},
|
series: {
|
index: 0,
|
data: y
|
}
|
}
|
const dropOptions = {
|
series: {
|
index: 0,
|
data: [percentDay],
|
label: {
|
color: '#fff',
|
formatter: () => day,
|
}
|
}
|
}
|
this.chart.chartInstanceLine.setOption(lineOptions)
|
if (this.chart.radioGroupVal === '7') {
|
this.chart.chartInstanceDrop1.setOption(dropOptions)
|
|
} else if (this.chart.radioGroupVal === '31') {
|
this.chart.chartInstanceDrop2.setOption(dropOptions)
|
}
|
},
|
screenAdapter() {
|
this.chart.chartInstanceLine?.resize()
|
this.chart.chartInstanceDrop1?.resize()
|
this.chart.chartInstanceDrop2?.resize()
|
},
|
queryTable() {
|
this.getLists()
|
},
|
/* --------详情页面-s */
|
renderDetail() {
|
this.isRenderDetail = true
|
this.setTableDetailColumn()
|
this.getDetailLists()
|
this.renderMap()
|
},
|
setTableDetailColumn() {
|
if (this.detail.tableColumns.length) return
|
this.detail.tableColumns = [
|
{name: "时间", key: "smTime"},
|
{name: "姓名", key: "userName", width: 70},
|
{name: "原因", key: "sosType", width: 80, formatter: (row) => this.detail.sosTypes[row.sosType] || ''},
|
{
|
operation: true, name: "操作", width: 100, value: [
|
{name: "查看", class: "table_btn", handleRow: this.warchDetailRow},
|
]
|
},
|
]
|
},
|
getDetailLists() {
|
const params = {
|
userId: this.userId,
|
strTime: this.detail.date?.[0],
|
endTime: this.detail.date?.[1],
|
}
|
this.detail.dataList = []
|
this.$http.getDetailWarning(params).then(res => {
|
if (res.statusMsg === 'ok') {
|
this.detail.dataList = res.data
|
}
|
})
|
},
|
// 查看具体报警信息
|
async warchDetailRow(row) {
|
const _position = await this.getAdress(row.xpoint, row.ypoint)
|
const info = {
|
cause: this.detail.sosTypes[row.sosType],
|
name: row.userName,
|
device: this.deviceNum,
|
position: `${_position}(经度:${row.ypoint}, 纬度${row.xpoint})`,
|
time: row.smTime,
|
}
|
this.detail.info = info
|
this.detail.isShowInfo = true
|
},
|
renderMap() {
|
AMapLoader.load({
|
key: "1dc3895771d98745fa27bbcc3280464f", // 申请好的Web端开发者Key,首次调用 load 时必填
|
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
}).then(AMap => {
|
this.detail.AMap = AMap
|
this.detail.map = new AMap.Map("container", {
|
resizeEnable: true,
|
viewMode: "2D", // 是否为3D地图模式
|
zoom: 13, // 初始化地图级别
|
})
|
})
|
},
|
createMapMarker(lnglatXY) {
|
if (!this.detail.marker) {
|
const AMap = this.detail.AMap
|
this.detail.marker = new AMap.Marker()
|
}
|
const marker = this.detail.marker
|
marker.setMap(null)
|
marker.setPosition(lnglatXY)
|
this.detail.map.add(marker)
|
this.detail.map.setFitView()
|
},
|
// 获取地址
|
getAdress(x, y) {
|
return new Promise(resolve => {
|
let address = ''
|
const AMap = this.detail.AMap
|
const lnglatXY = [y, x] // 位置的经纬度
|
this.createMapMarker(lnglatXY)
|
AMap.plugin('AMap.Geocoder', () => {
|
const geocoder = new AMap.Geocoder({
|
radius: 1000,
|
extensions: "all"
|
})
|
geocoder.getAddress(lnglatXY, function (status, result) {
|
if (status === 'complete' && result.info === 'OK') {
|
address = result.regeocode.formattedAddress
|
}
|
resolve(address)
|
})
|
})
|
})
|
},
|
hideDetail() {
|
this.clearMap()
|
this.detail.date = []
|
this.detail.isShowInfo = false
|
this.isRenderDetail = !this.isRenderDetail
|
},
|
queryDetail() {
|
this.getDetailLists()
|
},
|
/* --------详情页面-e */
|
clearMap() {
|
this.detail.map?.destroy()
|
},
|
clearChart() {
|
this.chart.chartInstanceLine?.clear()
|
this.chart.chartInstanceDrop1?.clear()
|
this.chart.chartInstanceDrop2?.clear()
|
},
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
@import '@/style/layout-main.scss';
|
|
::v-deep .el-radio-button__inner {
|
border: 1px solid #39B5FE;
|
color: #fff;
|
background: transparent;
|
}
|
|
.hide {
|
opacity: 0;
|
}
|
|
.show {
|
opacity: 1;
|
}
|
|
#container {
|
width: 100%;
|
height: 100%;
|
}
|
|
.main {
|
display: flex;
|
flex-direction: row;
|
color: #EBEBEB;
|
|
.main_left {
|
display: flex;
|
flex-direction: column;
|
width: 380px;
|
padding: 14px;
|
margin-right: 18px;
|
border: 1px solid #39B5FE;
|
border-radius: 10px;
|
box-shadow: rgba(0, 145, 255, 0.7) 0 0 18px inset;
|
box-sizing: content-box;
|
|
.search_item {
|
span {
|
display: inline-block;
|
min-width: 54px;
|
margin-right: 6px;
|
text-align: right;
|
}
|
|
.el-input {
|
width: 220px;
|
margin: 0 28px 16px 0;
|
}
|
}
|
|
::v-deep.main_left_table {
|
overflow: hidden;
|
|
.el-table {
|
display: flex;
|
flex-direction: column;
|
|
.el-table__body-wrapper {
|
overflow-y: auto;
|
flex: 1;
|
}
|
}
|
}
|
}
|
|
.main_right {
|
overflow: hidden;
|
display: flex;
|
flex-direction: column;
|
flex: 1;
|
padding: 20px;
|
border: 1px solid #39B5FE;
|
background-color: rgba(0, 52, 121, 0.3);
|
border-radius: 10px;
|
box-shadow: rgba(0, 145, 255, 0.7) 0 0 18px inset;
|
box-sizing: content-box;
|
|
.echart_options {
|
margin-bottom: 10px;
|
|
|
}
|
|
.echart_bar {
|
flex: 1;
|
}
|
|
.echart_drop {
|
flex: 1.1;
|
|
> div {
|
float: left;
|
width: 50%;
|
height: 100%;
|
}
|
}
|
}
|
|
.detail {
|
display: flex;
|
flex-direction: column;
|
position: absolute;
|
width: 100%;
|
height: 100%;
|
padding: 20px;
|
|
.detail_option {
|
.search_item {
|
float: left;
|
|
span {
|
display: inline-block;
|
margin-right: 6px;
|
}
|
|
.el-input {
|
width: 220px;
|
margin: 0 28px 16px 0;
|
}
|
|
.elDatePicker {
|
margin: 0 10px 14px 0;
|
}
|
}
|
}
|
|
.detail_botbox {
|
overflow: hidden;
|
flex: 1;
|
}
|
|
::v-deep.detail_table {
|
float: left;
|
width: 400px;
|
height: 100%;
|
margin-right: 20px;
|
|
.el-table {
|
display: flex;
|
flex-direction: column;
|
|
.el-table__body-wrapper {
|
overflow-y: auto;
|
flex: 1;
|
}
|
}
|
}
|
|
.detail_map {
|
position: relative;
|
overflow: hidden;
|
min-height: 200px;
|
height: 100%;
|
|
p {
|
display: flex;
|
width: 300px;
|
padding-left: 10px;
|
line-height: 32px;
|
word-break: break-all;
|
border-radius: 3px;
|
background: #143164;
|
|
span {
|
padding: 0 6px;
|
color: #39B5FE;
|
flex: 1;
|
}
|
|
}
|
|
.detail_map_info_l {
|
position: absolute;
|
left: 44px;
|
top: 160px;
|
padding: 0 20px 10px 20px;
|
border-radius: 5px;
|
background: #0D1846;
|
|
h2 {
|
margin-bottom: 30px;
|
color: #F94550;
|
}
|
}
|
|
.detail_map_info_r {
|
position: absolute;
|
right: 36px;
|
top: 260px;
|
padding: 0 20px;
|
border-radius: 5px;
|
background: #0D1846;
|
|
h2 {
|
margin-bottom: 30px;
|
color: #39B5FE;
|
}
|
}
|
}
|
|
}
|
}
|
</style>
|