From a8c870fc1cefb1a9cd651f46f759a146df661f60 Mon Sep 17 00:00:00 2001
From: 叶松 <2217086471@qq.com>
Date: 星期一, 27 十一月 2023 11:23:40 +0800
Subject: [PATCH] 供应商字段修改
---
web/src/views/SecureManage/SmartHelmet/AlarmRecord.vue | 728 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 725 insertions(+), 3 deletions(-)
diff --git a/web/src/views/SecureManage/SmartHelmet/AlarmRecord.vue b/web/src/views/SecureManage/SmartHelmet/AlarmRecord.vue
index 668cc49..9c82ec0 100644
--- a/web/src/views/SecureManage/SmartHelmet/AlarmRecord.vue
+++ b/web/src/views/SecureManage/SmartHelmet/AlarmRecord.vue
@@ -1,3 +1,725 @@
-<template>
- <div>报警记录</div>
-</template>
\ No newline at end of file
+<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>
\ No newline at end of file
--
Gitblit v1.9.3