Просмотр исходного кода

feature

- 增加 c1后台设备功耗查看页面
- 增加 cell,echarts和table组件
test
JinxChen 1 год назад
Родитель
Сommit
60833a1fc0
20 измененных файлов: 1572 добавлений и 17 удалений
  1. +10
    -2
      README.md
  2. +209
    -1
      src/api/core.js
  3. +25
    -0
      src/api/iot.js
  4. +16
    -0
      src/components/custom-cell/index.scss
  5. +58
    -0
      src/components/custom-cell/index.vue
  6. +12
    -0
      src/components/echarts/index.scss
  7. +67
    -0
      src/components/echarts/index.vue
  8. +37
    -0
      src/components/tables/index.scss
  9. +74
    -0
      src/components/tables/index.vue
  10. +26
    -3
      src/config/models.js
  11. +7
    -1
      src/main.js
  12. +14
    -1
      src/router/index.js
  13. +11
    -2
      src/store/index.js
  14. +59
    -0
      src/views/gps-card-frontend/device-power/index.scss
  15. +328
    -0
      src/views/gps-card-frontend/device-power/index.vue
  16. +15
    -0
      src/views/gps-card-frontend/device-setting/index.scss
  17. +449
    -0
      src/views/gps-card-frontend/device-setting/index.vue
  18. +0
    -0
      src/views/gps-card-frontend/drown-white-list/index.scss
  19. +148
    -0
      src/views/gps-card-frontend/drown-white-list/index.vue
  20. +7
    -7
      vue.config.js

+ 10
- 2
README.md Просмотреть файл

@@ -1,7 +1,7 @@
<!--
* @Date: 2022-08-17 16:19:13
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-09 09:47:52
* @LastEditTime: 2023-10-13 14:50:29
* @FilePath: \TelpoH5FrontendWeb\README.md
* @description: 项目说明
-->
@@ -718,4 +718,12 @@ update
`2023.10.9`
update
- 问卷调查
- 增加 答题完成返回错误后如果是从随手精灵公众号调过来的用户,则第8 11题文字变红
- 增加 答题完成返回错误后如果是从随手精灵公众号调过来的用户,则第8 11题文字变红



## v1.0.90
`2023.10.13`
feature
- 增加 c1后台设备功耗查看页面
- 增加 cell,echarts和table组件

+ 209
- 1
src/api/core.js Просмотреть файл

@@ -1,7 +1,7 @@
/*
* @Date: 2021-12-18 15:49:01
* @LastEditors: JinxChen
* @LastEditTime: 2023-03-27 15:29:01
* @LastEditTime: 2023-10-12 11:37:52
* @FilePath: \TelpoH5FrontendWeb\src\api\core.js
* @description:
* b端的接口, 每次调用前先获取token
@@ -12,6 +12,7 @@ const baseUrl = process.env.VUE_APP_BASE_API + 'gateway';
const service = axios.create({
baseURL: baseUrl,
});
const HTTP_PREFIX_CORE = process.env.VUE_APP_BASE_API + 'gateway/' + 'core';
service.interceptors.request.use(
request => {
if (localStorage.getItem(prefix + 'gatewayToken')) {
@@ -30,6 +31,30 @@ export const APICore = {
cardPackageList, //零川基础套餐列表
devicePayPackage,
drownReportFilterAdd,//添加过滤危险水域区域
setLocationConfig, //设置设备定位控制参数
getLocationConfig, //获取设备定位控制参数
getHealthConfig, //获取设备健康控制参数(心率、血氧、测温)
setHealthConfig, //设置设备健康控制参数(心率、血氧、测温)
setUploadConfig, //置设备上报周期参数
getUploadConfig, //取设备上报周期参数
setDrownConfig, //设置设备防溺水参数
getDrownConfig, //获取设备防溺水参数
setNowearConfig, //设置设备未佩戴检测参数
getNowearConfig, //获取设备未佩戴检测参数
setWatchConfig , //手表模式设置参数(平台)
getWatchConfig , //查看手表模式设置参数
getDrownReportFilterQuery, //获取水域告警白名单
drownReportFilterDelete, ////删除过滤危险水域区域
setAutoPlayConfigOfDiba, //设置迪爸自动播放参数接口
getAutoPlayConfigOfDiba, //获取迪爸自动播放列表接口
getBloodPressList, //获取血压数据列表
getBloodPressConfig, //获取设备血压周期性检测参数
setBloodPressConfig, //设置设备血压周期性检测参数
setPsychAbilityConfig, //心理监测能力开通(下发参数)
getPsychAbilityConfig,//获取心理监测能力开通参数
setIotCtlMode, //设置设备iot连接控制属性
getIotCtlMode, //获取设备iot连接控制属性
checkImei, //检查设备关联的物联网厂商信息
}
/* const headerAuth = this.$store.getters.gatewayToken; */
// 获取告警详情
@@ -101,4 +126,187 @@ function drownReportFilterAdd(data) {
data,
});
}

function setLocationConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetLocationConfig`,
method: 'post',
data: params,
});
}
function getLocationConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetLocationConfig`,
method: 'get',
params: {imei},
})
}
function setHealthConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetHealthConfig`,
method: 'post',
headers: {authKey: 'key1'},
data: params,
});
}
function getHealthConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetHealthConfig`,
method: 'get',
params: {imei},
})
}

function setUploadConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetUploadConfig`,
method: 'post',
data: params,
});
}
function getUploadConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetUploadConfig`,
method: 'get',
params: {imei},
})
}
function setAutoPlayConfigOfDiba(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/OpenAbility/Diba/setConfig`,
method: 'post',
data: params,
});
}

function getAutoPlayConfigOfDiba({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/OpenAbility/Diba/getConfig`,
method: 'get',
params: {imei},
})
}

function setDrownConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetDrownConfig`,
method: 'post',
data: params,
});
}
function getDrownConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetDrownConfig`,
method: 'get',
params: {imei},
})
}

function setNowearConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetNowearConfig`,
method: 'post',
data: params,
});
}
function getNowearConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetNowearConfig`,
method: 'get',
params: {imei},
})
}

function setWatchConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/Device/SetWatchConfig`,
method: 'post',
data: params,
});
}
function getWatchConfig({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/Device/GetWatchConfig`,
method: 'get',
params: {imei},
})
}
function getDrownReportFilterQuery({imei}) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/Device/DrownReportFilterQuery`,
method: 'get',
params: {imei},
})
}

function drownReportFilterDelete(data) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/Device/DrownReportFilterDelete`,
method: 'get',
params: data,
})
}

function getBloodPressList(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/healthy/BloodPressQuery`,
method: 'post',
data: params ,
});
}

function getBloodPressConfig(data) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetBloodPressConfig`,
method: 'get',
params: data,
})
}

function setBloodPressConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetBloodPressConfig`,
method: 'post',
data: params ,
});
}

function getPsychAbilityConfig(data) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetPsychAbilityConfig`,
method: 'get',
params: data,
})
}

function setPsychAbilityConfig(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetPsychAbilityConfig`,
method: 'post',
data: params ,
});
}
function setIotCtlMode(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/SetIotCtlMode`,
method: 'post',
data: params,
})
}
function getIotCtlMode(imei) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/open/OpenIot/GetIotCtlMode`,
method: 'get',
params: { imei },
})
}

function checkImei(params) {
return service({
url: `${HTTP_PREFIX_CORE}/api/v1/Device/CheckImei`,
method: 'post',
data: params,
})
}

export default APICore;

+ 25
- 0
src/api/iot.js Просмотреть файл

@@ -0,0 +1,25 @@
import axios from 'axios';
import prefix from '@/store/prefix';
const baseUrl = process.env.VUE_APP_BASE_API;
const service = axios.create({
baseURL: baseUrl,
});
service.interceptors.request.use(
request => {
/* if (localStorage.getItem(prefix + 'gatewayToken')) {
request.headers.AccessToken = localStorage.getItem(prefix + 'gatewayToken');
} */
return request;
},
);
export const APIIot = {
getdeviceinfo
}
function getdeviceinfo(params) {
return service({
url: `${baseUrl}iotservice/getdeviceinfo`,
method: 'post',
data: params
})
}
export default APIIot;

+ 16
- 0
src/components/custom-cell/index.scss Просмотреть файл

@@ -0,0 +1,16 @@
.custom-cell {
.van-cell {
padding: 10px 5px !important;
.van-cell__title {
width: 150px !important;
text-align: left !important;
}
.van-cell__value {
/* width: 200px !important; */
/* height: 60px !important; */
text-align: left !important;
padding-left: 10px;
/* overflow: scroll; */
}
}
}

+ 58
- 0
src/components/custom-cell/index.vue Просмотреть файл

@@ -0,0 +1,58 @@
<!--
* @Date: 2023-10-12 10:07:08
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-13 11:32:14
* @FilePath: \TelpoH5FrontendWeb\src\components\custom-cell\index.vue
* @description:
-->
<template>
<div class="custom-cell">
<van-cell-group>
<van-cell :title="title" :value="value" @click="onClick" />
</van-cell-group>
</div>
</template>

<script>
import { isNotNull} from "@/utils/index";
export default {
name: 'custom-cell',
props: {
title: {
type: String,
default: ''
},
value: {
type: String,
default: ''
},
data: {
type: Array,
default: ()=> []
},
click: {
type: String,
default: ''
}
},
data(){
return {

}
},
methods: {
onClick() {
if(isNotNull(this.click)) {
console.log(this.click);
this.$router.push({
name: this.click
})
}
}
}
}
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>

+ 12
- 0
src/components/echarts/index.scss Просмотреть файл

@@ -0,0 +1,12 @@
.charDom {
position: relative;
//屏幕大于750 或者小于1440
@media screen and (max-width: 1920px) and (min-width: 750px){
height: 100px;
width: 100%;
}
@media screen and (max-width: 750px) and (min-width: 200px){
height: 300px;
width: 100%;
}
}

+ 67
- 0
src/components/echarts/index.vue Просмотреть файл

@@ -0,0 +1,67 @@
<!--
* @Date: 2023-10-10 15:32:47
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-10 17:26:42
* @FilePath: \TelpoH5FrontendWeb\src\components\echarts\index.vue
* @description:
-->
<template>
<div :ref="id" id="charDom" class="charDom"/>
</template>

<script>
export default {
name: 'Echart',
props: {
option: {
type: Object,
default: () => {}
},
id: {
type: String,
default: 'charDom'
},
},
data(){
return {
chart: null,
}
},
watch: {
option: {
handler(val) {
this.chart.setOption(this.option)
},
deep: true
}
},
created() {},
mounted() {
this.renderCharts();
},
beforeDestroy() {
// 销毁echarts实例
/* this.chart.dispose()
this.chart = null */
},
methods: {
// 初始化
renderCharts() {
this.chart = this.$echarts.init(this.$refs[this.id]);
console.log("初始化中");
if (this.option) {
this.chart.setOption(this.option)
};
const _this = this;
// 注册点击事件
this.chart.on('click', function(params) {
_this.$emit('onClick', params)
})
}
}
}
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>

+ 37
- 0
src/components/tables/index.scss Просмотреть файл

@@ -0,0 +1,37 @@
.table-container {
table {
position: relative;
width: 100%;
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
border: .5px solid #e9e9e9;
overflow: scroll;
}

table th {
background: #f7f7f7;
color: #5c6b77;
font-weight: 600;
white-space: nowrap;

}

table td,
table th {
border: .5px solid #e9e9e9;
text-align: left;
@media screen and (max-width: 1920px) and (min-width: 550px){
padding: 4px;
}
@media screen and (max-width: 550px) and (min-width: 200px){
font-size: 16px;
padding: 8px;
}
}
tbody {
height: 50px;
overflow: scroll;
}

}

+ 74
- 0
src/components/tables/index.vue Просмотреть файл

@@ -0,0 +1,74 @@
<!--
* @Date: 2023-10-10 17:38:30
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-11 17:05:31
* @FilePath: \TelpoH5FrontendWeb\src\components\tables\index.vue
* @description:
-->
<template>
<div class="table-container">
<table>
<thead>
<tr>
<th
v-for="(item, key) in columns"
:key="key"
>{{ item.title }}</th>
</tr>
</thead>
<tbody>
<tr
v-for="(row, key1) in data"
:key="key1"
>
<td
v-for="(col, key2) in columns"
:key="key2"
:style="{'width': col.width}"
>
{{ row[col.key] }}
</td>
</tr>
</tbody>
</table>
</div>
</template>

<script>
export default {
name: '',
props: {
height: {
type: String,
default: '',
},
columns: {
type: Array,
require: true,
default(){
return []
}
},
data: {
type: Array,
require: true,
default(){
return []
}
}
/* row: {
type: Array,
default: []
} */

},
data(){
return {
}
}
}
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>

+ 26
- 3
src/config/models.js Просмотреть файл

@@ -1,11 +1,11 @@
/*
* @Date: 2021-11-20 10:26:39
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-09 09:38:30
* @LastEditTime: 2023-10-11 17:39:54
* @FilePath: \TelpoH5FrontendWeb\src\config\models.js
* @description:
*/
export const VERSION_MODEL = '1.0.89F'; //版本号
export const VERSION_MODEL = '1.0.90F'; //版本号
export const IMAGE_URL = {
production: 'http://zfb.ssjlai.com/web/',
test: 'http://zfb.ssjlai.com/web/',
@@ -60,4 +60,27 @@ export const EmotionModel = {
};

//心理健康相关接口地址
export const PsyBaseUrl = process.env.NODE_ENV === 'production' ? 'https://dbmq.rzliot.com/auth_heart' : 'https://dbmq.rzliot.com/heart';
export const PsyBaseUrl = process.env.NODE_ENV === 'production' ? 'https://dbmq.rzliot.com/auth_heart' : 'https://dbmq.rzliot.com/heart';


// 设备耗电情况
export const DEVICE_POWER = {
// 电量
BatteryLevel: {
title: '设备电量值',
value: 'BatteryLevel',
type: 1,
},
// 信号强度
status: {
title: '信号强度',
value: 'status',
type: 2,
},
// 离线行为
Offline: {
title: '设备离线行为',
value: 'offline',
type: 3,
}
}

+ 7
- 1
src/main.js Просмотреть файл

@@ -1,7 +1,7 @@
/*
* @Date: 2022-01-19 10:08:26
* @LastEditors: JinxChen
* @LastEditTime: 2023-09-20 14:15:47
* @LastEditTime: 2023-10-11 15:36:55
* @FilePath: \TelpoH5FrontendWeb\src\main.js
* @description:
*/
@@ -58,6 +58,9 @@ import {
Toast,
ActionSheet,
Progress,
DropdownMenu,
DropdownItem,
TreeSelect,
} from 'vant'; //按需加载vant组件

Vue
@@ -101,6 +104,9 @@ Vue
.use(Toast)
.use(ActionSheet)
.use(Progress)
.use(DropdownMenu)
.use(DropdownItem )
.use(TreeSelect)

Vue.config.productionTip = false;
Vue.config.devtools = true;


+ 14
- 1
src/router/index.js Просмотреть файл

@@ -1,7 +1,14 @@
/*
* @Date: 2023-09-21 09:54:53
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-13 11:30:23
* @FilePath: \TelpoH5FrontendWeb\src\router\index.js
* @description:
*/
/*
* @Date: 2023-06-01 18:41:50
* @LastEditors: JinxChen
* @LastEditTime: 2023-09-20 11:15:50
* @LastEditTime: 2023-10-10 15:56:50
* @FilePath: \TelpoH5FrontendWeb\src\router\index.js
* @description:
*/
@@ -59,6 +66,12 @@ const routes = [
{ path: '/aiCallAlarm', name: 'aiCallAlarm', component: resolve => require(['@/views/ai-call-alarm'], resolve) },
// 物联网卡错误页
{ path: '/iotcardError', name: 'iotcardError', component: resolve => require(['@/views/error-pages/iotcard-error'], resolve) },
// c1(4g管理后台)设备耗电情况页面
{ path: '/devicePower', name: 'devicePower', component: resolve => require(['@/views/gps-card-frontend/device-power'], resolve) },
// c1(4g管理后台)设备设置页面
{ path: '/deviceSetting', name: 'deviceSetting', component: resolve => require(['@/views/gps-card-frontend/device-setting'], resolve) },
// c1(4g管理后台)涉水区域白名单
{ path: '/drownWhiteList', name: 'drownWhiteList', component: resolve => require(['@/views/gps-card-frontend/drown-white-list'], resolve) },
];

const router = new VueRouter({


+ 11
- 2
src/store/index.js Просмотреть файл

@@ -1,7 +1,7 @@
/*
* @Date: 2022-08-17 16:18:02
* @LastEditors: JinxChen
* @LastEditTime: 2023-06-19 11:26:22
* @LastEditTime: 2023-10-13 14:45:16
* @FilePath: \TelpoH5FrontendWeb\src\store\index.js
* @description:
*/
@@ -13,7 +13,7 @@ import { isNotNull } from '@/utils';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
imei: '', //例子
imei: '', //
gatewayToken: '', //gateway接口token
token: '',
wxAuthCode: '',
@@ -22,6 +22,7 @@ export default new Vuex.Store({
isFromWx: null,
ssjlToken: '',
fromSsjl: '',
active: null, //点击左边树形图下标
},
mutations: {
imei(state, imei) {
@@ -60,6 +61,10 @@ export default new Vuex.Store({
state.fromSsjl = fromSsjl;
window.localStorage[prefix + 'fromSsjl'] = fromSsjl;
},
active(state, active) {
state.active = active;
window.localStorage[prefix + 'active'] = active;
},
},
getters: {
imei: state => {
@@ -98,6 +103,10 @@ export default new Vuex.Store({
if (state.fromSsjl != '') return state.fromSsjl;
return window.localStorage[prefix + 'fromSsjl'] == null ? '' : window.localStorage[prefix + 'fromSsjl'];
},
active: state => {
if (state.active != '') return state.active;
return window.localStorage[prefix + 'active'] == null ? '' : window.localStorage[prefix + 'active'];
},
},
actions: {},
modules: {}

+ 59
- 0
src/views/gps-card-frontend/device-power/index.scss Просмотреть файл

@@ -0,0 +1,59 @@
.device-power {
position: relative;
/* overflow: hidden; */
overflow: hidden;
height: 100vh;
background-color: #fff;
.top {
padding: 10px 15px;
text-align: left;
@media screen and (max-width: 550px) and (min-width: 200px){
font-size: 16px;
}
}
.action {
display: flex;
justify-content: space-between;
@media screen and (max-width: 550px) and (min-width: 200px){
justify-content: space-around;
}
align-items: center;
padding: 0 10px;
.left {
border: .5px solid $lineGray;;
.van-dropdown-menu {
.van-dropdown-menu__bar {
/* border: .5px solid #000; */
.van-dropdown-menu__item {
min-width: 150px !important;
}
}
}
}
.right {
.btn {
&.active {
color: $blue;
border: .5px solid $blue;
}
}
}
}
.details-container{
position: relative;
padding: 10px;

@media screen and (max-width: 1920px) and (min-width: 550px){
height: 100px;
overflow: scroll;
}
@media screen and (max-width: 550px) and (min-width: 200px){
max-height: 500px;
overflow: scroll;
}
.echart {
height: 30%;
padding: 0 5px;
}
}
}

+ 328
- 0
src/views/gps-card-frontend/device-power/index.vue Просмотреть файл

@@ -0,0 +1,328 @@
<!--
* @Date: 2023-10-10 15:29:50
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-13 14:41:57
* @FilePath: \TelpoH5FrontendWeb\src\views\gps-card-frontend\device-power\index.vue
* @description:
-->
<template>
<div class="device-power">
<van-nav-bar :left-arrow="true" @click-left="onNavBack">
<template #left>
<van-icon name="arrow-left" size="24" style="padding: 0"/>
<span>返回</span>
</template>
</van-nav-bar>
<div class="top">
<p>查看数据</p>
</div>
<div class="action">
<div class="left">
<van-dropdown-menu>
<van-dropdown-item style="min-width: 150px" v-model="dayValue" :options="dayOption" @change="onChange" />
</van-dropdown-menu>
</div>
<div class="right">
<div class="btn-container">
<van-button :class="['btn', {active: btnActive ===item.index }]" @click="onClickBtn(item.index)" v-for="(item, index) in btnList" :key="index">{{ item.text }}</van-button>
</div>
</div>
</div>
<div class="details-container" v-if="data.length > 0">
<Echart :option="chartOption" v-show="btnActive === 0"/>
<Table :columns="titleList" :data="tableData" v-show="btnActive === 1"/>
</div>
<div class="details-container no-data" v-else>
<van-empty image="error" description="暂无数据" />
</div>
</div>
</template>

<script>
import Echart from '@/components/echarts';
import Table from '@/components/tables';
import APIIot from '@/api/iot';
import { DEVICE_POWER } from "@/config/models";
import axios from 'axios';
export default {
name:'',
components: { Echart,Table },
data(){
return {
dayValue: 7,
dayOption: [
{ text: '7天', value: 7 },
{ text: '30天', value: 30 },
],
btnList: [
{ text: '图表', index: 0 },
{ text: '表格', index: 1 },
],
btnActive: 0,
chartOption: {},
titleList: [
{ title: '时间', width: '40%', key: 'time'},
{ title: '原始值', width: '60%', key: 'value' },
],
tableData: [],
echarts: {
title: '',
type: '',
},
data: [],
xAxisData: [],
filterData: [],
yAxisObject: {}
}
},
created() {

},
mounted() {
this.loadParams();
},
methods: {
loadParams() {
let params = this.$route.query;
if(params) {
this.echarts.title = DEVICE_POWER[params.title].title;
this.echarts.type = DEVICE_POWER[params.title].value;
// 获取接口数据
this.getData();
} else {
// todo跳转404页面
}
},
getData() {
this.$toast.loading();
let reqBody = {
days: String(this.dayValue),
identifier: this.echarts.type,
imei: /* '861281060086216' *//* '862838050029479' */this.$store.getters.imei
};
// 线上地址
let baseUrl = process.env.VUE_APP_BASE_API;
let reqUrl = `${baseUrl}iotservice/getdeviceinfo`;
// 开启代理如下
/* let reqUrl = `/api/id/getdeviceinfo`; */
axios.post(`${reqUrl}`, reqBody).then(res => {
let data = res.data;
if(data.code === 200) {
if(this.echarts.type === 'BatteryLevel' || this.echarts.type === 'status') {
this.filterData = data[this.echarts.type].data.list.propertyInfo;
} else if(this.echarts.type === 'status') {
this.filterData = data[this.echarts.type].data.list.propertyInfo;
} else if(this.echarts.type === 'offline') {
this.filterData = data.Offline.data;
}
if(this.echarts.type === 'status') {
// 信号强度
this.yAxisObject = {
type: "value",
/* max: 4,
min: 0,
interval: 1,
splitNumber : 1,
boundaryGap : [ '5%', '5%' ], */
}
this.titleList = [
{ title: '时间', width: '40%', key: 'time'},
{ title: '原始值', width: '60%', key: 'value' },
],
// 表格则要显示全部数据
this.tableData = this.filterData.map(item => {
return {
value: item.value,
time: this.$dayjs(this.$dayjs(Number(item.time))).format("YYYY/MM/DD hh:mm")
}
});
// 图表筛选过滤只显示 rssi <= 2的数据
this.data = this.filterData.map(item => {
// 序列化json
let json = JSON.parse(item.value);
return {
value: json.rssi,
time: this.$dayjs(this.$dayjs(Number(item.time))).format("YYYY/MM/DD hh:mm"),
type: 'status'
}
}).filter(f => {
return f.value <=2;
})
console.log(this.data);
} else if (this.echarts.type === 'offline') {
// 设备离线次数
this.titleList = [
{ title: '时间', width: '60%', key: 'time'},
{ title: '离线次数', width: '40%', key: 'value' },
],
this.yAxisObject = {
type: "value",
/* max: 10,
min: 0,
interval: 1,
splitNumber : 1,
boundaryGap : [ '5%', '5%' ], */
};
this.data = this.filterData.map(item => {
return {
/* value: item.value, */
time: item.createTime.slice(0,10),
day: item.createTime.slice(0,10),
type: 'offline'
}
}).reduce((accumulator, currentValue) => {
if (accumulator.find(obj => obj.day === currentValue.day)) {
accumulator.find(obj => obj.day === currentValue.day).value++;
} else {
accumulator.push({ day: currentValue.day, time: currentValue.time, value: 1, type: 'offline' });
}
return accumulator;
}, []).sort(function(date1, date2) {
// 日期升序排序
return date2.time < date1.time ? 1 : -1
});
this.tableData = this.filterData.map(item => {
return {
/* value: item.value, */
time: item.createTime.slice(0,10),
day: item.createTime.slice(0,10)
}
}).reduce((accumulator, currentValue) => {
// 筛选遍历数据,获取相同日期的数据,计算出现的次数后重新累加组合到一个新的数组里面
if (accumulator.find(obj => obj.day === currentValue.day)) {
accumulator.find(obj => obj.day === currentValue.day).value++;
} else {
accumulator.push({ day: currentValue.day, time: currentValue.time, value: 1 });
}
return accumulator;
}, []).sort(function(date1, date2) {
// 日期升序排序
return date2.time < date1.time ? 1 : -1
});
} else {
this.titleList = [
{ title: '时间', width: '40%', key: 'time'},
{ title: '电量', width: '60%', key: 'value' },
],
this.yAxisObject = {
type: "value",
max: 100,
min: 0,
interval: 20,
splitNumber : 1,
boundaryGap : [ '5%', '5%' ],
}
this.data = this.filterData.map(item => {
return {
value: item.value,
time: this.$dayjs(this.$dayjs(Number(item.time))).format("YYYY/MM/DD hh:mm"),
}
});
this.tableData = this.filterData.map(item => {
return {
value: item.value,
time: this.$dayjs(this.$dayjs(Number(item.time))).format("YYYY/MM/DD hh:mm")
}
});
}
this.xAxisData = this.data.map(item => {
return this.$dayjs(item.time).format("MM/DD");
})
this.chartOption = {
title: {
text: this.echarts.title,
},
xAxis: {
type: "category",
axisLine: {
show: false
},
textStyle: {
fontSize: 10
},
axisTick: {
show: false
},
splitLine: {
show: false,
lineStyle: {
color: "#ddd",
width: 2
}
},
nameLocation: 'center',
axisLabel: {
show: true,
fontSize: 12,
showMinLabel: true, //显示最小值
showMaxLabel: true, //显示最大值
},
data: this.xAxisData
},
yAxis: this.yAxisObject,
series: [
{
type: "line",
data: this.data,
/* areaStyle: {}, */
},
],
dataZoom: [
{
start: 0,
end: 100,
textStyle: {
color: "#FFF",
fontSize: 14
},
show: true,
height: 20,
bottom: 5,
handleStyle: {
borderWidth: 1,
borderCap: "square"
}
}
],
tooltip: {
trigger: "axis",
textStyle: {
fontSize: 14,
align: "center"
},
formatter: function(params) {
console.log(params);
return `${params[0].marker}${params[0].data.time}</br>
${ params[0].data.type === 'offline' ? '离线次数:' + params[0].data.value + '次' :
params[0].data.type === 'status' ? 'rssi值:' + params[0].data.value :
'电量:' + params[0].data.value}`
}
},
}
}
}).catch(() => {

}).finally(() => {
this.$toast.clear();
})
},
onClickBtn(value) {
this.btnActive = value;
this.getData();
},
onChange(value) {
this.dayValue = value;
this.getData();
},
onNavBack() {
this.$router.push({
name: 'deviceSetting'
})
}
}
}
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>

+ 15
- 0
src/views/gps-card-frontend/device-setting/index.scss Просмотреть файл

@@ -0,0 +1,15 @@
.device-setting {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
background-color: #fff;
.tree-select {
position: relative;
padding: 10px;
@media screen and (max-width: 550px) and (min-width: 200px){
font-size: 16px;
}

}
}

+ 449
- 0
src/views/gps-card-frontend/device-setting/index.vue Просмотреть файл

@@ -0,0 +1,449 @@
<!--
* @Date: 2023-10-11 15:34:12
* @LastEditors: JinxChen
* @LastEditTime: 2023-10-13 15:01:00
* @FilePath: \TelpoH5FrontendWeb\src\views\gps-card-frontend\device-setting\index.vue
* @description:
-->
<template>
<div classs="device-setting">
<div class="tree-select">
<van-tree-select :items="settingItems" :main-active-index.sync="active" :height="clientHeight" @click-nav="onCkickNav">
<template #content>
<div class="item" v-for="(item, index) in settingItems" :key="index" v-show="item.index === active">
<div class="item-setting" v-for="(child, index) in item.data" :key="index">
<customCell :title="child.name" :value="child.value" :click="child.router"/>
</div>
</div>
<div class="power" v-show="active === 10 || active === 11 || active === 12">
<van-button @click="onClick(active)">点击查看</van-button>
</div>
</template>
</van-tree-select>
</div>
</div>
</template>

<script>
import customCell from '@/components/custom-cell/index';
import { isNotNull} from "@/utils/index";
import APICore from "@/api/core";
export default {
name:'',
components: { customCell },
data(){
return {
active: 0,
settingItems: [
{ text: '监护角色', index: 0, data: [],},
{ text: '场景模式', index: 1, data: []},
{ text: '加强省电模式', index: 2, data: []},
{ text: '定位监测', index: 3, data: []},
{ text: '危险区域监测', index: 4, data: [] },
{ text: '健康监测', index: 5, data: []},
{ text: '血压监测', index: 6, data: []},
{ text: '心理监测', index: 7, data: []},
{ text: '佩戴监测', index: 8, data: []},
/* { text: '久坐提醒', index: 9, data: []}, */
{ text: '上报周期', index: 10, data: []},
{ text: '电量查看', index: 11, data: []},
{ text: '设备信号强度查看', index: 12, data: []},
{ text: '设备行为日志查看', index: 13, data: []},
],
dateList: [], //时间列表
clientHeight: '', //当前窗口可视页面高度
}
},
computed: {
imei() {
return this.$store.getters.imei/* '861281060086216' */;
},
},
created() {
this.getAuth();
this.getUrlQueryParams();
},
mounted() {
this.$toast.loading({message: "加载中"});
this.getWatchConfig();
this.getIotCtlMode();
this.getLocationConfig();
this.getDrownConfig();
this.getHealthConfig();
this.getBloodConfig();
this.getPsychAbilityConfig();
this.getNowearConfig();
this.getUploadConfig();
this.clientHeight = document.documentElement.clientHeight;
this.active = Number(this.$store.getters.active) || 0;
this.$toast.success({message: "加载完成"});
},
methods: {
// 获取b端接口的token
getAuth() {
let manufactorId = "5bf13062-a41e-4d00-ba14-1101aad12650";
APICore.getAuth({ manufactorId: manufactorId }).then(res => {
this.$store.commit("gatewayToken", res.data.data);
});
},
getUrlQueryParams() {
// 从url中获取参数并缓存
let params = this.$route.query;
if (isNotNull( params )) {
// 首次进入且正确传参
//this.imei = params.imei;
if(params.accessToken) {this.$store.commit('accessToken', params.accessToken); }
this.$store.commit('imei', params.imei);
}
},
// 获取设备场景模式参数
getWatchConfig() {
APICore.getWatchConfig({imei: this.imei}).then(res => {
let data = res.data;
if(data) {
const modeId = data.modeId;
const roleId = data.roleId;
this.modeId = data.modeId;
this.roleId = roleId;
this.settingItems[0].text = `监护角色(${roleId === 1 ? '学生' : '老人'})`;
this.settingItems[1].text = `场景模式(${this.getModeById(modeId)})`;
} else {
this.settingItems[0].text = `监护角色(学生)`;
this.settingItems[1].text = `场景模式(无)`;
/* this.modeId = 1;
this.roleId = 1; */
}
})
},
// 通过模式id获取场景模式
getModeById(id) {
if(id === 1) {
return '标准'
} else if (id === 2) {
return '省电'
} else {
return '个性'
}
},
// 组装选项数据
concatTitle(title, status, power){
return `${title}(${status}) (${power})`
},
// 获取加强省电模式参数配置
getIotCtlMode() {
APICore.getIotCtlMode(this.imei).then(res => {
let data = res.data.data;
console.log("data", data);
if(data) {
this.checked = data.mode === 1;
this.settingItems[2].text = this.concatTitle('加强省电模式', data.mode === 1 ? '打开' : '关闭', data.mode === 1 ? '耗电高' : '耗电低');
this.settingItems[2].data = [
{ name: '开启状态:', value: data.enabled === 1 ? '打开': '关闭' },
];
} else {
this.settingItems[2].text = this.concatTitle('加强省电模式','关闭', '耗电低');
}
})
},
// 获取设备定位参数
getLocationConfig() {
APICore.getLocationConfig({imei: this.imei}).then(res => {
let data = res.data.data;
console.log(data);
if(data) {
this.settingItems[3].text = this.concatTitle('定位监测', data.enabled === 1 ? '打开': '关闭', data.enabled === 1 ? '耗电高' : '耗电低');
this.settingItems[3].data = [
{ name: '开启状态:', value: data.enabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: data.sampleinteval + '分钟' },
];
} else {
this.settingItems[3].text = this.concatTitle('定位监测','关闭', '耗电低');
}
})
},
// 获取免告警水域
getDrownReportFilterQuery() {
APICore.getDrownReportFilterQuery({imei: this.imei}).then(res => {
let data = res.data.data;
if(data) {
let json = {};
for(var i=0; i<data.length; i++){
json[i] = data[i];
}
this.drownWhite = JSON.stringify(json);
}
})
},
// 获取设备危险区域参数
getDrownConfig() {
APICore.getDrownConfig({imei: this.imei}).then(res => {
let data = res.data.data;
if(data) {
this.settingItems[4].text = this.concatTitle('危险区域监测', data.enabled === 1 ? '打开': '关闭', data.enabled === 1 ? '耗电高' : '耗电低');
this.settingItems[4].data = [
{ name: '涉水监测:', value: data.enabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: data.config.intervallvl1 + data.config.intervallvl2 + '分钟' },
{ name: '告警阈值:', value: data.config.warningdistance + '米' },
{ name: '涉水停留告警间隔:', value: (data.config.distancelvl2 / 60) + '分钟' },
{ name: '告警提示持续次数:', value: data.config.warningtimes + '次' },
{ name: '首次告警逗留设置:', value: data.config.delaytimes + '次' },
{ name: '时速免告警(≥):', value: data.config.ignorespeed + '公里' },
{ name: '免告警水域:', value: '查看', router: 'drownWhiteList' },
{ name: '告警方式:', value: `${data.config.vibrateenabled === 1 ? '震动' : '无'} , ${data.config.lcdenabled === 1 ? '亮屏' : '无'} , ${data.config.musicenabled === 1 ? '声音' : '无'}`},
];
} else {
this.settingItems[4].text = this.concatTitle('危险区域监测','关闭', '耗电低');
this.settingItems[4].data = [];
}
})
},

// 格式化某些特殊参数值的时间显示方式
formatInteval(value) {
return value >= 360 ? (value / 60) + '小时' : value + '分钟'
},
// 获取设备健康参数
getHealthConfig() {
APICore.getHealthConfig({imei: this.imei}).then(res => {
let data = res.data.data;
if(data) {
let healthEnablelist = [
{ enabled: data.config.heartrateenabled},
{ enabled: data.config.spo2enabled},
{ enabled: data.config.temperatureenabled},
];
let config = data.config;
// 获取健康设置打开的次数
const healthSettingCount = healthEnablelist.reduce((acc, cur) => cur.enabled === 1 ? ++acc : acc, 0);
this.settingItems[5].text = this.concatTitle('健康监测', healthSettingCount >= 3 ? '打开'
: healthSettingCount >= 1 ? '部分'
: '关闭', healthSettingCount > 2 ? '耗电高': healthSettingCount === 2 ? '耗电中': '耗电低');
this.settingItems[5].data = [
{ name: '体温监测:', value: config.temperatureenabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: this.formatInteval(config.temperatureinteval) },
{ name: '告警阈值-高温:', value: (config.temperaturemaxvalue / 10) + '度' },
/* { name: '告警阈值-低温:', value: config.temperatureminvalue + '度' }, */
{ name: '告警方式:', value: `${config.temperaturevibrateenabled === 1 ? '震动' : '无'} , ${config.temperaturelcdenabled === 1 ? '亮屏' : '无'}`},

{ name: '心率监测:', value: config.heartrateenabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: this.formatInteval(config.heartrateinteval) },
{ name: '告警阈值-上限:', value: config.heartratemaxvalue + '次' },
{ name: '告警阈值-下限:', value: config.heartrateminvalue + '次' },
{ name: '告警方式:', value: `${config.heartratevibrateenabled === 1 ? '震动' : '无'} , ${config.heartratelcdenabled === 1 ? '亮屏' : '无'}`},

{ name: '血氧监测:', value: config.spo2enabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: this.formatInteval(config.spo2inteval) },
{ name: '告警阈值-低于:', value: config.spo2minvalue + '%' },
/* { name: '告警阈值-低温:', value: config.temperatureminvalue + '度' }, */
{ name: '告警方式:', value: `${config.spo2vibrateenabled === 1 ? '震动' : '无'} , ${config.spo2lcdenabled === 1 ? '亮屏' : '无'}`},
]
} else {
this.settingItems[5].text = this.concatTitle('健康监测','关闭', '耗电低');
this.settingItems[5].data = [];
}
})
},
// 获取血压监测参数设置
getBloodConfig() {
APICore.getBloodPressConfig({imei: this.imei}).then(res => {
let data = res.data.data;
if(data) {
this.settingItems[6].text = this.concatTitle('血压监测', data.bloodPressenabled === 1 ? '打开': '关闭', data.bloodPressenabled === 1 ? '耗电高' : '耗电低');
this.settingItems[6].data = [
{ name: '血压监测:', value: data.bloodPressenabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: this.formatInteval(data.bloodPressinteval) },
{ name: '告警阈值-收缩压:', value: String(data.systolicmaxvalue)},
{ name: '告警方式:', value: `${data.bloodPressvibrateenabled === 1 ? '震动' : '无'} ,${data.bloodPresslcdenabled === 1 ? '亮屏' : '无'}`},
]
} else {
this.settingItems[6].text = this.concatTitle('血压监测','关闭', '耗电低');
this.settingItems[6].data = [];
}
})
},
// 格式化等级
formatReminder(value) {
let text = "";
if (value == 1) {
text = "轻度";
} else if (value == 2) {
text = "中度";
} else if (value == 3) {
text = "重度";
}
return text;
},
// 格式化监测时段
formatTimeArea(timeArr) {
let timeToString = timeArr.map(item => {
return `{时段: ${item.time},时长:${item.duration};}`;
});
return String(timeToString);
},
// 获取心理监测参数设置
getPsychAbilityConfig() {
APICore.getPsychAbilityConfig({imei: this.imei}).then(res => {
let data = res.data.data;
if (data) {
this.settingItems[7].text = this.concatTitle('心理监测', data.enabled === 1 ? '打开': '关闭', data.enabled === 1 ? '耗电高' : '耗电低');
this.settingItems[7].data = [
{ name: '心理监测:', value: data.enabled === 1 ? '打开': '关闭' },
{ name: '设备显示:', value: data.device_display === 1 ? '打开': '关闭' },
{ name: '监测时段:', value: this.formatTimeArea(data.time_area) },
{ name: '提醒设置:', value: data.reminder_setting.enable === 1 ? '打开': '关闭' },
{ name: '抑郁等级:', value: this.formatReminder(data.reminder_setting.setting.depressive) },
{ name: '压力等级:', value: this.formatReminder(data.reminder_setting.setting.pressure) },
{ name: '疲劳等级:', value: this.formatReminder(data.reminder_setting.setting.fatigue) },
{ name: '告警方式:', value: `${data.vibrating_screen === 1 ? '震动' : '无'}, ${data.brightening_screen === 1 ? '亮屏' : '无'}`},
]
} else {
this.settingItems[7].text = this.concatTitle('心理监测', '关闭', '耗电低');
this.settingItems[7].data = [];
}
})
},
// 转换时间格式
shiftTime(time, model) {
if(time) {
let startTime = '{' + time.slice(0,2) + ":" + time.slice(2,4);
let endTime = time.slice(4,6) + ":" + time.slice(6,8) + '}';
let timeObj = {
startTime: startTime,
endTime: endTime,
};
this.dateList.push(timeObj);
}
},
// 转化时间数组 :)
fomatTimeArr(arr) {
let timeString = arr.map(item => {
return item.startTime + '-' + item.endTime
});
return String(timeString);
},
// 获取佩戴监测参数设置
getNowearConfig() {
APICore.getNowearConfig({ imei: this.imei }).then(res => {
let data = res.data.data;
if(data) {
this.dateList = [];
this.shiftTime(data.timearea1, 0);
this.shiftTime(data.timearea2, 1);
this.shiftTime(data.timearea3, 2);
this.shiftTime(data.timearea4, 3);
this.shiftTime(data.timearea5, 4);
this.shiftTime(data.timearea6, 5);
this.shiftTime(data.timearea7, 6);
this.shiftTime(data.timearea8, 7);
this.shiftTime(data.timearea9, 8);
this.shiftTime(data.timearea10, 9);
this.settingItems[8].text = this.concatTitle('佩戴监测', data.enabled === 1 ? '打开': '关闭', data.enabled === 1 ? '耗电高' : '耗电低');
this.settingItems[8].data = [
{ name: '佩戴监测:', value: data.enabled === 1 ? '打开': '关闭' },
{ name: '检测周期:', value: (data.interval / 60) + '分钟' },
{ name: '检测时段:', value: this.fomatTimeArr(this.dateList)},
{ name: '未佩戴处理方式:', value: data.mode === 1 ? '不处理': '飞行模式' },
{ name: '佩戴提醒:', value: data.warningtimes !== 0 ? '打开' : '关闭' },
{ name: '提醒时间间隔:', value: (data.warninginterval / 60) + '分钟' },
{ name: '提醒次数:', value: data.warningtimes + '次'},
{ name: '告警方式:', value: `${data.vibrateenabled === 1 ? '震动' : '无'} ,${data.lcdenabled === 1 ? '亮屏' : '无'} ,${data.soundenabled === 1 ? '声音' : '无'}`},
]
} else {
this.settingItems[8].text = this.concatTitle('佩戴监测', '关闭', '耗电低');
this.settingItems[8].data = [];
}
})
},
// 获取设备上报参数
getUploadConfig() {
APICore.getUploadConfig({imei: this.imei}).then(res => {
const data = res.data.data;
if(data) {
this.settingItems[9].text = `上报周期(${data.uploadinteval}分钟)`;
} else {
this.settingItems[9].text = '关闭';
}
})
},
// 点击左边树形图
onCkickNav(value) {
console.log("value", value);
this.active = value;
this.$store.commit('active', value);
switch(value) {
/* case 10:
case 11:
case 12:
this.$router.push({
name: 'devicePower',
query: {
title: `${value === 10 ? 'BatteryLevel' : value === 11 ? 'status': 'Offline'}`
}
});
break; */
case 0:
this.getWatchConfig();
break;
case 1:
this.getWatchConfig();
break;
case 2:
this.getIotCtlMode();
break;
case 3:
this.getLocationConfig();
break;
case 4:
this.getDrownConfig();
break;
case 5:
this.getHealthConfig();
break;
case 6:
this.getBloodConfig();
break;
case 7:
this.getPsychAbilityConfig();
break;
case 8:
this.getNowearConfig();
break;
case 9:
this.getUploadConfig();
break;
default: break;

}
},
// 点击页面查看按钮
onClick(value) {
if(value) {
this.$router.push({
name: 'devicePower',
query: {
title: `${value === 10 ? 'BatteryLevel' : value === 11 ? 'status': 'Offline'}`
}
})
}
}
}
}
</script>

<style lang="scss">
.van-tree-select__nav-item {
padding: 15px 5px !important;
}
.van-tree-select__content {
padding: 5px;
}
.van-tree-select__nav{
flex: 1 !important;
}
.van-tree-select__content {
@include center();
}
</style>
<style scoped lang="scss">
@import "./index.scss";
</style>

+ 0
- 0
src/views/gps-card-frontend/drown-white-list/index.scss Просмотреть файл


+ 148
- 0
src/views/gps-card-frontend/drown-white-list/index.vue Просмотреть файл

@@ -0,0 +1,148 @@
<template>
<div class="drown-white-list">
<van-nav-bar title="免告警水域" :border="true" left-arrow @click-left="onNavBack"/>
<div class="main">
<div class="list" v-if="drownList.length > 0">
<div class="item" v-for="(item, index) in drownList" :key="index">
<p><span>poiId:{{ item.poiId }}</span></p>
<p><span>水域类型:{{ item.title }}</span></p>
<p><span>水域名称:{{ item.address }}</span></p>
<p><span>设置时间:{{ item.createTime }}</span></p>
<!-- <div class="btn-con">
<div class="btn" @click="onDelete(item.imei, item.poiId)">
<p>删除</p>
</div>
</div> -->
</div>
</div>
<div class="noData" v-else>
<p>暂无数据~</p>
</div>
</div>
</div>
</template>

<script>
import { isNotNull} from "@/utils/index";
import APICore from "@/api/core";
export default {
name:'',
data(){
return {
drownList: [],
}
},
computed: {
imei() {
return this.$store.getters.imei;
},
},
mounted() {
this.getDrownReportFilterQuery();
},
methods: {
onNavBack(){
this.$router.push({
name: 'deviceSetting'
})
},
// 获取免告警水域
getDrownReportFilterQuery() {
this.$toast.loading({ message: '数据加载中' });
APICore.getDrownReportFilterQuery({imei: this.imei}).then(res => {
let data = res.data.data;
console.log(data);
if(data) {
if(isNotNull(data)) {
this.drownList = data;
this.$toast.success({ message: '数据加载完成' });
}
}
})
},
}
}
</script>

<style scoped lang="scss">
.drown-white-list {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
.main {
/* height: calc(100vh - 88px);
overflow: auto; */
overflow: auto;
.list {
@media screen and (max-width: 1920px) and (min-width: 750px){
padding: 2vh;
height: 70vh;
display: flex;
justify-content: flex-start;
align-content: center;
align-items: center;
flex-wrap: wrap;
}
@media screen and (max-width: 750px) and (min-width: 200px){
display: flex;
justify-content: flex-start;
align-content: center;
align-items: center;
flex-direction: column;
height: calc(100vh - 88px);
}
.item {
@media screen and (max-width: 1920px) and (min-width: 750px){
width: 25%;
}
@media screen and (max-width: 750px) and (min-width: 200px){
width: 300px;
font-size: 16px;
}
margin: 2vh;
padding: 1vh;
/* font-size: 16px; */
border: 1px solid $border_color;
border-radius: 8px;
p {
padding: 4px 0;
}
.btn-con {
display: flex;
justify-content: flex-end;
align-items: center;
.btn {
height: 30px;
width: 110px;
@include center();
border-radius: 15px;
margin-top: 10px;
background-color: red;
color: #fff;

}
}
}
}
.noData {

@media screen and (max-width: 1920px) and (min-width: 750px){
height: 100px;
width: 100%;
}
@media screen and (max-width: 750px) and (min-width: 200px){
height: 225px;
width: 100%;
}
@include center();
margin: 100px auto 0;
background-size: 165px 120px;
p {
@include colorAndFont(#999, 28);
margin: 100px auto 0;
}
}
}
}
</style>

+ 7
- 7
vue.config.js Просмотреть файл

@@ -1,7 +1,7 @@
/*
* @Author: your name
* @Date: 2020-04-15 10:00:32
* @LastEditTime: 2023-06-14 17:10:10
* @LastEditTime: 2023-10-12 17:24:41
* @LastEditors: JinxChen
* @Description: In User Settings Edit
* @FilePath: \TelpoH5FrontendWeb\vue.config.js
@@ -14,10 +14,10 @@ const pxtorem = require('postcss-pxtorem'); // 把代码中px转为rem

const CompressionPlugin = require("compression-webpack-plugin");
const port = process.env.port || process.env.npm_config_port || 8080;/* 7788 */ // dev port
/* const proxy = process.env.NODE_ENV === 'development' ?{
const proxy = process.env.NODE_ENV === 'development' ?{
// 调试完毕需要把这个代理注释掉,否则发布到线上会有问题产生
'/api/id': {
target: 'https://id.ssjlai.com/watersoutboundapi/',
/* '/api/id': {
target: 'http://id.ssjlai.com/iotservice',
changeOrigin: true,
pathRewrite: {
'^/api/id': ''
@@ -29,9 +29,9 @@ const port = process.env.port || process.env.npm_config_port || 8080;/* 7788 */
pathRewrite: {
'^/api/ai': ''
}
}
} */
}
: null; */
: null;
module.exports = {
// 注意: 多页面配置 不再使用全路径,单页面时可以开启
publicPath: './',
@@ -46,7 +46,7 @@ module.exports = {
warnings: false,
errors: true
},
/* proxy: proxy, */
/* proxy: proxy, */ //开启代理后必须也要把这个开启,否则不生效
/* host: '192.168.3.186', */// 原为: hotst: 'localhost', 可在同一ip局域网下通过网址生成二维码的方式调试h5, 注意:调试完毕请注释
//disableHostCheck: true, //真机调试开启
},


Загрузка…
Отмена
Сохранить