Przeglądaj źródła

我的模块子内容迁移

test
chenJinxu 11 miesięcy temu
rodzic
commit
45c6106371
84 zmienionych plików z 17206 dodań i 48 usunięć
  1. +7
    -2
      package-lock.json
  2. +2
    -1
      package.json
  3. +5
    -3
      src/api/core.js
  4. +77
    -0
      src/assets/css/mixin.scss
  5. BIN
      src/assets/icon.png
  6. BIN
      src/assets/img/callLog.png
  7. BIN
      src/assets/img/drownReport.png
  8. BIN
      src/assets/img/health/blood_icon.png
  9. BIN
      src/assets/img/health/blood_oxygen.png
  10. BIN
      src/assets/img/health/bulb.png
  11. BIN
      src/assets/img/health/gps.png
  12. BIN
      src/assets/img/health/gps_frequency.png
  13. BIN
      src/assets/img/health/health.png
  14. BIN
      src/assets/img/health/heartRate.png
  15. BIN
      src/assets/img/health/location.png
  16. BIN
      src/assets/img/health/psychological_icon.png
  17. BIN
      src/assets/img/health/report_ frequency.png
  18. BIN
      src/assets/img/health/rest.png
  19. BIN
      src/assets/img/health/right_more.png
  20. BIN
      src/assets/img/health/setting.png
  21. BIN
      src/assets/img/health/temperature.png
  22. BIN
      src/assets/img/healthy.png
  23. BIN
      src/assets/img/home/layer.png
  24. BIN
      src/assets/img/home/lbs_icon.png
  25. +6
    -0
      src/assets/img/home/md-highlight_off.svg
  26. BIN
      src/assets/img/home/message.png
  27. BIN
      src/assets/img/home/phone.png
  28. BIN
      src/assets/img/home/spread_left.png
  29. BIN
      src/assets/img/home/spread_right.png
  30. BIN
      src/assets/img/home/trajectory.png
  31. BIN
      src/assets/img/home/warning.png
  32. BIN
      src/assets/img/leaveDrownReport.png
  33. BIN
      src/assets/img/noWear.png
  34. BIN
      src/assets/img/phone_ record.png
  35. BIN
      src/assets/img/prohibition.png
  36. BIN
      src/assets/img/spo.png
  37. BIN
      src/assets/img/tooltip-sizing.png
  38. BIN
      src/assets/img/wear.png
  39. +40
    -0
      src/common/amap.js
  40. +246
    -0
      src/common/own.js
  41. +2
    -1
      src/components/NavBar.vue
  42. +103
    -1
      src/components/SubmenuList.vue
  43. +34
    -0
      src/components/overlay-loading/overlay-loading.vue
  44. +2
    -2
      src/config/env.development.js
  45. +2
    -2
      src/config/env.production.js
  46. +2
    -2
      src/config/env.test.js
  47. +7
    -0
      src/config/models.js
  48. +5
    -0
      src/main.js
  49. +156
    -0
      src/router/router.config.js
  50. +1
    -1
      src/services/dialog-service.js
  51. +2
    -2
      src/views/myself/addFamilyNumber.vue
  52. +118
    -0
      src/views/myself/callList.vue
  53. +2
    -2
      src/views/myself/changeFamilyNumber.vue
  54. +235
    -0
      src/views/myself/changePayPassword.vue
  55. +225
    -0
      src/views/myself/clock.vue
  56. +588
    -0
      src/views/myself/deviceSetting/blood.vue
  57. +1398
    -0
      src/views/myself/deviceSetting/dangerAreaMonitor.vue
  58. +199
    -0
      src/views/myself/deviceSetting/drownWhiteList.vue
  59. +1094
    -0
      src/views/myself/deviceSetting/healthMonitor.vue
  60. +407
    -0
      src/views/myself/deviceSetting/locationMonitor.vue
  61. +889
    -0
      src/views/myself/deviceSetting/personInfos.vue
  62. +1288
    -0
      src/views/myself/deviceSetting/psychologicalSetting.vue
  63. +223
    -0
      src/views/myself/deviceSetting/sceneMode.vue
  64. +886
    -0
      src/views/myself/deviceSetting/settingIndex.vue
  65. +1168
    -0
      src/views/myself/deviceSetting/wearMonitor.vue
  66. +102
    -0
      src/views/myself/help.vue
  67. +3
    -2
      src/views/myself/index.scss
  68. +113
    -26
      src/views/myself/index.vue
  69. +581
    -0
      src/views/myself/location.scss
  70. +1705
    -0
      src/views/myself/location.vue
  71. +260
    -0
      src/views/myself/management.vue
  72. +227
    -0
      src/views/myself/messageList.vue
  73. +435
    -0
      src/views/myself/news/news.vue
  74. +252
    -0
      src/views/myself/prohibit.vue
  75. +321
    -0
      src/views/myself/replace.vue
  76. +157
    -0
      src/views/myself/sendMessage.vue
  77. +317
    -0
      src/views/myself/setupClockPeriod.vue
  78. +443
    -0
      src/views/myself/setupProhibitPeriod.vue
  79. +237
    -0
      src/views/myself/setupSleepPeriod.vue
  80. +239
    -0
      src/views/myself/sleep.vue
  81. +50
    -0
      src/views/myself/trajectory.scss
  82. +2203
    -0
      src/views/myself/trajectory.vue
  83. +141
    -0
      src/views/myself/week.vue
  84. +1
    -1
      vue.config.js

+ 7
- 2
package-lock.json Wyświetl plik

@@ -1,6 +1,6 @@
{
"name": "vue-h5-template",
"version": "2.1.0",
"name": "health-student",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -5378,6 +5378,11 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"js-base64": {
"version": "2.6.4",
"resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz",
"integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
},
"js-message": {
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz",


+ 2
- 1
package.json Wyświetl plik

@@ -21,7 +21,8 @@
"vue-router": "^3.5.4",
"vuex": "^3.6.2",
"dayjs": "^1.11.7",
"echarts": "^5.4.1"
"echarts": "^5.4.1",
"js-base64": "^2.5.2"
},
"devDependencies": {
"@babel/core": "^7.18.10",


+ 5
- 3
src/api/core.js Wyświetl plik

@@ -1,12 +1,14 @@
// b端的接口, 每次调用前先获取token
import axios from 'axios';
const baseUrl = process.env.VUE_APP_BASE_API.replace('webapi', 'gateway');
import { baseApi } from '@/config';
import prefix from '@/store/prefix';
const baseUrl = baseApi.replace('webapi', 'gateway');
const service = axios.create({
baseURL: baseUrl
});
service.interceptors.request.use(request => {
if (localStorage.getItem('gatewayToken')) {
request.headers.AccessToken = localStorage.getItem('gatewayToken');
if (localStorage.getItem(prefix + 'gatewayToken')) {
request.headers.AccessToken = localStorage.getItem(prefix + 'gatewayToken');
}
return request;
});


+ 77
- 0
src/assets/css/mixin.scss Wyświetl plik

@@ -1,4 +1,13 @@
// mixin
@use "sass:math";
$background: #f2f4f5;
$blue: #2599ff;
$next: #8bc6fa;
$border_color: #d1d1d1;
$green: #189b3b;
$next_green: #8ccd9d;
$red: #ff8c8c;

// 清除浮动
@mixin clearfix {
&:after {
@@ -34,3 +43,71 @@
flex-wrap: $fw;
-webkit-flex-wrap: $fw;
}
// 雪碧图路径
/* @mixin icon($spriteUrl) {
background: transparent url($spriteUrl) no-repeat;
background-size: 400px 400px;
} */
@mixin icon {
background: transparent url('~@/assets/icon.png') no-repeat;
background-size: 400px 400px;
}
@mixin bgPosition(
$spriteWidth,
$spriteHeight,
$iconWidth,
$iconHeight,
$iconX,
$iconY
) {
background-position: (
math.div($iconX ,($spriteWidth - $iconWidth)) * 100%
math.div($iconY,($spriteHeight - $iconHeight)) * 100%
);
}

@mixin icon_position($iconWidth, $iconHeight, $iconX, $iconY) {
$spriteWidth: 400;
$spriteHeight: 400;
@include bgPosition(
$spriteWidth,
$spriteHeight,
$iconWidth,
$iconHeight,
$iconX,
$iconY
);
}
@mixin border {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
top: -50%;
right: -50%;
bottom: -50%;
left: -50% !important;
border-bottom: 1px solid $border_color;
-webkit-transform: scale(.5);
transform: scale(.5);
}

@mixin colorAndFont($color, $fontSize) {
color: $color;
font-size: $fontSize + px;
}
@mixin center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin bgimg($path, $width, $height) {
background-image: $path;
background-size: $width, $height;
width: $width + px;
height: $height + px;
display: flex;
justify-content: center;
align-items: center;
}

BIN
src/assets/icon.png Wyświetl plik

Before After
Width: 400  |  Height: 400  |  Size: 39KB

BIN
src/assets/img/callLog.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 104KB

BIN
src/assets/img/drownReport.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 105KB

BIN
src/assets/img/health/blood_icon.png Wyświetl plik

Before After
Width: 32  |  Height: 38  |  Size: 2.2KB

BIN
src/assets/img/health/blood_oxygen.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 4.0KB

BIN
src/assets/img/health/bulb.png Wyświetl plik

Before After
Width: 11  |  Height: 13  |  Size: 376B

BIN
src/assets/img/health/gps.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.2KB

BIN
src/assets/img/health/gps_frequency.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.5KB

BIN
src/assets/img/health/health.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 4.8KB

BIN
src/assets/img/health/heartRate.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.4KB

BIN
src/assets/img/health/location.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.2KB

BIN
src/assets/img/health/psychological_icon.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 2.3KB

BIN
src/assets/img/health/report_ frequency.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.3KB

BIN
src/assets/img/health/rest.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.2KB

BIN
src/assets/img/health/right_more.png Wyświetl plik

Before After
Width: 35  |  Height: 35  |  Size: 2.9KB

BIN
src/assets/img/health/setting.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 4.3KB

BIN
src/assets/img/health/temperature.png Wyświetl plik

Before After
Width: 50  |  Height: 50  |  Size: 3.4KB

BIN
src/assets/img/healthy.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 105KB

BIN
src/assets/img/home/layer.png Wyświetl plik

Before After
Width: 21  |  Height: 30  |  Size: 1.1KB

BIN
src/assets/img/home/lbs_icon.png Wyświetl plik

Before After
Width: 30  |  Height: 30  |  Size: 815B

+ 6
- 0
src/assets/img/home/md-highlight_off.svg Wyświetl plik

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="35" height="35" style="border-color: rgba(0,0,0,0);border-width: bpx;border-style: undefined" filter="none">
<g>
<path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="rgba(67.065,67.065,67.065,1)"></path>
</g>
</svg>

BIN
src/assets/img/home/message.png Wyświetl plik

Before After
Width: 29  |  Height: 29  |  Size: 1.3KB

BIN
src/assets/img/home/phone.png Wyświetl plik

Before After
Width: 29  |  Height: 27  |  Size: 990B

BIN
src/assets/img/home/spread_left.png Wyświetl plik

Before After
Width: 26  |  Height: 26  |  Size: 833B

BIN
src/assets/img/home/spread_right.png Wyświetl plik

Before After
Width: 26  |  Height: 26  |  Size: 810B

BIN
src/assets/img/home/trajectory.png Wyświetl plik

Before After
Width: 27  |  Height: 30  |  Size: 1.3KB

BIN
src/assets/img/home/warning.png Wyświetl plik

Before After
Width: 30  |  Height: 26  |  Size: 1.0KB

BIN
src/assets/img/leaveDrownReport.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 105KB

BIN
src/assets/img/noWear.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 105KB

BIN
src/assets/img/phone_ record.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 606B

BIN
src/assets/img/prohibition.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 3.1KB

BIN
src/assets/img/spo.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 1.1KB

BIN
src/assets/img/tooltip-sizing.png Wyświetl plik

Before After
Width: 118  |  Height: 160  |  Size: 5.2KB

BIN
src/assets/img/wear.png Wyświetl plik

Before After
Width: 40  |  Height: 40  |  Size: 105KB

+ 40
- 0
src/common/amap.js Wyświetl plik

@@ -0,0 +1,40 @@
export default function MapLoader(isSyncLoad = false, pluginsArr = []) {
// plugin: 字符串数组[ 'AMap.Geocoder', ... ]
return new Promise((resolve, reject) => {
try {
if (window.AMap && (pluginsArr === null || pluginsArr === undefined || pluginsArr.length === 0)) {
resolve(window.AMap);
} else {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = !isSyncLoad;
script.src = 'https://webapi.amap.com/maps?v=1.4.15&callback=initAMap&key='
+ '6e4a6c39ea6d18b8dd3151baa3a7c0d5'
+ '&plugin=AMap.BezierCurveEditor'
+ (pluginsArr ? ',' + pluginsArr.join(',') : '');
script.onerror = reject;
document.head.appendChild(script);

var script1 = document.createElement('script');
script1.type = 'text/javascript';
script1.async = false;
script1.src = 'https://webapi.amap.com/ui/1.0/main.js?v=1.0.11';
script1.onerror = reject;
if (isSyncLoad) {
document.head.appendChild(script1);
}

}
window.initAMap = () => {
resolve(window.AMap);
}
// JSAPI key搭配静态安全密钥以明文设置, 详情见: https://lbs.amap.com/api/jsapi-v2/guide/abc/load
window._AMapSecurityConfig = {
securityJsCode:'6a421e1233cd12dd4899e373e11bb641',
}
} catch (e) {
console.log(e);
}

})
}

+ 246
- 0
src/common/own.js Wyświetl plik

@@ -0,0 +1,246 @@
import { Base64 } from 'js-base64';

function formatTime(date) {
let datee = date.toString();
return datee.replace(/T/g, ' ').replace(/-/g, '/');
}

function getNowFormatDate(val, type, flag) {
let i = 1 * val;
let sp = '-';
const oneDay = 24 * 60 * 60 * 1000;
let date = new Date(new Date() - -i * oneDay);
let year = date.getFullYear();
let month = date.getMonth() + 1;
let strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = '0' + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = '0' + strDate;
}
if (type == 'year') {
return year;
} else if (type == 'month') {
return year + sp + month;
} else {
if (flag) {
return year + '年' + month + '月' + strDate + '日';
}
return year + sp + month + sp + strDate;
}
}

// 将时间改为 *分钟前|*小时前|刚刚……
function translateTime(date) {
return getDateDiff(formatTime(date));
}

function getDateDiff(date) {
let minute = 1000 * 60;
let hour = minute * 60;
let day = hour * 24;
// eslint-disable-next-line no-unused-vars
let halfamonth = day * 15;
let month = day * 30;
let result = null;

var dateTimeStamp = new Date(date);
var now = new Date().getTime();
var diffValue = now - dateTimeStamp;
/* if (diffValue < 0) {
console.log('结束日期不能小于开始日期!');
console.log(`开始日期:${dateTimeStamp}结束日期:${now}`);
console.log(`参数为:${date}`);
return 'null'; // TODO 方便测试
} */
var monthC = diffValue / month;
var weekC = diffValue / (7 * day);
var dayC = diffValue / day;
var hourC = diffValue / hour;
var minC = diffValue / minute;
if (monthC >= 1) {
result = `${parseInt(monthC)}个月前`;
} else if (weekC >= 1) {
result = `${parseInt(weekC)}周前`;
} else if (dayC >= 1) {
result = `${parseInt(dayC)}天前`;
} else if (hourC >= 1) {
result = `${parseInt(hourC)}小时前`;
} else if (minC >= 1) {
result = `${parseInt(minC)}分钟前`;
} else result = '刚刚';
return result;
}

Date.prototype.Format = function (fmt) {
var o = {
'M+': this.getMonth() + 1, //月份
'd+': this.getDate(), //日
'h+': this.getHours(), //小时
'm+': this.getMinutes(), //分
's+': this.getSeconds(), //秒
'q+': Math.floor((this.getMonth() + 3) / 3), //季度
S: this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp('(' + k + ')').test(fmt))
fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
return fmt;
};

function formatnumber(value, num) {
let _value = value.toString();
let _dot = _value.indexOf('.');
let _valueLen = _value.length;
if (num == 0) {
if (_dot != -1) {
_value = _value.substring(0, _dot);
}
} else {
//如果没有小数点
if (_dot == -1) {
_value = _value + '.';
for (let i = 1; i <= num; i++) {
_value = _value + '0';
}
} else {
//有小数点,超出位数自动截取,否则补0
_value = _value.substring(0, _dot + num + 1);
for (let i = _valueLen; i <= _dot + num; i++) {
_value = _value + '0';
}
}
}
return _value;
}

function round(src, pos, type) {
//src代表要转化的值,pos表示要保留的位数
let num = Math.floor(src * Math.pow(10, pos)) / Math.pow(10, pos);
let val = type == 'string' ? formatnumber(num, pos) : parseFloat(formatnumber(num, pos));
return val;
}

/**
* 防抖使用,_type,index,item不用管,是changfield的参数
* methods: {
改变场数
changefield: _debounce(function(_type, index, item) {
do something ...
}, 200)
}
*/
// 防抖
function _debounce(fn, delay) {
// eslint-disable-next-line no-redeclare
var delay = delay || 200;
var timer;
return function () {
var th = this;
var args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
timer = null;
fn.apply(th, args);
}, delay);
};
}

// 节流
function _throttle(fn, interval) {
var last;
var timer;
// eslint-disable-next-line no-redeclare
var interval = interval || 200;
return function () {
var th = this;
var args = arguments;
var now = +new Date();
/* + 隐式类型转换,通过调用 valueOf() 获取时间戳 */
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(function () {
last = now;
fn.apply(th, args);
}, interval);
} else {
last = now;
fn.apply(th, args);
}
};
}

// base64 编码
function base64Encode(str, isURI) {
if (isURI) {
return Base64.encodeURI(str);
}
return Base64.encode(str);
}

// base64 解码
function base64Decode(str) {
return Base64.decode(str);
}

/**
* 判断是否为空
*/
function isNull(o) {
/*return o === null
|| o === undefined
|| o === ''
|| JSON.stringify(o) === '{}'
|| JSON.stringify(o) === '[]';*/
if (o === null || o === undefined || o === '') {
return true;
// eslint-disable-next-line
} else if (Array.prototype.isPrototypeOf(o) && o.length === 0) {
return true;
// eslint-disable-next-line
} else if (Object.prototype.isPrototypeOf(o) && Object.keys(o).length === 0) {
return true;
}
return false;
}

/**
* 判断是否为非空
*/
function isNotNull(o) {
return !isNull(o);
}

/**
* 清除 localStorage
* @param store 要将 $store 传进来
*/
function clearLocalStorage(store) {
try {
for (let k in store.getters) {
store.commit(k, '');
}
} catch (e) {
console.log(e);
}
}

export default {
formatTime,
getDateDiff,
getNowFormatDate,
translateTime,
formatnumber,
round,
_debounce,
_throttle,
base64Encode,
base64Decode,
isNull,
isNotNull,
clearLocalStorage
};

+ 2
- 1
src/components/NavBar.vue Wyświetl plik

@@ -8,7 +8,8 @@
:left-arrow="leftArrow"
@click-left="onClickLeft"
@click-right="onClickRight"
></van-nav-bar>
>
</van-nav-bar>
</div>
</template>



+ 103
- 1
src/components/SubmenuList.vue Wyświetl plik

@@ -21,10 +21,32 @@
</div>
</div>
<!-- <div class="footer"></div> -->
<van-dialog v-model="dialog.show" :title="dialog.title" confirm-button-text="关闭">
<template #default>
<div class="dialog">
<van-cell value="重启" border @click="onClick(3)">
<!-- 使用 title 插槽来自定义标题 -->
<!-- <template #right-icon>
<van-icon name="search" class="search-icon" />
</template> -->
</van-cell>
<van-cell value="关机" border @click="onClick(3)">
<!-- 使用 title 插槽来自定义标题 -->
<!-- <template #right-icon>
<van-icon name="search" class="search-icon" />
</template> -->
</van-cell>
</div>
</template>
</van-dialog>
</div>
</template>

<script>
import { VersionModel } from '@/config/models';
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
import APICommand from '@/api/command';
export default {
name: 'SubmenuList',
props: {
@@ -42,7 +64,12 @@ export default {
}
},
data() {
return {};
return {
dialog: {
title: '',
show: false
}
};
},
created() {},
mounted() {},
@@ -54,8 +81,75 @@ export default {
this.$router.push({
name: `${item.routerName}`
});
} else if (item.showType === 'newDialog') {
switch (item.routerName) {
case 'remote':
this.dialog.show = true;
this.dialog.title = '远程控制';
break;
case 'version':
this.$dialog.confirm({
title: '当前版本信息',
message: `${VersionModel}`,
showCancelButton: false
});
break;
case 'logout':
this.$dialog
.confirm({
title: '确定要退出登录?',
showCancelButton: true
})
.then(() => {})
.catch(() => {});
break;
default:
break;
}
}
} else {
this.$dialog.confirm({
title: '提示',
message: `功能开发中`,
showCancelButton: false
});
}
},
onClick(model) {
let val = null;
let code = '0005'; // 定位0002 || 控制0005
val = Number(model);
this.sendCommand(code, JSON.stringify(val));
},
sendCommand(cmdCode, cmdValue) {
ToastService.loading({
message: '操作中'
});
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
let item = res.data;
if (item.stateCode == 1) {
ToastService.success({
message: '操作成功'
});
} else if (cmdCode === '0005') {
DialogService.confirm({ title: '设备离线,操作失败' });
} else {
DialogService.confirm({ title: '操作失败', message: '设备不在线' });
}
})
.catch(() => {
ToastService.clear();
})
.finally(() => {
ToastService.clear();
});
}
}
};
@@ -111,6 +205,14 @@ export default {
}
}
}
.dialog {
height: 300px;
padding: 0 80px;
@include flexbox(center, center, column, wrap);
.van-cell {
border-bottom: 1px solid $border_color;
}
}
}
/* @import url(); 引入css类 */
</style>

+ 34
- 0
src/components/overlay-loading/overlay-loading.vue Wyświetl plik

@@ -0,0 +1,34 @@
<template>
<van-overlay :show="showOverlay" z-index="600" class-name="overlay-loading">
<div class="loading-container">
<van-loading type="circular" size="15vw"/>
</div>
</van-overlay>
</template>

<script>
export default {
props: {
showOverlay: {
type: Boolean,
default: false,
},
},
data() {
return {}
},
methods: {},
mounted() {
},
}
</script>
<style lang="scss">
.overlay-loading {
.loading-container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

+ 2
- 2
src/config/env.development.js Wyświetl plik

@@ -1,8 +1,8 @@
// 本地环境配置
module.exports = {
title: '健康同学',
baseUrl: 'https://id.ssjlai.com/', // 项目地址
baseApi: 'https://id.ssjlai.com/', // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
baseUrl: 'https://id.ssjlai.com/webapi', // 项目地址
baseApi: 'https://id.ssjlai.com/webapi', // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
APPID: 'xxx',
APPSECRET: 'xxx',
$cdn: 'https://www.sunniejs.cn/static'


+ 2
- 2
src/config/env.production.js Wyświetl plik

@@ -1,8 +1,8 @@
// 正式
module.exports = {
title: '健康同学',
baseUrl: 'https://ai.ssjlai.com/', // 正式项目地址
baseApi: 'https://ai.ssjlai.com/', // 正式api请求地址
baseUrl: 'https://ai.ssjlai.com/webapi', // 正式项目地址
baseApi: 'https://ai.ssjlai.com/webapi', // 正式api请求地址
APPID: 'xxx',
APPSECRET: 'xxx',
$cdn: 'https://www.sunniejs.cn/static'


+ 2
- 2
src/config/env.test.js Wyświetl plik

@@ -1,7 +1,7 @@
module.exports = {
title: '健康同学',
baseUrl: 'https://id.ssjlai.com/', // 测试项目地址
baseApi: 'https://id.ssjlai.com/', // 测试api请求地址
baseUrl: 'https://id.ssjlai.com/webapi', // 测试项目地址
baseApi: 'https://id.ssjlai.com/webapi', // 测试api请求地址
APPID: 'xxx',
APPSECRET: 'xxx',
$cdn: 'https://www.sunniejs.cn/static'


+ 7
- 0
src/config/models.js Wyświetl plik

@@ -85,3 +85,10 @@ export const WxOcrServiceId = {
test: 'wx79ac3de8be320b71',
development: 'wx79ac3de8be320b71'
};
export const ErrorAMapMsgModel = {
OUT_OF_SERVICE: 'OUT_OF_SERVICE', // 使用路径规划服务接口时可能出现该问题,规划点(包括起点、终点、途经点)不在中国陆地范围内
NO_ROADS_NEARBY: 'NO_ROADS_NEARBY', // 使用路径规划服务接口时可能出现该问题,划点(起点、终点、途经点)附近搜不到路
ROUTE_FAIL: 'ROUTE_FAIL', // 使用路径规划服务接口时可能出现该问题,路线计算失败,通常是由于道路连通关系导致
OVER_DIRECTION_RANGE: 'OVER_DIRECTION_RANGE', // 使用路径规划服务接口时可能出现该问题,路线计算失败,通常是由于道路起点和终点距离过长导致
NO_DATA: 'NO_DATA' // 此错误在服务接口status='complete'时的result.info值出现,故判断时需要注意(与以上的错误不一样,status!=='complete')
};

+ 5
- 0
src/main.js Wyświetl plik

@@ -7,10 +7,12 @@ import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store/index';
import request from './config/request';
// 设置 js中可以访问 $cdn
import { $cdn } from '@/config';
Vue.prototype.$cdn = $cdn;
import dayjs from 'dayjs';
import own from '@/common/own.js';
// 引入echarts
import * as echarts from 'echarts';
// 全局引入按需引入UI库 vant
@@ -22,6 +24,9 @@ import 'amfe-flexible';
Vue.prototype.$dayjs = dayjs;
Vue.prototype.$echarts = echarts;
Vue.prototype.$store = store;
Vue.prototype.$own = own;
Vue.prototype.$axios = request;
Vue.prototype.$green = '#189b3b';

// filters
import './filters';


+ 156
- 0
src/router/router.config.js Wyświetl plik

@@ -59,6 +59,162 @@ export const constantRouterMap = [
name: 'addFamilyNumber',
component: () => import('@/views/myself/addFamilyNumber'),
meta: { title: '增加亲情号码', keepAlive: false }
},
{
path: '/sendMessage',
name: 'sendMessage',
component: () => import('@/views/myself/sendMessage'),
meta: { title: '留言', keepAlive: false }
},
{
path: '/callList',
name: 'callList',
component: () => import('@/views/myself/callList'),
meta: { title: '通话记录', keepAlive: false }
},
{
path: '/prohibit',
name: 'prohibit',
component: () => import('@/views/myself/prohibit'),
meta: { title: '上课禁止时段', keepAlive: false }
},
{
path: '/setupProhibitPeriod',
name: 'setupProhibitPeriod',
component: () => import('@/views/myself/setupProhibitPeriod'),
meta: { title: '设置上课禁止时段', keepAlive: false }
},
{
path: '/clock',
name: 'clock',
component: () => import('@/views/myself/clock'),
meta: { title: '闹钟', keepAlive: false }
},
{
path: '/setupClockPeriod',
name: 'setupClockPeriod',
component: () => import('@/views/myself/setupClockPeriod'),
meta: { title: '设置闹钟', keepAlive: false }
},
{
path: '/changePayPassword',
name: 'changePayPassword',
component: () => import('@/views/myself/changePayPassword'),
meta: { title: '修改支付密码', keepAlive: false }
},
{
path: '/messageList',
name: 'messageList',
component: () => import('@/views/myself/messageList'),
meta: { title: '短信代收', keepAlive: false }
},
{
path: '/management',
name: 'management',
component: () => import('@/views/myself/management'),
meta: { title: '亲友关注', keepAlive: false }
},
{
path: '/replace',
name: 'replace',
component: () => import('@/views/myself/replace'),
meta: { title: '管理员转让', keepAlive: false }
},
{
path: '/sleep',
name: 'sleep',
component: () => import('@/views/myself/sleep'),
meta: { title: '休眠设置', keepAlive: false }
},
{
path: '/watchSetting',
name: 'watchSetting',
component: () => import('@/views/myself/deviceSetting/settingIndex'),
meta: { title: '参数设置', keepAlive: false }
},
{
path: '/sceneMode',
name: 'sceneMode',
component: () => import('@/views/myself/deviceSetting/sceneMode'),
meta: { title: '场景模式', keepAlive: false }
},
{
path: '/locationMonitor',
name: 'locationMonitor',
component: () => import('@/views/myself/deviceSetting/locationMonitor'),
meta: { title: '定位监测', keepAlive: false }
},
{
path: '/dangerAreaMonitor',
name: 'dangerAreaMonitor',
component: () => import('@/views/myself/deviceSetting/dangerAreaMonitor'),
meta: { title: '危险区域监测', keepAlive: false }
},
{
path: '/drownWhiteList',
name: 'drownWhiteList',
component: () => import('@/views/myself/deviceSetting/drownWhiteList'),
meta: { title: '免告警水域', keepAlive: false }
},
{
path: '/healthMonitor',
name: 'healthMonitor',
component: () => import('@/views/myself/deviceSetting/healthMonitor'),
meta: { title: '健康监测', keepAlive: false }
},
{
path: '/blood',
name: 'blood',
component: () => import('@/views/myself/deviceSetting/blood'),
meta: { title: '血压监测', keepAlive: false }
},
{
path: '/psychologicalSetting',
name: 'psychologicalSetting',
component: () => import('@/views/myself/deviceSetting/psychologicalSetting'),
meta: { title: '心理监测', keepAlive: false }
},
{
path: '/personInfos',
name: 'personInfos',
component: () => import('@/views/myself/deviceSetting/personInfos'),
meta: { title: '个人资料设置', keepAlive: false }
},
{
path: '/wearMonitor',
name: 'wearMonitor',
component: () => import('@/views/myself/deviceSetting/wearMonitor'),
meta: { title: '佩戴监测', keepAlive: false }
},
{
path: '/setupSleepPeriod',
name: 'setupSleepPeriod',
component: () => import('@/views/myself/setupSleepPeriod'),
meta: { title: '休眠设置', keepAlive: false }
},
{
path: '/help',
name: 'help',
component: () => import('@/views/myself/help'),
meta: { title: '常见问题', keepAlive: false }
},
{
path: '/location',
name: 'location',
component: () => import('@/views/myself/location'),
meta: { title: '定位', keepAlive: false }
},
{
path: '/trajectory',
name: 'trajectory',
component: () => import('@/views/myself/trajectory'),
meta: { title: '轨迹', keepAlive: false }
},
{
path: '/news',
name: 'news',
component: () => import('@/views/myself/news/news'),
meta: { title: '消息', keepAlive: false }
}
]
}


+ 1
- 1
src/services/dialog-service.js Wyświetl plik

@@ -12,7 +12,7 @@ let DialogService = {
cancelButtonText
}) {
return Dialog.confirm({
title: title || '信息提示',
title: title || '提示',
message: message || '',
className: className || 'device_confirm',
showCancelButton: showCancelButton || false,


+ 2
- 2
src/views/myself/addFamilyNumber.vue Wyświetl plik

@@ -532,8 +532,8 @@ export default {

<style lang="scss" scoped>
.family_save {
width: 100px;
line-height: 60px;
width: 80px;
line-height: 40px;
background: #1989fa;
color: #fff;
font-size: 30px;


+ 118
- 0
src/views/myself/callList.vue Wyświetl plik

@@ -0,0 +1,118 @@
<template>
<div class="call-list">
<van-nav-bar title="通话清单" left-arrow :border="true" @click-left="onNavBack" />
<div class="newsNotData" v-show="list.length == 0">您暂时还没有通话记录~</div>
<van-list
v-model="loading"
class="call-list-container"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<div v-for="(item, index) in list" :key="index" :title="item" class="call-list">
<van-row type="flex" justify="center" class="date-row">
<van-col span="12">
<!--<p class="call-list-date">{{item.dDateTime}}</p>-->
</van-col>
</van-row>
<div class="call-list-content">
<van-row type="flex" justify="center">
<van-col span="23" offset="1">
<p class="call-list-record">通话记录</p>
<p class="call-list-detail">{{ item.dDateTime }}</p>
<p class="call-list-detail">{{ item.sCallLog }}</p>
</van-col>
</van-row>
</div>
</div>
</van-list>
</div>
</template>

<script>
import ToastService from '../../services/toast-service';
import APIDevice from '../../api/device';
export default {
data() {
return {
loading: false,
finished: false,
list: []
};
},
methods: {
onLoad() {
this.loading = false;
},
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},

getCallList() {
/* let url = `/api/DeviceCommunication/GetCallLogList`;
let jsonData = { deviceId: this.$store.getters.deviceId }; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APIDevice.getCallLogList({
deviceId: this.$route.query.deviceId ? this.$route.query.deviceId : this.$store.getters.deviceId
})
.then(res => {
this.list = res.data.callLogList || [];
})
.catch(e => console.log(e))
.finally(() => ToastService.clear());
}
},

created() {
this.getCallList();
}
};
</script>

<style lang="scss" scoped>
.call-list {
.newsNotData {
height: calc(100vh - 160px);
@include flexbox(center, center, column, nowrap);
font-size: 32px;
}
.call-list-container {
padding: 30px;
height: calc(100vh - 160px);
overflow: scroll;
}
.call-list-date {
color: #999;
font-size: 28px;
text-align: center;
margin-bottom: 40px;
}
.call-list-content {
background-color: #f0f0f0ef;
padding: 20px;
border-radius: 30px;
margin-top: 20px;
.call-list-record {
color: #313131;
font-size: 28px;
margin-bottom: 40px;
}
.call-list-detail {
color: #313131;
font-size: 30px;
}
}
.record {
color: #313131;
font-size: 30px;
}
.detail {
color: #666;
font-size: 28px;
}
}
</style>

+ 2
- 2
src/views/myself/changeFamilyNumber.vue Wyświetl plik

@@ -573,8 +573,8 @@ export default {
padding: 0 10px;
}
.save {
width: 100px;
line-height: 60px;
width: 80px;
line-height: 40px;
background: #1989fa;
color: #fff;
font-size: 30px;


+ 235
- 0
src/views/myself/changePayPassword.vue Wyświetl plik

@@ -0,0 +1,235 @@
<template>
<div class="forgetPaw">
<van-nav-bar title="修改支付密码" left-arrow @click-left="onNavBack" />
<ul class="con ul mt30">
<li>
<span class>支付密码</span>
<label>
<!-- 1. 把e - + 换空;2. 把数字之外的值换空; 3.空格换空 -->
<input
type="tel"
placeholder="请填写新的支付密码"
maxlength="4"
oninput="value=value.replace(/e|-|\+/ig,'').replace(/[^0-9]/ig,'').replace(/\s+/g,'')"
v-model.trim="password"
/>
</label>
</li>
</ul>

<div :class="['next', { blue: activeColor }]" @click="onSubmit">修改</div>
</div>
</template>

<script>
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
import APICommand from '@/api/command';
export default {
data() {
return {
password: ''
};
},
watch: {
password() {
if (this.password.length > 4) {
this.password = this.password.slice(0, 4);
}
}
},
methods: {
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
// 修改
onSubmit() {
//判断是否是纯数字并且四位
let reg = /\d{4,}$/;
if (this.password !== '' && this.password.length === 4 && reg.test(this.password)) {
DialogService.confirm({
title: '提示',
message: '真的修改支付密码吗?',
showCancelButton: true
})
.then(() => {
this.changePayPassword();
})
.catch(() => {});
} else {
DialogService.confirm({
title: '温馨提示',
message: '支付密码只能是四位纯数字,请您重新输入。'
});
}
},
// 修改支付密码
changePayPassword() {
// todo 调取修改支付密码的接口
ToastService.loading({ message: '修改中...' });
let reqBody = {
imei: this.$route.query.code,
text: this.password
};
APICommand.SetPayPassword(reqBody)
.then(res => {
let data = res.data;
if (data.stateCode === 1) {
ToastService.success({
message: '修改成功',
duration: 1500
});
setTimeout(() => {
this.$router.push({ name: 'device' });
}, 2000);
} else {
DialogService.confirm({
title: '提示',
message: data.message
});
}
})
.catch(error => {
console.log('error::', error);
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
}, 1500);
});
}
},
computed: {
activeColor() {
return this.password !== '';
}
}
};
</script>

<style lang="scss" scoped>
.forgetPaw {
height: 100vh;
background: $background;

.title {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 0 px2rem(40);
height: px2rem(120);
color: #999;
font-size: px2rem(24);

span {
color: $green;
}
}

.con {
display: flex;
align-items: center;
padding: 0 40px;
height: 88px;
background: #fff;

&.ul {
flex-flow: column;
height: auto;
}

li {
position: relative;
width: 100%;
display: flex;
align-items: center;
height: 88px;
border-bottom: 1px solid $border_color;

&:last-child {
border: none;
}

i {
position: absolute;
right: 25px;
width: 32px;
height: 32px;
/* background: url(./img/eyes-close.png) center no-repeat; */
background-size: 32px 32px;

&.on {
/* background: url(./img/eyes-open.png) center no-repeat; */
background-size: 32px 32px;
}
}
}

span {
width: 150px;
color: #333333;
font-size: 28px;

&.border_right {
width: 115px;
border-right: 1px solid #b3b4b4;
}
}

label {
input {
display: flex;
align-items: center;
width: 340px;
height: 60px;
color: #333;
font-size: 28px;
text-indent: 0;

&.ti50 {
text-indent: 50px;
}

&::-webkit-input-placeholder {
color: #e1e4e9;
}
}
}

a {
flex: auto;
color: #333333;
font-size: 28px;

&:before {
content: ' ';
width: 0;
height: 30px;
margin-right: 20px;
border: 1px solid #b3b4b4;
}
}
}

.next {
@include flexbox(center, center, column, nowrap);
margin: 230px auto 0;
width: 550px;
height: 80px;
border-radius: 10px;
background: $next;
color: #fff;
font-size: 36px;

&.blue {
background: $green;
}

&.res {
margin: 140px auto 0;
}
}
}
</style>
>

+ 225
- 0
src/views/myself/clock.vue Wyświetl plik

@@ -0,0 +1,225 @@
<template>
<div class="clock" :style="{ background: listData.length == 0 ? '#fff ' : '#f2f4f5' }">
<van-nav-bar title="设置闹钟" left-arrow :border="true" @click-left="onNavBack">
<van-icon name="plus" slot="right" id="plus-icon" @click="onAddClick" />
</van-nav-bar>
<div class="clock-list-container" v-show="isShowPage">
<van-cell v-for="(item, index) in listData" :key="`prohibit_${index}`" class="clock">
<van-swipe-cell>
<div class="area">
<div :class="[{ active: item.Active }, 'left']" @click="onListClick(item.Id)">
<div class="title">{{ item.StartTime }}</div>
<div class="date">
<span v-for="(data, index) in formatWeekdays(item.Weekdays)" :key="`date_${index}`">{{ data }}</span>
</div>
</div>
<van-switch :value="item.Active == 1" @input="onInput($event, item.Id)" :active-color="$green" />
</div>
<template slot="right">
<van-button square type="danger" text="删除" @click="onClose(item.Id)" />
</template>
</van-swipe-cell>
</van-cell>
<div class="noData_img" v-show="listData.length == 0">您还没有给定位卡设置闹钟,快去添加吧~</div>
</div>
</div>
</template>

<script>
import DialogService from '../../services/dialog-service';
import { DeviceCommandModel } from '../../config/models';
import ToastService from '../../services/toast-service';
import APICommand from '@/api/command';
export default {
data() {
return {
listData: [],
serialNo: '',
isShowPage: false
};
},
methods: {
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
onAddClick() {
this.$router.push({
name: 'setupClockPeriod',
query: { code: this.$route.query.code }
});
},
onInput(checked, id) {
this.listData.map(val => {
console.log(val.Active);
if (val.Id == id) {
val.Active = checked ? 1 : 0;
}
return val;
});
let cmdCode = DeviceCommandModel.clock;
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
// console.log(222);
},
onListClick(id) {
this.$router.push({
name: 'setupClockPeriod',
query: { code: this.$route.query.code, id }
});
},

//滑动单元格
onClose(id) {
this.listData.some((val, i) => {
if (val.Id == id) {
this.listData.splice(i, 1);
return true;
}
});
let cmdCode = DeviceCommandModel.clock;
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
},

//获取信息
getCommandList() {
ToastService.loading();
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId };
this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
if (res.data.stateCode) {
ToastService.clear();
let item = res.data;
let cmdValue = item.items.filter(val => val.cmdCode == DeviceCommandModel.clock);
if (cmdValue.length) {
let parseValue = JSON.parse(cmdValue[0].cmdValue);
this.listData = parseValue.Items;
}
} else {
DialogService.confirm({ title: res.data.message });
}
this.isShowPage = true;
})
.catch(() => {
ToastService.clear();
this.isShowPage = true;
})
.finally(() => {
ToastService.clear();
});
},
//处理方面的
formatWeekdays(str) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
switch (Number(val)) {
case 1:
newArr.push('周一 ');
break;
case 2:
newArr.push('周二 ');
break;
case 3:
newArr.push('周三 ');
break;
case 4:
newArr.push('周四 ');
break;
case 5:
newArr.push('周五 ');
break;
case 6:
newArr.push('周六 ');
break;
case 7:
newArr.push('周日 ');
break;
default:
newArr = [];
}
});
return newArr;
},
//提交
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
}; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
ToastService.clear();
let item = res.data;
if (item.stateCode == 1) {
ToastService.success({ message: '操作成功' });
} else {
DialogService.confirm({ title: '操作失败,请重新设置' });
}
})
.catch(() => {
ToastService.clear();
});
}
},
created() {
this.getCommandList();
}
};
</script>

<style lang="scss" scoped>
.clock {
.clock-list-container {
height: calc(100vh - 160px);
overflow: scroll;
.area {
padding: 0 30px;
height: 100%;
margin-bottom: 50px;
display: flex;
justify-content: space-between;
align-items: center;
.title {
font-size: 32px;
}
}
}
}

.noData_img {
margin: 200px auto 0;
width: 640px;
height: 238px;
/* background: url(../../assets/img/uyqk-noData.png) center no-repeat; */
background-size: 336px 238px;
display: flex;
justify-content: center;
align-items: flex-end;
font-size: 28px;
}
</style>

+ 588
- 0
src/views/myself/deviceSetting/blood.vue Wyświetl plik

@@ -0,0 +1,588 @@
<template>
<div class="location-monitor-container">
<!-- nav -->
<div class="nav-bar">
<van-nav-bar title="血压监测" left-text="返回" @click-left="onNavBack" left-arrow>
<template #right>
<!-- <div class="setupClock_save" @click="onSubmit">保存</div> -->
<van-button type="primary" @click="onSubmit" size="small">保存</van-button>
</template>
</van-nav-bar>
</div>
<!-- main -->
<div class="main" v-if="isLoading">
<!-- 血压 -->
<div class="list">
<div class="item" v-show="true">
<div class="left">
<span class="title">开启血压监测:</span>
</div>
<div class="right">
<!-- <img :src="rightIcon" alt=""> -->
<van-switch v-model="bloodConfig.bloodPressenabled" :active-color="$green" />
</div>
</div>

<div class="item left-gray" v-show="bloodConfig.bloodPressenabled">
<div class="left">
<span class="title gray">检测周期:</span>
</div>
<div class="right" @click="onClick('bloodPressinteval')">
<span>{{ formatInteval(bloodConfig.bloodPressinteval) }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item left-gray" v-show="bloodConfig.bloodPressenabled">
<div class="left">
<span class="title gray">告警阈值-收缩压:</span>
</div>
<div class="right" @click="onClick('systolicmaxvalue')">
<span>{{ bloodConfig.systolicmaxvalue }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>
<div class="item alarmType left-gray" v-show="bloodConfig.bloodPressenabled">
<div class="left">
<span class="title gray">告警方式:</span>
</div>
<div class="right">
<div class="checkbox-group">
<van-checkbox
name="bloodPressvibrateenabled"
v-model="bloodConfig.bloodPressvibrateenabled"
shape="square"
direction="horizontal"
>震动</van-checkbox
>
<van-checkbox
name="bloodPresslcdenabled"
v-model="bloodConfig.bloodPresslcdenabled"
shape="square"
direction="horizontal"
>亮屏</van-checkbox
>
</div>
</div>
</div>
<div class="item" v-show="false">
<div class="left">
<span class="title">修改登记信息</span>
</div>
<div class="right" @click="onUpdateInfos()">
<span>修改</span>
<img :src="rightIcon" alt="" />
</div>
</div>
</div>
</div>

<!-- 弹窗 -->
<van-dialog v-model="dialog.isDialogshow" show-cancel-button cancel-button-text="返回" :show-confirm-button="false">
<template #title>
<div class="title">
<span>设置</span>
</div>
</template>
<template #default>
<div class="dialog-container">
<div class="selectConfirm">
<div class="con">
<van-cell v-for="(item, index) in dialog.confirmData" :key="`selectVPT${index}`" @click="onSelect(item)">
<div class="text">
<div v-html="item.text"></div>
</div>
<em :class="['circle', { on: selectConfirmActive == index }]"></em>
</van-cell>
</div>
</div>
</div>
</template>
</van-dialog>
</div>
</template>

<script>
import ToastService from '@/services/toast-service';
import DialogService from '@/services/dialog-service';
import APIHealthy from '@/api/heathly';
import APIDevice from '@/api/device';
import { isNull } from '@/services/utils-service';
export default {
name: '',
data() {
return {
rightIcon: require('../../../assets/img/health/right_more.png'),
checked: false,
sampleinteval: '', //上报频率-定位检测
temperatureAlarmType: ['temperaturevibrateenabled', 'temperaturelcdenabled', 'temperaturereportenabled'], //体温告警方式
heartrateAlarmType: ['heartratevibrateenabled', 'heartratelcdenabled', 'heartratereportenabled'], //心率
spo2AlarmType: ['spo2vibrateenabled', 'spo2lcdenabled', 'spo2reportenabled'], //血氧
dialog: {
isDialogshow: false,
title: '上报频率',
confirmData: []
},
bloodConfig: {
imei: '',
bloodPressenabled: 0, //血压使能 0禁用 1启用
bloodPressinteval: 360, //血压检测周期,单位分钟,最小10分钟,最大1400分钟,默认360分钟。设置时以10分钟为颗粒度
systolicminvalue: 0, //血压收缩压告警的最小值,
systolicmaxvalue: 140, //血压收缩压告警的最大值,
diastolicminvalue: 0, //血压舒张压告警的最小值
diastolicmaxvalue: 0, //血压舒张压告警的最大值
bloodPressvibrateenabled: 0, //血压异常时是否震动 0禁用 1启用
bloodPresslcdenabled: 0, //血压异常时是否亮屏 0禁用 1启用
bloodPressreportenabled: 1 //血压异常时是否上报数据 0禁用 1启用
},
// todo 以下这些弹窗列表可以用函数生成
// 检测周期时间数据
// 15、30、60、120
monitorList: [
{
text: '10分钟',
model: 6,
checked: false,
value: 10
},
{
text: '15分钟',
model: 0,
checked: false,
value: 15
},
{
text: '30分钟',
model: 1,
checked: false,
value: 30
},
{
text: '60分钟',
model: 2,
checked: false,
value: 60
},
/* {
text: "120分钟",
model: 3,
checked: false,
value: 120
}, */
{
text: '6小时',
model: 4,
checked: false,
value: 360
},
{
text: '8小时',
model: 5,
checked: false,
value: 480
}
],
//血压弹窗收缩压数据
bloodMaxList: [
{
text: '120',
model: 3,
checked: false,
className: 'circle',
value: 120,
name: '血压监测'
},
{
text: '140',
model: 0,
checked: false,
className: 'circle',
value: 140,
name: '血压监测'
},
{
text: '160',
model: 1,
checked: false,
className: 'circle',
value: 160,
name: '血压监测'
},
{
text: '180',
model: 2,
checked: false,
className: 'circle',
value: 180,
name: '血压监测'
}
],
//血压弹窗舒张值上限数据
bloodMinList: [
{
text: '90',
model: 0,
checked: false,
className: 'circle',
value: 90,
name: '血压监测'
},
{
text: '100',
model: 1,
checked: false,
className: 'circle',
value: 100,
name: '血压监测'
},
{
text: '110',
model: 2,
checked: false,
className: 'circle',
value: 110,
name: '血压监测'
}
],
selectConfirmActive: 0,
currentDiallogName: '',
isRegisterBlood: null, //是否已经登记个人信息
isSetAgeAgain: null, //是否需要重新设置年龄
isLoading: false
};
},
computed: {
imei() {
return this.$store.getters.serialNo;
},
watchRole() {
return this.$store.getters.watchRole;
}
},
mounted() {
this.getPersonData();
this.getBloodConfig();
},
methods: {
onNavBack() {
let fromRouter = this.$route.query.from;
this.$router.push({
name: fromRouter ? fromRouter : 'watchSetting'
});
},
onSubmit() {
ToastService.loading({ message: '设置中' });
/* if(!this.isRegisterBlood) {
return DialogService.confirm({
title: '信息提示',
message: '使用血压监测功能前需要登记使用者信息,是否前往登记?',
showCancelButton: true
}).then(() => {
this.$router.push({
name: 'registeUserInfos',
query: {
from: 'blood'
}
});
}).catch(() =>{})
} */ /* else if(this.isSetAgeAgain) {
// 2023.06.26 需求取消 小于16岁年龄限制
return DialogService.confirm({
title: '信息提示',
message: '使用血压监测功能年龄最小需要大于16岁,是否需要前往登记?',
showCancelButton: true
}).then(() => {
this.$router.push({
name: 'registeUserInfos',
query: {
from: 'blood'
}
});
}).catch(() =>{})
} */
let reqBody = { ...this.bloodConfig };
Object.values(this.bloodConfig).filter((item, index) => {
if (typeof item === 'boolean') {
item = item === false ? 0 : 1;
reqBody[Object.keys(this.bloodConfig)[index]] = item;
} else {
reqBody[Object.keys(this.bloodConfig)[index]] = item;
}
});
reqBody.imei = this.imei;
console.log('保存的数据', reqBody);
APIHealthy.setBloodPressConfig(reqBody)
.then(res => {
if (res.data.stateCode === 1) {
ToastService.success({ message: '设置成功' });
let fromRouter = this.$route.query.from;
setTimeout(() => {
this.$router.push({
name: fromRouter ? fromRouter : 'watchSetting'
});
}, 1500);
} else {
DialogService.confirm({
title: '设置失败',
message: `${res.data.message}`
});
}
})
.catch(e => {
DialogService.confirm({
title: '设置失败',
message: `${e.message}`
});
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
}, 1500);
});
},
onSelect(data) {
this.bloodConfig[this.currentDiallogName] = data.value;
this.selectConfirmActive = data.model;
this.dialog.isDialogshow = false;
},
onClick(name) {
this.currentDiallogName = name;
this.dialog.confirmData = [];
const intevalList = ['temperatureinteval', 'spo2inteval', 'heartrateinteval', 'bloodPressinteval'];
if (intevalList.includes(name)) {
this.dialog.confirmData = this.monitorList;
} else if (name === 'systolicmaxvalue') {
// 血压-收缩压
this.dialog.confirmData = this.bloodMaxList;
} else if (name === 'bloodminvalue') {
// 血压-舒张压
this.dialog.confirmData = this.bloodMinList;
}
let seclectIndex = this.dialog.confirmData.findIndex(item => {
return item.value === this.bloodConfig[name];
});
this.selectConfirmActive = seclectIndex;
this.dialog.isDialogshow = true;
},
getResult(number1, number2) {
const result = parseInt(number1) / parseInt(number2);
return result.toString().indexOf('.') != -1 ? parseInt(result).toFixed(2).slice(0, 1) : result;
},
getPersonData() {
APIDevice.getPersonInfo({
userId: this.$store.getters.userId,
deviceId: this.$store.getters.deviceId
})
.then(res => {
let data = res.data;
if (isNull(data.gender) || data.height === 0 || data.weight === 0 || isNull(data.bornDate)) {
this.isRegisterBlood = false;
// 未进行信息登记,无法使用血压周期性下发功能
// 2023.08.04 血压个人资料不完整,跳转个人信息等级页面
setTimeout(() => {
this.$router.push({
name: 'registeUserInfos',
query: {
from: 'blood',
backRouter: 'watchSetting'
}
});
}, 1500);
} else {
// 2023.06.26 需求取消 小于16岁年龄限制
/* if(isNotNull(data.age)) {
if(Number(data.age) < 16) {
// 血压限制 大于 >16,需要重新设置年龄
this.isSetAgeAgain = true;
}
} */
this.isRegisterBlood = true;
}
})
.catch(e => {
console.log('e', e);
DialogService.confirm({
message: `${e.message}`
});
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
this.isLoading = true;
}, 1500);
});
},
getBloodConfig() {
ToastService.loading({ message: '数据加载中' });
APIHealthy.getBloodPressConfig(this.imei)
.then(res => {
let data = res.data.data;
if (data) {
let bloodConfig = data;
this.bloodConfig.bloodPressenabled = bloodConfig.bloodPressenabled === 1;
this.bloodConfig.bloodPressinteval = bloodConfig.bloodPressinteval;
this.bloodConfig.systolicminvalue = bloodConfig.systolicminvalue;
this.bloodConfig.systolicmaxvalue = bloodConfig.systolicmaxvalue;
this.bloodConfig.diastolicminvalue = bloodConfig.diastolicminvalue;
this.bloodConfig.diastolicmaxvalue = bloodConfig.diastolicmaxvalue;
this.bloodConfig.bloodPressvibrateenabled = bloodConfig.bloodPressvibrateenabled === 1;
this.bloodConfig.bloodPresslcdenabled = bloodConfig.bloodPresslcdenabled === 1;
this.bloodConfig.bloodPressreportenabled = bloodConfig.bloodPressreportenabled === 1;
} else {
//1 是学生 2是老人
this.bloodConfig.systolicmaxvalue = this.watchRole === 1 ? 120 : 140;
this.bloodConfig.bloodPressinteval = this.watchRole === 1 ? 360 : 60;
}
ToastService.success({ message: '数据加载完成' });
})
.catch(e => {
console.log('e', e);
ToastService.clear();
DialogService.confirm({
message: `${e.message}`
});
});
},
onUpdateInfos() {
this.$router.push({
name: 'registeUserInfos',
query: {
from: 'blood'
}
});
},
// 格式化某些特殊参数值的时间显示方式
formatInteval(value) {
return value >= 360 ? value / 60 + '小时' : value + '分钟';
}
}
};
</script>

<style scoped lang="scss">
.location-monitor-container {
height: 100vh;
overflow: hidden;
/* padding: 0 20px; */
.nav-bar {
height: 100px;
padding: 0 20px;
}
.main {
height: calc(100vh - 160px);
background-color: $background;
padding: 20px;
overflow: scroll;
.list {
height: auto;
background-color: #fff;
border-radius: 8px;
margin-bottom: 20px;
.item {
height: auto;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #e5e5e5;
.left {
@include center();
span {
color: #282828;
font-size: 32px;
}
.title {
font-weight: 450;
&.gray {
color: gray;
}
}
}
.right {
/* width: 60%; */
@include center();
font-size: 32px;
img {
height: 35px;
width: 35px;
}
span {
font-size: 32px;
margin-right: 10px;
color: #aaaaaa;
}
.checkbox-group {
@include center();
.van-checkbox {
padding: 5px;
}
}
}
&.left-gray {
padding-left: 30px;
color: gray;
}
&.alarmType {
height: 180px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
.left {
}
.right {
margin-left: 40px;
width: 60%;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
}
}
}
}
.title {
font-size: 32px;
}
.selectConfirm {
padding: 0;
.con {
.van-cell {
height: 60px;
.van-cell__value {
em {
font-style: normal;
position: absolute;
top: 0;
right: 0;
@include colorAndFont(#999, 24);
&.circle {
width: 20px;
height: 20px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;

&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 14px;
height: 14px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
}
}
}
</style>

+ 1398
- 0
src/views/myself/deviceSetting/dangerAreaMonitor.vue
Plik diff jest za duży
Wyświetl plik


+ 199
- 0
src/views/myself/deviceSetting/drownWhiteList.vue Wyświetl plik

@@ -0,0 +1,199 @@
<!--
* @Date: 2023-05-05 10:07:58
* @LastEditors: JinxChen
* @LastEditTime: 2023-05-20 10:57:51
* @FilePath: \ParentWeb\src\views\device\watchSetting\drownWhiteList.vue
* @description:
-->
<template>
<div class="drown-white-list">
<van-nav-bar title="免告警水域" :border="true" left-arrow @click-left="onNavBack" />
<div class="main" v-show="isPageShow">
<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 APIAlarm from '@/api/core';
import { isNotNull } from '@/services/utils-service';
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
export default {
name: '',
data() {
return {
date: new Date().Format('yyyy-MM-dd'),
bloodIcon: require('../../../assets/img/health/blood_icon.png'),
drownList: [],
isPageShow: false
};
},
computed: {
imei() {
return this.$store.getters.serialNo;
}
},
created() {
this.getAuth();
this.getDrownReportFilterQuery();
},
methods: {
getAuth() {
let manufactorId = '5bf13062-a41e-4d00-ba14-1101aad12650';
APIAlarm.getAuth({ manufactorId: manufactorId }).then(res => {
this.$store.commit('gatewayToken', res.data.data);
});
},
onNavBack() {
this.$router.push({
name: 'dangerAreaMonitor'
});
},
getDrownReportFilterQuery() {
ToastService.loading({ message: '数据加载中' });
let reqBody = {
imei: this.imei /* '864316050221113' */
};
APIAlarm.getDrownReportFilterQuery(reqBody)
.then(res => {
if (res.data.code === 106 || res.data.code === 104) {
// token过期
this.getAuth();
setTimeout(() => {
this.getDrownReportFilterQuery();
}, 1500);
} else {
let data = res.data.data;
if (isNotNull(data)) {
console.log('水域告警白名单数据', data);
this.drownList = data;
}
}
ToastService.success({ message: '数据加载完成' });
this.isPageShow = true;
})
.catch(e => {
console.log(e);
ToastService.clear();
this.isPageShow = true;
});
},
onDelete(imei, poiId) {
DialogService.confirm({
message: '是否要删除此告警水域',
showCancelButton: true
})
.then(() => {
this.deleteDrownReportFilter(imei, poiId);
})
.catch(() => {});
},
deleteDrownReportFilter(imei, poiId) {
ToastService.loading({
message: '删除中'
});
let reqBody = {
imei: imei || this.imei,
poiId: poiId
};
APIAlarm.drownReportFilterDelete(reqBody)
.then(res => {
let data = res.data;
console.log('删除data', data);
if (data.code === 0) {
ToastService.success({
message: '删除成功'
});
}
this.getDrownReportFilterQuery();
})
.catch(e => {
DialogService.confirm({
message: `${e.message}`
});
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
}, 1500);
});
}
}
};
</script>

<style scoped lang="scss">
.drown-white-list {
height: 100vh;
width: 100%;
overflow: hidden;
.main {
height: calc(100vh - 160px);
overflow: scroll;
.list {
@include center();
flex-direction: column;
.item {
width: 600px;
margin: 20px 0;
padding: 30px;
font-size: 32px;
border: 2px solid $border_color;
border-radius: 15px;
p {
padding: 8px 0;
}
.btn-con {
display: flex;
justify-content: flex-end;
align-items: center;
.btn {
height: 60px;
width: 220px;
@include center();
border-radius: 30px;
margin-top: 20px;
background-color: red;
color: #fff;
}
}
}
}
.noData {
height: 450px;
@include center();
margin: 200px auto 0;
/* background: url('../../../assets/img/news-noData.png') center no-repeat;
background-size: 336px 236px; */
p {
@include colorAndFont(#999, 28);
margin: 200px auto 0;
}
}
}
}
</style>

+ 1094
- 0
src/views/myself/deviceSetting/healthMonitor.vue
Plik diff jest za duży
Wyświetl plik


+ 407
- 0
src/views/myself/deviceSetting/locationMonitor.vue Wyświetl plik

@@ -0,0 +1,407 @@
<template>
<div class="location-monitor-container">
<!-- nav -->
<div class="nav-bar">
<van-nav-bar title="定位监测" left-text="返回" @click-left="onNavBack" left-arrow>
<template #right>
<!-- <div class="setupClock_save" @click="onSubmit">保存</div> -->
<van-button type="primary" @click="onSubmit" size="small">保存</van-button>
</template>
</van-nav-bar>
</div>
<!-- main -->
<div class="main">
<div class="list">
<div class="item">
<div class="left">
<span class="title">定位监测:</span>
</div>
<div class="right">
<!-- <img :src="rightIcon" alt=""> -->
<van-switch v-model="checked" :active-color="$green" />
</div>
</div>

<div class="item left-gray" v-show="checked">
<div class="left">
<span class="title gray">检测周期:</span>
</div>
<div class="right" @click="onClick">
<span>{{ sampleinteval }}分钟</span>
<img :src="rightIcon" alt="" />
</div>
</div>

<!-- <div class="item alarmType left-gray" v-show="checked">
<div class="left">
<span class="title gray">告警方式:</span>
</div>
<div class="right">
<img :src="rightIcon" alt="">
<van-checkbox-group v-model="alarmType" direction="horizontal" >
<van-checkbox name="a" shape="square">震动</van-checkbox>
<van-checkbox name="b" shape="square">亮屏</van-checkbox>
<van-checkbox name="c" shape="square">公众号推送</van-checkbox>
</van-checkbox-group>
</div>
</div> -->
</div>
</div>

<!-- 弹窗 -->
<van-dialog v-model="dialog.isDialogshow" cancelButtonText="返回" show-cancel-button :show-confirm-button="false">
<template #title>
<div class="title">
<span>{{ dialog.title }}</span>
</div>
</template>
<template #default>
<div class="dialog-container">
<div class="selectConfirm">
<div class="con">
<van-cell v-for="(item, index) in dialog.confirmData" :key="`selectVPT${index}`" @click="onSelect(item)">
<div class="text">
<div v-html="item.text"></div>
</div>
<em :class="['circle', { on: selectConfirmActive == index }]"></em>
</van-cell>
</div>
</div>
</div>
</template>
</van-dialog>
</div>
</template>

<script>
import ToastService from '@/services/toast-service';
import DialogService from '@/services/dialog-service';
import APIHealthy from '@/api/heathly';
export default {
name: '',
data() {
return {
rightIcon: require('../../../assets/img/health/right_more.png'),
checked: false,
sampleinteval: 15, //检测周期-定位检测
alarmType: ['a', 'b'], //告警方式
dialog: {
isDialogshow: false,
title: '检测周期',
confirmData: [
{
text: '3分钟',
model: 0,
checked: false,
value: 3
},
{
text: '5分钟',
model: 1,
checked: false,
value: 5
},
{
text: '10分钟',
model: 2,
checked: false,
value: 10
},
{
text: '15分钟',
model: 3,
checked: false,
value: 15
},
/* {
text: "20分钟",
model: 2,
checked: false,
value: 20
}, */
{
text: '30分钟',
model: 4,
checked: false,
value: 30
},
/* {
text: "40分钟",
model: 4,
checked: false,
value: 40
},
{
text: "50分钟",
model: 5,
checked: false,
value: 50
}, */
{
text: '60分钟',
model: 5,
checked: false,
value: 60
}
]
},
selectConfirmActive: 0
};
},
computed: {
imei() {
return this.$store.getters.serialNo;
}
},
created() {
this.getLocationConfig();
},
methods: {
// 返回
onNavBack() {
this.$router.push({
name: 'watchSetting'
});
},
// 保存
onSubmit() {
ToastService.loading({ message: '设置中' });
let reqBody = {
imei: this.imei,
enabled: this.checked === true ? 1 : 0, //启用 0禁用 1启用
sampleinteval: Number(this.sampleinteval) //上报周期 分钟为单位,取值范围是2 ~120
};
APIHealthy.setLocationConfig(reqBody)
.then(res => {
console.log('设置', res);
if (res.data.stateCode === 1) {
ToastService.success({ message: '设置成功' });
setTimeout(() => {
this.$router.push({
name: 'watchSetting'
});
}, 1500);
} else {
DialogService.confirm({
title: '设置失败',
message: `${res.data.message}`
});
}
})
.catch(e => {
DialogService.confirm({
title: '设置失败',
message: `${e.message}`
});
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
}, 1500);
});
},
// 选择弹窗内容
onSelect(data) {
console.log('选择了', data.value);
const uploadinteval = this.$store.getters.uploadinteval;
this.selectConfirmActive = data.model;
this.dialog.isDialogshow = false;
this.sampleinteval = data.value;
console.log(this.sampleinteval, uploadinteval);
},
// 点击菜单列表
onClick() {
this.dialog.isDialogshow = true;
// 先注释,保不准这个功能又用回呢
//const uploadinteval = this.$store.getters.uploadinteval;
/* let result = this.getResult(uploadinteval, this.sampleinteval); */
let seclectIndex = this.dialog.confirmData.findIndex(item => {
return item.value === this.sampleinteval;
});
/* if(result === 5) {
this.selectConfirmActive = 3;
} else {
this.selectConfirmActive = seclectIndex;
} */
this.selectConfirmActive = seclectIndex;
console.log('seclectIndex', seclectIndex);
},
// 计算两个数相除,并获取到小数点两位,再截取两位
getResult(number1, number2) {
const result = parseInt(number1) / parseInt(number2);
console.log('result', result.toString().indexOf('.'));
return result.toString().indexOf('.') != -1 ? parseInt(result).toFixed(2).slice(0, 1) : result;
},
// 获取设备定位配置
getLocationConfig() {
ToastService.loading({ message: '数据加载中' });
APIHealthy.getLocationConfig({ imei: this.imei })
.then(res => {
console.log('res', res);
ToastService.success({ message: '数据加载完成' });
let data = res.data.data;
if (data) {
console.log('定位data', data);
this.checked = data.enabled === 1;
this.sampleinteval = data.sampleinteval;
}
})
.catch(e => {
console.log('e', e);
DialogService.confirm({
message: `${e.message}`
});
})
.finally(() => {
setTimeout(() => {
ToastService.clear();
}, 1500);
});
}
}
};
</script>

<style scoped lang="scss">
.location-monitor-container {
height: 100vh;
overflow: hidden;
.nav-bar {
height: 90px;
padding: 0 20px;
}
.main {
height: calc(100vh - 160px);
background-color: $background;
padding: 20px;
.list {
height: auto;
background-color: #fff;
border-radius: 8px;
.item {
height: auto;
padding: 20px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #e5e5e5;
.left {
@include center();
span {
color: #282828;
font-size: 32px;
}
.title {
font-weight: 450;
&.gray {
color: gray;
}
}
}
.right {
/* width: 60%; */
@include center();
img {
height: 35px;
width: 35px;
}
span {
font-size: 32px;
margin-right: 10px;
color: #aaaaaa;
}
}
&.left-gray {
padding-left: 30px;
color: gray;
}
&.alarmType {
height: 180px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
.left {
}
.right {
margin-left: 40px;
width: 60%;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
}
}
}
}
.title {
font-size: 32px;
}
.dialog-container {
padding: 20px 60px;
font-size: 32px;
.selectConfirm {
padding: 0;
.con {
.van-cell {
height: 60px;
.van-cell__value {
em {
font-style: normal;
position: absolute;
top: 0;
right: 0;
@include colorAndFont(#999, 24);
&.circle {
width: 20px;
height: 20px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;

&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 14px;
height: 14px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
}
}
.input-con {
display: flex;
justify-content: flex-start;
align-items: center;
label {
color: #000;
}
input {
// width: 100%;
margin-left: 15px;
display: flex;
width: 80px;
height: 72px;
text-indent: 15px;
border-bottom: 1px solid #000;
}
}
p {
font-size: 32px;
margin: 5px 0;
color: #999;
}
}
}
</style>

+ 889
- 0
src/views/myself/deviceSetting/personInfos.vue Wyświetl plik

@@ -0,0 +1,889 @@
<template>
<div class="registe-user-infos-container">
<div class="nav-bar">
<van-nav-bar :title="navBarTitle" :left-arrow="true" @click-left="onNavBack">
<!-- <template #right>
<div class="setupClock_save">保存</div>
</template> -->
</van-nav-bar>
</div>
<div class="main">
<div class="list">
<div class="avatar" v-show="$route.query.from === 'login'">
<div class="avatar-con">
<div class="avatar-img"></div>
<div class="avatar-text">
<span>设置头像</span>
</div>
</div>
</div>
<div class="item">
<div class="left importance">
<span class="title gray">设备昵称:</span>
</div>
<div class="right" @click="onClick">
<input type="text" maxlength="6" v-model.trim="personData.nickName" placeholder="请输入昵称" />
<img :src="rightIcon" alt="" />
</div>
</div>
<div class="item">
<div class="left importance">
<span class="title gray">性别:</span>
</div>
<div class="right" @click="onClick('gender')">
<span>{{ unshiftGender(personData.gender) || '请输入' }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item">
<div class="left importance">
<span class="title gray">身高(cm):</span>
</div>
<div class="right" @click="onClick('height')">
<!-- <span>{{ height }}</span> -->
<input
type="number"
placeholder="请输入身高"
oninput="if(value.length>3)value=value.slice(0,3)"
onKeypress="return(/[\d]/.test(String.fromCharCode(event.keyCode)))"
v-model.trim="personData.height"
/>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item">
<div class="left importance">
<span class="title gray">体重(kg):</span>
</div>
<div class="right" @click="onClick('weight')">
<input
type="number"
placeholder="请输入体重"
oninput="if(value.length>3)value=value.slice(0,3)"
onKeypress="return(/[\d]/.test(String.fromCharCode(event.keyCode)))"
v-model.trim="personData.weight"
/>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item">
<div class="left importance">
<span class="title gray">出生日期:</span>
</div>
<div class="right" @click="onClick('bornDate')">
<span>{{ formatBorndate(handleData(personData.bornDate)) || '请输入' }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item">
<div class="left importance">
<span class="title gray">职业:</span>
</div>
<div class="right" @click="onClick('profession')">
<span>{{ calcProfession(personData.profession) || '请选择' }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>

<div class="item isHasBlood" v-show="this.$route.query.from === 'watchSetting'">
<div class="left importance">
<span class="title gray">是否有高血压史:</span>
</div>
<div class="right">
<!-- <img :src="rightIcon" alt=""> -->
<van-radio-group v-model="personData.ishypertension" direction="horizontal">
<van-radio name="1" :checked-color="$green">有过</van-radio>
<van-radio name="0" :checked-color="$green">没有</van-radio>
</van-radio-group>
</div>
</div>

<div class="item isHasBlood">
<div class="left importance">
<span class="title gray">作息是否规律:</span>
</div>
<div class="right">
<van-radio-group v-model="personData.regularity" direction="horizontal">
<van-radio name="1" :checked-color="$green">是</van-radio>
<van-radio name="0" :checked-color="$green">否</van-radio>
</van-radio-group>
</div>
</div>

<div class="item isHasBlood">
<div class="left importance">
<span class="title gray">是否受到慢性病困扰:</span>
</div>
<div class="right">
<van-radio-group v-model="personData.chronicDisease" direction="horizontal">
<van-radio name="1" :checked-color="$green">是</van-radio>
<van-radio name="0" :checked-color="$green">否</van-radio>
</van-radio-group>
</div>
</div>
</div>
<div class="bottom-btn">
<div class="btn" @click="onSubmit">{{ btnText }}</div>
</div>
</div>

<!-- 时间选择器弹窗 -->
<van-dialog v-model="isDateShow" :show-confirm-button="false" :close-on-click-overlay="true">
<template #title>
<div class="title">
<span>出生日期</span>
</div>
</template>
<template #default>
<div class="date-dialog-container">
<div class="date-bottom">
<van-datetime-picker
v-model="currentDate"
type="date"
:min-date="minDate"
:max-date="maxDate"
:visible-item-count="4"
:show-toolbar="false"
/>
</div>
<div class="button-box">
<!-- <div class="button" @click="onCancel">
<span>关闭</span>
</div> -->
<div class="button">
<div class="btn-item" @click="onCancelDate"><p class="cancel">返回</p></div>
<div class="btn-item" @click="onConfirmDate"><p class="confirm">完成</p></div>
</div>
</div>
</div>
</template>
</van-dialog>

<!-- 性别选择弹窗 -->
<van-dialog v-model="isConfirmShow" cancelButtonText="返回" show-cancel-button :show-confirm-button="false">
<template #title>
<div class="title">
<span>{{ dialogTitle }}</span>
</div>
</template>
<template #default>
<div class="dialog-container">
<div class="selectConfirm">
<div class="con">
<van-cell v-for="(item, index) in confirmData" :key="`selectVPT${index}`" @click="onSelect(item)">
<div class="text">
<div v-html="item.text"></div>
</div>
<em :class="['circle', { on: selectConfirmActive == index }]"></em>
</van-cell>
</div>
</div>
</div>
</template>
</van-dialog>
</div>
</template>

<script>
import APIDevice from '@/api/device';
import { isNotNull, isNull } from '@/services/utils-service';
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
export default {
name: '',
data() {
return {
isHasBlood: '1',
userName: '',
bornDate: '',
gender: '男',
height: '',
weight: '',
rightIcon: require('../../../assets/img/health/right_more.png'),
isDateShow: false,
currentDate: '',
minDate: '',
maxDate: '',
isConfirmShow: false,
currentGender: '',
genderConfirmData: [
{
text: '男',
model: 0,
checked: false,
value: true
},
{
text: '女',
model: 1,
checked: false,
value: false
}
],
professionConfirmData: [
{
text: '互联网行业',
model: 0,
checked: false,
value: '1'
},
{
text: '教培行业',
model: 1,
checked: false,
value: '2'
},
{
text: '医警教行业',
model: 2,
checked: false,
value: '3'
},
{
text: '护理行业',
model: 3,
checked: false,
value: '4'
},
{
text: '法律行业',
model: 4,
checked: false,
value: '5'
},
{
text: '销售行业',
model: 5,
checked: false,
value: '6'
},
{
text: '封闭隔离行业',
model: 6,
checked: false,
value: '7'
},
{
text: '学生',
model: 7,
checked: false,
value: '8'
},
{
text: '小学生',
model: 8,
checked: false,
value: '81'
},
{
text: '初中生',
model: 9,
checked: false,
value: '82'
},
{
text: '高中生',
model: 10,
checked: false,
value: '83'
},
{
text: '自由职业',
model: 11,
checked: false,
value: '9'
},
{
text: '待业',
model: 12,
checked: false,
value: '10'
},
{
text: '其它',
model: 13,
checked: false,
value: '11'
}
],
confirmData: [],
selectConfirmActive: 0,
personData: {
Uid: '',
DeviceSn: '',
bornDate: '',
height: null,
weight: null,
gender: null,
profession: '',
regularity: '1',
chronicDisease: '0',
ishypertension: '0'
},
btnText: '' || '下一步',
currentDiallogName: '',
dialogTitle: '',
profession: '',
uid: '',
navBarTitle: ''
};
},
computed: {},
created() {
this.loadParams();
this.setMaxDate();
this.getPersonData();
this.navBarTitle = this.$route.query.from === 'psychologicalSetting' ? '登记佩戴者信息' : '添加成员';
},
methods: {
loadParams() {
let params = this.$route.query;
if (params) {
if (params.from === 'watchSetting' || params.isShowSubmit) {
this.btnText = '保存';
}
}
},
setMaxDate() {
let maxDate = new Date().setFullYear(new Date().getFullYear());
let minDate = new Date().setFullYear(new Date().getFullYear() - 150);
this.maxDate = new Date(maxDate);
this.minDate = new Date(minDate);
this.currentDate = new Date(maxDate);
},
getPersonData() {
/* ToastService.loading({
message: '数据加载中'
}); */
APIDevice.getPersonInfo({
userId: this.$store.getters.userId,
deviceId: this.$store.getters.deviceId
}).then(res => {
console.log('用户信息', res);
let data = res.data;
this.personData = data;
this.currentDate = data.bornDate ? new Date(data.bornDate) : this.currentDate;
this.personData.height = data.height === 0 ? '' : data.height;
this.personData.weight = data.weight === 0 ? '' : data.weight;
this.personData.ishypertension = String(data.ishypertension);
this.personData.chronicDisease = String(data.chronicDisease);
this.personData.regularity = String(data.regularity);
this.personData.profession = String(data.profession);
this.currentGender = data.gender;
this.uid = data.uid;
/* ToastService.success({
message: '数据加载完成'
}) */
});
},
onNavBack() {
let fromRouter = this.$route.query.from;
this.$store.commit('notJump', 1);
this.$router.push({
name: fromRouter ? fromRouter : 'psychologicalIndex',
notJump: true
});
},
onClick(name) {
this.currentDiallogName = name;
if (name === 'bornDate') {
this.isDateShow = true;
} else if (name === 'gender') {
this.confirmData = this.genderConfirmData;
this.dialogTitle = '性别';
this.selectConfirmActive = this.confirmData.findIndex(item => {
return item.value == this.personData.gender;
});
this.isConfirmShow = true;
} else if (name === 'profession') {
this.confirmData = this.professionConfirmData;
this.dialogTitle = '职业选择';
this.selectConfirmActive = this.confirmData.findIndex(item => {
return item.value == this.personData.profession;
});
this.isConfirmShow = true;
}
},
onSubmit() {
let data = this.personData;
let intReg = /^[1-9]\d*$/;
if (isNull(data.nickName)) {
return DialogService.confirm({
message: '昵称不能为空'
});
} else if (isNull(data.height) || data.height == 0 || !intReg.test(data.height)) {
return DialogService.confirm({
message: '身高不能为空,不能为0,\n不能存在小数点,只能是整数'
});
} else if (isNull(data.weight) || data.weight == 0 || !intReg.test(data.weight)) {
return DialogService.confirm({
message: '体重不能为空,不能为0,\n不能存在小数点,只能是整数'
});
} else if (isNull(data.bornDate)) {
return DialogService.confirm({
message: '出生日期不能为空'
});
} else if (isNull(data.profession) || data.profession === '0') {
return DialogService.confirm({
message: '职业不能为空'
});
}

this.savePersonInfo();
},
savePersonInfo() {
let reqBody = { ...this.personData };
reqBody['userId'] = this.$store.getters.userId;
reqBody.weight = Number(reqBody.weight);
reqBody.height = Number(reqBody.height);
reqBody.ishypertension = Number(reqBody.ishypertension);
reqBody.chronicDisease = Number(reqBody.chronicDisease);
reqBody.regularity = Number(reqBody.regularity);
reqBody.profession = Number(reqBody.profession);
// 2023.07/19 增加容错 deviceId和serialNo关键参数为空时使用缓存里面的数据
reqBody.deviceId = reqBody.deviceId || this.$store.getters.deviceId;
reqBody.serialNo = reqBody.serialNo || this.$store.getters.serialNo;
console.log('请求的参数', reqBody);
ToastService.loading({
message: '保存中'
});
APIDevice.updatePersonInfo(reqBody).then(res => {
ToastService.clear();
console.log(res.data);
if (res.data.stateCode == 1) {
ToastService.success({
message: '保存成功'
});
this.getPersonData();
if (this.$route.query.from === 'watchSetting') {
setTimeout(() => {
this.$router.push({
name: 'watchSetting'
});
}, 1500);
} else if (this.$route.query.from === 'psychologicalSetting') {
setTimeout(() => {
this.$router.push({
name: 'psychologicalSetting',
from: 'watchSetting'
});
}, 1500);
} else if (this.$route.query.from === 'login') {
console.log('注册过来,下一步绑定设备');
} else {
setTimeout(() => {
this.$router.push({
name: 'psychologicalSetting',
query: { from: 'psychologicalRegUserInfos', uid: this.uid }
});
}, 1500);
}
} else {
DialogService.confirm({
title: res.data.message
});
}
});
},
onCancelDate() {
this.isDateShow = false;
//this.currentDate = new Date(this.$own.formatTime(this.personData.bornDate)).Format("yyyy-MM-dd");
},
// 通过职业的value值展示职业的中文昵称
calcProfession(value) {
let result = '';
if (value !== '0' || value !== 0 || isNotNull(value) || value != '') {
let index = this.professionConfirmData.findIndex(item => {
return value === item.value;
});
if (index >= 0) {
result = this.professionConfirmData[index].text;
}
}
return result;
},
onConfirmDate() {
this.isDateShow = false;
this.personData.bornDate = new Date(this.currentDate).Format('yyyy-MM-dd');
},
onSelect(item) {
this.personData[this.currentDiallogName] = item.value;
if (this.currentDiallogName === 'profession') {
this.profession = item.text;
}
this.personData[this.currentDiallogName] = item.value;
this.selectConfirmActive = item.model;
this.isConfirmShow = false;
},
unshiftGender(gender) {
let sex = null;
if (isNotNull(gender)) {
if (gender == true) {
sex = '男';
} else {
sex = '女';
}
} else {
sex = '';
}
return sex;
},
handleData(val) {
return val == null || val == '' || val == undefined || val == 'Unknown' ? '' : val;
},
formatBorndate(date) {
return date == '' ? '' : new Date(this.$own.formatTime(date)).Format('yyyy-MM-dd');
}
}
};
</script>
<style scoped lang="scss">
.registe-user-infos-container {
height: 100vh;
overflow: hidden;
.nav-bar {
height: 100px;
padding: 0 20px;
}
.main {
position: relative;
height: calc(100vh - 80px);
background-color: $background;
.list {
position: relative;
height: 78%;
background-color: #fff;
border-radius: 8px;
overflow: scroll;
z-index: 99;
//@at-rootpadding: 0 20px;
.avatar {
position: relative;
height: 240px;
@include center();
.avatar-con {
@include center();
flex-direction: column;
.avatar-img {
height: 120px;
width: 120px;
border: 2px solid #333;
border-radius: 50%;
margin-bottom: 10px;
}
.avatar-text {
font-size: 36px;
font-weight: bold;
}
}
}
.item {
position: relative;
height: 60px;
padding: 20px 40px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e5e5e5;
.left {
@include center();
span {
color: #282828;
font-size: 32px;
}
.title {
font-weight: 450;
&.gray {
color: #000;
}
}
&.importance {
span {
&:after {
content: '*';
position: absolute;
left: 10px;
top: 40px;
@include colorAndFont($red, 34);
z-index: 1000;
}
}
}
}
.right {
width: 40%;
display: flex;
justify-content: flex-end;
align-items: center;
input {
display: flex;
width: 220px;
height: 59px;
color: #aaaaaa;
font-size: 36px;
border-bottom: 1px solid #e5e5e5;
text-indent: 10px;
text-align: right;
&::-webkit-input-placeholder {
color: #aaaaaa;
font-size: 30px;
}
}
img {
height: 35px;
width: 35px;
}
span {
font-size: 32px;
margin-right: 10px;
color: #aaaaaa;
}
}
&.left-gray {
padding-left: 30px;
/* color: gray; */
}
&.isHasBlood {
/* height: 120px; */
display: flex;
justify-content: space-between;
align-items: center;
.left {
}
.right {
width: 50%;
display: flex;
justify-content: flex-end;
align-items: flex-end;
font-size: 32px;
}
}
}
}
.bottom-btn {
position: relative;
margin-top: 80px;
height: 120px;
width: 100%;
@include center();
z-index: 999;
clear: both;
.btn {
position: relative;
height: 100px;
width: 560px;
background-color: $green;
color: #fff;
font-size: 32px;
border-radius: 50px;
@include center();
}
}
}
.dialog-container {
padding: 30px 40px 0 40px;
font-size: 32px;
.selectConfirm {
flex: 1;
width: 100%;
overflow: scroll;
padding: 0;
.con {
flex: 1;
max-height: 550px;
width: 100%;
overflow: scroll;
}
}
}
.date-dialog-container {
padding: 30px 40px 0 40px;
font-size: 32px;
.selectConfirm {
height: 550px;
width: 100%;
overflow: scroll;
padding: 0;
}
.con {
height: 550px;
width: 100%;
overflow: scroll;
padding-bottom: 20px;
border-bottom: 1px solid #999;
.con-item {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 20px 0;
label {
margin-right: 15px;
}
.cloose {
height: 40px;
padding: 10px;
background-color: $green;
font-size: 28px;
color: #fff;
/* border-radius: 20px; */
border-bottom-left-radius: 15px;
border-top-left-radius: 15px;
@include center();
}
.birthday {
height: 60px;
width: 220px;
background-color: $background;
border-bottom-right-radius: 15px;
border-top-right-radius: 15px;
@include center();
}
input {
margin-left: 15px;
display: flex;
width: 200px;
height: 72px;
text-indent: 15px;
border-bottom: 1px solid #000;
}
}
.select-con {
height: 400px;
overflow: scroll;
padding: 15px 0;
}
.tips {
margin: 15px 0;
}
}
.button {
height: 80px;
@include center();
p {
font-size: 32px;
color: #000;
}
}
.input-con {
display: flex;
justify-content: flex-start;
align-items: center;
label {
color: #000;
}
input {
// width: 100%;
margin-left: 15px;
display: flex;
width: 80px;
height: 72px;
text-indent: 15px;
border-bottom: 1px solid #000;
}
}
p {
font-size: 32px;
margin: 15px 0;
color: #999;
}
.error-tips {
color: red;
}
.button-box {
position: absolute;
bottom: 0;
height: 90px;
width: 100%;
z-index: 999;
background-color: #fff;
@include center();
.button {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
.btn-item {
width: 200px;
p {
font-size: 32px;
height: 80px;
width: 100%;
color: #000;
@include center();
}
.confirm {
color: $green;
}
.delete {
color: red;
}
.cancel {
color: #000;
}
}
}
}
.button {
display: flex;
justify-content: space-around;
align-items: center;
p {
width: 40%;
color: #000;
@include center();
}
.confirm {
color: $green;
}
}
}
.title {
font-size: 32px;
}
.selectConfirm {
padding: 0;
.con {
.van-cell {
height: 60px;
.van-cell__value {
em {
font-style: normal;
position: absolute;
top: 0;
right: 0;
@include colorAndFont(#999, 24);
&.circle {
width: 20px;
height: 20px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;

&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 14px;
height: 14px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
}
}
}
</style>

+ 1288
- 0
src/views/myself/deviceSetting/psychologicalSetting.vue
Plik diff jest za duży
Wyświetl plik


+ 223
- 0
src/views/myself/deviceSetting/sceneMode.vue Wyświetl plik

@@ -0,0 +1,223 @@
<template>
<div class="location-monitor-container">
<!-- nav -->
<div class="nav-bar">
<van-nav-bar title="场景模式" left-text="返回" @click-left="onNavBack" left-arrow>
<template #right>
<!-- <div class="setupClock_save" @click="onSubmit">保存</div> -->
<van-button type="primary" @click="onSubmit" size="small">保存</van-button>
</template>
</van-nav-bar>
</div>
<!-- main -->
<div class="main">
<div class="list">
<div class="item">
<div class="top">
<div class="left">
<span class="title">省电模式</span>
</div>
<div class="right">
<!-- <img :src="rightIcon" alt=""> -->
<van-switch v-model="checked" :active-color="$green" />
</div>
</div>
<div class="bottom">
<p>开启后能延长设备的续航时间,但只能打电话</p>
</div>
</div>
<div :class="['item']">
<div class="top">
<div class="left">
<span class="title">常规模式</span>
</div>
</div>
<div class="bottom radios">
<div class="radio-group">
<van-radio-group v-model="radio" direction="horizontal">
<van-radio name="1" :disabled="checked">标准</van-radio>
<van-radio name="2" :disabled="true">个性</van-radio>
</van-radio-group>
</div>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
import ToastService from '@/services/toast-service';
import DialogService from '@/services/dialog-service';
import APIHealthy from '@/api/heathly';
export default {
name: '',
data() {
return {
rightIcon: require('../../../assets/img/health/right_more.png'),
checked: false,
selectConfirmActive: 0,
radio: '1',
modeId: null || 1,
roleId: null
};
},
watch: {
checked: {
handler(n) {
if (n === true) {
this.modeId = 2;
} else {
this.modeId = 1;
}
},
deep: true
},
radio: {
handler(n) {
if (n === '1') {
this.modeId = 1;
this.checked = false;
} else if (n === '3') {
this.modeId = 3;
this.checked = false;
}
},
deep: true
}
},
computed: {
imei() {
return this.$store.getters.serialNo;
}
},
created() {
this.getWatchConfig();
//this.getLocationConfig();
},
methods: {
// 返回
onNavBack() {
this.$router.push({
name: 'watchSetting'
});
},
// 保存
onSubmit() {
if (this.modeId == 3) {
return DialogService.confirm({
message: '请切换标准模式或者省电模式再保存'
});
}
this.setWatchConfig();
},
// 设置设备数据上报周期
setWatchConfig() {
ToastService.loading({ message: '设置中' });
let reqBody = {
imei: this.imei,
roleId: this.roleId,
modeId: this.modeId
};
APIHealthy.setWatchConfig(reqBody)
.then(res => {
console.log('设置上报参数', res);
const data = res.data;
if (data.stateCode === 1) {
ToastService.success({ message: '设置成功' });
setTimeout(() => {
this.$router.push({
name: 'watchSetting'
});
}, 1500);
} else {
DialogService.confirm({
title: '设置失败',
message: `${res.data.message}`
});
}
})
.catch(error => {
console.log('接口报错了', error);
})
.finally(() => {
ToastService.clear();
});
},
// 获取设备场景模式参数
getWatchConfig() {
APIHealthy.getWatchConfig(this.imei).then(res => {
let data = res.data.data;
if (data) {
console.log('场景模式', data);
const modeId = data.modeId;
const roleId = data.roleId;
this.modeId = modeId;
this.roleId = roleId;
if (modeId === 1) {
this.radio = '1';
} else if (modeId === 2) {
this.checked = true;
} else if (modeId === 3) {
this.radio = '2';
}
} else {
this.modeId = 1;
this.roleId = this.$store.getters.roleUser === '1' ? 1 : 2;
}
});
}
}
};
</script>

<style lang="scss"></style>
<style scoped lang="scss">
.location-monitor-container {
height: 100vh;
overflow: hidden;
.nav-bar {
height: 90px;
padding: 0 20px;
}
.main {
height: calc(100vh - 160px);
background-color: $background;
padding: 20px;
.list {
height: auto;
border-radius: 8px;
.item {
padding: 20px 15px;
margin: 20px 0;
background-color: #fff;
.top {
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
}
.bottom {
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin: 10px 0;
p {
font-size: 32px;
color: gray;
/* line-height: 60px; */
}
&.radios {
margin: 20px 0;
@include center();
font-size: 32px;
}
}
}
}
}
.title {
font-size: 32px;
}
}
</style>

+ 886
- 0
src/views/myself/deviceSetting/settingIndex.vue Wyświetl plik

@@ -0,0 +1,886 @@
<template>
<div class="setting-container">
<!-- nav -->
<van-nav-bar title="参数设置" left-arrow :border="true" @click-left="onNavBack"> </van-nav-bar>
<!-- main -->
<div class="setting-main">
<div class="top">
<div
class="setting-item"
v-for="(item, index) in settingListTop"
:key="index"
@click="onRoute(item)"
v-show="item.show"
>
<div class="left">
<span
>{{ item.name }} <span v-show="item.remark !== ''">({{ item.remark }})</span></span
>
</div>
<div class="right">
<img :src="rightIcon" alt="" />
</div>
</div>
</div>
<div class="bottom">
<div
class="setting-item"
v-for="(item, index) in settingListBottom"
:key="index"
@click="onRoute(item)"
v-show="item.show"
>
<div class="left">
<span
>{{ item.name }}<span v-show="item.remark !== ''">({{ item.remark }})</span></span
>
</div>
<div class="right">
<span>{{ item.powerStatus }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>
</div>

<div class="bottom">
<div class="setting-item" v-for="(item, index) in settingListBottomUp" :key="index" @click="onRoute(item)">
<div class="left">
<span>{{ item.name }}({{ item.remark }})</span>
</div>
<div class="right">
<span>{{ item.powerStatus }}</span>
<img :src="rightIcon" alt="" />
</div>
</div>
</div>
</div>
<!-- 弹窗 -->
<van-dialog
v-model="dialog.isDialogshow"
:show-cancel-button="false"
:show-confirm-button="true"
confirm-button-text="返回"
>
<template #title>
<div class="title">
<span>{{ dialog.title }}</span>
</div>
</template>
<template #default>
<div class="dialog-container">
<div class="selectConfirm">
<div class="con">
<p>请选择多少时间上报一次数据:</p>
<div class="select-con" ref="select">
<van-cell
v-for="(item, index) in dialog.confirmData"
:key="`selectVPT${index}`"
@click="onSelect(item)"
>
<div class="text">
<div v-html="item.text"></div>
</div>
<em :class="['circle', { on: selectConfirmActive == index }]"></em>
</van-cell>
</div>
<div class="tips">
<p>温馨提示:</p>
<p>数字越小,越耗电,请慎重修改</p>
</div>
</div>
</div>
</div>
</template>
</van-dialog>

<van-dialog
v-model="isUserRoleDialogshow"
show-cancel-button
cancel-button-text="返回"
:show-confirm-button="false"
>
<template #title>
<div class="title">
<span>监护角色</span>
</div>
</template>
<template #default>
<div class="dialog-container">
<div class="selectConfirm">
<div class="con">
<van-cell
v-for="(item, index) in userRoleData"
:key="`selectUserRole${index}`"
@click="onSelectUserRole(item)"
>
<div class="text">
<div v-html="item.text"></div>
</div>
<em :class="['circle', { on: selectUserConfirmActive == index }]"></em>
</van-cell>
</div>
</div>
</div>
</template>
</van-dialog>
</div>
</template>

<script>
import ToastService from '@/services/toast-service';
import DialogService from '@/services/dialog-service';
import APIHealthy from '@/api/heathly';
export default {
name: '',
data() {
// Do Not disturb
return {
settingListTop: [
{ name: '监护角色', iconUrl: '', className: 'userRole', routerName: '', remark: '', show: true },
{ name: '场景模式', iconUrl: '', className: 'sceneMode', routerName: 'sceneMode', remark: '', show: true },
{
name: '加强省电模式',
iconUrl: '',
className: 'deepPowerDownMode',
routerName: 'deepPowerDownMode',
remark: '',
show: false
},
{ name: '免扰设置', iconUrl: '', className: '', routerName: 'notDisturb', remark: '', show: false },
{
name: '健康信息登记',
iconUrl: '',
className: '',
routerName: 'psychologicalRegUserInfos',
remark: '',
show: false
},
{ name: '设备名片', iconUrl: '', className: '', routerName: 'equipmentCard', remark: '', show: false }
],
settingListBottom: [
{
name: '定位监测',
iconUrl: '',
className: 'locationMonitor',
routerName: 'locationMonitor',
remark: '',
powerStatus: '',
show: true
},
{
name: '危险区域监测',
iconUrl: '',
className: 'dangerAreaMonitor',
routerName: 'dangerAreaMonitor',
remark: '',
powerStatus: '',
show: true
},
{
name: '健康监测',
iconUrl: '',
className: 'healthMonitor',
routerName: 'healthMonitor',
remark: '',
powerStatus: '',
show: true
},
{
name: '血压监测',
iconUrl: '',
className: 'blood',
routerName: 'blood',
remark: '',
powerStatus: '',
show: true
},
{
name: '心理监测',
iconUrl: '',
className: 'psychologicalSetting',
routerName: 'psychologicalSetting',
remark: '',
show: true
},
{
name: '佩戴监测',
iconUrl: '',
className: 'wearMonitor',
routerName: 'wearMonitor',
remark: '',
powerStatus: '',
show: true
},
{
name: '久坐提醒',
iconUrl: '',
className: 'longSitReminder',
routerName: 'longSitReminder',
remark: '',
powerStatus: '',
show: false
},
{
name: '抬腕亮屏',
iconUrl: '',
className: 'raiseToLightScreen',
routerName: 'raiseToLightScreen',
remark: '',
powerStatus: '',
show: false
}
],
userRoleData: [
{ text: '学生', value: 1 },
{ text: '老人', value: 2 }
],
selectUserConfirmActive: 0,
isUserRoleDialogshow: false,
settingListBottomUp: [
{ name: '上报周期', iconUrl: '', className: 'uploadinteval', routerName: '', remark: '', powerStatus: '' }
],
rightIcon: /* require('../../../assets/img/health/right_more.png') */ '',
dialog: {
isDialogshow: false,
title: '上报周期',
confirmData: [
{
text: '15分钟',
model: 0,
checked: false,
value: 15
},
{
text: '30分钟',
model: 1,
checked: false,
value: 30
},
{
text: '60分钟',
model: 2,
checked: false,
value: 60
},
{
text: '120分钟',
model: 3,
checked: false,
value: 120
}
]
},
selectConfirmActive: 0, // 弹窗选中
uploadinteval: 60,
roleId: null,
version: 30071 //可以显示强省电模式设置菜单的设备的版本
};
},
computed: {
imei() {
return this.$store.getters.serialNo;
},
iotCardTitle() {
return this.$store.getters.iotCardTitle;
},
deviceVersion() {
return this.$store.getters.deviceVersion;
}
},
created() {
/* this.settingListBottom[6].show = process.env.NODE_ENV !== 'production'; */
/* this.settingListBottom[7].show = process.env.NODE_ENV !== "production"; */
/* this.settingListTop[2].show =
this.iotCardTitle === '零川' &&
process.env.NODE_ENV !== 'production' &&
parseInt(this.deviceVersion) > this.version; */
this.loadRequest();
},
methods: {
async loadRequest() {
ToastService.loading({
message: '数据加载中'
});
const allPromise = [
this.getLocationConfig(),
this.getHealthConfig(),
this.getDrownConfig(),
this.getNowearConfig(),
this.getWatchConfig(),
this.getPsychAbilityConfig(),
this.getBloodConfig(),
this.getUploadConfig(),
this.getLongSitReminder()
];
const promise = Promise.all(allPromise);
try {
const result = await promise;
const isLoadAllSuccess = result.every(item => {
return item;
});
if (isLoadAllSuccess) {
ToastService.success({
message: '数据加载完成',
duration: 2000
});
} else {
ToastService.clear();
DialogService.comfirm({
title: '提示',
message: '数据加载失败,请重试'
});
}
} catch (error) {
console.log('error', error);
ToastService.clear();
}
},
onNavBack() {
this.$router.push({
name: 'Myself'
});
},
onRoute(item) {
if (this.modeId === 2 && item.className !== 'sceneMode' && item.className !== 'userRole') {
DialogService.confirm({
message: '当前模式为省电模式,请关闭省电模式后再操作',
showCancelButton: true,
cancelButtonText: '返回'
});
} else if (item.className === 'uploadinteval') {
let selectIndex = this.dialog.confirmData.findIndex(item => {
return item.value === this.uploadinteval;
});
this.selectConfirmActive = selectIndex;
this.dialog.isDialogshow = true;
// 2023.6.7 因弹窗参数减少,取消动态滚动
/* setTimeout(() => {
let selectScollEl = this.$refs.select;
selectScollEl.scrollTop = this.getScroll(uploadinteval);
},1000); */
} else if (item.className === 'userRole') {
let selectIndex = this.userRoleData.findIndex(item => {
return item.value === this.roleId;
});
this.selectUserConfirmActive = selectIndex;
this.isUserRoleDialogshow = true;
} else if (
item.routerName === 'psychologicalSetting' ||
item.routerName === 'psychologicalRegUserInfos' ||
item.routerName === 'blood'
) {
this.$router.push({
name: item.routerName,
query: {
from: 'watchSetting'
}
});
} else if (item.routerName !== '') {
this.$router.push({ name: item.routerName });
}
},
getScroll(value) {
console.log('value', value);
if (value > 90) {
return 600;
} else if (value > 60 && value < 90) {
return 350;
} else if (value === 60) {
return 120;
} else if (value < 60) {
return 10;
}
},
onSelect(data) {
console.log('选择了', data);
this.selectConfirmActive = data.model;
if (data.value === 10) {
DialogService.confirm({
message: '切换后数据更新更快、但耗电也高,确定切换吗?',
showCancelButton: true
})
.then(() => {
this.uploadinteval = data.value;
this.setUploadConfig();
})
.catch(() => {});
} else {
this.uploadinteval = data.value;
this.setUploadConfig();
}
this.dialog.isDialogshow = false;
},
// 获取设备上报参数
getUploadConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getUploadConfig({ imei: this.imei })
.then(res => {
console.log('获取上报参数', res);
const data = res.data;
if (data.data) {
this.uploadinteval = data.data.uploadinteval;
let selectIndex = this.dialog.confirmData.findIndex(item => {
return item.value === data.data.uploadinteval;
});
console.log('selectIndex', selectIndex);
this.selectConfirmActive = selectIndex;
this.$store.commit('uploadinteval', data.data.uploadinteval);
let index = this.settingListBottomUp.findIndex(item => {
return item.className === 'uploadinteval';
});
this.settingListBottomUp[index].remark = data.data.uploadinteval + '分钟';
/* ToastService.success({message: "加载成功"}); */
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 获取设备定位参数
getLocationConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getLocationConfig({ imei: this.imei })
.then(res => {
let data = res.data.data;
if (data) {
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'locationMonitor';
});
this.settingListBottom[index].remark = data.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.enabled === 1 ? '耗电高' : '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 获取设备危险区域参数
getDrownConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getDrownConfig(this.imei)
.then(res => {
let data = res.data.data;
if (data) {
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'dangerAreaMonitor';
});
this.settingListBottom[index].remark = data.config.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.config.enabled === 1 ? '耗电高' : '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
getPsychAbilityConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getPsychAbilityConfig(this.imei)
.then(res => {
let data = res.data.data;
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'psychologicalSetting';
});
if (data) {
this.settingListBottom[index].remark = data.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.enabled === 1 ? '耗电高' : '耗电低';
} else {
this.settingListBottom[index].remark = '关闭';
this.settingListBottom[index].powerStatus = '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 获取设备健康参数
getHealthConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getHealthConfig({ imei: this.imei })
.then(res => {
let data = res.data.data;
if (data) {
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'healthMonitor';
});
let healthEnablelist = [
{ enabled: data.config.heartrateenabled },
{ enabled: data.config.spo2enabled },
{ enabled: data.config.temperatureenabled }
];
console.log('healthEnablelist', healthEnablelist);
// 获取健康设置打开的次数
const healthSettingCount = healthEnablelist.reduce((acc, cur) => (cur.enabled === 1 ? ++acc : acc), 0);
console.log('healthSettingCount', healthSettingCount);
this.settingListBottom[index].remark =
healthSettingCount >= 3 ? '打开' : healthSettingCount >= 1 ? '部分' : '关闭';
this.settingListBottom[index].powerStatus =
healthSettingCount > 2 ? '耗电高' : healthSettingCount === 2 ? '耗电中' : '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 获取设备佩戴检测参数
getNowearConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getNowearConfig(this.imei)
.then(res => {
let data = res.data.data;
if (data) {
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'wearMonitor';
});
this.settingListBottom[index].remark = data.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.enabled === 1 ? '耗电高' : '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 设置设备数据上报周期
setWatchConfig(value) {
if (value) {
ToastService.loading({ message: '设置中' });
}
let reqBody = {
imei: this.imei,
roleId: this.roleId,
modeId: this.modeId
};
console.log('reqBody', reqBody);
APIHealthy.setWatchConfig(reqBody)
.then(res => {
console.log('设置上报参数', res);
const data = res.data;
if (data.stateCode === 1) {
if (value) {
ToastService.success({ message: '设置成功' });
}
this.getWatchConfig();
this.getHealthConfig();
} else {
DialogService.confirm({
title: '设置失败',
message: `${res.data.message}`
});
}
})
.catch(error => {
console.log('接口报错了', error);
})
.finally(() => {
ToastService.clear();
});
},
// 获取设备场景模式参数
getWatchConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getWatchConfig(this.imei)
.then(res => {
let data = res.data.data;
if (data) {
console.log('场景模式', data);
const modeId = data.modeId;
const roleId = data.roleId;
this.modeId = data.modeId;
this.roleId = roleId;
this.$store.commit('watchRole', roleId);
this.settingListTop[0].remark = roleId === 1 ? '学生' : '老人';
this.settingListTop[1].remark = this.getModeById(modeId);
} else {
this.modeId = 1;
this.roleId = 1;
this.$store.commit('watchRole', 1);
this.setWatchConfig(false);
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 获取设备血压周期性参数
getBloodConfig() {
return new Promise((resolve, reject) => {
APIHealthy.getBloodPressConfig(this.imei)
.then(res => {
let data = res.data.data;
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'blood';
});
if (data) {
this.settingListBottom[index].remark = data.bloodPressenabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.bloodPressenabled === 1 ? '耗电高' : '耗电低';
} else {
this.settingListBottom[index].remark = '关闭';
this.settingListBottom[index].powerStatus = '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
getRaiseToLightScreen() {
APIHealthy.getRaiseToLightScreen(this.imei).then(res => {
let data = res.data.data;
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'raiseToLightScreen';
});
if (data) {
this.settingListBottom[index].remark = data.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.enabled === 1 ? '耗电高' : '耗电低';
} else {
this.settingListBottom[index].remark = '关闭';
this.settingListBottom[index].powerStatus = '耗电低';
}
});
},
getLongSitReminder() {
return new Promise((resolve, reject) => {
APIHealthy.getLongSitReminder(this.imei)
.then(res => {
let data = res.data.data;
let index = this.settingListBottom.findIndex(item => {
return item.routerName === 'longSitReminder';
});
if (data) {
this.settingListBottom[index].remark = data.enabled === 1 ? '打开' : '关闭';
this.settingListBottom[index].powerStatus = data.enabled === 1 ? '耗电高' : '耗电低';
} else {
this.settingListBottom[index].remark = '关闭';
this.settingListBottom[index].powerStatus = '耗电低';
}
resolve(true);
})
.catch(() => {
reject(false);
});
});
},
// 通过模式id获取场景模式
getModeById(id) {
if (id === 1) {
return '标准';
} else if (id === 2) {
return '省电';
} else {
return '个性';
}
},
// 设置设备数据上报周期
setUploadConfig() {
/* let reg = /^[1-9]+[0-9]*$/;
if(this.uploadinteval === '') {
return DialogService.confirm({
message: '上报周期不能为空'
})
} else if(!reg.test(this.uploadinteval)) {
return DialogService.confirm({
message: '上报周期只能为正整数'
})
} */
ToastService.loading({ message: '设置中' });
let reqBody = {
imei: this.imei,
uploadinteval: Number(this.uploadinteval)
};
APIHealthy.setUploadConfig(reqBody).then(res => {
console.log('设置上报参数', res);
this.$store.commit('uploadinteval', this.uploadinteval);
ToastService.success({ message: '设置成功' });
this.getUploadConfig();
this.getWatchConfig();
});
},
// 设置选择属性
onSelectUserRole(value) {
console.log('this.roleI', this.roleId);
DialogService.confirm({
message: '切换后默认参数会变化,确定要切换?',
showCancelButton: true,
cancelButtonText: '返回'
})
.then(() => {
this.roleId = value.value;
this.modeId = this.modeId === 3 ? 1 : this.modeId;
this.isUserRoleDialogshow = false;
this.setWatchConfig(true);
})
.catch(() => {});
}
}
};
</script>

<style scoped lang="scss">
.setting-container {
height: 100vh;
background-color: $background;
overflow: hidden;
.setting-main {
height: calc(100vh - 160px);
padding: 20px;
background-color: $background;
overflow: scroll;
.top {
background-color: white;
.setting-item {
height: 120px;
padding: 0 40px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #d2d0d0;
.left {
@include center();
img {
height: 45px;
width: 45px;
margin-right: 20px;
}
span {
color: #282828;
font-size: 34px;
}
}
.right {
@include center();
img {
height: 35px;
width: 35px;
}
}
}
}
.bottom {
margin: 20px 0 40px 0;
background-color: white;
.setting-item {
height: 120px;
padding: 0 40px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #d2d0d0;
.left {
@include center();
img {
height: 45px;
width: 45px;
margin-right: 20px;
}
span {
color: #282828;
font-size: 34px;
}
}
.middle {
span {
color: #c0baba;
font-size: 32px;
}
}
.right {
@include center();
span {
padding-right: 80px;
color: #c0baba;
font-size: 32px;
}
img {
height: 35px;
width: 35px;
}
}
}
}
}
.dialog-container {
padding: 20px 60px;
font-size: 32px;
.selectConfirm {
padding: 0;
.con {
.van-cell {
height: 60px;
.van-cell__value {
em {
font-style: normal;
position: absolute;
top: 0;
right: 0;
@include colorAndFont(#999, 24);
&.circle {
width: 20px;
height: 20px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;

&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 14px;
height: 14px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
}
}
.input-con {
display: flex;
justify-content: flex-start;
align-items: center;
label {
color: #000;
}
input {
// width: 100%;
margin-left: 15px;
display: flex;
width: 80px;
height: 72px;
text-indent: 15px;
border-bottom: 1px solid #000;
}
}
p {
font-size: 32px;
margin: 5px 0;
color: #999;
}
}
.title {
font-size: 32px;
}
}
</style>

+ 1168
- 0
src/views/myself/deviceSetting/wearMonitor.vue
Plik diff jest za duży
Wyświetl plik


+ 102
- 0
src/views/myself/help.vue Wyświetl plik

@@ -0,0 +1,102 @@
<template>
<div class="help">
<van-nav-bar title="常见问题" left-arrow @click-left="$router.push({ name: 'Myself' })" />
<div class="help-con">
<!-- <h2>常见问题</h2> -->
<h4>4G电子设备如何激活并绑定?</h4>
<p>
1)首次使用4G电子设备,请按照说明书的流程正确安装好SIM卡,然后按照移动端提示扫描说明书上的二维码完成绑定操作。
</p>
<p>2)已绑定4G电子设备,请按照移动端提示扫描4G电子设备二维码并让管理员在移动端中点击“同意”加入家庭按钮。</p>
<h4>4G电子设备管理员是谁?</h4>
<p>
默认情况下,4G电子设备管理员是第一个绑定4G电子设备的家庭成员;在“用户列表”界面可以查看当前管理员是谁,管理员可以在此界面下将自己的权限转移给任意一个家庭成员。
</p>
<h4>一台手机可以绑定几张4G电子设备,如何绑定更多4G电子设备?</h4>
<p>一台手机最多可以绑定5张4G电子设备;在移动端我的界面的“添加设备”菜单即可绑定4G电子设备支付。</p>
<h4>什么是亲情号码?</h4>
<p>设置为亲情号码则可以给4G电子设备打电话;4G电子设备只能给亲情号码打电话。</p>
<h4>如何确定4G电子设备充电状态?</h4>
<p>
4G电子设备充电时,会有充电状态提示,充满时也会有充满提示(注意:全新的4G电子设备或长时间不用的4G电子设备刚充电时可能要等待一段时间才会显示充电图标)。
</p>
<!--<h4>什么是4G电子设备聆听?</h4>
<p>
聆听是指用户通过移动端发送聆听指令给4G电子设备,4G电子设备接到后静默状态中拨打用户指定的手机号码,接听电话后实现实时聆听。
</p>
<p>注意:</p>
<p>1)聆听是通过通话实现的,消耗的是通话时长。</p>
<p> 2)信号不好会导致指令无法发送,聆听功能不能使用,请尝试换个时间或地点再次使用。</p>
<p>
3)聆听情况下,4G电子设备会自动拨打发起聆听用户指定的手机号码,此时无法使用4G电子设备其他功能。
</p>
<p>4)聆听情况下,4G电子设备不会听到您发出的声音。</p>
<p>
5)设置聆听号码前,请先将聆听号码设置到“亲情号码”中,聆听号码只能在“亲情号码”中选择一个。
</p>-->
<h4>如何判断4G电子设备联网状态?</h4>
<p>4G电子设备开机后,在屏幕顶部有图标显示联网状态;若联网不正常,请长按电源键5秒重启4G电子设备。</p>
<h4>4G电子设备如何关机?</h4>
<p>
为保证宝贝使用4G电子设备的安全,4G电子设备端不建议关机操作,需操作关机长按电源键5秒,关机可以通过移动端远程操作。
</p>
<h4>4G电子设备能待机多久?</h4>
<p>
4G电子设备电池容量为1000毫安,理想情况下可待机5天,实际续航时间与所在地区网络信号状况及4G电子设备使用频率有关系。
</p>
<h4>4G电子设备支持什么SIM卡?</h4>
<p>4G电子设备支持Nano-SIM卡,支持移动/电信/联通4G-LTE网络;不支持使用剪卡。</p>
<h4>如何为4G电子设备电话号码充值?</h4>
<p>根据4G电子设备sim卡类型(移动、电信、联通等)进行充值。</p>
<h4>4G电子设备支持7天无理由退货吗?</h4>
<p>支持7天无理由退货。</p>
<p>您购买时支付的费用将全额原路退还至您的支付渠道。</p>
<h4>4G电子设备的定位精度怎么样?</h4>
<p>室外最高精度可达15米,室内最高精度可达20米。</p>
<p>Wifi热点分布、基站信号强弱、建筑物遮挡及天气状况对定位精度会有一定程度影响。</p>
<h4>通话质量怎么样?</h4>
<p>4G电子设备通话的效果跟手机基本一样,通话信号质量跟您当地的移动/电信/联通信号有关。</p>
<h4>智能卡的辐射大吗?</h4>
<p>
4G电子设备打电话时是免提模式,无需紧贴头部,所以对人体的辐射非常小。
经权威认证机构测试,4G电子设备在通话时SAR辐射峰值小于2 W/Kg,低于中国国家标准GB 21288-2007对手机SAR值不超过2
W/Kg的要求,请家长们放心给孩子使用。
</p>

<h4>4G电子设备充电时有哪些注意事项?</h4>
<p>1)请将4G电子设备置于0度以上的环境中充电,避免低温下充电损伤电池。</p>
<p>2)4G电子设备从低电状态到充满,大约需要3小时。</p>
<p>
3)如果4G电子设备插上充电器很快充满(例如,当前40%电量,花30分钟就已经充满),这是充电虚高现象,请持续充电1小时以上。
</p>
<p>4)4G电子设备电量严重不足并关机,需要持续充电几分钟后才会开机。</p>

<h4>如何绑定支付宝支付?</h4>
<p>1)手机打开数据,定位,蓝牙,保证手机能连接到公网;</p>
<p>2)打开4G电子设备的“支付码”。</p>
<p>3)打开手机的支付宝扫码功能,扫“支付码”显示绑定码。</p>
<p>4)扫码过程中手机会通过蓝牙与4G电子设备通讯,完成绑定后,则提示绑定成功,则完成绑定。</p>
</div>
</div>
</template>
<style lang="scss" scoped>
.help {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
.help-con {
position: relative;
height: calc(100vh - 160px);
padding: 20px 40px;
overflow: scroll;
h4 {
font-size: 38px;
padding: 10px 0;
}
p {
font-size: 32px;
}
}
}
</style>

+ 3
- 2
src/views/myself/index.scss Wyświetl plik

@@ -11,7 +11,7 @@
.banner {
height: 420px;
width: 100%;
background-color: greenyellow;
background-color: green;
border-radius: 60px;
.top {
height: 320px;
@@ -59,8 +59,9 @@
max-width: 90px;
min-width: 90px;
border-radius: 10px;
background-color: green;
background-color: $green;
@include flexbox(center, center, column, nowrap);
color: #fff;
}
}
&.safe-helper {


+ 113
- 26
src/views/myself/index.vue Wyświetl plik

@@ -32,11 +32,11 @@
</div>
<div class="safe-helper-container">
<div class="top">
<p>桂城街道深海路105号平洲桂城广东天波教育科技有限公司</p>
<span>纬度:23.0263313634643 经度:113.175114274988</span>
<p>{{ currentDevice.address }}</p>
<span>纬度: {{ currentDevice.lat }} 经度: {{ currentDevice.lng }}</span>
</div>
<div class="bottom">
<p>进入地图 <span>></span></p>
<p @click="goMap">进入地图 <span>></span></p>
</div>
</div>
</div>
@@ -77,23 +77,35 @@ export default {
{
imgPath: require('../../assets/logo.png'),
text: '亲情号码',
bgColor: 'red',
bgColor: this.$green,
showType: 'newPage',
routerName: 'familyNumber'
},
{ imgPath: require('../../assets/logo.png'), text: '留言', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '通话记录', bgColor: 'red' }
{
imgPath: require('../../assets/logo.png'),
text: '留言',
bgColor: this.$green,
showType: 'newPage',
routerName: 'sendMessage'
},
{
imgPath: require('../../assets/logo.png'),
text: '通话记录',
bgColor: this.$green,
showType: 'newPage',
routerName: 'callList'
}
]
},
device: {
title: '孩子管理',
list: [
/* { imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '留言', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '留言', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '测试设置', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '留言', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '留言', bgColor: 'green' } */
]
@@ -101,39 +113,109 @@ export default {
studyHelper: {
title: '学习助手',
list: [
{ imgPath: require('../../assets/logo.png'), text: '课堂禁用', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '课程表', bgColor: 'red' }
{
imgPath: require('../../assets/logo.png'),
text: '课堂禁用',
bgColor: this.$green,
showType: 'newPage',
routerName: 'prohibit'
},
{ imgPath: require('../../assets/logo.png'), text: '课程表', bgColor: 'green' }
]
},
lifeHelper: {
title: '生活助手',
list: [
{ imgPath: require('../../assets/logo.png'), text: '闹钟', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '支付密码修改', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '短信修改', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '亲友关注', bgColor: 'red' }
{
imgPath: require('../../assets/logo.png'),
text: '闹钟',
bgColor: this.$green,
showType: 'newPage',
routerName: 'clock'
},
{
imgPath: require('../../assets/logo.png'),
text: '支付密码修改',
bgColor: this.$green,
showType: 'newPage',
routerName: 'changePayPassword'
},
{
imgPath: require('../../assets/logo.png'),
text: '短信代收',
bgColor: this.$green,
showType: 'newPage',
routerName: 'messageList'
},
{
imgPath: require('../../assets/logo.png'),
text: '亲友关注',
bgColor: this.$green,
showType: 'newPage',
routerName: 'management'
}
]
},
paramSetting: {
title: '参数设置',
list: [
{ imgPath: require('../../assets/logo.png'), text: '参数设置', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '远程设置', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '休眠设置', bgColor: 'red' }
{
imgPath: require('../../assets/logo.png'),
text: '参数设置',
bgColor: this.$green,
showType: 'newPage',
routerName: 'watchSetting'
},
{
imgPath: require('../../assets/logo.png'),
text: '远程控制',
bgColor: this.$green,
showType: 'newDialog',
routerName: 'remote'
},
{
imgPath: require('../../assets/logo.png'),
text: '休眠设置',
bgColor: this.$green,
showType: 'newPage',
routerName: 'sleep'
}
]
},
othersSetting: {
title: '其他设置',
list: [
{ imgPath: require('../../assets/logo.png'), text: '账号安全', bgColor: 'green' },
{ imgPath: require('../../assets/logo.png'), text: '常见问题', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '版本信息', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '关于我们', bgColor: 'red' },
{ imgPath: require('../../assets/logo.png'), text: '退出登录', bgColor: 'red' }
{
imgPath: require('../../assets/logo.png'),
text: '常见问题',
bgColor: this.$green,
showType: 'newPage',
routerName: 'help'
},
{
imgPath: require('../../assets/logo.png'),
text: '版本信息',
bgColor: this.$green,
showType: 'newDialog',
routerName: 'version'
},
{ imgPath: require('../../assets/logo.png'), text: '关于我们', bgColor: 'green' },
{
imgPath: require('../../assets/logo.png'),
text: '退出登录',
bgColor: 'green',
showType: 'newDialog',
routerName: 'logout'
}
]
},

userImg: require('../../assets/logo.png') //用户头像
userImg: require('../../assets/logo.png'), //用户头像
currentDevice: {
address: '',
lat: '',
lng: ''
}
};
},
created() {},
@@ -184,6 +266,7 @@ export default {
});

if (isNotNull(item.devicesList)) {
this.currentDevice = { ...item.devicesList[0] };
item.devicesList.forEach(val => {
if (val.deviceId == that.$store.getters.deviceId) {
this.$store.commit('roleUser', val.roleUser);
@@ -201,11 +284,15 @@ export default {
.finally(() => {
ToastService.clear();
});
},
goMap() {
this.$router.push({
name: 'location'
});
}
}
};
</script>
<style scoped lang="scss">
@import './index.scss';
/* @import url(); 引入css类 */
@import './index.scss'; /* @import url(); 引入css类 */
</style>

+ 581
- 0
src/views/myself/location.scss Wyświetl plik

@@ -0,0 +1,581 @@
.home {

overflow: hidden;
.map-con {
height: calc(100vh - 160px);
background-color: $background;
padding: 20px;
overflow: scroll;
.areaMask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 666;
}

.top {
width: 100%;
position: absolute;
top: 100px;
left: 0;
font-size: 16px;
/* 掉线提示语 */
.notice-is-online {
height: 80px;
position: relative;
z-index: 11;
.van-notice-bar {
height: 100%;
font-size: 16px;
.van-notice-bar__content {
font-size: 16px !important;
}
.van-notice-bar__left-icon {
font-size: 16px;
}
.van-notice-bar__wrap {
height: 80px;
line-height: 80px;
padding-left: 5px;
font-size: 16px;
}
.van-notice-bar__right-icon {
font-size: 16px;
}
}
}
i.news {
position: absolute;
right: 30px;
top: 30px;
width: 70px;
height: 70px;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 50%;
z-index: 11;

&:before {
content: '';
position: absolute;
left: 10px;
top: 10px;
width: 50px;
height: 50px;
@include icon;
@include icon_position(50, 50, 0, 150);
z-index: 8;
}

&.on {
&:after {
content: '';
position: absolute;
right: 2px;
top: 4px;
width: 16px;
height: 16px;
background: #f35151;
border-radius: 50%;

}
}
}
.shortcuts-container {
position: absolute;
right: 30px;
top: 15vh;
width: 110px;
padding: 20px 0;
background-color: #FFFFFF;
border-radius: 55px;
box-shadow: 0px 8px 25px 0px rgba(117,124,140,0.48);
opacity: 0.9;
z-index: 19;
.shortcuts {
position: relative;
border-width: 80%;
height: 80px;
@include center();
flex-direction: column;
padding: 10px;
margin: 10px 0;
/* .van-image {
height: 40px;
width: 40px;
} */
.layer {
height: 40px;
width: 28px;
}
.trajectory {
height: 40px;
width: 36px;
}
.warning {
height: 35px;
width: 40px;
}
.message {
height: 38px;
width: 38px;
}
.phone {
height: 36px;
width: 38px;
}
.spread_right {
height: 35px;
width: 34px;
}
.shortcuts-title {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
p {
font-size: 24px;
line-height: 40px;
color: #666;
padding-top: 8px;
}
}
}
.hide {
@include center();
}
// :nth-child(3)告警消息在哪里就给哪里添加样式 first-child
.shortcuts:nth-child(3) {
.news {
&:before {
}
&.on {
&:after {
content: '';
position: absolute;
right: 1px;
top: 4px;
width: 16px;
height: 16px;
background: #f35151;
border-radius: 50%;

}
}
}
}
.shortcuts:last-child {
border:none;
}
.shortcuts::after {
content: '';
width: 20px;
height: 1px;
display: block;
margin: 0 auto;
border-bottom: 1px solid rgba(151, 151, 151, 0.1);
}
}
.shortcuts-hide {
position: absolute;
right: 0;
top: 60vh;
height: 68px;
width: 129px;
background-color: #FFFFFF;
z-index: 19;
padding: 19px 0;
border-top-left-radius: 53px;
border-bottom-left-radius: 53px;
box-shadow: 0px 8px 25px 0px rgba(117,124,140,0.48);
opacity: 0.9;
p {
font-size: 24px;
margin: 0 34px 0 46px;
}
i {
/* @include icon_position(50, 50, 50, 200); */
background: no-repeat;
margin: 5px 42px 0 53px;
@include bgimg(url('../..//assets/img/home/spread_left.png'), 34, 35);
}
}
.noData {
position: absolute;
left: 0;
width: 100%;
height: 70px;
@include center();
@include colorAndFont(#ff9625, 28);
background-color: #ffe9d2;
z-index: 12;
}
.imgArea {
position: absolute;
top: 20px;
left: 20px;
padding: 8px;
display: flex;
justify-content: flex-start;
align-items: center;
background: #fff;
border-radius: 50px;
z-index: 13;


img {
width: 60px !important;
height: 60px !important;
border-radius: 50%;
object-fit: cover;
}

span {
padding: 0 12px;
@include colorAndFont(#333, 28);
}
}

.conArea {
position: absolute;
left: 0;
top: 0;
width: 100%;
padding: 12px 0 12px 20px;
background: #fff;
box-sizing: border-box;
display: flex;
transform: translateX(-100%);
transition: left .4s ease-in-out;
z-index: 667;
overflow: scroll;

&.active {
transform: translateX(0);
}

.list {
@include center();
flex-flow: column;
@include colorAndFont(#333, 24);
margin-right: 28px;

.Myname {
&.active {
text-decoration: underline;
font-weight: bold;
}
}

.imgA {
width: 100px;
height: 100px;
background: #c5c5c5;
border-radius: 50%;
position: relative;
@include center();
margin-bottom: 12px;



&>img {
width: 88px;
height: 88px;
border-radius: 50%;
object-fit: cover;
}

&.active {
width: 105px;
height: 105px;
position: relative;
background: #c5c5c5;
box-shadow: 0 0 10px 4px rgba(185, 185, 185, 0.8);

&:after {
content: '';
position: absolute;
bottom: -15px;
width: 0;
height: 0;
border-top: 16px solid #c5c5c5;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
}
}

&.online {
background: #5fcc0e;

&.active {
position: relative;
background: #5fcc0e;
box-shadow: 0 0 10px 4px rgba(95, 204, 14, 0.8);

&:after {
content: '';
position: absolute;
bottom: -15px;
width: 0;
height: 0;
border-top: 16px solid #5fcc0e;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
}
}
}
}

}
}
}

.bottom {
width: 100%;
position: fixed;
left: 0;
bottom: 0;
z-index: 600;
box-shadow: 0 0 20px rgba(185, 185, 185, 0.4);

.conArea {
position: relative;

.toggle {
position: absolute;
left: 20px;
// top: px2rem(-238);
top: -154px;
width: 84px;
background: #fff;
border-radius: 10px;
@include center();
flex-flow: column;

span {
width: 84px;
height: 92px;
@include center();

i {
width: 50px;
height: 50px;
@include icon;
@include icon_position(50, 50, 0, 200);

&.tole {
@include icon_position(50, 50, 300, 100);
}
}

// &:last-child i {
// @include icon_position(50, 50, 0, 300);

// &.on {
// -webkit-transform: rotate(360deg);
// animation: rotation 1s linear infinite;
// -moz-animation: rotation 1s linear infinite;
// -webkit-animation: rotation 1s linear infinite;
// -o-animation: rotation 1s linear infinite;
// }
// }

}
}
.con {
margin-bottom: 5px;
padding: 20px 0 0 28px;
// min-height: px2rem(184);
background: #fff;
border-radius: 24px 24px 0 0;
// box-shadow: 0 5px 4px palegoldenrod;

.title {
width: 600px;
@include colorAndFont(#333, 34);
margin-bottom: 36px;
}

.adr {
// @include colorAndFont(#999, 28);
// padding-right: px2rem(140);
// margin-bottom: 36px;

span {
margin-left: 15px;
padding: 0 8px;
height: 30px;
@include colorAndFont(#999, 20);
background: #fafafa;
border: 1px solid #b5b5b5;
border-radius: 4px;
}
}

.states {
display: flex;
justify-content: flex-start;
align-items: center;

span {
display: flex;
justify-content: flex-start;
align-items: center;
@include colorAndFont(#999, 24);

em {
position: relative;
margin-right: 10px;
padding: 1px;
width: 34px;
height: 20px;
border: 2px solid #5fcc0e;
border-radius: 4px;
box-sizing: border-box;
display: flex;
align-items: center;

i {
content: '';
width: 100%;
height: 100%;
background: #5fcc0e;
}

&:after {
content: ' ';
width: 4px;
height: 8px;
background: #5fcc0e;
position: absolute;
right: -4px;
}

&.red {
@include center();
border-color: #ff4b21;
background: transparent;

i {
width: 11px;
height: 14px;
@include icon;
@include icon_position(11, 14, 20, 125);
}

&:after {
background: #ff4b21;
}
}

&.warn {
justify-content: flex-start;
border-color: #ff4b21;
background: transparent;

i {
background: #ff4b21;
}

&:after {
background: #ff4b21;
}
}
}

&:first-child {
color: $blue;
margin-right: 24px;
// &:before {
// content: '';
// margin-right: 10px;
// display: inline-block;
// width: 42px;
// height: px2rem(26);
// background: #ff8c8c;
// }
}
}
}

.operate {
position: absolute;
right: 40px;
top: -50px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-flow: column;

span {
width: 84px;
height: 84px;
background: #fff;
border-radius: 50%;
margin-top: 4px;
margin-bottom: 20px;
box-shadow: 0 0 14px 2px rgba(150, 150, 150, 0.4);
@include center();

i {
width: 50px;
height: 50px;
@include icon;
@include icon_position(50, 50, 0, 300);
}

&.position {
background: $blue;
box-shadow: 0 0 14px 2px rgba(37, 153, 255, 0.4);
i {
@include icon_position(50, 50, 0, 350);

&.on {
-webkit-transform: rotate(360deg);

animation: rotation 1s linear infinite;

-moz-animation: rotation 1s linear infinite;

-webkit-animation: rotation 1s linear infinite;

-o-animation: rotation 1s linear infinite;
}
}
.interval-time {
@include colorAndFont(#eee, 24);
}
.icon-loading {
/* position: absolute;
top: 0;
left: 0; */
height: 40px;
width: 40px;
.van-loading__circular {
background: #3296fa;
}
}
}
}

em {
font-style: normal;
@include colorAndFont(#999, 20);
}
}
}
}



.tarbar {
position: relative;
}
}
}
}

+ 1705
- 0
src/views/myself/location.vue
Plik diff jest za duży
Wyświetl plik


+ 260
- 0
src/views/myself/management.vue Wyświetl plik

@@ -0,0 +1,260 @@
<template>
<div class="management">
<van-nav-bar title="用户列表" left-arrow @click-left="onNavBack">
<van-icon name="friends-o" slot="right" v-show="show" id="friends-o" @click="onIconClick" />
</van-nav-bar>
<div class="management-con">
<van-cell v-for="(item, index) in listData" :key="`management_${index}`">
<img :src="item.imagePath" />
<div class="con">
<span class="cell">
{{ item.relationName }}
<i>({{ item.userName }})</i>
</span>
<span>{{ item.userMobile }}</span>
</div>
<em v-show="item.bindType == 0">(管理员)</em>
</van-cell>
</div>
</div>
</template>

<script>
import APIUser from '@/api/user';
export default {
data() {
return {
listData: [],
show: false
};
},
methods: {
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
getListData() {
/* let url = `/api/User/AdminList`;
let jsonData = {
deviceId: this.$store.getters.deviceId
}; */
/* this.$axios
.post(url, jsonData) */
APIUser.getAdminList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
console.log(res.data);
let item = res.data;
this.listData = item.adminList;
item.adminList.forEach(val => {
if (val.userId == this.$store.getters.userId && val.bindType == 0) {
this.show = true;
}
});
})
.catch(err => {
console.log(err);
});
},
onIconClick() {
this.$router.push({ name: 'replace' });
}
},
created() {
this.getListData();
}
};
</script>

<style lang="scss" scoped>
i#friends-o {
color: #2599ff !important;
font-size: 48px !important;
}
.management {
position: relative;
.management-con {
position: relative;
height: calc(100vh - 160px);
overflow: scroll;
.van-cell {
position: relative;
width: 100%;
height: 60px;
align-items: center;
padding: 0 16px;
box-sizing: border-box;
background-color: #fff;

&:after {
content: '';
@include border();
}

&:nth-child(2) {
margin-top: 20px;
}

&:not(:last-child):after {
left: 0;
border-color: $border_color;
}

i {
font-size: 16px;
}

.van-cell__value {
display: flex;
align-items: center;
height: 100%;
position: relative;

img {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 15px;
object-fit: cover;
}

.con {
display: flex;
justify-content: center;
align-items: flex-start;
flex-flow: column;

span {
@include colorAndFont(#999, 20);
line-height: 1;

&.cell {
@include colorAndFont(#333, 17);
margin-bottom: 7px;

&.mbnone {
margin-bottom: 0;
}

i {
margin-left: -14px;
font-style: normal;
@include colorAndFont(#999, 17);
}
}
}
}

input[type='text'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}
input[type='number'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}
input[type='tel'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}

.van-switch {
position: absolute;
right: 0;
}

em {
font-style: normal;
position: absolute;
right: 0;
@include colorAndFont(#999, 18);

&.fs30 {
font-size: 30px;
margin-right: 24px;
color: red;
span {
color: #000;
margin-right: 20px;
}
}

&.circle {
width: 32px;
height: 32px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;

&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
.tips-container {
padding: 20px;
p {
font-size: 32px;
color: red;
margin: 20px;
line-height: 55px;
}
}

.submit {
@include flexbox(flex-end, center, column, nowrap);
flex-flow: column;
padding: 0 40px;
position: absolute;
left: 0;
bottom: 82px;

a {
@include flexbox(flex-end, center, column, nowrap);
margin-bottom: 40px;
width: 578px;
height: 88px;
background: $next;
color: #fff;
font-size: 17px;
border-radius: 10px;

&.next {
background: $green;
}
}
}
}
}
</style>

+ 227
- 0
src/views/myself/messageList.vue Wyświetl plik

@@ -0,0 +1,227 @@
<template>
<div class="message-list">
<van-nav-bar title="短信代收" left-arrow :border="true" @click-left="onNavBack" />
<div class="newsNotData" v-show="list.length == 0">宝贝暂时还没有短信记录~</div>
<!-- 下拉加载 -->

<!-- todo -->
<van-tabs v-model="tabActive" v-show="false">
<van-tab>
<template #title> <van-icon name="more-o" />选项 </template>
内容 {{ tabActive }}
</van-tab>
<van-tab>
<template #title> <van-icon name="more-o" />选项 </template>
内容 {{ tabActive }}
</van-tab>
</van-tabs>

<van-list
v-model="loading"
class="call-list-container"
:finished="finished"
finished-text
:immediate-check="false"
@load="onLoad"
>
<!-- 有短信的样式 -->
<div v-for="(item, index) in list" class="call-list" :key="index">
<van-row type="flex" justify="center" class="date-row">
<van-col span="12"></van-col>
</van-row>
<div class="call-list-content">
<van-row type="flex" justify="center">
<van-col span="12">
<p class="send-number">
<span style="color: #999">发送方:</span>
{{ item.sendNumber || '' }}
</p>
</van-col>
<van-col span="11" offset="1">
<p class="time">{{ item.createTime || '' }}</p>
</van-col>
</van-row>
<van-row type="flex" justify="center">
<van-col span="24">
<p class="call-list-detail">{{ item.smsContent || '' }}</p>
</van-col>
</van-row>
<van-row type="flex" justify="center">
<van-col span="14">
<p class="receive-number" v-show="item.receiveNumber">接收方:{{ item.receiveNumber || '' }}</p>
</van-col>
<van-col span="9" offset="1">
<p class="time" v-show="item.readFlag">宝贝{{ item.readFlag ? '已读' : '未读' }}</p>
</van-col>
</van-row>
</div>
</div>
</van-list>
</div>
</template>

<script>
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
// 引入List
import APIDevice from '../../api/device';
export default {
data() {
return {
loading: false,
finished: false, //没有更多了 加载完
list: [],
pageNumber: 8,
begNumber: 1,
tabActive: 0
};
},
methods: {
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
// 上拉加载
onLoad() {
this.loading = false;
// setTimeout(()=>{
// console.log('触发了加载');
// this.pageNumber=this.pageNumber+=2;
// this.getCallList(this.pageNumber);
// this.loading=false;
// if(this.list.length<=8){
// this.loading = false;
// this.finished=true;
// }
// },1500)
},
// 获取数据
getCallList() {
ToastService.loading();
/* let url = `/api/DeviceCommunication/SetSMSLog`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
pageNumber: this.pageNumber,
begNumber: this.begNumber
}; */
/* this.$axios.post(url, jsonData) */
APIDevice.setSMSLog({
deviceId: this.$store.getters.deviceId,
pageNumber: this.pageNumber,
begNumber: this.begNumber
}).then(res => {
if (res.data.stateCode === 1) {
// console.log(res.data);
this.list = res.data.smsLogList || [];
this.assembleData();
ToastService.clear();
ToastService.success({
message: '获取成功'
});
} else {
DialogService.confirm({
title: res.data.message
});
}
});
},
assembleData() {
if (this.list.length > 0) {
this.list = this.list.map(item => {
if (item.createTime) {
let pastTime = item.createTime;
// eslint-disable-next-line no-useless-escape
let lastTime = pastTime.replace(/\-/g, '/');
item.createTime = lastTime;
}
return item;
});
}
}
},

created() {
this.getCallList();
}
};
</script>

<style lang="scss">
// 上拉加载样式
.message-list {
.van-list__finished-text,
.van-loading__text {
font-size: 36px !important;
margin-top: 20px !important;
}

.van-tab {
font-size: 28px;
display: flex;
justify-content: center;
.van-tab__text {
margin: auto;
}
}
.newsNotData {
height: calc(100vh - 160px);
font-size: 32px;
@include flexbox(center, center, column, nowrap);
}
.call-list-container {
height: calc(100vh - 160px);
overflow: scroll;
padding-bottom: 20px;
background-color: $background;
}

.call-list {
padding: 20px;
.date-row {
background-color: $background;
}
.call-list-date {
color: #999;
font-size: 24px;
text-align: center;
margin-bottom: 30px;
}
.call-list-content {
background-color: #fff;
padding: 40px;
border-radius: 30px;
.send-number {
font-size: 28px;
color: #999;
}
.time {
text-align: right;
font-size: 28px;
color: #999;
}
.receive-number {
text-align: left;
font-size: 28px;
color: #999;
}
.call-list-record {
color: #313131;
font-size: 30px;
margin-bottom: 20px;
}
.call-list-detail {
color: #999;
font-size: 24px;
}
}
.record {
color: #313131;
font-size: 26px;
}
.detail {
color: #666;
font-size: 28px;
}
}
}
</style>

+ 435
- 0
src/views/myself/news/news.vue Wyświetl plik

@@ -0,0 +1,435 @@
<template>
<div class="news">
<van-nav-bar title="消息通知" left-arrow @click-left="onNavBack" left-text="返回" />
<div class="list-con">
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
<div class="item">
<div :class="[formatClass(item.typeName), 'list']" v-for="(item, index) in listData" :key="index">
<div class="title">
<span>{{ new Date($own.formatTime(item.time)).Format('MM月dd日 hh:mm') }}</span>
</div>
<div class="con" @click="listClick(item.typeName, item)">
<div class="left">
<i></i>
</div>
<div class="left">
<p class="tit">{{ formatClass(item.typeName, true) }}</p>
<p class="time">{{ new Date($own.formatTime(item.time)).Format('yyyy-MM-dd hh:mm:ss') }}</p>
<p>{{ item.message }}</p>
</div>
<div class="right" v-show="formatClass(item.typeName) == 'sos' || item.typeName == 'DrownReport'">
详情
</div>
</div>
</div>
</div>
</van-list>
<div class="newsNotData" v-if="!isHasData">暂无消息~</div>
</div>
</div>
</template>

<script>
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
import APIUser from '@/api/user';
export default {
data() {
return {
personName: '',
listData: [],
loading: false,
finished: false,
pageNumber: 5, //每次显示多少条
begNumber: 1, //页数
isHasData: false //是否存在数据
};
},
methods: {
// 返回
onNavBack() {
// this.$router.go(-1);
// todo 此处不能修改为 go(-1);因为情景有:微信推送时进入该页面,此时点击返回就该路由至首页。
this.$router.push({ name: 'location' });
},
getData(begNumber, pageNumber, firstLoad) {
/* let url = "/api/Alarm/AlarmList";
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
pageNumber,
begNumber,
timeOffset: -new Date().getTimezoneOffset() / 60
};
this.$axios
.post(url, jsonData) */
if (firstLoad) {
ToastService.loading({
message: '加载中'
});
}
APIUser.alarmList({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
pageNumber,
begNumber,
timeOffset: -new Date().getTimezoneOffset() / 60
})
.then(res => {
let item = res.data;
this.isHasData = item.alarmList.length > 0;
item.alarmList.forEach(val => {
this.listData.push(val);
});
this.loading = false;
if (item.alarmList == null || item.alarmList.length == 0) {
this.finished = true;
}
})
.catch(err => {
console.log(err);
})
.finally(() => {
ToastService.clear();
});
},
listClick(name, item) {
if (name == 'SOS') {
this.$router.push({ name: 'details', query: item });
} else if (name == 'DrownReport') {
// 重新组装接口数据
let queryData = item.urlDetail.split('?');
let params = queryData[1].split('&');
let queryBody = {
imei: this.formatUrl(params, 'imei'),
poiId: this.formatUrl(params, 'poiId'),
title: this.formatUrl(params, 'title'),
lng: this.formatUrl(params, 'lng'),
lat: this.formatUrl(params, 'lat'),
address: this.formatUrl(params, 'address'),
time: this.formatUrl(params, 'time'),
status: this.formatUrl(params, 'status'),
showBack: '1'
};
this.$router.push({ name: 'dangerAreaDetails', query: queryBody });
}
},
formatUrl(params, name) {
let valueList = params
.filter(item => {
return item.split('=')[0] === name;
})[0]
.split('=');
return valueList[1];
},
formatClass(val, text) {
let value = '';
/* Area = 6,//区域警告
Temperature = 10,//体温推送
CallLog = 11, //话单推送
Healthy = 12, //心率、血氧、血压推送
DrownReport = 13, //水域告警推送
NoWear = 14, //水域告警推送 */
switch (val) {
case 'SOS':
value = text ? '报警通知' : 'sos';
break;
case 'LowBattery':
value = text ? '电量通知' : 'warning';
break;
case 'Entry':
case 'Exit':
value = text ? '围栏通知' : 'outOfRange';
break;
case 'PowerOff':
value = text ? '关机报警' : 'off';
break;
case 'Area':
value = text ? '区域报警' : 'area';
break;
/* case "Temperature":
value = text ? '体温报警' : 'default'
break; */
case 'CallLog':
value = text ? '话单推送' : 'callLog';
break;
case 'Healthy':
value = text ? '健康通知' : 'healthy';
break;
case 'DrownReport':
value = text ? '水域通知' : 'drownReport';
break;
case 'NoWear':
value = text ? '携带监测' : 'noWear';
break;
}
return value;
},
onLoad() {
this.begNumber++;
this.getData(this.begNumber, this.pageNumber);
}
},
mounted() {
this.getData(this.begNumber, this.pageNumber, true);
let url = window.location.search;
let id = url.split('user_id=')[1];
let alarmUrl = window.location.href.split('msgId=')[1];
if (alarmUrl) {
this.$router.push({ name: 'alarmDetails', query: { msgId: alarmUrl } });
}
if (id) {
if (id != this.$store.getters.userId) {
DialogService.confirm({
title: '登录失效,请重新登录~'
}).then(() => {
this.$router.push({ name: 'login' });
});
}
}
console.log(this.$store.getters.userId);
}
};
</script>
<style lang="scss" scoped>
.news {
height: 100vh;
overflow: hidden;
background-color: $background;
.list-con {
position: relative;
height: calc(100vh - 160px);
overflow: scroll;
.newsNotData {
@include center();
font-size: 32px;
padding: 20px;
}

.item {
padding: 0 35px;
display: flex;
flex-flow: column;
justify-content: flex-start;
align-items: center;

.list {
width: 100%;

.title {
@include center;
margin: 20px 0;

span {
padding: 8px 12px;
@include colorAndFont(#fff, 24);
border-radius: 25px;
background: #d1d1d1;
}
}

.con {
padding: 18px 20px 35px;
position: relative;
width: 100%;
background: #fff;
border-radius: 10px;
box-sizing: border-box;
display: flex;
align-items: center;

.left {
display: flex;
align-items: flex-start;
flex-flow: column;

i {
width: 80px;
height: 80px;
border-radius: 50%;
margin-right: 15px;
@include center();
&:after {
content: '';
position: absolute;
}
}

p {
@include colorAndFont(#787878, 28);

&.tit {
@include colorAndFont(#313131, 32);
font-weight: 600;
margin-bottom: 2px;
}

&.time {
@include colorAndFont(#b4b7be, 24);
margin-bottom: 12px;
}
}
}

.right {
padding: 5px 20px;
position: absolute;
top: 30px;
right: 30px;
background: $blue;
border-radius: 4px;
@include colorAndFont(#fff, 28);
}
}

&.warning {
.con {
.left {
i {
background: #ff4c39;

&:after {
width: 24px;
height: 40px;
@include icon;
@include icon_position(24, 40, 368, 6);
}
}
}
}
}

&.sos {
.con {
.left {
i {
background: #ffa92f;

&:after {
width: 56px;
height: 19px;
@include icon;
@include icon_position(56, 19, 306, 20);
}
}
}
}
}

&.outOfRange {
.con {
.left {
i {
background: $blue;

&:after {
width: 52px;
height: 52px;
@include icon;
@include icon_position(52, 52, 251, 0);
}
}
}
}
}

&.off {
.con {
.left {
i {
background: #fd6666;

&:after {
width: 50px;
height: 50px;
@include icon;
@include icon_position(50, 50, 300, 150);
}
}
}
}
}
&.default {
.con {
.left {
i {
background: $background;
&:after {
width: 60px;
height: 60px;
@include icon;
@include icon_position(50, 50, 250, 200);
}
}
}
}
}
&.drownReport {
.con {
.left {
i {
background: $next;
@include center();
&:after {
width: 50px;
height: 50px;
background: url('~@/assets/img/drownReport.png') no-repeat;
background-size: 50px;
}
}
}
}
}
&.callLog {
.con {
.left {
i {
background: $background;
@include center();
&:after {
width: 50px;
height: 50px;
background: url('~@/assets/img/callLog.png') no-repeat;
background-size: 50px;
}
}
}
}
}
&.healthy {
.con {
.left {
i {
background: $background;
@include center();
&:after {
width: 50px;
height: 50px;
background: url('~@/assets/img/healthy.png') no-repeat;
background-size: 50px;
}
}
}
}
}
&.noWear {
.con {
.left {
i {
background: $background;
@include center();
&:after {
width: 50px;
height: 50px;
background: url('~@/assets/img/noWear.png') no-repeat;
background-size: 50px;
}
}
}
}
}
}
}
}
}
</style>

+ 252
- 0
src/views/myself/prohibit.vue Wyświetl plik

@@ -0,0 +1,252 @@
<template>
<div class="prohibit" :style="{ background: listData.length == 0 ? '#fff ' : '#f2f4f5' }">
<van-nav-bar title="上课禁止时段" left-arrow :border="true" @click-left="onNavBack">
<van-icon name="plus" slot="right" id="plus-icon" @click="onAddClick" />
</van-nav-bar>
<div class="prohibit-list-container" v-show="isShowPage">
<div class="con" v-show="listData.length > 0">
<!-- 内容 -->
<van-cell v-for="(item, index) in listData" :key="`prohibit_${index}`">
<van-swipe-cell>
<div class="area">
<div :class="[{ active: item.Active }, 'left']" @click="listClick(item)">
<div class="title">{{ item.StartTime }}-{{ item.EndTime }}</div>
<div class="date">
<span v-for="(data, index) in formatWeekdays(item.Weekdays)" :key="`date_${index}`">{{ data }}</span>
<span>
<van-icon
name="lock"
v-if="!item.Editable && item.RecordType === prohibitModel.recordType.manufactor"
/>
</span>
</div>
</div>
<van-switch :value="item.Active == 1" @input="onInput($event, item.Id)" :active-color="$green" />
</div>
<template slot="right">
<van-button square type="danger" text="删除" @click="onClose(item)" />
</template>
</van-swipe-cell>
</van-cell>
<div class="watchTips" v-show="deviceType == '2'">
<p>课堂免打扰时段不能使用设备,也不能呼入电话及无响铃</p>
</div>
</div>

<div class="noData_img" v-show="listData.length == 0">
<div v-if="deviceType == '1'" class="watchTips">您还没有给定位卡设置禁用时段,快去添加吧~</div>
<div v-else class="watchTips">
<p>请点击右上角“+”号添加课堂免打扰时段。</p>
<p>课堂免打扰时段不能使用设备,也不能呼入电话及无响铃</p>
</div>
</div>
</div>
</div>
</template>

<script>
import { DeviceCommandModel, ProhibitModel } from '../../config/models';
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
import APICommand from '@/api/command';
export default {
data() {
return {
switchShow: false,
listData: [],
serialNo: '',
prohibitModel: ProhibitModel,
deviceType: this.$store.getters.deviceType,
isShowPage: false
};
},
methods: {
// 返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
getCommandList() {
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId }; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
ToastService.clear();
console.log(res.data);
let item = res.data;
let listData = [];
let cmdData = item.items.filter(val => val.cmdCode == DeviceCommandModel.prohibition);
let parseValue = JSON.parse(cmdData[0].cmdValue);
parseValue.Items.forEach(val => {
listData.push(val);
});
this.listData = listData;
this.isShowPage = true;
})
.catch(() => {
ToastService.clear();
this.isShowPage = true;
})
.finally(() => {
ToastService.clear();
});
},
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
}; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
let item = res.data;
let status = item.stateCode == 1 ? '操作成功' : '保存失败,请重新设置';
ToastService.clear();
if (item.stateCode == 1) {
ToastService.success({ message: status });
} else {
DialogService.confirm({ title: '操作失败,请重新设置' });
}
})
.catch(() => {
ToastService.clear();
})
.finally(() => this.getCommandList());
},
onAddClick() {
this.$router.push({
name: 'setupProhibitPeriod',
query: { title: '添加上课禁用时段', code: this.$route.query.code }
});
},
switchClick() {
this.switchShow = !this.switchShow;
},
onInput(checked, id) {
this.listData.map(val => {
if (val.Id == id) {
val.Active = checked ? 1 : 0;
}
return val;
});
console.log(this.listData);
let cmdCode = DeviceCommandModel.prohibition;
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
},
listClick(item) {
if (item.RecordType !== ProhibitModel.recordType.manufactor) {
this.$router.push({
name: 'setupProhibitPeriod',
query: { title: '设置时段', code: this.$route.query.code, id: item.Id, show: false }
});
} else {
this.tipsOnEditable();
}
},
tipsOnEditable() {
DialogService.confirm({
title: '抱歉,该记录不可操作',
message: '该记录为教师端所设,家长端不可以操作'
});
},
formatWeekdays(str) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
switch (Number(val)) {
case 1:
newArr.push('周一 ');
break;
case 2:
newArr.push('周二 ');
break;
case 3:
newArr.push('周三 ');
break;
case 4:
newArr.push('周四 ');
break;
case 5:
newArr.push('周五 ');
break;
case 6:
newArr.push('周六 ');
break;
case 7:
newArr.push('周日 ');
break;
default:
newArr = [];
}
});
return newArr;
},
//滑动单元格
onClose(item) {
if (item.RecordType !== ProhibitModel.recordType.manufactor) {
const req = this.listData.filter(val => val.Id !== item.Id);
let cmdCode = DeviceCommandModel.prohibition;
let cmdValue = {
Items: req
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
ToastService.success({ message: '操作成功' });
} else {
this.tipsOnEditable();
}
}
},
computed: {},
created() {
this.getCommandList();
}
};
</script>
<style lang="scss" scoped>
.prohibit {
height: 100vh;
.prohibit-list-container {
/* padding: 30px; */
height: calc(100vh - 160px);
overflow: scroll;
.con {
width: 100%;
background: #fff;
margin-bottom: 50px;
.area {
padding: 0 30px;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
}
.noData_img,
.watchTips {
font-size: 32px;
height: 400px;
@include flexbox(center, center, column, nowrap);
}
}
}
</style>

+ 321
- 0
src/views/myself/replace.vue Wyświetl plik

@@ -0,0 +1,321 @@
<template>
<div class="replace">
<div class="management oh_100vh_bgColor">
<van-nav-bar title="管理员转让" left-arrow @click-left="$router.push({ name: 'management' })" />
<div class="management-con">
<van-cell v-for="(item, index) in listData" :key="`list_data_${index}`" @click="listClick(index, item.userId)">
<img :src="item.imagePath" />
<div class="con">
<span class="cell">
{{ item.relationName }}
<i v-show="item.userName != ''">({{ item.userName }})</i>
</span>
<span>{{ item.userMobile }}</span>
</div>
<em :class="[{ on: index == active }, 'circle']"></em>
</van-cell>
<div class="submit">
<div class="btn" :class="[{ next: blueClass }]" @click="onSubmitClick">转让管理员</div>
</div>
</div>
</div>
</div>
</template>

<script>
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
export default {
data() {
return {
active: -1,
listData: [],
mainUserId: '',
viceUserId: ''
};
},
methods: {
getUsersList() {
let url = `/api/User/AdminList`;
let jsonData = {
deviceId: this.$store.getters.deviceId
};
this.$axios
.post(url, jsonData)
.then(res => {
console.log(res);
let item = res.data;
let newData = [];
newData = item.adminList;

newData.forEach((val, index) => {
if (val.bindType == 0) {
this.active = index;
this.mainUserId = val.userId;
}
});

this.listData = newData;
})
.catch(() => {});
},
listClick(index, id) {
this.active = index;
this.viceUserId = id;
},
onSubmitClick() {
if (!this.listData || this.listData.length == 1) {
DialogService.confirm({
title: '当前账号已是主管理员'
});
} else {
DialogService.confirm({
title: '转让管理员',
message: '是否确定转让管理员?',
confirmButtonText: '转让管理员',
showCancelButton: true
})
.then(() => {
if (this.mainUserId == this.viceUserId || this.viceUserId == '') {
DialogService.confirm({
title: '当前账号已是主管理员'
});
} else {
let url = `/api/User/AdminTransfer`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
mainUserId: this.mainUserId,
viceUserId: this.viceUserId
};
this.$axios
.post(url, jsonData)
.then(res => {
let item = res.data;
console.log(item);
if (item.stateCode == 0) {
DialogService.confirm({
title: item.message
});
} else {
ToastService.clear();
ToastService.success({
message: '转让成功'
});
}
})
.catch(() => {});
}
})
.catch(() => {});
}
}
/* dialog(message) {
this.$dialog.confirm({
title: message,
className: "device_confirm",
confirmButtonColor: "#3296fa",
cancelButtonColor: "#999",
overlayStyle: { backgroundColor: "rgba(0,0,0,.5)" },
showCancelButton: false
});
} */
},
computed: {
blueClass() {
return this.listData && this.listData.length != 1;
}
},
created() {
this.getUsersList();
}
};
</script>
<style lang="scss" scoped>
i#friends-o {
color: #2599ff !important;
font-size: 48px !important;
}
.replace {
.management {
position: relative;
.management-con {
position: relative;
height: calc(100vh - 160px);
overflow: scroll;
.van-cell {
position: relative;
width: 100%;
height: 60px;
align-items: center;
padding: 0 16px;
box-sizing: border-box;
background-color: #fff;

&:after {
content: '';
@include border();
}

&:nth-child(2) {
margin-top: 20px;
}

&:not(:last-child):after {
left: 0;
border-color: $border_color;
}

i {
font-size: 16px;
}

.van-cell__value {
display: flex;
align-items: center;
height: 100%;
position: relative;

img {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 15px;
object-fit: cover;
}

.con {
display: flex;
justify-content: center;
align-items: flex-start;
flex-flow: column;

span {
@include colorAndFont(#999, 20);
line-height: 1;

&.cell {
@include colorAndFont(#333, 17);
margin-bottom: 7px;

&.mbnone {
margin-bottom: 0;
}

i {
margin-left: -14px;
font-style: normal;
@include colorAndFont(#999, 17);
}
}
}
}

input[type='text'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}
input[type='number'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}
input[type='tel'] {
position: absolute;
right: 0;
display: flex;
width: 200px;
height: 70px;
@include colorAndFont(#999, 28);
text-align: right;
}

.van-switch {
position: absolute;
right: 0;
}

em {
font-style: normal;
position: absolute;
right: 0;
@include colorAndFont(#999, 16);

&.fs30 {
font-size: 30px;
margin-right: 24px;
color: red;
span {
color: #000;
margin-right: 20px;
}
}

&.circle {
width: 20px;
height: 20px;
border: 2px solid #bfbfbf;
border-radius: 50%;
position: absolute;
right: 15px;

&.on {
border-color: $green;
&:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 16px;
height: 16px;
background: $green;
border-radius: 50%;
}
}
}
}
}
}
.tips-container {
padding: 20px;
p {
font-size: 32px;
color: red;
margin: 20px;
line-height: 55px;
}
}

.submit {
@include center();
padding: 0 80px;
position: absolute;
left: 0;
bottom: 82px;
.btn {
@include center();
width: 578px;
height: 88px;
background: $next;
color: #fff;
font-size: 36px;
border-radius: 10px;

&.next {
background: $green;
}
}
}
}
}
}
</style>

+ 157
- 0
src/views/myself/sendMessage.vue Wyświetl plik

@@ -0,0 +1,157 @@
<template>
<div class="sendMessage">
<van-nav-bar title="留言" left-arrow :border="true" @click-left="onNavBack"></van-nav-bar>
<div class="mt20"></div>
<div class="textArea">
<textarea
placeholder="请输入内容"
v-model.trim="inputVal"
@input="inputChange"
maxlength="70"
@blur="fixScroll"
/>
<span class="text">{{ this.num }}/70</span>
</div>
<div :class="[{ active: inputVal.length > 0 }, 'next']" @click="onSendCommand">发送</div>
</div>
</template>

<script>
import { DeviceCommandModel } from '../../config/models';
import ToastService from '../../services/toast-service';
import DialogService from '../../services/dialog-service';
import APICommand from '@/api/command';
export default {
data() {
return {
inputVal: '',
num: 0,
isSending: false
};
},
methods: {
//返回
onNavBack() {
this.$router.push({ name: this.$route.query.from ? this.$route.query.from : 'Myself' });
},
inputChange() {
this.num = this.inputVal.length;
},
fixScroll() {
let u = navigator.userAgent;
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if (isiOS) {
window.scrollTo(0, 0);
}
},
onSendCommand() {
// TODO 修改按钮的触发形式:输入字符串为空时,不可提交
// if (this.inputVal === '') return;
ToastService.loading();
if (this.inputVal === '' && this.isSending == false) {
console.log('not ok');
ToastService.clear();
DialogService.confirm({ title: '请输入内容' });
}
// if (this.isSending) {
// return;
// }
this.isSending = false;
/* let url = `/api/Command/SendCommand`; */
let cmdValue = {
Username: this.longName,
Parameter: this.inputVal
};
/* let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode: DeviceCommandModel.sendMsg,
cmdValue: JSON.stringify(cmdValue)
}; */

if (this.inputVal.length > 0) {
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode: DeviceCommandModel.sendMsg,
cmdValue: JSON.stringify(cmdValue)
})
.then(res => {
ToastService.clear();
let item = res.data;
if (item.stateCode == 1) {
console.log(item);
ToastService.clear();
ToastService.success({ message: '发送成功' });
this.inputVal = '';
this.inputChange();
} else {
ToastService.clear();
DialogService.confirm({
title: '发送失败,请重新设置'
});
this.inputVal = '';
}
})
.catch(err => console.log(err))
.finally(() => (this.isSending = false));
}
}
},
created() {
this.idCode = this.$route.query.code;
this.longName = this.$route.query.longName;
}
};
</script>
<style lang="scss" scoped>
.sendMessage {
background-color: $background;

.mt20 {
height: 20px;
background-color: $background;
}

.textArea {
position: relative;
.text {
position: absolute;
right: 30px;
bottom: 30px;
@include colorAndFont(#999, 24);
}
}

.next {
@include center();
margin: 100px auto 0;
width: 550px;
height: 80px;
border-radius: 10px;
background: $next_green;
color: #fff;
font-size: 36px;

&.active {
background: $green;
}

&.res {
margin: 140px auto 0;
}
}

textarea {
padding: 20px 30px;
width: 100%;
height: 354px;
box-sizing: border-box;
@include colorAndFont(#666, 34);
}
}
</style>

+ 317
- 0
src/views/myself/setupClockPeriod.vue Wyświetl plik

@@ -0,0 +1,317 @@
/* * @Author: chenjinxu * @Date: 2021-04-15 10:48:22 * @Last Modified by: chenjinxu * @Last Modified time: 2021-05-06
18:55:52 */
<template>
<div class="period oh_100vh_bgColor">
<van-nav-bar title="设置闹钟" left-text="返回" @click-left="onNavBack">
<template #right>
<div class="setupClock_save" @click="onSubmit">保存</div>
</template>
</van-nav-bar>
<div class="top">
<van-datetime-picker
v-model="startTime"
type="time"
:min-hour="0"
:max-hour="23"
:show-toolbar="false"
:item-height="itemHeight"
:visible-item-count="3"
/>
</div>
<van-cell value-class="week-value" title="重复周期" is-link @click="popupShowClick">
<span
v-show="checkData.length != 0"
class="text"
v-for="(item, index) in checkData"
:key="`check_data_${index}`"
>{{ item.value.slice(1, 3) }}</span
>
<span v-show="checkData.length == 0" class="text">不勾选周期时默认为一次性闹钟</span>
</van-cell>

<week :popupShow="popupShow" :checkValue="checkData" @emitCheckboxValue="handleCheckboxValue" />
</div>
</template>

<script>
import week from './week';
import { DeviceCommandModel } from '../../config/models';
import APICommandList from '../../api/command-list';
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
import APICommand from '@/api/command';
export default {
components: { week },
data() {
return {
itemHeight: Number(((document.body.clientWidth / 750) * 98).toFixed()),
startTime: '08:30',
popupShow: false,
checkData: [],
listData: [],
repeatStr: '', //重复的数据
isSaving: false
};
},
computed: {
checkDataFormat() {
let data = '';
if (this.checkData.length > 0) {
this.checkData.forEach(val => {
data += val.id;
});
} else {
return '';
}
return data;
},
isAdd() {
return this.$own.isNull(this.$route.query.id);
}
},
created() {
this.getCommandList();
this.formatObj();
},
mounted() {},
methods: {
//返回
onNavBack() {
this.$router.go(-1);
},
// todo 命名
async getList() {
ToastService.loading();
try {
let result = await APICommandList.getClocks();
if (result.data.stateCode === 1) {
this.listData = APICommandList.getCmdValue(result.data.items, DeviceCommandModel.clock);
const cmdValue = this.updateList();
let res = await APICommandList.setClocks(cmdValue);
let item = res.data;
console.log(item);
if (res.data.stateCode === 1) {
// TODO 执行 getList方法时会再执行这个toast导致再执行一次onClose方法
/* ToastService.success({
message: "编辑成功",
onClose: ()=>this.onNavBack()
}); */
ToastService.clear();
} else {
DialogService.confirm({ title: '保存失败,请重新设置' });
}
}
} catch (e) {
/* console.log(e);
this.$toast.clear(); */
}
this.isSaving = false;
},
getCommandList() {
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId };
this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
let item = res.data;
let listData = [];
let cmdData = item.items.filter(val => val.cmdCode == DeviceCommandModel.clock);
if (this.$own.isNotNull(cmdData)) {
let parseValue = JSON.parse(cmdData[0].cmdValue);
parseValue.Items.forEach(val => {
listData.push(val);
});
if (this.$own.isNotNull(this.$route.query.id)) {
listData.forEach(val => {
if (val.Id == this.$route.query.id) {
this.startTime = val.StartTime;
this.endTime = val.EndTime;
}
});
}
this.listData = listData;
} else {
this.listData = [];
}
})
.catch(err => {
console.log(err);
});
},
//post
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$route.query.code,
cmdCode,
cmdValue
}; */
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
let item = res.data;
let status = item.stateCode == 1 ? '保存成功' : '保存失败';
if (item.stateCode == 1) {
/* this.$dialog.confirm({
tittle:status,
message:status,
className: "device_confirm",
showCancelButton: false
}).then(() => {

}); */
ToastService.success({
message: status,
onClose: () => this.onNavBack()
});
} else {
DialogService.confirm({
title: status
});
}
this.isSaving = false;
})
.catch(() => {
this.isSaving = false;
});
},
//重复周期的是否显示
popupShowClick() {
this.popupShow = !this.popupShow;
},
//处理周期组件转过来的数据
handleCheckboxValue(val) {
this.checkData = val.data;
this.popupShow = val.flag;
},
//保存
onSubmit() {
if (this.isSaving) {
return;
} else if (this.isAdd && this.listData.length >= 10) {
DialogService.confirm({ title: '保存失败', message: '闹钟最多可设置10个' });
return;
}
this.isSaving = true;
let queryId = this.$route.query.id;
if (queryId) {
this.listData.forEach(val => {
if (val.Id == queryId) {
(val.StartTime = this.startTime), (val.Weekdays = this.checkDataFormat);
}
});
} else {
this.listData.push({
StartTime: this.startTime,
Active: 1,
Weekdays: this.checkDataFormat
});
}

let cmdCode = DeviceCommandModel.clock; //上课禁用
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
},
updateList() {
if (!this.isAdd) {
this.listData.forEach(val => {
if (val.Id == this.$route.query.id) {
val.StartTime = this.startTime;
val.Weekdays = this.checkDataFormat;
}
});
} else {
this.listData.push({
StartTime: this.startTime,
Active: 1,
Weekdays: this.checkDataFormat
});
}
return JSON.stringify({ Items: this.listData });
},

//1234567转周几
formatWeekdays(str) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
switch (Number(val)) {
case 1:
newArr.push('周一');
break;
case 2:
newArr.push('周二');
break;
case 3:
newArr.push('周三');
break;
case 4:
newArr.push('周四');
break;
case 5:
newArr.push('周五');
break;
case 6:
newArr.push('周六');
break;
case 7:
newArr.push('周日');
break;
default:
newArr = [];
}
});
return newArr;
},
formatObj(str) {
if (str != '' && str != null) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
newArr.push({
value: `每${this.formatWeekdays(val)}`,
className: 'active',
id: Number(val)
});
});
return newArr;
}
},
cancel() {
this.$router.go(-1);
}
}
};
</script>

<style lang="scss" scoped>
// 保存按钮样式
.van-nav-bar__right {
.setupClock_save {
width: 80px;
line-height: 40px;
background: #1989fa;
color: #fff;
}
}
.week-value {
display: flex;
justify-content: flex-end;
flex: 2;
}
</style>

+ 443
- 0
src/views/myself/setupProhibitPeriod.vue Wyświetl plik

@@ -0,0 +1,443 @@
<template>
<div class="period oh_100vh_bgColor">
<van-nav-bar :title="$route.query.title" left-text="返回" @click-left="onCancel">
<div class="setupProhibitPeriod_save" @click="onSubmit" slot="right">保存</div>
</van-nav-bar>
<van-cell class title="从" :value="startTime" is-link @click="onStartClick" />
<div class="top" v-show="startShow">
<van-datetime-picker
v-model="startTime"
type="time"
:min-hour="0"
:max-hour="23"
:show-toolbar="false"
:item-height="itemHeight"
:visible-item-count="3"
/>
</div>
<van-cell title="至" :value="endTime" is-link @click="onEndClick" />
<div class="top" v-show="endShow">
<van-datetime-picker
v-model="endTime"
type="time"
:min-hour="0"
:max-hour="23"
:show-toolbar="false"
:item-height="itemHeight"
:visible-item-count="3"
/>
</div>
<van-cell
center
title="重复周期"
value-class="week-value"
is-link
@click="popupShowClick"
v-show="!$route.query.show"
>
<span
v-show="checkData.length != 0"
class="text"
v-for="(item, index) in checkData"
:key="`check_data_${index}`"
>{{ item.value.slice(1, 3) }}</span
>
<span v-show="checkData.length == 0" class="text">至少选一个周期</span>
</van-cell>

<week :popupShow="popupShow" :checkValue="checkData" @emitCheckboxValue="handleCheckboxValue" />
</div>
</template>

<script>
import week from './week';
import { DeviceCommandModel, ProhibitModel } from '../../config/models';
import DialogService from '../../services/dialog-service';
import ToastService from '../../services/toast-service';
import APICommand from '@/api/command';
export default {
components: { week },
data() {
return {
itemHeight: Number(((document.body.clientWidth / 750) * 98).toFixed()),
startTime: '08:30',
endTime: '09:10',
startShow: false,
endShow: false,
popupShow: false,
pickerValue: '',
checkData: [],
listData: [],
repeatStr: '', //重复的数据
isSaving: false
};
},
methods: {
//返回
onNavBack() {
this.$router.go(-1);
},
getCommandList() {
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId }; */
/* this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
ToastService.clear();
let item = res.data;
let listData = [];
let cmdData = item.items.filter(val => val.cmdCode == DeviceCommandModel.prohibition);
if (this.$own.isNull(cmdData)) {
this.listData = [];
} else {
let parseValue = JSON.parse(cmdData[0].cmdValue);
parseValue.Items.forEach(val => {
listData.push(val);
});
if (this.$own.isNotNull(this.$route.query.id)) {
this.checkData = [];
listData.forEach(val => {
if (val.Id == this.$route.query.id) {
this.startTime = val.StartTime;
this.endTime = val.EndTime;
this.checkData = this.formatObj(val.Weekdays);
}
});
}
this.listData = listData;
}
})
.catch(err => {
DialogService.confirm({
message: err.message ? err.message : '系统繁忙,请稍后再试'
});
});
},
//post
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let that = this; */
this.isSaving = true;
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
}; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
ToastService.clear();
let item = res.data;
let status = item.stateCode == 1 ? '保存成功' : '保存失败,请重新设置';
if (item.stateCode == 1) {
ToastService.clear();
ToastService.success({ message: status, onClose: () => this.onNavBack() });
} else {
DialogService.confirm({ title: status });
}
})
.catch(() => {})
.finally(() => (this.isSaving = false));
},
onStartClick() {
this.startShow = !this.startShow;
this.endShow = false;
},
onEndClick() {
this.startShow = false;
this.endShow = !this.endShow;
},
//重复周期的是否显示
popupShowClick() {
this.popupShow = !this.popupShow;
},
//处理周期组件转过来的数据
handleCheckboxValue(val) {
this.checkData = val.data;
this.popupShow = val.flag;
},
// 真保存
onSubmit() {
if (this.isSaving) return;
if (this.checkData.length == 0) {
DialogService.confirm({ title: '设置失败', message: '至少选择一个周期' });
return;
}
// 开始时间不能大于结束时间
let startConflict = this.startTime.replace(':', '');
let endConflict = this.endTime.replace(':', '');
if (Number(startConflict) > Number(endConflict)) {
DialogService.confirm({ title: '设置失败', message: '开始时间不能大于结束时间' });
return;
} else {
let confirmFlag = true; //是否给予提交flag
let queryId = this.$route.query.id;
// 提交值的判断
if (this.listData.length != 0) {
for (let i = 0; i < this.listData.length; i++) {
let val = this.listData[i];
if (val.Id != queryId) {
let flag = false; //周期是否有重复flag
let repeatStr = ''; //重复项
let checkDataFormat = Array.from(this.checkDataFormat);
let Weekdays = Array.from(val.Weekdays);
Weekdays.forEach(wValue => {
checkDataFormat.forEach(cValue => {
if (cValue == wValue) {
//证明数组里有相同的周期的
flag = true; //有相同周期
confirmFlag = false; //不给提交
repeatStr += cValue;
}
});
});
this.repeatStr = repeatStr; //赋值给this.repeatStr
if (flag) {
let start1 = val.StartTime;
let end1 = val.EndTime;
let start2 = this.startTime;
let end2 = this.endTime;
//判断时间是否有交叉
if ((start1 >= start2 && start1 < end2) || (start1 < start2 && end1 > start2)) {
let message = `${this.formatWeekdays(this.repeatStr)}的时间有交叉,请重新选择`;
DialogService.confirm({
title: message
});
confirmFlag = false;
return false;
} else {
confirmFlag = true;
}
} else {
confirmFlag = true;
}
}
}
} else {
confirmFlag = true;
}

console.log(confirmFlag);

if (confirmFlag) {
let queryId = this.$route.query.id;
if (queryId) {
this.listData.forEach(val => {
if (val.Id == queryId) {
(val.StartTime = this.startTime), (val.EndTime = this.endTime), (val.Weekdays = this.checkDataFormat);
}
});
} else {
this.listData.push({
StartTime: this.startTime,
EndTime: this.endTime,
Active: 1,
Weekdays: this.checkDataFormat,
RecordType: ProhibitModel.recordType.parentWeb,
Editable: ProhibitModel.editable.parentWeb
});
}
let cmdCode = DeviceCommandModel.prohibition; //上课禁用
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
}
}
},
//保存
// todo Deprecated 弃用
confirm() {
if (this.isSaving) return;
if (this.checkData.length == 0) {
DialogService.confirm({ title: '至少选一个周期' });
return;
} else {
let confirmFlag = true; //是否给予提交flag
let queryId = this.$route.query.id;

// 提交值的判断
if (this.listData.length != 0) {
this.listData.forEach(val => {
if (val.Id != queryId) {
let flag = false; //周期是否有重复flag
let repeatStr = ''; //重复项
let checkDataFormat = Array.from(this.checkDataFormat);
let Weekdays = Array.from(val.Weekdays);
Weekdays.forEach(wValue => {
checkDataFormat.forEach(cValue => {
if (cValue == wValue) {
//证明数组里有相同的周期的
flag = true; //有相同周期
confirmFlag = false; //不给提交
repeatStr += cValue;
}
});
});
this.repeatStr = repeatStr; //赋值给this.repeatStr

if (flag) {
let start1 = '1900/01/01 ' + val.StartTime;
let end1 = '1900/01/01 ' + val.EndTime;
let start2 = '1900/01/01 ' + this.startTime;
let end2 = '1900/01/01 ' + this.endTime;
//判断时间是否有交叉
if ((start1 >= start2 && start1 < end2) || (start1 < start2 && end1 > start2)) {
let message = `${this.formatWeekdays(this.repeatStr)}的时间有交叉,请重新选择`;
DialogService.confirm({ title: message });
confirmFlag = false;
return false;
} else {
confirmFlag = true;
}
} else {
confirmFlag = true;
}
}
});
} else {
confirmFlag = true;
}
console.log(confirmFlag);
if (confirmFlag) {
let queryId = this.$route.query.id;
if (queryId) {
this.listData.forEach(val => {
if (val.Id == queryId) {
(val.StartTime = this.startTime), (val.EndTime = this.endTime), (val.Weekdays = this.checkDataFormat);
}
});
} else {
this.listData.push({
StartTime: this.startTime,
EndTime: this.endTime,
Active: 1,
Weekdays: this.checkDataFormat
});
}

let cmdCode = DeviceCommandModel.prohibition; //上课禁用
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
}
}
},
removalTime(arr1, arr2) {
let Weekdays = Array.from(arr1);
let checkDataFormat = Array.from(arr2);
Weekdays.forEach(wValue => {
checkDataFormat.forEach((cValue, cIndex) => {
if (cValue == wValue) {
checkDataFormat.splice(cIndex, 1);
}
});
});
return checkDataFormat;
},
//1234567转周几
formatWeekdays(str) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
switch (Number(val)) {
case 1:
newArr.push('周一');
break;
case 2:
newArr.push('周二');
break;
case 3:
newArr.push('周三');
break;
case 4:
newArr.push('周四');
break;
case 5:
newArr.push('周五');
break;
case 6:
newArr.push('周六');
break;
case 7:
newArr.push('周日');
break;
default:
newArr = [];
}
});
return newArr;
},
formatObj(str) {
if (str != '' && str != null) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
newArr.push({
value: `每${this.formatWeekdays(val)}`,
className: 'active',
id: Number(val)
});
});
return newArr;
}
},
onCancel() {
this.$router.go(-1);
}
//dialog弹窗
/* dialog(message) {
this.$dialog.confirm({
title: message,
className: "device_confirm",
showCancelButton: false
});
} */
},
computed: {
checkDataFormat() {
let data = '';
if (this.checkData.length > 0) {
this.checkData.forEach(val => {
data += val.id;
});
}
return data;
}
},
created() {
this.getCommandList();
this.formatObj();
}
};
</script>
<style lang="scss" scoped>
.van-nav-bar__right {
.setupProhibitPeriod_save {
width: 80px;
line-height: 40px;
background: #1989fa;
color: #fff;
}
}
.week-value {
display: flex;
justify-content: flex-end;
flex: 2;
}
</style>

+ 237
- 0
src/views/myself/setupSleepPeriod.vue Wyświetl plik

@@ -0,0 +1,237 @@
<template>
<div class="period oh_100vh_bgColor">
<van-nav-bar title="休眠设置" left-text="返回" @click-left="onNavBack">
<div class="setupsleep_save" slot="right" @click="onSubmit">保存</div>
</van-nav-bar>
<van-cell class title="从" :value="startTime" is-link @click="onStartClick" />
<div class="top" v-show="startShow">
<van-datetime-picker
v-model="startTime"
type="time"
:min-hour="0"
:max-hour="23"
:show-toolbar="false"
:visible-item-count="3"
/>
</div>
<van-cell title="至" :value="endTime" is-link @click="onEndClick" />
<div class="top" v-show="endShow">
<van-datetime-picker
v-model="endTime"
type="time"
:min-hour="0"
:max-hour="23"
:show-toolbar="false"
:visible-item-count="3"
/>
</div>
</div>
</template>

<script>
import { DeviceCommandModel } from '../../config/models';
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
import APICommand from '@/api/command';
export default {
data() {
return {
startTime: '08:30',
endTime: '09:10',
startShow: false,
endShow: false,
checkData: [],
listData: [],
repeatStr: '', //重复的数据
isSaving: false
};
},
methods: {
//返回
onNavBack() {
this.$router.go(-1);
},
getCommandList() {
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId }; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
ToastService.clear();
let item = res.data;
let listData = [];
let cmdData = item.items.filter(val => val.cmdCode == DeviceCommandModel.sleep);
if (this.$own.isNull(cmdData)) {
this.listData = [];
} else {
let parseValue = JSON.parse(cmdData[0].cmdValue);
parseValue.Items.forEach(val => {
listData.push(val);
});
if (this.$own.isNotNull(this.$route.query.id)) {
listData.forEach(val => {
if (val.Id == this.$route.query.id) {
this.startTime = val.StartTime;
this.endTime = val.EndTime;
}
});
}
this.listData = listData;
}
})
.catch(err => {
DialogService.confirm({
message: err.message ? err.message : '系统繁忙,请稍后再试'
});
});
},
//post
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
}; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
ToastService.clear();
let item = res.data;
let status = item.stateCode == 1 ? '保存成功' : '保存失败,请重新设置';
if (item.stateCode == 1) {
ToastService.success({ message: status, onClose: () => this.onNavBack() });
} else {
DialogService.confirm({ title: status });
}
})
.catch(() => {})
.finally(() => (this.isSaving = false));
},

onStartClick() {
this.startShow = !this.startShow;
this.endShow = false;
},

onEndClick() {
this.startShow = false;
this.endShow = !this.endShow;
},
//保存
onSubmit() {
if (this.isSaving) {
return;
}
let startTimes = this.startTime.replace(':', '');
let endTimes = this.endTime.replace(':', '');
if (Number(startTimes) == Number(endTimes)) {
DialogService.confirm({ title: '设置失败', message: '开始时间不能等于结束时间' });
return false;
}

this.isSaving = true;
let queryId = this.$route.query.id;
let confirmFlag = true;

try {
this.listData.forEach(val => {
if (queryId != val.Id) {
let start1 = '1900/01/01 ' + val.StartTime;
let end1 = '1900/01/01 ' + val.EndTime;
let start2 = '1900/01/01 ' + this.startTime;
let end2 = '1900/01/01 ' + this.endTime;
//判断时间是否有交叉
if ((start1 >= start2 && start1 < end2) || (start1 < start2 && end1 > start2)) {
let message = `时间有交叉,请重新选择`;
DialogService.confirm({
title: message
});
confirmFlag = false;
this.isSaving = false;
throw new Error('抛异常来终止forEach::休眠时间有交叉!');
}
}
});
} catch (e) {
console.log(e);
}

if (!confirmFlag) {
return false;
}

if (queryId) {
this.listData.forEach(val => {
if (val.Id == queryId) {
val.StartTime = this.startTime;
val.EndTime = this.endTime;
val.Weekdays = '1234567';
}
});
} else {
this.listData.push({
StartTime: this.startTime,
EndTime: this.endTime,
Active: 1,
Weekdays: '1234567'
});
}

let cmdCode = DeviceCommandModel.sleep; //上课禁用
let cmdValue = {
Items: this.listData
};

this.sendCommand(cmdCode, JSON.stringify(cmdValue));
}
/* cancel() {
let name = "sleep";
this.$router.go(-1);
}, */
//dialog弹窗
/* dialog(message) {
this.$dialog.confirm({
title: message,
className: "device_confirm",
showCancelButton: false
});
} */
},
computed: {
contrastTime() {
let startTime = '1997/06/11 ' + this.startTime;
let endTime = '1997/06/11 ' + this.endTime;
return startTime >= endTime;
}
},
created() {
this.getCommandList();
}
};
</script>
<style lang="scss">
.van-nav-bar__right {
.setupsleep_save {
width: 80px;
line-height: 40px;
background: #1989fa;
color: #fff;
}
}
</style>

+ 239
- 0
src/views/myself/sleep.vue Wyświetl plik

@@ -0,0 +1,239 @@
<template>
<div class="sleep" :style="{ background: listData.length == 0 ? '#fff ' : '#f2f4f5' }">
<van-nav-bar title="休眠设置" left-arrow :border="true" @click-left="onNavBack">
<van-icon name="plus" slot="right" id="plus-icon" @click="onAddClick" />
</van-nav-bar>
<div class="sleep-list-container" v-show="isShowPage">
<div class="con">
<van-cell v-for="(item, index) in listData" :key="`prohibit_${index}`">
<van-swipe-cell>
<div class="area">
<div :class="[{ active: item.Active }, 'left']" @click="onListClick(item.Id)">
<div class="title">{{ item.StartTime }}-{{ item.EndTime }}</div>
</div>
<van-switch :value="item.Active == 1" @input="onInput($event, item.Id)" :active-color="$green" />
</div>
<template slot="right">
<van-button square type="danger" text="删除" @click="onClose(item.Id)" />
</template>
</van-swipe-cell>
</van-cell>
<div class="watchTips" v-show="deviceType == '2'">
<p>休眠时间段:期间会自动切断网络,但有呼入电话或者亮屏设备时自动结束休眠</p>
</div>
</div>

<div class="noData_img" v-show="listData.length == 0">
<div v-if="deviceType == '1'">您还没有给定位卡设置休眠时段,赶紧去添加吧~</div>
<div v-else class="watchTips">
<p>请点击右上角“+”号添加休眠时段。</p>
<p>休眠时间段:期间会自动切断网络,但有呼入电话或者亮屏设备时自动结束休眠</p>
</div>
</div>
</div>
</div>
</template>

<script>
import { DeviceCommandModel } from '../../config/models';
import DialogService from '@/services/dialog-service';
import ToastService from '@/services/toast-service';
import APICommand from '@/api/command';
export default {
data() {
return {
switchShow: false,
listData: [],
serialNo: '',
deviceType: this.$store.getters.deviceType,
isShowPage: false
};
},
methods: {
//返回
onNavBack() {
this.$router.push({ name: 'Myself' });
},
onAddClick() {
this.$router.push({
name: 'setupSleepPeriod',
query: { code: this.$route.query.code }
});
},
switchClick() {
this.switchShow = !this.switchShow;
},
onInput(checked, id) {
/* this.$dialog.confirm({
title: "提醒",
className: "device_confirm",
message: "是否切换开关?"
}) */

this.listData.map(val => {
if (val.Id == id) {
val.Active = checked ? 1 : 0;
}
return val;
});
let cmdCode = DeviceCommandModel.sleep;
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
},
onListClick(id) {
this.$router.push({
name: 'setupSleepPeriod',
query: { code: this.$route.query.code, id }
});
},
//滑动单元格
onClose(id) {
this.listData.some((val, i) => {
if (val.Id == id) {
this.listData.splice(i, 1);
return true;
}
});
let cmdCode = DeviceCommandModel.sleep;
let cmdValue = {
Items: this.listData
};
this.sendCommand(cmdCode, JSON.stringify(cmdValue));
},

//获取信息
getCommandList() {
/* let url = `/api/Command/CommandList`;
let jsonData = { deviceId: this.$store.getters.deviceId };
ToastService.loading();
this.$axios
.post(url, jsonData) */
APICommand.commandList({
deviceId: this.$store.getters.deviceId
})
.then(res => {
ToastService.clear();
console.log(res.data);
let item = res.data;
let listData = [];
let cmdData = item.items.filter(val => val.cmdCode == DeviceCommandModel.sleep);
let parseValue = JSON.parse(cmdData[0].cmdValue);
parseValue.Items.forEach(val => {
listData.push(val);
});
this.listData = listData;
this.isShowPage = true;
})
.catch(() => {
this.isShowPage = true;
});
},
//处理方面的
formatWeekdays(str) {
let arr = Array.from(str);
let newArr = [];
arr.forEach(val => {
switch (Number(val)) {
case 1:
newArr.push('周一 ');
break;
case 2:
newArr.push('周二 ');
break;
case 3:
newArr.push('周三 ');
break;
case 4:
newArr.push('周四 ');
break;
case 5:
newArr.push('周五 ');
break;
case 6:
newArr.push('周六 ');
break;
case 7:
newArr.push('周日 ');
break;
default:
newArr = [];
}
});
return newArr;
},
//提交
sendCommand(cmdCode, cmdValue) {
ToastService.loading();
/* let url = `/api/Command/SendCommand`;
let jsonData = {
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
}; */
ToastService.loading();
/* this.$axios
.post(url, jsonData) */
APICommand.sendCommand({
deviceId: this.$store.getters.deviceId,
userId: this.$store.getters.userId,
serialNo: this.$store.getters.serialNo,
cmdCode,
cmdValue
})
.then(res => {
console.log(res.data);
ToastService.clear();
let item = res.data;
if (item.stateCode == 1) {
ToastService.clear();
ToastService.success({ message: '操作成功' });
} else {
DialogService.confirm({ title: '操作失败' });
}
})
.catch(() => {});
}
},
created() {
this.getCommandList();
}
};
</script>
<style lang="scss" scoped>
.sleep {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
.sleep-list-container {
position: relative;
height: calc(100vh - 160px);
overflow: scroll;
.con {
width: 100%;
background: #fff;
.area {
padding: 0 30px;
height: 100px;
display: flex;
justify-content: space-between;
align-items: center;
.title {
font-size: 36px;
}
}
}
.noData_img,
.watchTips {
font-size: 32px;
height: 400px;
padding: 0 40px;
@include flexbox(center, center, column, nowrap);
}
}
}
</style>

+ 50
- 0
src/views/myself/trajectory.scss Wyświetl plik

@@ -0,0 +1,50 @@
.calendar {
position: relative;
width: 100%;
height: 500px;
background-color: #fff;
z-index: 999;
.van-calendar {
.van-calendar__header {
box-shadow: unset;
.van-calendar__header-title {
display: none;
}
.van-calendar__month-title {
display: none;
@include colorAndFont(#333, 16);
padding: 20px 0 10px;
}
.van-calendar__weekdays {
span {
@include colorAndFont(#666, 14);
padding: 25px 0;
}
}
}
.van-calendar__month-title {
@include colorAndFont(#666, 14);
}
.van-calendar__days {
.van-calendar__day {
@include colorAndFont(#666, 14);
height: 35px;
.van-calendar__selected-day {
width: 27px;
height: 27px;
border-radius: 50%;
}
}
.van-calendar__day--disabled {
color: #c8c9cc;
}
}
}
}

+ 2203
- 0
src/views/myself/trajectory.vue
Plik diff jest za duży
Wyświetl plik


+ 141
- 0
src/views/myself/week.vue Wyświetl plik

@@ -0,0 +1,141 @@
<template>
<div class="popup oh_100vh_bgColor" v-show="show">
<van-nav-bar title="重复" left-arrow :border="true" @click-left="goBack" />

<van-cell v-for="(item, index) in checkData" :key="`checked_${index}`" :title="item.value">
<label :class="item.className" @click="onListClick($event)">
<input type="checkbox" :value="item" v-model="value" />
</label>
</van-cell>
</div>
</template>

<script>
export default {
props: {
popupShow: {
type: Boolean,
default: false
},
checkValue: {
type: Array
}
},
data() {
return {
value: [],
show: false,
checkData: [
{ value: '每周一', className: '', id: 1 },
{ value: '每周二', className: '', id: 2 },
{ value: '每周三', className: '', id: 3 },
{ value: '每周四', className: '', id: 4 },
{ value: '每周五', className: '', id: 5 },
{ value: '每周六', className: '', id: 6 },
{ value: '每周日', className: '', id: 7 }
]
};
},
methods: {
goBack() {
this.show = false;
this.$emit('emitCheckboxValue', {
data: this.handleValue(),
flag: false
});
},
onListClick(e) {
if (e.target.classList.length == 0) {
e.target.classList.add('active');
} else {
e.target.classList.remove('active');
}
},
handleValue() {
let val = this.value.map(v => {
return {
value: v.value,
className: 'active',
id: v.id
};
});
let newVal = val.sort((a, b) => {
return -(b.id - a.id);
});
return newVal;
},
changeData(value) {
this.value = value;
if (this.value.length != 0) {
this.value.forEach(val => {
this.checkData.forEach(v => {
if (val.id == v.id) {
v.className = val.className;
}
});
});
}
}
},
created() {
this.changeData(this.checkValue);
},
watch: {
popupShow(flag) {
this.show = flag;
},
checkValue: {
handler(n) {
console.log('watch handle', n);
this.changeData(n);
},
deep: true,
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.popup {
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 88;
.van-cell__value {
display: flex;
justify-content: flex-end;
}
.van-cell__value label {
display: flex;
justify-content: center;
align-items: center;
width: 34px;
height: 34px;
border: 1px solid #999;
border-radius: 4px;
box-sizing: border-box;
position: relative;
input {
-webkit-appearance: none;
display: none;
}

&.active {
border: 1px solid $green;
background: $green;

&:before {
content: '';
position: absolute;
left: 0;
top: 1px;
width: 25px;
height: 25px;
@include icon();
@include icon_position(25, 25, 258, 61);
}
}
}
}
</style>

+ 1
- 1
vue.config.js Wyświetl plik

@@ -45,7 +45,7 @@ module.exports = defineConfig({
lintOnSave: !IS_PROD,
productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
devServer: {
port: 9020, // 端口
port: 8080, // 端口
open: false, // 启动后打开浏览器
client: {
overlay: {


Ładowanie…
Anuluj
Zapisz