feat: 项目初始化
This commit is contained in:
621
src/my/addController.vue
Normal file
621
src/my/addController.vue
Normal file
@@ -0,0 +1,621 @@
|
||||
<template>
|
||||
<view class="controller_home">
|
||||
<view class="body">
|
||||
<nut-cell>
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-steps :current="current">
|
||||
<nut-step title="第一步" />
|
||||
<nut-step title="第二步" />
|
||||
<nut-step title="第三步" />
|
||||
<nut-step title="第四步" />
|
||||
</nut-steps>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
<nut-config-provider :theme-vars="themeVars1">
|
||||
<nut-cell>
|
||||
<nut-row v-if="current === 1">
|
||||
<nut-col :span="24" class="font_36 f_weight c_222">
|
||||
检查设备
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="font_32 c_666 m_t_20">
|
||||
请检查设备是否上电,网络指示灯处于常亮状态。
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<nut-row v-else-if="current === 2">
|
||||
<nut-col :span="24" class="font_36 f_weight c_222">
|
||||
请选择当前进线电压
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="font_36 f_weight c_222 m_t_20">
|
||||
220V
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-radio-group v-model="inputVoltage" direction="horizontal">
|
||||
<nut-radio :label="1" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
A相
|
||||
</nut-radio>
|
||||
<nut-radio :label="2" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
B相
|
||||
</nut-radio>
|
||||
<nut-radio :label="3" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
C相
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="font_36 f_weight c_222 m_t_20">
|
||||
380V
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-radio-group v-model="inputVoltage" direction="horizontal">
|
||||
<nut-radio :label="4" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
ABC相
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<nut-row v-else-if="current === 3">
|
||||
<nut-col :span="24" class="font_36 f_weight c_222">
|
||||
请选择设备是否插入溶解氧探头
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-radio-group v-model="isHave">
|
||||
<nut-radio :label="1" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
有溶解氧探头
|
||||
</nut-radio>
|
||||
<nut-radio :label="2" icon-size="20">
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" size="20" />
|
||||
</template>
|
||||
无溶解氧探头
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<nut-row v-else-if="current === 4">
|
||||
<nut-col :span="24" class="font_36 f_weight c_222">
|
||||
请选择要放置塘口的设备
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-checkbox-group v-model="listPutPondPartId">
|
||||
<nut-checkbox
|
||||
label="0"
|
||||
:style="{ width: '100%' }"
|
||||
v-if="isHave == 1"
|
||||
>
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
溶解氧检测仪
|
||||
</nut-checkbox>
|
||||
<nut-checkbox
|
||||
label="1"
|
||||
:style="{ width: '100%' }"
|
||||
class="m_t_15"
|
||||
>
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
开关1
|
||||
</nut-checkbox>
|
||||
<nut-checkbox
|
||||
label="2"
|
||||
:style="{ width: '100%' }"
|
||||
class="m_t_15"
|
||||
>
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
开关2
|
||||
</nut-checkbox>
|
||||
<nut-checkbox
|
||||
label="3"
|
||||
:style="{ width: '100%' }"
|
||||
class="m_t_15"
|
||||
>
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
开关3
|
||||
</nut-checkbox>
|
||||
<nut-checkbox
|
||||
label="4"
|
||||
:style="{ width: '100%' }"
|
||||
class="m_t_15"
|
||||
>
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
开关4
|
||||
</nut-checkbox>
|
||||
</nut-checkbox-group>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
<nut-cell v-if="current == 3 && isHave == 1">
|
||||
<nut-row>
|
||||
<nut-col :span="24" class="m_t_10">
|
||||
<nut-radio-group v-model="waterType" direction="horizontal">
|
||||
<nut-radio :label="1" icon-size="25">
|
||||
淡水
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
<nut-radio :label="2" icon-size="25">
|
||||
海水
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
<nut-col :span="24" v-if="waterType == 2">
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-cell
|
||||
title="请设置您的盐度"
|
||||
is-link
|
||||
:desc="salt + '‰'"
|
||||
@click="setSalt"
|
||||
></nut-cell>
|
||||
</nut-config-provider>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="c_888 font_28">
|
||||
<view>淡水养殖无需设置,海水根据实际盐度设置。</view>
|
||||
<!-- <view>(盐度输入数值0-40‰)</view> -->
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-cell
|
||||
title="设置告警值"
|
||||
is-link
|
||||
:desc="String(alarm)"
|
||||
@click="setAlarm"
|
||||
></nut-cell>
|
||||
</nut-config-provider>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="c_888 font_28">
|
||||
<view>当溶解氧低于设定数值时会电话告警</view>
|
||||
<view>(数值默认为3,可设定最低值不能低于1.5) </view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
</nut-config-provider>
|
||||
<view>
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
size="large"
|
||||
:loading="isLoading"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
marginBottom: '15px',
|
||||
}"
|
||||
@click="prev"
|
||||
v-if="current != 1"
|
||||
>
|
||||
上一步
|
||||
</nut-button>
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
}"
|
||||
@click="next"
|
||||
>{{ current == 4 ? "添加" : "下一步" }}</nut-button
|
||||
>
|
||||
</view>
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-dialog v-model:visible="saltShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<view class="d_title">请设置您的盐度</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="view_f">
|
||||
<view :style="{ width: '20%' }" class="font_32 c_444"
|
||||
>盐度</view
|
||||
>
|
||||
<view :style="{ width: '80%' }">
|
||||
<nut-input
|
||||
type="digit"
|
||||
@blur="upValue"
|
||||
v-model="salt"
|
||||
placeholder="(盐度输入数值0-40‰)"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
max-length="5"
|
||||
clearable
|
||||
:cursor="String(salt).length"
|
||||
>
|
||||
<template #right>
|
||||
<text class="c_222">‰</text>
|
||||
</template>
|
||||
</nut-input>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="saltShow = false"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
@click="saltShow = false"
|
||||
>
|
||||
确定
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
<nut-dialog v-model:visible="alarmShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<view class="d_title">低溶解氧告警值</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="view_f">
|
||||
<view :style="{ width: '20%' }" class="font_32 c_444"
|
||||
>告警值</view
|
||||
>
|
||||
<view :style="{ width: '80%' }">
|
||||
<nut-input
|
||||
type="digit"
|
||||
@blur="upAlarmValue"
|
||||
v-model="alarm"
|
||||
placeholder="1.5~20"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
max-length="5"
|
||||
clearable
|
||||
:cursor="String(alarm).length"
|
||||
>
|
||||
<template #right>
|
||||
<text class="c_222">Mg/L</text>
|
||||
</template>
|
||||
</nut-input>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="alarmShow = false"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
@click="alarmShow = false"
|
||||
>
|
||||
确定
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
</nut-config-provider>
|
||||
</view>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { addDeviceController, checkDeviceStatus } from "@/api/device";
|
||||
import { IconFont } from "@nutui/icons-vue-taro";
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "添加测控一体机",
|
||||
});
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const r = instance.router.params.params;
|
||||
const page = instance.router.params.page;
|
||||
const params = r ? JSON.parse(r) : undefined;
|
||||
const check = `https://www.yuceyun.cn/wechat/check.png`;
|
||||
const check_a = `https://www.yuceyun.cn/wechat/check_a.png`;
|
||||
const r_v = `https://www.yuceyun.cn/wechat/r_v.png`;
|
||||
// const params = {
|
||||
// devNum: "12312399",
|
||||
// devType: 2,
|
||||
// pondId: [1],
|
||||
// pondName: "我的一号塘口"
|
||||
// }
|
||||
// 步骤
|
||||
const current = ref<number>(1);
|
||||
const themeVars = ref({
|
||||
cellBoxShadow: "0px 0px 0px 0px",
|
||||
cellPadding: "0",
|
||||
cellColor: "#666666",
|
||||
cellTitleFont: "32rpx",
|
||||
cellTitleDescFont: "30rpx",
|
||||
cellDescFont: "30rpx",
|
||||
cellDescColor: "#222222",
|
||||
popupBorderRadius: "10rpx",
|
||||
checkboxLabelFontSize: "30rpx",
|
||||
});
|
||||
const themeVars1 = ref({
|
||||
radioLabelFontSize: "30rpx",
|
||||
});
|
||||
// 盐度
|
||||
const salt = ref<number>(40);
|
||||
// 电压
|
||||
const inputVoltage = ref<number>(1);
|
||||
const saltShow = ref<boolean>(false);
|
||||
const alarm = ref<number>(3);
|
||||
const alarmShow = ref<boolean>(false);
|
||||
const isHave = ref<number>(1);
|
||||
const listPutPondPartId = ref(["0"]);
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const status = ref(0);
|
||||
const isLoading = ref<boolean>(false);
|
||||
const waterType = ref<number>(1);
|
||||
|
||||
/** ----------------metod start------------------ */
|
||||
// 监测设备在线状态
|
||||
function getCheckDevice() {
|
||||
const data = {
|
||||
devicetype: params.devType,
|
||||
serialnum: params.devNum,
|
||||
};
|
||||
isLoading.value = true;
|
||||
checkDeviceStatus(data)
|
||||
.then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
status.value = res.data;
|
||||
if (status.value == 0) {
|
||||
state.show = true;
|
||||
state.msg = "设备未激活";
|
||||
} else if (status.value == 1) {
|
||||
current.value = 2;
|
||||
} else if (status.value == 3) {
|
||||
state.show = true;
|
||||
state.msg = "设备离线";
|
||||
} else if (status.value == 8) {
|
||||
state.show = true;
|
||||
state.msg = "设备禁用";
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
});
|
||||
}
|
||||
function next() {
|
||||
const num = current.value;
|
||||
if (num == 4) {
|
||||
// 验证参数,发起添加设备请求
|
||||
if (salt.value) {
|
||||
if (Number(salt.value) < 0 || Number(salt.value) > 40) {
|
||||
state.show = true;
|
||||
state.msg = "盐度范围为0-40";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "请录入盐度";
|
||||
return;
|
||||
}
|
||||
if (alarm.value) {
|
||||
if (Number(alarm.value) < 1.5 || Number(alarm.value) > 20) {
|
||||
state.show = true;
|
||||
state.msg = "告警值范围为1.5-20";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "请录入告警值";
|
||||
return;
|
||||
}
|
||||
if (listPutPondPartId.value.length <= 0) {
|
||||
state.show = true;
|
||||
state.msg = "请选择放置的设备";
|
||||
return;
|
||||
}
|
||||
// 发起添加设备请求
|
||||
const data = {
|
||||
serialNum: params.devNum,
|
||||
pondId: params.pondId[0],
|
||||
salinityCompensation: waterType.value == 1 ? 0 : Number(salt.value),
|
||||
oxyWarnLower: Number(alarm.value),
|
||||
inputVoltage: Number(inputVoltage.value),
|
||||
listPutPondPartId: listPutPondPartId.value,
|
||||
isOxygenUsed:isHave.value==1?true:false
|
||||
};
|
||||
addDeviceController(data).then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
Taro.redirectTo({
|
||||
url: "/my/addDevSuccess?name=添加测控一体机&page=" + page,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (num != 1 && status.value == 1) {
|
||||
current.value = num + 1;
|
||||
}
|
||||
if (num == 1) {
|
||||
// 检查设备状态
|
||||
getCheckDevice();
|
||||
} else {
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 上一步
|
||||
function prev() {
|
||||
const num = current.value;
|
||||
current.value = num - 1;
|
||||
}
|
||||
// 设置盐度弹框
|
||||
function setSalt() {
|
||||
saltShow.value = true;
|
||||
}
|
||||
// 验证输入框内容
|
||||
function upValue() {
|
||||
const val = salt.value;
|
||||
if (Number(val) < 0 || Number(val) > 40) {
|
||||
salt.value = 40;
|
||||
}
|
||||
}
|
||||
// 设置高净值弹框
|
||||
function setAlarm() {
|
||||
alarmShow.value = true;
|
||||
}
|
||||
// 验证输入框内容
|
||||
function upAlarmValue() {
|
||||
const val = alarm.value;
|
||||
if (Number(val) < 1.5 || Number(val) > 20) {
|
||||
alarm.value = 20;
|
||||
}
|
||||
}
|
||||
/** ----------------metod end-------------------- */
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.controller_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("https://www.yuceyun.cn/wechat/bg.jpg");
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
font-size: 32px;
|
||||
font-family: "PingFang SC";
|
||||
font-weight: 400;
|
||||
|
||||
.body {
|
||||
padding: 15px;
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.mt {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
font-size: 28px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background: RGB(21, 137, 233, 0.1);
|
||||
border-radius: 4px;
|
||||
color: #1589e9;
|
||||
font-size: 28rpx;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 48px;
|
||||
color: #444444;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.nut-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog__content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nut-input {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
500
src/my/addDetector.vue
Normal file
500
src/my/addDetector.vue
Normal file
@@ -0,0 +1,500 @@
|
||||
<template>
|
||||
<view class="detector_home">
|
||||
<view class="body">
|
||||
<nut-cell>
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-steps :current="current">
|
||||
<nut-step title="第一步" />
|
||||
<nut-step title="第二步" />
|
||||
<nut-step title="第三步" />
|
||||
</nut-steps>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
<nut-cell>
|
||||
<nut-row v-if="current === 1">
|
||||
<nut-col :span="24">
|
||||
<nut-col :span="2"
|
||||
><img
|
||||
:src="dc_1"
|
||||
:style="{
|
||||
width: '48rpx',
|
||||
height: '48rpx',
|
||||
marginRight: '20rpx',
|
||||
}"
|
||||
/></nut-col>
|
||||
<nut-col :span="22" class="font_36 f_weight c_222"
|
||||
>检查设备</nut-col
|
||||
>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-col :span="2"> </nut-col>
|
||||
<nut-col :span="22" class="font_32 c_666"
|
||||
>请检查设备是否上电,网络指示灯处于常亮状态。</nut-col
|
||||
>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="m_t_20">
|
||||
<nut-col :span="2"
|
||||
><img
|
||||
:src="dc_2"
|
||||
:style="{
|
||||
width: '48rpx',
|
||||
height: '48rpx',
|
||||
marginRight: '20rpx',
|
||||
}"
|
||||
/></nut-col>
|
||||
<nut-col :span="22" class="font_36 f_weight c_222"
|
||||
>检测设备</nut-col
|
||||
>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-col :span="2"> </nut-col>
|
||||
<nut-col :span="22" class="font_32 c_666"
|
||||
>正式使用前,将设备提前上电,并将探头浸泡在水中24小时以上,使用最佳。</nut-col
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<nut-row v-else-if="current === 2 && status == 1">
|
||||
<nut-col :span="24" class="m_t_10">
|
||||
<nut-radio-group v-model="waterType" direction="horizontal">
|
||||
<nut-radio :label="1" icon-size="25">
|
||||
淡水
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
<nut-radio :label="2" icon-size="25">
|
||||
海水
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
<nut-col :span="24" v-if="waterType == 2">
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-cell
|
||||
title="请设置您的盐度"
|
||||
is-link
|
||||
:desc="salt + '‰'"
|
||||
@click="setSalt"
|
||||
></nut-cell>
|
||||
</nut-config-provider>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="c_888 font_28">
|
||||
<view>淡水养殖无需设置,海水根据实际盐度设置。</view>
|
||||
<!-- <view>(盐度输入数值0-40‰)</view> -->
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<nut-row v-else-if="current === 3 && status == 1">
|
||||
<nut-col :span="24">
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-cell
|
||||
title="溶解氧告警值设置"
|
||||
is-link
|
||||
:desc="String(alarm) + 'Mg/L'"
|
||||
@click="setAlarm"
|
||||
></nut-cell>
|
||||
</nut-config-provider>
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="c_888 font_28">
|
||||
<view>当溶解氧低于设定数值时会电话告警</view>
|
||||
<view>(数值默认为3Mg/L,可设定最低值不能低于1.5Mg/L) </view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
<view>
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
size="large"
|
||||
:loading="isLoading"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
marginBottom: '15px',
|
||||
}"
|
||||
@click="prev"
|
||||
v-if="current != 1"
|
||||
>
|
||||
上一步
|
||||
</nut-button>
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="isLoading"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
}"
|
||||
@click="next"
|
||||
>{{ current == 3 ? "添加" : "下一步" }}</nut-button
|
||||
>
|
||||
</view>
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-dialog v-model:visible="saltShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<view class="d_title">请设置您的盐度</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="view_f">
|
||||
<view :style="{ width: '20%' }" class="font_32 c_444"
|
||||
>盐度</view
|
||||
>
|
||||
<view :style="{ width: '80%' }">
|
||||
<nut-input
|
||||
type="digit"
|
||||
@blur="upValue"
|
||||
v-model="salt"
|
||||
placeholder="(盐度输入数值0-40‰)"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
clearable
|
||||
max-length="5"
|
||||
:cursor="String(salt).length"
|
||||
>
|
||||
<template #right>
|
||||
<text class="c_222">‰</text>
|
||||
</template>
|
||||
</nut-input>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="saltShow = false"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
@click="saltShow = false"
|
||||
>
|
||||
确定
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
<nut-dialog v-model:visible="alarmShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<view class="d_title">溶解氧告警值设置</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="view_f">
|
||||
<view :style="{ width: '20%' }" class="font_32 c_444"
|
||||
>告警值</view
|
||||
>
|
||||
<view :style="{ width: '80%' }">
|
||||
<nut-input
|
||||
type="digit"
|
||||
@blur="upAlarmValue"
|
||||
v-model="alarm"
|
||||
placeholder="1.5~20"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
clearable
|
||||
max-length="5"
|
||||
:cursor="String(alarm).length"
|
||||
>
|
||||
<template #right>
|
||||
<text class="c_222">Mg/L</text>
|
||||
</template>
|
||||
</nut-input>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="alarmShow = false"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
@click="alarmShow = false"
|
||||
>
|
||||
确定
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
</nut-config-provider>
|
||||
</view>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { addDeviceDetector, checkDeviceStatus } from "@/api/device";
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
import { IconFont } from "@nutui/icons-vue-taro";
|
||||
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "添加水质检测仪",
|
||||
});
|
||||
const dc_1 = imgUrl + "dc_1.png";
|
||||
const dc_2 = imgUrl + "dc_2.png";
|
||||
const check = `https://www.yuceyun.cn/wechat/check.png`;
|
||||
const check_a = `https://www.yuceyun.cn/wechat/check_a.png`;
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const r = instance.router.params.params;
|
||||
const page = instance.router.params.page;
|
||||
const params = r ? JSON.parse(r) : undefined;
|
||||
// 步骤
|
||||
const current = ref<number>(1);
|
||||
const themeVars = ref({
|
||||
cellBoxShadow: "0px 0px 0px 0px",
|
||||
cellPadding: "0",
|
||||
cellColor: "#666666",
|
||||
cellTitleFont: "32rpx",
|
||||
cellTitleDescFont: "30rpx",
|
||||
cellDescFont: "30rpx",
|
||||
cellDescColor: "#222222",
|
||||
popupBorderRadius: "10rpx",
|
||||
});
|
||||
// 盐度
|
||||
const salt = ref<number>(30);
|
||||
const waterType = ref<number>(1);
|
||||
const saltShow = ref<boolean>(false);
|
||||
const alarm = ref<number>(3);
|
||||
const alarmShow = ref<boolean>(false);
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const status = ref(0);
|
||||
const isLoading = ref<boolean>(false);
|
||||
/** ----------------metod start------------------ */
|
||||
// 监测设备在线状态
|
||||
function getCheckDevice() {
|
||||
const data = {
|
||||
devicetype: params.devType,
|
||||
serialnum: params.devNum,
|
||||
};
|
||||
isLoading.value = true;
|
||||
checkDeviceStatus(data)
|
||||
.then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
status.value = res.data;
|
||||
if (status.value == 0) {
|
||||
state.show = true;
|
||||
state.msg = "设备未激活";
|
||||
} else if (status.value == 1) {
|
||||
current.value = 2;
|
||||
} else if (status.value == 3) {
|
||||
state.show = true;
|
||||
state.msg = "设备离线";
|
||||
} else if (status.value == 8) {
|
||||
state.show = true;
|
||||
state.msg = "设备禁用";
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "设备异常";
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
});
|
||||
}
|
||||
function next() {
|
||||
const num = current.value;
|
||||
if (num == 3) {
|
||||
isLoading.value = true;
|
||||
// 验证参数,发起添加设备请求
|
||||
if (salt.value) {
|
||||
if (Number(salt.value) < 0 || Number(salt.value) > 40) {
|
||||
state.show = true;
|
||||
state.msg = "盐度范围为0-40";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "请录入盐度";
|
||||
return;
|
||||
}
|
||||
if (alarm.value) {
|
||||
if (Number(alarm.value) < 1.5 || Number(alarm.value) > 20) {
|
||||
state.show = true;
|
||||
state.msg = "告警值范围为1.5-20";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "请录入告警值";
|
||||
return;
|
||||
}
|
||||
// 发起添加设备请求
|
||||
const data = {
|
||||
serialNum: Number(params.devNum),
|
||||
pondId: Number(params.pondId[0]),
|
||||
salinityCompensation: waterType.value == 1 ? 0 : Number(salt.value),
|
||||
oxyWarnLower: Number(alarm.value),
|
||||
};
|
||||
addDeviceDetector(data)
|
||||
.then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
Taro.redirectTo({
|
||||
url: "/my/addDevSuccess?name=添加水质检测仪&page=" + page,
|
||||
});
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
isLoading.value = false;
|
||||
});
|
||||
} else {
|
||||
if (num != 1 && status.value == 1) {
|
||||
current.value = num + 1;
|
||||
}
|
||||
if (num == 1) {
|
||||
// 检查设备状态
|
||||
getCheckDevice();
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 上一步
|
||||
function prev() {
|
||||
const num = current.value;
|
||||
current.value = num - 1;
|
||||
}
|
||||
// 设置盐度弹框
|
||||
function setSalt() {
|
||||
saltShow.value = true;
|
||||
}
|
||||
// 验证输入框内容
|
||||
function upValue() {
|
||||
const val = salt.value;
|
||||
if (Number(val) < 0 || Number(val) > 40) {
|
||||
salt.value = 40;
|
||||
}
|
||||
}
|
||||
// 设置高净值弹框
|
||||
function setAlarm() {
|
||||
alarmShow.value = true;
|
||||
}
|
||||
// 验证输入框内容
|
||||
function upAlarmValue() {
|
||||
const val = alarm.value;
|
||||
if (Number(val) < 1.5 || Number(val) > 20) {
|
||||
alarm.value = 20;
|
||||
}
|
||||
}
|
||||
/** ----------------metod end-------------------- */
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.detector_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("https://www.yuceyun.cn/wechat/bg.jpg");
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
font-size: 32px;
|
||||
font-family: "PingFang SC";
|
||||
font-weight: 400;
|
||||
|
||||
.body {
|
||||
padding: 15px;
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.mt {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
font-size: 28px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background: RGB(21, 137, 233, 0.1);
|
||||
border-radius: 4px;
|
||||
color: #1589e9;
|
||||
font-size: 28rpx;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 48px;
|
||||
color: #444444;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.nut-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog__content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nut-input {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
src/my/addDevSuccess.vue
Normal file
79
src/my/addDevSuccess.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<view class="d_home">
|
||||
<view class="body">
|
||||
<nut-cell>
|
||||
<nut-row class="center-grid">
|
||||
<nut-col :span="24">
|
||||
<nut-empty>
|
||||
<template #image>
|
||||
<img :src="addS" />
|
||||
</template>
|
||||
<template #description>
|
||||
<view class="font_38 c_222 m_t_20">添加成功</view>
|
||||
<view class="font_28 c_888 m_t_20">点击返回按钮查看</view>
|
||||
</template>
|
||||
<div class="m_t_20">
|
||||
<nut-button
|
||||
type="primary"
|
||||
shape="square"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
}"
|
||||
@click="back"
|
||||
>返回</nut-button
|
||||
>
|
||||
</div>
|
||||
</nut-empty>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
import Taro from "@tarojs/taro";
|
||||
const getCurrentInstance = Taro.getCurrentInstance();
|
||||
const params_router = getCurrentInstance.router.params;
|
||||
Taro.setNavigationBarTitle({
|
||||
title: params_router.name ? params_router.name : "添加成功",
|
||||
});
|
||||
|
||||
const addS = `${imgUrl}addS.png`;
|
||||
function back() {
|
||||
if (params_router.page == "home") {
|
||||
Taro.switchTab({
|
||||
url: "/pages/main/home",
|
||||
});
|
||||
} else {
|
||||
Taro.navigateBack({ delta: 2 });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.d_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("https://www.yuceyun.cn/wechat/bg.jpg");
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 32px;
|
||||
font-family: "PingFang SC";
|
||||
font-weight: 400;
|
||||
|
||||
.body {
|
||||
padding: 15px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
174
src/my/addDevice.vue
Normal file
174
src/my/addDevice.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<view class="dev_add_home">
|
||||
<view class="body">
|
||||
<view>
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-cell>
|
||||
<nut-row>
|
||||
<nut-col :span="24" class="title"> 设备类型 </nut-col>
|
||||
<nut-col :span="24" class="m_t_10">
|
||||
<nut-radio-group v-model="params.devType">
|
||||
<nut-radio label="1" icon-size="25">
|
||||
水质检测仪
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
<nut-radio label="2" icon-size="25">
|
||||
控制一体机
|
||||
<template #icon>
|
||||
<IconFont :name="check" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="check_a" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="title"> 设备号 </nut-col>
|
||||
<nut-col :span="24" class="m_t_10">
|
||||
<nut-input
|
||||
v-model="params.devNum"
|
||||
placeholder="请输入设备号"
|
||||
type="number"
|
||||
autofocus
|
||||
:cursor="String(params.devNum).length"
|
||||
>
|
||||
<!-- <template #right>
|
||||
<nut-button type="primary" size="small" shape="square"
|
||||
@click="scan">扫一扫</nut-button>
|
||||
</template> -->
|
||||
</nut-input>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '10px',
|
||||
}"
|
||||
:loading="isLoading"
|
||||
@click="submit"
|
||||
>提交</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import Taro from "@tarojs/taro";
|
||||
import { IconFont } from "@nutui/icons-vue-taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { paramsType } from "./types";
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "添加设备",
|
||||
});
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const page = instance.router.params.page;
|
||||
const pondId = instance.router.params.pondId;
|
||||
const check = `https://www.yuceyun.cn/wechat/check.png`;
|
||||
const check_a = `https://www.yuceyun.cn/wechat/check_a.png`;
|
||||
// const pondId = 1
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
// 1扫码2手动
|
||||
const params = reactive<paramsType>({
|
||||
pondId: [],
|
||||
pondName: "",
|
||||
devType: "1",
|
||||
devNum: "",
|
||||
});
|
||||
const isLoading = ref(false)
|
||||
/**---------------method start-------------------- */
|
||||
Taro.useDidShow(() => {
|
||||
if (pondId) {
|
||||
params.pondId = [pondId];
|
||||
}
|
||||
});
|
||||
// 进入不同设备添加页面
|
||||
function submit() {
|
||||
if (params.pondId.length <= 0) {
|
||||
state.show = true;
|
||||
state.msg = "请选择塘口";
|
||||
return;
|
||||
}
|
||||
if (!params.devNum) {
|
||||
state.show = true;
|
||||
state.msg = "请输入设备号";
|
||||
return;
|
||||
}
|
||||
if (params.devType == 1) {
|
||||
isLoading.value = false
|
||||
Taro.navigateTo({
|
||||
url: "/my/addDetector?params=" + JSON.stringify(params) + "&page=" + page,
|
||||
});
|
||||
} else {
|
||||
isLoading.value = false
|
||||
Taro.navigateTo({
|
||||
url:
|
||||
"/my/addController?params=" + JSON.stringify(params) + "&page=" + page,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**---------------method end---------------------- */
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.dev_add_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("https://www.yuceyun.cn/wechat/devBg.png");
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
.body {
|
||||
padding: 220px 20px;
|
||||
|
||||
.title {
|
||||
font-size: 30px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.nut-input {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog__content {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
275
src/my/alarmPhone.vue
Normal file
275
src/my/alarmPhone.vue
Normal file
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<view class="phone_home">
|
||||
<nut-config-provider :theme="themeVars">
|
||||
<scroll-view :scroll-y="true" :style="{ height: '100%' }">
|
||||
<view class="body">
|
||||
<view>
|
||||
<nut-cell-group>
|
||||
<nut-cell>
|
||||
<template #title>
|
||||
<view class="view_f">
|
||||
<view>第一报警电话</view>
|
||||
<view @click="changeSort(phone1, 1)">
|
||||
<RectDown />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #link>
|
||||
<nut-input
|
||||
type="number"
|
||||
max-length="11"
|
||||
v-model="phone1"
|
||||
placeholder="请输入第一报警电话"
|
||||
:cursor="String(phone1).length"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
clearable
|
||||
/>
|
||||
</template>
|
||||
</nut-cell>
|
||||
<nut-cell title="第二报警电话">
|
||||
<template #title>
|
||||
<view class="view_f">
|
||||
<view>第二报警电话</view>
|
||||
<view @click="changeSort(phone2, 2)">
|
||||
<RectUp />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #link>
|
||||
<nut-input
|
||||
type="number"
|
||||
max-length="11"
|
||||
v-model="phone2"
|
||||
placeholder="请输入第二报警电话"
|
||||
:cursor="String(phone2).length"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
clearable
|
||||
/>
|
||||
</template>
|
||||
</nut-cell>
|
||||
<nut-cell title="第三报警电话">
|
||||
<template #title>
|
||||
<view class="view_f">
|
||||
<view>第三报警电话</view>
|
||||
<view @click="changeSort(phone3, 3)">
|
||||
<RectUp />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #link>
|
||||
<nut-input
|
||||
type="number"
|
||||
max-length="11"
|
||||
v-model="phone3"
|
||||
placeholder="请输入第三报警电话"
|
||||
:cursor="String(phone3).length"
|
||||
:border="false"
|
||||
input-align="right"
|
||||
clearable
|
||||
/>
|
||||
</template>
|
||||
</nut-cell>
|
||||
</nut-cell-group>
|
||||
<nut-row>
|
||||
<nut-col :span="24" class="d_desc">
|
||||
出现溶解氧过低、水温过高或过低、控制器开关异常等情况时,会进行电话报警,会按优先级别拨打电话,如无人接听会拨打下一优先级电话。报警电话号码为:
|
||||
<text :style="{ color: '#222' }">057123675281、057123675271、057123675287、02162321772</text>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="btn">
|
||||
<nut-row>
|
||||
<nut-col :span="24" :style="{ padding: '0 20rpx' }">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '0px',
|
||||
}"
|
||||
:loading="isLoading"
|
||||
@click="save"
|
||||
>保存</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</nut-config-provider>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { warnPhoneList, updateWarnPhone } from "@/api/my";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { RectUp, RectDown } from "@nutui/icons-vue-taro";
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "报警电话",
|
||||
});
|
||||
const themeVars = ref({
|
||||
cellTitleFont: "32rpx",
|
||||
cellDescFont: "32rpx",
|
||||
cellDescColor: "#222222",
|
||||
celColor: "#666666",
|
||||
});
|
||||
const phone1 = ref(
|
||||
Taro.getStorageSync("Phone") ? Taro.getStorageSync("Phone") : "-"
|
||||
);
|
||||
const phone2 = ref();
|
||||
const phone3 = ref();
|
||||
const phoneList = ref([]);
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const isLoading = ref(false)
|
||||
/** --------------- method start---------------------- */
|
||||
Taro.useDidShow(() => {
|
||||
// 获取报警电话列表
|
||||
getWarnPhoneList();
|
||||
});
|
||||
// 获取报警电话列表
|
||||
function getWarnPhoneList() {
|
||||
warnPhoneList().then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
phoneList.value = res.data;
|
||||
phone1.value = res.data[0] ? res.data[0] : "";
|
||||
phone2.value = res.data[1] ? res.data[1] : "";
|
||||
phone3.value = res.data[2] ? res.data[2] : "";
|
||||
}
|
||||
});
|
||||
}
|
||||
// 保存修改
|
||||
function save() {
|
||||
if (!phone1.value) {
|
||||
state.show = true;
|
||||
state.msg = "请输入第一报警电话";
|
||||
return;
|
||||
}
|
||||
if (phone1.value) {
|
||||
if (!isValidPhoneNumber(phone1.value)) {
|
||||
state.show = true;
|
||||
state.msg = "第一报警电话格式错误";
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (phone2.value) {
|
||||
if (!isValidPhoneNumber(phone2.value)) {
|
||||
state.show = true;
|
||||
state.msg = "第二报警电话格式错误";
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (phone3.value) {
|
||||
if (!isValidPhoneNumber(phone3.value)) {
|
||||
state.show = true;
|
||||
state.msg = "第三报警电话格式错误";
|
||||
return;
|
||||
}
|
||||
}
|
||||
Taro.showModal({
|
||||
title: "提示",
|
||||
content: "确认保存报警电话!",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
let data = [
|
||||
phone1.value ? phone1.value : undefined,
|
||||
phone2.value ? phone2.value : undefined,
|
||||
phone3.value ? phone3.value : undefined,
|
||||
];
|
||||
data = data.filter(
|
||||
(item) => item !== null && item !== undefined && item !== ""
|
||||
);
|
||||
const params = {
|
||||
listPhone: data,
|
||||
};
|
||||
isLoading.value = true
|
||||
updateWarnPhone(params).then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
state.show = true;
|
||||
state.msg = "保存成功";
|
||||
}
|
||||
}).finally(()=>{
|
||||
isLoading.value = false
|
||||
})
|
||||
} else if (res.cancel) {
|
||||
phone1.value = phoneList.value[0] ? phoneList.value[0] : "";
|
||||
phone2.value = phoneList.value[1] ? phoneList.value[1] : "";
|
||||
phone3.value = phoneList.value[2] ? phoneList.value[2] : "";
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
function isValidPhoneNumber(phoneNumber) {
|
||||
const regex = /^1[3-9]\d{9}$/;
|
||||
return regex.test(phoneNumber);
|
||||
}
|
||||
// 调整顺序
|
||||
function changeSort(phone, sort) {
|
||||
if (sort == 1) {
|
||||
phone1.value = phone2.value;
|
||||
phone2.value = phone;
|
||||
} else if (sort == 2) {
|
||||
phone2.value = phone1.value;
|
||||
phone1.value = phone;
|
||||
} else if (sort == 3) {
|
||||
phone3.value = phone2.value;
|
||||
phone2.value = phone;
|
||||
}
|
||||
}
|
||||
/** --------------- method end------------------------ */
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.phone_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
.body {
|
||||
padding: 20px;
|
||||
|
||||
.nut-cell__value {
|
||||
color: #222;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.nut-cell__title {
|
||||
min-width: 230px;
|
||||
}
|
||||
|
||||
.d_desc {
|
||||
font-size: 32px;
|
||||
color: #929a9b;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
// padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
488
src/my/deviceList.vue
Normal file
488
src/my/deviceList.vue
Normal file
@@ -0,0 +1,488 @@
|
||||
<template>
|
||||
<view class="dev_home">
|
||||
<scroll-view :scroll-y="true" :style="{ height: '100%' }">
|
||||
<view class="body">
|
||||
<view v-if="deviceList.length > 0">
|
||||
<view v-for="item in deviceList" :key="item.id">
|
||||
<nut-cell @click="selectInfo(item.id, item.deviceType, item.deviceName)">
|
||||
<nut-row class="view_f">
|
||||
<nut-col
|
||||
:span="4"
|
||||
@click="selectInfo(item.id, item.deviceType, item.deviceName)"
|
||||
>
|
||||
<img
|
||||
:src="item.deviceType == 1 ? rongjieyang : kongzhiqi"
|
||||
width="80rpx"
|
||||
height="80rpx"
|
||||
/>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="14"
|
||||
|
||||
>
|
||||
<view class="title">{{ item.deviceName }}</view>
|
||||
<view class="font_30 c_666 mt"
|
||||
>{{ item.pondInfo ? item.pondInfo.pondName : "无塘口" }}
|
||||
</view>
|
||||
<view class="time mt"
|
||||
>{{
|
||||
item.deadTime ? formatDate(new Date(item.deadTime)) : ""
|
||||
}}
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="6"
|
||||
:style="{
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<!-- <nut-button type="danger" size="mini" @click="removeDev(item.id)">移除</nut-button> -->
|
||||
<view
|
||||
class="price"
|
||||
style="line-height: 1"
|
||||
>
|
||||
<RectRight />
|
||||
</view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<nut-cell>
|
||||
<nut-col :span="24">
|
||||
<nut-empty description="暂无设备">
|
||||
<template #image>
|
||||
<img :src="pond404" />
|
||||
</template>
|
||||
</nut-empty>
|
||||
</nut-col>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view :style="{ marginBottom: '80px' }"> </view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="btn">
|
||||
<nut-row>
|
||||
<nut-col :span="24" :style="{ padding: '0 20rpx' }">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '0px',
|
||||
}"
|
||||
@click="alertShow = true"
|
||||
>新增设备</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
<!-- 弹出添加设备提示 -->
|
||||
<nut-config-provider :theme-vars="themeVars">
|
||||
<nut-dialog v-model:visible="alertShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }" class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24" class="font_36 f_weight c_222">
|
||||
请选择添加设备方式
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<view v-if="!pondId">
|
||||
<nut-col :span="24">
|
||||
<nut-cell
|
||||
title="塘口"
|
||||
:desc="params.pondName ? params.pondName : '请选择'"
|
||||
@click="popupPond"
|
||||
is-link
|
||||
/>
|
||||
</nut-col>
|
||||
</view>
|
||||
<nut-col :span="24">
|
||||
<nut-button
|
||||
block
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
marginTop: '20px',
|
||||
}"
|
||||
@click="goScan"
|
||||
>扫描二维码</nut-button
|
||||
>
|
||||
<nut-button
|
||||
block
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
marginTop: '20px',
|
||||
}"
|
||||
@click="goInput"
|
||||
>输入设备号</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
<!-- 提醒扫码异常 -->
|
||||
<nut-dialog v-model:visible="errorShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="24"
|
||||
class="d_title"
|
||||
:style="{ textAlign: 'center' }"
|
||||
>
|
||||
扫描识别失败,请前往手动录入
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn" :style="{ position: 'absolute' }">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="errorShow = false"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
>
|
||||
<nut-button type="primary" shape="square" block @click="goInput"
|
||||
>确定</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
<!-- 选择塘口 -->
|
||||
<nut-popup v-model:visible="showPond" position="bottom">
|
||||
<nut-picker
|
||||
v-model="p"
|
||||
:columns="pondList"
|
||||
title="请选择塘口"
|
||||
@confirm="confirm"
|
||||
:field-names="{ text: 'pondName', value: 'id' }"
|
||||
@cancel="cancel"
|
||||
/>
|
||||
</nut-popup>
|
||||
</nut-config-provider>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
import { formatDate } from "@/utils/tools";
|
||||
import { IconFont, RectRight } from "@nutui/icons-vue-taro";
|
||||
import {
|
||||
allDeviceList,
|
||||
deviceDel,
|
||||
deviceScan,
|
||||
deviceUnbind,
|
||||
} from "@/api/device";
|
||||
import { getPond2 } from "@/api/home";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "设备列表",
|
||||
});
|
||||
const dev = `${imgUrl}dev.png`;
|
||||
const dev_exp = `${imgUrl}dev_exp.png`;
|
||||
const pond404 = `${imgUrl}zanwurenwu.png`;
|
||||
const rongjieyang = `${imgUrl}rongjieyang.png`;
|
||||
const kongzhiqi = `${imgUrl}kongzhiqi.png`;
|
||||
const deviceList = ref<any[]>([]);
|
||||
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const pondId = instance.router.params.pondId;
|
||||
const page = instance.router.params.page;
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const themeVars = ref({
|
||||
cellBoxShadow: "0px",
|
||||
cellPadding: "0",
|
||||
popupBorderRadius: "10rpx",
|
||||
cellDescColor: "#222222",
|
||||
});
|
||||
const alertShow = ref(false);
|
||||
const errorShow = ref(false);
|
||||
const showPond = ref(false);
|
||||
const p = ref([]);
|
||||
const params = reactive<paramsType>({
|
||||
pondId: [],
|
||||
pondName: "",
|
||||
devType: "1",
|
||||
devNum: "",
|
||||
});
|
||||
const pondList = ref([]);
|
||||
/** ------------------method start------------------------ */
|
||||
Taro.useDidShow(() => {
|
||||
// 查询设备列表
|
||||
getDeviceList();
|
||||
// 查询塘口列表
|
||||
getPondList();
|
||||
if (pondId) {
|
||||
p.value = [pondId];
|
||||
alertShow.value = true;
|
||||
params.pondId = [pondId];
|
||||
}
|
||||
});
|
||||
// 设备列表
|
||||
function getDeviceList() {
|
||||
allDeviceList({ type: 1 }).then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
deviceList.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 添加设备-点击触发弹框
|
||||
function addDevice() {
|
||||
// 跳转到添加设备页面
|
||||
Taro.navigateTo({
|
||||
url: "/my/addDevice?page=deviceList",
|
||||
});
|
||||
}
|
||||
// 跳转到设备详情页面
|
||||
function selectInfo(id: number, type: number, name: string) {
|
||||
if (type == 1) {
|
||||
Taro.navigateTo({
|
||||
url: `/home/wqm?id=${id}&name=${name}`,
|
||||
});
|
||||
} else {
|
||||
Taro.navigateTo({
|
||||
url: `/home/ctr?id=${id}&name=${name}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
// 移除设备
|
||||
function removeDev(id: number) {
|
||||
Taro.showModal({
|
||||
title: "提示",
|
||||
content: "确认移除该设备?",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
deviceUnbind({ id }).then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
state.show = true;
|
||||
state.msg = "移除成功";
|
||||
getDeviceList();
|
||||
}
|
||||
});
|
||||
} else if (res.cancel) {
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
// 手动
|
||||
function goInput() {
|
||||
if (params.pondId.length > 0) {
|
||||
const pid = params.pondId;
|
||||
alertShow.value = false;
|
||||
Taro.navigateTo({
|
||||
url: "/my/addDevice?pondId=" + pid + "&page=" + page,
|
||||
});
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "请选择塘口";
|
||||
}
|
||||
}
|
||||
/** 扫码识别 */
|
||||
function goScan() {
|
||||
if (params.pondId.length <= 0) {
|
||||
state.show = true;
|
||||
state.msg = "请选择塘口";
|
||||
return;
|
||||
}
|
||||
Taro.scanCode({
|
||||
success: (res) => {
|
||||
const result = res.result;
|
||||
deviceScan({ qrcode: result }).then((v) => {
|
||||
if (v.statusCode == 200) {
|
||||
params.devType = String(v.data.deviceType);
|
||||
params.devNum = v.data.serialNum;
|
||||
alertShow.value = false;
|
||||
// 成功前往添加设备页面
|
||||
submit();
|
||||
} else {
|
||||
errorShow.value = false;
|
||||
alertShow.value = true;
|
||||
state.show = true;
|
||||
state.msg = "设备码识别失败";
|
||||
}
|
||||
});
|
||||
},
|
||||
fail: () => {
|
||||
errorShow.value = false;
|
||||
alertShow.value = true;
|
||||
state.show = true;
|
||||
state.msg = "设备码识别失败";
|
||||
},
|
||||
});
|
||||
}
|
||||
// 取消塘口选择
|
||||
// 进入不同设备添加页面
|
||||
function submit() {
|
||||
if (params.pondId.length <= 0) {
|
||||
state.show = true;
|
||||
state.msg = "请选择塘口";
|
||||
return;
|
||||
}
|
||||
if (!params.devNum) {
|
||||
state.show = true;
|
||||
state.msg = "请输入设备号";
|
||||
return;
|
||||
}
|
||||
if (params.devType == 1) {
|
||||
Taro.navigateTo({
|
||||
url: "/my/addDetector?params=" + JSON.stringify(params) + "&page=" + page,
|
||||
});
|
||||
} else {
|
||||
Taro.navigateTo({
|
||||
url:
|
||||
"/my/addController?params=" + JSON.stringify(params) + "&page=" + page,
|
||||
});
|
||||
}
|
||||
}
|
||||
// 查询塘口列表
|
||||
function getPondList() {
|
||||
getPond2().then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
pondList.value = res.data;
|
||||
if (pondId) {
|
||||
params.pondName = res.data.find((r) => r.id == pondId)?.["pondName"];
|
||||
params.pondId = [pondId];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// 确定选择塘口
|
||||
function confirm({ selectedValue, selectedOptions }) {
|
||||
showPond.value = false;
|
||||
params.pondId = selectedValue;
|
||||
params.pondName = selectedOptions[0].pondName;
|
||||
}
|
||||
// 取消选择塘口
|
||||
function cancel() {
|
||||
showPond.value = false;
|
||||
params.pondName = "";
|
||||
params.pondId = [];
|
||||
}
|
||||
// 弹出塘口选择框
|
||||
function popupPond() {
|
||||
if (pondList.value.length > 0) {
|
||||
showPond.value = true;
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "暂无塘口,请添加塘口";
|
||||
}
|
||||
}
|
||||
/** ------------------method end-------------------------- */
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.dev_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
.body {
|
||||
padding: 20px;
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.mt {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
font-size: 28px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 48px;
|
||||
color: #444444;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background: RGB(226, 35, 35, 0.1);
|
||||
border-radius: 4px;
|
||||
color: #e22323;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
// padding: 20px;
|
||||
}
|
||||
|
||||
.nut-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog__content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nut-popup--center.round {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.nut-input--border {
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.d_btn {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
font-size: 32rpx;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
line-height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
740
src/my/deviceRecharge.vue
Normal file
740
src/my/deviceRecharge.vue
Normal file
@@ -0,0 +1,740 @@
|
||||
<template>
|
||||
<view class="dev_re_home">
|
||||
<scroll-view :scroll-y="true" :style="{ height: '100%' }">
|
||||
<view class="body">
|
||||
<view v-if="deviceList.length > 0">
|
||||
<nut-checkbox-group v-model="rechargeList">
|
||||
<view v-for="(item, index) in deviceList" :key="index">
|
||||
<nut-cell>
|
||||
<nut-checkbox :label="item.id" :style="{ width: '100%' }">
|
||||
<nut-row :gutter="10">
|
||||
<nut-col :span="4">
|
||||
<img
|
||||
:src="item.deviceType == 1 ? rongjieyang : kongzhiqi"
|
||||
width="80rpx"
|
||||
height="80rpx"
|
||||
/>
|
||||
</nut-col>
|
||||
<nut-col :span="10">
|
||||
<view :style="{ display: 'flex', alignItems: 'center' }">
|
||||
<view class="title">{{ item.deviceName }}</view>
|
||||
</view>
|
||||
<view class="pond">{{
|
||||
item.pondInfo ? item.pondInfo.pondName : "无塘口"
|
||||
}}</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="10"
|
||||
:style="{
|
||||
|
||||
height: '100%',
|
||||
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="time"
|
||||
:class="item.deadDay>=0 ?'c_E22323':item.ex? 'mt' : ''"
|
||||
>
|
||||
{{ item.deadTime ? formatDate(new Date(item.deadTime)) : "" }}
|
||||
</view>
|
||||
<view v-if="item.deadDay>=0" class="c_E22323">
|
||||
已过期
|
||||
</view>
|
||||
<view v-else-if="item.ex" class="mt">
|
||||
即将到期
|
||||
</view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-checkbox>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view :style="{ marginBottom: '80px' }"> </view>
|
||||
</nut-checkbox-group>
|
||||
</view>
|
||||
<view v-else>
|
||||
<nut-cell>
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<nut-empty description="暂无设备">
|
||||
<template #image>
|
||||
<img :src="pond404" />
|
||||
</template>
|
||||
</nut-empty>
|
||||
</nut-col>
|
||||
<nut-col :span="24" :style="{ padding: '0 20rpx' }">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '0px',
|
||||
}"
|
||||
@click="goBack"
|
||||
>返回</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-cell>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="btn" v-if="deviceList.length > 0">
|
||||
<nut-row>
|
||||
<nut-col :span="24" :style="{ padding: '20rpx' }">
|
||||
<nut-row
|
||||
:style="{ display: 'flex', alignItems: 'center', justifyContent: 'center' }"
|
||||
>
|
||||
<nut-col :span="8" class="container">
|
||||
<view>
|
||||
<nut-checkbox v-model="selectAll" @change="changeAll">
|
||||
全选
|
||||
</nut-checkbox>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col :span="8" class="container">
|
||||
<view>
|
||||
<nut-checkbox v-model="expSoon" @change="changeEx">
|
||||
即将到期
|
||||
</nut-checkbox>
|
||||
</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="8"
|
||||
:style="{ background: '#17B4B2', color: '#fff' }"
|
||||
class="container"
|
||||
>
|
||||
<view
|
||||
@click="next"
|
||||
:style="{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
}"
|
||||
>
|
||||
<view class="btn_title"> 下一步 </view>
|
||||
<view class="btn_desc">
|
||||
(已选{{ rechargeList.length }}台,共{{ deviceList.length }}台)
|
||||
</view>
|
||||
</view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<nut-popup v-model:visible="devOpen" position="bottom" :style="{ height: '55%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="6" @click="devOpen = false">
|
||||
<RectLeft />
|
||||
</nut-col>
|
||||
<nut-col :span="12" class="d_title">设备充值</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-radio-group
|
||||
v-model="reType"
|
||||
direction="horizontal"
|
||||
text-position="left"
|
||||
:style="{ widht: '100%' }"
|
||||
@change="changeType"
|
||||
>
|
||||
<view v-if="payItem.length > 0">
|
||||
<nut-cell
|
||||
:class="reType == item.id ? 'nutActive' : ''"
|
||||
v-for="(item, index) in payItem"
|
||||
:key="index"
|
||||
>
|
||||
<nut-radio :label="item.id" :style="{ width: '100%' }">
|
||||
<nut-row :gutter="10">
|
||||
<nut-col :span="6">
|
||||
<img
|
||||
:src="year"
|
||||
width="128rpx"
|
||||
height="86rpx"
|
||||
v-if="item.id == 10003"
|
||||
/>
|
||||
<img
|
||||
:src="quarter"
|
||||
width="128rpx"
|
||||
height="86rpx"
|
||||
v-if="item.id == 10002"
|
||||
/>
|
||||
<img
|
||||
:src="month"
|
||||
width="128rpx"
|
||||
height="86rpx"
|
||||
v-if="item.id == 10001"
|
||||
/>
|
||||
</nut-col>
|
||||
<nut-col :span="12">
|
||||
<view :style="{ display: 'flex', alignItems: 'center' }">
|
||||
<view class="title">{{ item.title }}</view>
|
||||
</view>
|
||||
<view class="time">{{ item.description }}</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="6"
|
||||
:style="{
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<view class="price" style="line-height: 98rpx">
|
||||
¥{{ item.amount }}
|
||||
</view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<template #icon>
|
||||
<IconFont :name="r_d" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view>
|
||||
<nut-cell :class="reType == 0 ? 'nutActive' : ''">
|
||||
<nut-radio :label="1" :style="{ width: '100%' }">
|
||||
<nut-row :gutter="10">
|
||||
<nut-col :span="6">
|
||||
<img :src="year" width="128rpx" height="86rpx" />
|
||||
</nut-col>
|
||||
<nut-col :span="12">
|
||||
<view :style="{ display: 'flex', alignItems: 'center' }">
|
||||
<view class="title">年卡</view>
|
||||
</view>
|
||||
<view class="time">增加一年使用时间</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="6"
|
||||
:style="{
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<view class="price" style="line-height: 98rpx"> ¥45 </view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<template #icon>
|
||||
<IconFont :name="r_d" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view>
|
||||
<nut-cell :class="reType == 1 ? 'nutActive' : ''">
|
||||
<nut-radio :label="1" :style="{ width: '100%' }">
|
||||
<nut-row :gutter="10">
|
||||
<nut-col :span="6">
|
||||
<img :src="quarter" width="128rpx" height="86rpx" />
|
||||
</nut-col>
|
||||
<nut-col :span="12">
|
||||
<view :style="{ display: 'flex', alignItems: 'center' }">
|
||||
<view class="title">季卡</view>
|
||||
</view>
|
||||
<view class="time">增加3个月使用时间</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="6"
|
||||
:style="{
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<view class="price" style="line-height: 98rpx"> ¥45 </view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<template #icon>
|
||||
<IconFont :name="r_d" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view>
|
||||
<nut-cell :class="reType == 2 ? 'nutActive' : ''">
|
||||
<nut-radio :label="2" :style="{ width: '100%' }">
|
||||
<nut-row :gutter="10">
|
||||
<nut-col :span="6">
|
||||
<img :src="month" width="128rpx" height="86rpx" />
|
||||
</nut-col>
|
||||
<nut-col :span="12">
|
||||
<view :style="{ display: 'flex', alignItems: 'center' }">
|
||||
<view class="title">月卡</view>
|
||||
</view>
|
||||
<view class="time">增加一个月使用时间</view>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="6"
|
||||
:style="{
|
||||
justifyContent: 'flex-end',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<view class="price" style="line-height: 98rpx"> ¥15 </view>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
<template #icon>
|
||||
<IconFont :name="r_d" />
|
||||
</template>
|
||||
<template #checkedIcon>
|
||||
<IconFont :name="r_v" />
|
||||
</template>
|
||||
</nut-radio>
|
||||
</nut-cell>
|
||||
</view>
|
||||
</view>
|
||||
</nut-radio-group>
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="24"
|
||||
class="font_32"
|
||||
:style="{ textAlign: 'center', padding: '20rpx' }"
|
||||
>
|
||||
<text>续费</text>
|
||||
<text class="font_36 c_E22323">{{ rechargeList.length }}台</text>
|
||||
<text>设备,</text>
|
||||
<text>总计:</text>
|
||||
<text class="font_36 c_E22323">{{ totalPrice }} 元</text>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="loading"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '38rpx !important',
|
||||
borderRadius: '10px',
|
||||
}"
|
||||
@click="wxpay"
|
||||
>微信支付</nut-button
|
||||
>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</nut-popup>
|
||||
<nut-toast :msg="state.msg" v-model:visible="state.show" :type="state.type" />
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { IconFont, RectLeft } from "@nutui/icons-vue-taro";
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { allDeviceList } from "@/api/device";
|
||||
import { payOption, createOrder, wxPayOrder } from "@/api/my";
|
||||
import CryptoJS from "crypto-js";
|
||||
import jsrsasign from "jsrsasign";
|
||||
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "设备充值",
|
||||
});
|
||||
|
||||
const kaiguan = `${imgUrl}kaiguan.png`;
|
||||
const rongjieyang = `${imgUrl}rongjieyang.png`;
|
||||
const kongzhiqi = `${imgUrl}kongzhiqi.png`;
|
||||
|
||||
const dev = `${imgUrl}dev.png`;
|
||||
const dev1 = `${imgUrl}dev1.png`;
|
||||
const dev2 = `${imgUrl}dev2.png`;
|
||||
const month = `${imgUrl}month.png`;
|
||||
const quarter = `${imgUrl}quarter.png`;
|
||||
const year = `${imgUrl}year.png`;
|
||||
const r_d = `${imgUrl}r_d.png`;
|
||||
const r_v = `${imgUrl}r_v.png`;
|
||||
const pond404 = `${imgUrl}zanwurenwu.png`;
|
||||
const devOpen = ref(false);
|
||||
const loading = ref(false);
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const rechargeList = ref([]);
|
||||
const deviceList: any = ref([]);
|
||||
// 全选
|
||||
const selectAll = ref(false);
|
||||
// 即将过期选择
|
||||
const expSoon = ref(false);
|
||||
// 充值的类目
|
||||
const reType = ref(0);
|
||||
const totalPrice = ref(0);
|
||||
const payItem = ref([]);
|
||||
/** ----------------method start------------------ */
|
||||
Taro.useDidShow(() => {
|
||||
// 查询设备列表
|
||||
getDeviceList();
|
||||
});
|
||||
// 支付选项
|
||||
function getPayItem() {
|
||||
payOption().then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
payItem.value = res.data;
|
||||
reType.value = res.data[0]["id"];
|
||||
}
|
||||
});
|
||||
}
|
||||
// 设备列表
|
||||
function getDeviceList() {
|
||||
allDeviceList({ type: 1 }).then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
res.data.forEach((item: any) => {
|
||||
const deadDay = daysBeforeToday(formatDate(new Date(item.deadTime)));
|
||||
item.deadDay = deadDay
|
||||
if (deadDay >= -30) {
|
||||
item.ex = true;
|
||||
}
|
||||
});
|
||||
deviceList.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
/** 全选 */
|
||||
function changeAll(state) {
|
||||
expSoon.value = false;
|
||||
const res: any = [];
|
||||
deviceList.value.forEach((r: any, i: number) => {
|
||||
res.push(r.id);
|
||||
});
|
||||
if (state) {
|
||||
rechargeList.value = res;
|
||||
} else {
|
||||
rechargeList.value = [];
|
||||
}
|
||||
}
|
||||
/** 即将到期 */
|
||||
function changeEx(state) {
|
||||
selectAll.value = false;
|
||||
const res: any = [];
|
||||
deviceList.value.forEach((r: any, i: number) => {
|
||||
if (r.ex) {
|
||||
res.push(r.id);
|
||||
}
|
||||
});
|
||||
if (state) {
|
||||
rechargeList.value = res;
|
||||
} else {
|
||||
rechargeList.value = [];
|
||||
}
|
||||
}
|
||||
/** 下一步 */
|
||||
function next() {
|
||||
payOption().then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
res.data.forEach((item) => {
|
||||
// 分转元
|
||||
item.amount = item.amount / 100;
|
||||
});
|
||||
payItem.value = res.data;
|
||||
reType.value = res.data[0]["id"];
|
||||
if (rechargeList.value.length > 0) {
|
||||
devOpen.value = true;
|
||||
if (payItem.value.length > 0) {
|
||||
totalPrice.value =
|
||||
Number(payItem.value[0]["amount"]) * rechargeList.value.length;
|
||||
} else {
|
||||
totalPrice.value = 99 * rechargeList.value.length;
|
||||
}
|
||||
} else {
|
||||
state.msg = "请选择续费设备";
|
||||
state.show = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/** 微信支付 */
|
||||
function wxpay() {
|
||||
loading.value = true;
|
||||
Taro.login({
|
||||
success: function (r) {
|
||||
if (r.code) {
|
||||
const data = {
|
||||
js_code: r.code,
|
||||
payId: reType.value,
|
||||
listDeviceId: rechargeList.value,
|
||||
};
|
||||
// 创建订单
|
||||
createOrder(data).then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
const orderInfo = res.data;
|
||||
// 时间戳
|
||||
const timestamp = String(Math.floor(Date.now() / 1000));
|
||||
const appid = "wx9fb4034ebe52af77";
|
||||
// 随机字符串
|
||||
const nonceStr = generateRandomString(32);
|
||||
const rsaParam = {
|
||||
appId: appid,
|
||||
timeStamp: timestamp,
|
||||
nonceStr,
|
||||
package: `prepay_id=${orderInfo.prepayId}`,
|
||||
};
|
||||
const sign = rsaEncrypt(rsaParam);
|
||||
Taro.requestPayment({
|
||||
timeStamp: timestamp,
|
||||
nonceStr: nonceStr,
|
||||
package: `prepay_id=${orderInfo.prepayId}`,
|
||||
signType: "RSA",
|
||||
paySign: sign,
|
||||
success: function (res) {
|
||||
devOpen.value = false;
|
||||
state.msg = "续费成功";
|
||||
state.show = true;
|
||||
loading.value = false;
|
||||
getDeviceList()
|
||||
},
|
||||
fail: function (res) {
|
||||
devOpen.value = false;
|
||||
state.msg = "续费异常,请稍后再试";
|
||||
state.show = true;
|
||||
loading.value = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
loading.value = false;
|
||||
},
|
||||
complete: function () {},
|
||||
});
|
||||
}
|
||||
|
||||
function generateRandomString(length) {
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
let result = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
const randomIndex = Math.floor(Math.random() * chars.length);
|
||||
result += chars.charAt(randomIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function rsaEncrypt(data) {
|
||||
const publicKeyPem = `-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDLEVxkdX6NJtDo
|
||||
zXOzkxn7kqR3MMc05/duLON4yjmLhTPQD8iiDoCOEuZEy8dLloi1OlXO3zu/F5jd
|
||||
9ynk8x++Px5A8gBQ16GZAMH18BQDzcFzy0EPe9ckiN3IXO8GT8Ht9oP430ugxF6t
|
||||
GM7Ixh93v48n7tUOZTISX5TzZCbXOiITH40b++/LB2LaMo9xAC4dEQs+2S4x5gO9
|
||||
PAh637ZAtVlbYxmJMYxzUM09KyXAoDlmO6YlO25EBkei7ZbyQob698s35+rSeq93
|
||||
oFfUiegEL35SWeuuwp8ZFFvq24EUW7/n4U50/rS5hIFerEfcrFj2yPhP3sQtd4I+
|
||||
FjaEKzQLAgMBAAECggEBALxeUV9a4labUCT0GETWyr5j7C4oUFHSb+KCv0uYA0NZ
|
||||
/5McYRd67mNcQsBEa43BiPTbtSdeSnTbtdEI6pLXuHVo5W6HTiWvsNZWLpYt6tMQ
|
||||
dUgtnh932D2qvFiVZKBtMc7E4uzkbaonHk/heEgkCKKzTl9Tm81rr8P9aBVSrPjt
|
||||
6Xs7lORsD9bCoweYwfcrHELb+sLek/dOd9eCyabq7r5FV4EqOwJhw8btD7xgjw+o
|
||||
uVF3kWyhLSEwjpN/oo4w5r4yVPlMnSTn7MtTRFyJcU/w5YBk8MedGSTKRIvzPv4s
|
||||
RWU3ChTP5evGAh/FnpP6JGEhyvYGW0DqmuJUXK1n0fECgYEA/sSCT6Z+HSlwu/ui
|
||||
OSlDDFKZ/ci7vJcuksgf5Tw5Kj0fBVhgImO8hTS9nqCQx73JJTsUpTzyYOVxUd9b
|
||||
Aqp42dgVbDYTmkfBi0xAZpnQD4Z4LUj6OkS2k3+2CPNN+jQpibGjGy11NDV/U8EQ
|
||||
P/9ioz+PoqwENG6wsaCT9LOC2DkCgYEAzAzUXJdH5T2LpSeO8e2NHtW6flemsJJ0
|
||||
+m0O03OWxQr6KNjFpNkTFoK6A2NYOiyqMZcQb+viHGFTFpFHkozo3QPaXpZsz3BC
|
||||
y9nQzqDbP3/MtfksE/MXOOw0qtdqT3csIxiXZqIjGYqAU08xcKyItZJGnIh/aKYn
|
||||
yobDnKkCRmMCgYB9mvbAPE6bJA4/r/03/17eGW9wjuH4RfUhSudmxn1MlNvRb9Pd
|
||||
wJx2dB00sucOg0RDRdCU8upw2U44Vk1xkAiLJpzRQAwEGXKTseFidFz++oYPlZZA
|
||||
2hXFvMZLvWDphYQhLeJDiPLq7aE78siHNOs1nyW6xuI/037r5EZt838ECQKBgQDC
|
||||
3+XY3+ob92Fsw5DzYIoMTtajXxalP9pUaN9l9tihKtCrPgvUWjSupP79yV0zggCx
|
||||
B7L9EOyLai+uN+WBAu5KVimxeDxHCNHiWg3fqSR7SpS5nlUIYHtnM79BAiZX6lrO
|
||||
0eeWb3bSJ8JSzilLkJunvSGO0ZXM3hLWi0o6TfcMPQKBgQDlmSC6/Ja4M+lGZEMx
|
||||
raCryScSi1kj3KkZFcGQEEejltpet2u06af/qA+tmMW7uxjLj5R80yqsYmUqS6Md
|
||||
pHc1U7XsqU2MinqVJz47H8WZwYMDDLjNOI2f4coqbtBBOA6GKt+gYYqYxkpvVanT
|
||||
oShAmWqOcPsioBVCFRVGvMlcNA==
|
||||
-----END PRIVATE KEY-----`;
|
||||
let encipher = new jsrsasign.RSAKey();
|
||||
// 把私钥转成16进制并设置秘钥
|
||||
encipher = jsrsasign.KEYUTIL.getKey(publicKeyPem);
|
||||
// 设置SHA256withRSA方式加密
|
||||
const sig = new jsrsasign.KJUR.crypto.Signature({
|
||||
alg: "SHA256withRSA",
|
||||
});
|
||||
// 初始化
|
||||
sig.init(encipher);
|
||||
// 需要加密的字段,这里注意下一定要按每一个字段一行,切末位加上 \n
|
||||
const str =
|
||||
`${data.appId}\n` +
|
||||
`${data.timeStamp}\n` +
|
||||
`${data.nonceStr}\n` +
|
||||
`${data.package}\n`;
|
||||
sig.updateString(str);
|
||||
// 加密后,转成base64
|
||||
return jsrsasign.hextob64(sig.sign());
|
||||
}
|
||||
function changeType() {
|
||||
/**
|
||||
* 0 99
|
||||
* 1 45
|
||||
* 2 15
|
||||
*/
|
||||
const count = rechargeList.value.length;
|
||||
const type = reType.value;
|
||||
var price = 0;
|
||||
if (payItem.value.length > 0) {
|
||||
const payRes = payItem.value.filter((item) => item.id == type);
|
||||
price = count * Number(payRes[0]["amount"]);
|
||||
} else {
|
||||
var price = 99;
|
||||
if (type == 0) {
|
||||
price = count * 99;
|
||||
} else if (type == 1) {
|
||||
price = count * 45;
|
||||
} else if (type == 2) {
|
||||
price = count * 15;
|
||||
}
|
||||
}
|
||||
|
||||
totalPrice.value = price;
|
||||
}
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
Taro.switchTab({
|
||||
url: "/pages/main/my",
|
||||
});
|
||||
}
|
||||
/** ----------------method end-------------------- */
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.dev_re_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 20px;
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pond {
|
||||
font-size: 30px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.mt {
|
||||
color: rgb(255, 190, 13) !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 10px;
|
||||
font-size: 28px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 30px;
|
||||
color: #17b4b2;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
|
||||
.btn_title {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.btn_desc {
|
||||
font-size: 24px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.d_body {
|
||||
padding: 30px;
|
||||
|
||||
.d_title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #222;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.d_content {
|
||||
font-size: 28rpx;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.d_c_title {
|
||||
font-size: 32rpx;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
color: #222222;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 38px;
|
||||
color: #17b4b2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 26px;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nut-radio-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nut-cell {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.nutActive {
|
||||
border: 1px solid #17b4b2;
|
||||
borderradius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.d_btn {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
font-size: 32rpx;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
line-height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
160
src/my/help.vue
Normal file
160
src/my/help.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<view class="help_home">
|
||||
<nut-config-provider :theme="themeVars">
|
||||
<scroll-view :scroll-y="true" :style="{ height: '100%' }">
|
||||
<view class="body">
|
||||
<view>
|
||||
<nut-cell title="售后服务电话" desc="17685506229" />
|
||||
<nut-cell-group>
|
||||
<nut-cell title="溶解氧设备安装使用指导" is-link />
|
||||
<nut-cell title="测控一体机安装使用指导" is-link />
|
||||
</nut-cell-group>
|
||||
<nut-cell-group>
|
||||
<nut-cell title="用户使用协议" is-link @click="toAgreement" />
|
||||
<nut-cell title="隐私保护政策" is-link @click="toPriAgreement" />
|
||||
</nut-cell-group>
|
||||
<nut-cell-group>
|
||||
<nut-cell
|
||||
title="检测更新"
|
||||
:desc="version"
|
||||
is-link
|
||||
@click="checkUpdate"
|
||||
/>
|
||||
<!-- <nut-cell title="注销账号" is-link @click="logOut" /> -->
|
||||
</nut-cell-group>
|
||||
<nut-row>
|
||||
<nut-col :span="24" class="d_desc">
|
||||
提示:养殖设备为养殖工作的辅助工具,不能完全代替养殖工作的管理,您仍需留意养殖情况的变化并及时处理避免造成损失。
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</nut-config-provider>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { logoutFun } from "@/api/login";
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "使用帮助",
|
||||
});
|
||||
const store: any = inject("store");
|
||||
const themeVars = ref({
|
||||
cellTitleFont: "32rpx",
|
||||
cellDescFont: "32rpx",
|
||||
cellDescColor: "#222222",
|
||||
celColor: "#666666",
|
||||
});
|
||||
const version = Taro.getAccountInfoSync()["miniProgram"]["version"];
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
function checkUpdate() {
|
||||
//判断目前微信版本是否支持自动更新
|
||||
if (Taro.canIUse("getUpdateManager")) {
|
||||
const update = Taro.getUpdateManager();
|
||||
update.onCheckForUpdate((res) => {
|
||||
//检测是否有新版本
|
||||
if (res.hasUpdate) {
|
||||
update.onUpdateReady(() => {
|
||||
// update.applyUpdate();
|
||||
//如果有新版本,给用户提示确认更新即可
|
||||
Taro.showModal({
|
||||
title: "更新提示",
|
||||
content: "新版本已经准备好,是否重启应用?",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启,如果想静默更新,直接在检测有新版本的时候调用此方法即可
|
||||
update.applyUpdate();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
//如果自动更新失败,给用户提示手动更新(有些小程序涉及到多ID使用,不更新会出现莫名的缓存bug,大部分小程序不用执行这一步)
|
||||
update.onUpdateFailed(() => {
|
||||
Taro.showModal({
|
||||
title: "已经有新版本了",
|
||||
content: "新版本已经上线,请您删除当前小程序,重新打开。",
|
||||
});
|
||||
});
|
||||
} else {
|
||||
state.show = true;
|
||||
state.msg = "已是最新版本";
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Taro.showModal({
|
||||
title: "提示",
|
||||
content: "当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。",
|
||||
});
|
||||
}
|
||||
}
|
||||
/** 查看用户协议 */
|
||||
function toAgreement() {
|
||||
Taro.redirectTo({
|
||||
url: "/agreement/index",
|
||||
});
|
||||
}
|
||||
/** 隐私协议 */
|
||||
function toPriAgreement() {
|
||||
Taro.redirectTo({
|
||||
url: "/agreement/indexpri",
|
||||
});
|
||||
}
|
||||
/** 退出登录 */
|
||||
function logOut() {
|
||||
Taro.showModal({
|
||||
title: "提示",
|
||||
content: "确认注销当前账号?",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
logoutFun();
|
||||
Taro.clearStorageSync();
|
||||
Taro.clearStorage();
|
||||
store.updateRootUserId(null);
|
||||
store.updateRootUserName(null);
|
||||
Taro.redirectTo({
|
||||
url: "/pages/login/index?agreement=1",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.help_home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
|
||||
.body {
|
||||
padding: 20px;
|
||||
|
||||
.nut-cell__value {
|
||||
color: #222;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.d_desc {
|
||||
font-size: 32px;
|
||||
color: #929a9b;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
4
src/my/index.config.ts
Normal file
4
src/my/index.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationStyle: 'custom',
|
||||
disableScroll: true
|
||||
})
|
||||
257
src/my/subAccount.vue
Normal file
257
src/my/subAccount.vue
Normal file
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<nut-row class="sub_home">
|
||||
<nut-col :span="24" class="body" :style="{ padding: '0 20rpx' }">
|
||||
<nut-config-provider :theme="themeVars">
|
||||
<view v-if="accountList.length > 0">
|
||||
<nut-cell v-for="item in accountList" :key="item.id">
|
||||
<template #icon>
|
||||
<IconFont :name="phone" :style="{ height: '50rpx' }" />
|
||||
</template>
|
||||
<template #title>
|
||||
<view class="c_222 font_36">{{ item.mobilePhone }}</view>
|
||||
</template>
|
||||
<template #link>
|
||||
<view @click="del(item.id)" class="c_E22323 font_36">删除</view>
|
||||
</template>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<view v-else>
|
||||
<nut-cell>
|
||||
<nut-col :span="24">
|
||||
<nut-empty description="暂无子账号">
|
||||
<template #image>
|
||||
<img :src="pond404" />
|
||||
</template>
|
||||
</nut-empty>
|
||||
</nut-col>
|
||||
</nut-cell>
|
||||
</view>
|
||||
<!-- <nut-row>
|
||||
<nut-col :span="24" class="d_desc">
|
||||
1.如有其他用户需要查看您账号内绑定的设备信息,将其注册账号时使用的手机号添加为子账号即可。
|
||||
</nut-col>
|
||||
<nut-col :span="24" class="d_desc">
|
||||
2.子账号有权进行参数配置,告警、定时设置等,但无权转移塘口、增删设备。
|
||||
</nut-col>
|
||||
</nut-row> -->
|
||||
</nut-config-provider>
|
||||
</nut-col>
|
||||
<nut-col :span="24" :style="{ padding: '0 20rpx' }">
|
||||
<view class="btn">
|
||||
<nut-button
|
||||
block
|
||||
shape="square"
|
||||
type="primary"
|
||||
size="large"
|
||||
:style="{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '14px !important',
|
||||
borderRadius: '0px',
|
||||
}"
|
||||
@click="add"
|
||||
>新增子账号</nut-button
|
||||
>
|
||||
</view>
|
||||
</nut-col>
|
||||
<!-- 弹出层提示 -->
|
||||
<nut-toast
|
||||
:msg="state.msg"
|
||||
v-model:visible="state.show"
|
||||
:type="state.type"
|
||||
/>
|
||||
<!-- 弹出添加设备提示 -->
|
||||
<nut-config-provider :theme-vars="themeVars2">
|
||||
<nut-dialog v-model:visible="addShow" text-align="left" no-footer>
|
||||
<view :style="{ height: '100%' }">
|
||||
<view class="d_body">
|
||||
<nut-row>
|
||||
<nut-col :span="24">
|
||||
<view class="d_title">设置子账号</view>
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-divider class="divider" />
|
||||
</nut-col>
|
||||
<nut-col :span="24">
|
||||
<nut-input
|
||||
type="digit"
|
||||
v-model="account"
|
||||
placeholder="请输入子账号的手机号"
|
||||
:border="false"
|
||||
input-align="left"
|
||||
clearable
|
||||
max-length="11"
|
||||
>
|
||||
</nut-input>
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
<view class="d_btn">
|
||||
<nut-row>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#222' }"
|
||||
@click="cancel"
|
||||
>
|
||||
取消
|
||||
</nut-col>
|
||||
<nut-col
|
||||
:span="12"
|
||||
:style="{ border: '1px solid #eee', color: '#15BBC5' }"
|
||||
@click="submitD"
|
||||
>
|
||||
确定
|
||||
</nut-col>
|
||||
</nut-row>
|
||||
</view>
|
||||
</view>
|
||||
</nut-dialog>
|
||||
</nut-config-provider>
|
||||
</nut-row>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { list_user_child, add_user_child, delete_user_child } from "@/api/sub";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { stateType } from "@/utils/types";
|
||||
import { IconFont } from "@nutui/icons-vue-taro";
|
||||
import { imgUrl } from "@/utils/imgUrl";
|
||||
import { debounce,throttle } from 'lodash';
|
||||
definePageConfig({
|
||||
navigationBarTitleText: "子账号管理",
|
||||
});
|
||||
const pond404 = `${imgUrl}zanwurenwu.png`;
|
||||
const phone = `${imgUrl}phone.png`;
|
||||
const themeVars = ref({
|
||||
cellTitleFont: "36rpx",
|
||||
cellDescFont: "36rpx",
|
||||
cellDescColor: "#222222",
|
||||
celColor: "#666666",
|
||||
});
|
||||
const themeVars2 = ref({
|
||||
cellBoxShadow: "0px",
|
||||
cellPadding: "0",
|
||||
popupBorderRadius: "10rpx",
|
||||
cellDescColor: "#222222",
|
||||
});
|
||||
const accountList = ref([]);
|
||||
const state: stateType = reactive({
|
||||
msg: "",
|
||||
type: "text",
|
||||
center: true,
|
||||
show: false,
|
||||
});
|
||||
const addShow = ref(false);
|
||||
const account = ref("");
|
||||
/** --------------- method start---------------------- */
|
||||
Taro.useDidShow(() => {
|
||||
// 获取列表
|
||||
getAccountList();
|
||||
});
|
||||
// 获取子账号列表
|
||||
function getAccountList() {
|
||||
list_user_child().then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
accountList.value = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 新增
|
||||
function add() {
|
||||
addShow.value = true;
|
||||
}
|
||||
// 验证手机号码
|
||||
function isValidPhoneNumber(phoneNumber) {
|
||||
const regex = /^1[3-9]\d{9}$/;
|
||||
return regex.test(phoneNumber);
|
||||
}
|
||||
// 删除
|
||||
function del(id) {
|
||||
Taro.showModal({
|
||||
title: "提示",
|
||||
content: "确认删除该子账号!",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
delete_user_child({ id }).then((res: any) => {
|
||||
if (res.statusCode == 200) {
|
||||
state.show = true;
|
||||
state.msg = "删除成功";
|
||||
getAccountList();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
function cancel() {
|
||||
account.value = "";
|
||||
addShow.value = false;
|
||||
}
|
||||
const submitD = debounce(submit, 300);
|
||||
function submit() {
|
||||
if (!account.value) {
|
||||
state.show = true;
|
||||
state.msg = "请输入手机号";
|
||||
return;
|
||||
}
|
||||
if (!isValidPhoneNumber(account.value)) {
|
||||
state.show = true;
|
||||
state.msg = "手机号格式错误";
|
||||
return;
|
||||
}
|
||||
add_user_child(Number(account.value)).then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
state.show = true;
|
||||
state.msg = "添加成功";
|
||||
|
||||
cancel();
|
||||
getAccountList();
|
||||
}
|
||||
});
|
||||
}
|
||||
/** --------------- method end------------------------ */
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.sub_home {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #e5ebed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
margin: 0;
|
||||
|
||||
.body {
|
||||
.nut-cell__value {
|
||||
color: #222;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.nut-cell__title {
|
||||
min-width: 230px;
|
||||
}
|
||||
|
||||
.d_desc {
|
||||
font-size: 32px;
|
||||
color: #929a9b;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 95%;
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
// padding: 20px;
|
||||
}
|
||||
|
||||
.nut-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nut-dialog__content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nut-input {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
6
src/my/types.ts
Normal file
6
src/my/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface paramsType {
|
||||
pondId: string | any;
|
||||
pondName: string;
|
||||
devType: number | undefined;
|
||||
devNum: string | undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user