温度接入数据库
parent
04e19f22df
commit
f5b9b4687f
|
|
@ -0,0 +1,12 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询DTU温湿度上报数据列表
|
||||||
|
export function findDtuDataByInfo(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/data/findDtuDataByInfo',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
<template>
|
||||||
|
<view class="container" :style="{padding: linePadding}">
|
||||||
|
<!-- 带文字的分割线 -->
|
||||||
|
<view class="divider" :style="{margin: lineMargin}">
|
||||||
|
<view class="line" :style="{height: lineHeight,backgroundColor: lineColor}"></view>
|
||||||
|
<text :style="{padding: textPadding,fontSize: fontSize,color: fontColor,fontWeight: fontWeight}">{{ lineText }}</text>
|
||||||
|
<view class="line" :style="{height: lineHeight,backgroundColor: lineColor,}"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "DividerText",
|
||||||
|
props: {
|
||||||
|
|
||||||
|
// 线边距
|
||||||
|
linePadding: {
|
||||||
|
type: String,
|
||||||
|
default: '10rpx 0'
|
||||||
|
},
|
||||||
|
//线距离上面的距离
|
||||||
|
lineMargin: {
|
||||||
|
type: String,
|
||||||
|
default: '30rpx 0'
|
||||||
|
},
|
||||||
|
// 分割线粗细
|
||||||
|
lineHeight: {
|
||||||
|
type: String,
|
||||||
|
default: '1rpx'
|
||||||
|
},
|
||||||
|
// 分割线颜色
|
||||||
|
lineColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#e5e5e5'
|
||||||
|
},
|
||||||
|
// 字体距离分割线中间的距离
|
||||||
|
textPadding: {
|
||||||
|
type: String,
|
||||||
|
default: '0 20rpx'
|
||||||
|
},
|
||||||
|
// 字体大小
|
||||||
|
fontSize: {
|
||||||
|
type: String,
|
||||||
|
default: '28rpx'
|
||||||
|
},
|
||||||
|
// 字体颜色
|
||||||
|
fontColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#999'
|
||||||
|
},
|
||||||
|
// 字体粗细
|
||||||
|
fontWeight: {
|
||||||
|
type: String,
|
||||||
|
default: 'normal'
|
||||||
|
},
|
||||||
|
// 分割线文字
|
||||||
|
lineText: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
flex: 1
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<view class="divider" :style="{ margin: margin }">
|
||||||
|
<view
|
||||||
|
:style="{
|
||||||
|
backgroundColor: color,
|
||||||
|
height: thickness + 'rpx',
|
||||||
|
width: hasMargin ? 'calc(100% - ' + sideMargin + 'rpx)' : '100%'
|
||||||
|
}"
|
||||||
|
></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Divider",
|
||||||
|
props: {
|
||||||
|
// 分割线颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: "#e5e5e5"
|
||||||
|
},
|
||||||
|
// 分割线厚度
|
||||||
|
thickness: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
// 上下外边距(如:"20rpx 0")
|
||||||
|
margin: {
|
||||||
|
type: String,
|
||||||
|
default: "20rpx 0"
|
||||||
|
},
|
||||||
|
// 是否有左右边距
|
||||||
|
hasMargin: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 左右边距大小
|
||||||
|
sideMargin: {
|
||||||
|
type: Number,
|
||||||
|
default: 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.divider {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// 应用全局配置
|
// 应用全局配置
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// baseUrl: 'https://vue.ruoyi.vip/prod-api',
|
// baseUrl: 'https://vue.ruoyi.vip/prod-api',
|
||||||
// baseUrl: 'http://localhost:8088',
|
baseUrl: 'http://172.14.24.109:8088',
|
||||||
baseUrl: 'http://1.94.254.176:8088',
|
// baseUrl: 'http://1.94.254.176:8088',
|
||||||
// 应用信息
|
// 应用信息
|
||||||
appInfo: {
|
appInfo: {
|
||||||
// 应用名称
|
// 应用名称
|
||||||
|
|
|
||||||
2
main.js
2
main.js
|
|
@ -5,6 +5,8 @@ import store from './store' // store
|
||||||
import plugins from './plugins' // plugins
|
import plugins from './plugins' // plugins
|
||||||
import './permission' // permission
|
import './permission' // permission
|
||||||
import { getDicts } from "@/api/system/dict/data"
|
import { getDicts } from "@/api/system/dict/data"
|
||||||
|
import "./utils/uni.css";
|
||||||
|
|
||||||
|
|
||||||
Vue.use(plugins)
|
Vue.use(plugins)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,63 @@
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<!-- 控制设置标题 -->
|
<!-- 控制设置标题 -->
|
||||||
<view class="control-title">控制设置</view>
|
<view class="control-title">控制设置</view>
|
||||||
<uni-section title="请选择大棚:" titleFontSize="16px" type="line">
|
<uni-section title="请选择大棚:" titleFontSize="18px" type="line">
|
||||||
<view class="uni-px-5 uni-pb-5">
|
<view class="uni-px-5 uni-pb-5">
|
||||||
<uni-data-select v-model="value" :localdata="range" @change="change"></uni-data-select>
|
<uni-data-select v-model="value" :localdata="range" @change="change"></uni-data-select>
|
||||||
</view>
|
</view>
|
||||||
</uni-section>
|
</uni-section>
|
||||||
|
|
||||||
<uni-section :title="title" titleFontSize="16px" type="line" v-if="value!== 1">
|
|
||||||
<template v-slot:right>
|
<uni-section title="实时温湿度" titleFontSize="16px" type="line" v-if="value!== 1">
|
||||||
|
<template v-slot:right >
|
||||||
{{ temp }}
|
{{ temp }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<view class="uni-flex_control uni-row" >
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.temp1 }}</text>
|
||||||
|
<text class="data">温度1</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.temp2 }}</text>
|
||||||
|
<text class="data">温度2</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.temp3 }}</text>
|
||||||
|
<text class="data">温度3</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.temp4 }}</text>
|
||||||
|
<text class="data">温度4</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="uni-flex_control uni-row" >
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.humi1 }}</text>
|
||||||
|
<text class="data">湿度1</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.humi2 }}</text>
|
||||||
|
<text class="data">湿度2</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.humi3 }}</text>
|
||||||
|
<text class="data">湿度3</text>
|
||||||
|
</view>
|
||||||
|
<view class="text uni-flex_control uni-view">
|
||||||
|
<text class="data" :style="fontStyle">{{ liveData.humi4 }}</text>
|
||||||
|
<text class="data">湿度4</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</uni-section>
|
||||||
|
|
||||||
|
<uni-section title="设备控制" titleFontSize="16px" type="line" v-if="value!== 1">
|
||||||
|
|
||||||
<!-- 卷膜/卷被卡片容器(2列栅格布局) -->
|
<!-- 卷膜/卷被卡片容器(2列栅格布局) -->
|
||||||
<view class="card-grid">
|
<view class="card-grid">
|
||||||
<!-- 卷被开卡片 -->
|
<!-- 卷被开卡片 -->
|
||||||
|
|
@ -107,8 +154,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mqtt from 'mqtt'
|
import mqtt from 'mqtt'
|
||||||
|
import UniDatetimePicker
|
||||||
|
from "../../uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue";
|
||||||
|
import { findDtuDataByInfo } from "@/api/system/data";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
dicts: ['sys_data_map'],
|
||||||
|
components: {
|
||||||
|
UniDatetimePicker
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
temp: "",
|
temp: "",
|
||||||
|
|
@ -136,6 +190,16 @@ export default {
|
||||||
title:'',
|
title:'',
|
||||||
message: {},
|
message: {},
|
||||||
connected:false,
|
connected:false,
|
||||||
|
liveData: {
|
||||||
|
temp1: '数据加载中...',
|
||||||
|
temp2: '数据加载中...',
|
||||||
|
temp3: '数据加载中...',
|
||||||
|
temp4: '数据加载中...',
|
||||||
|
humi1: '数据加载中...',
|
||||||
|
humi2: '数据加载中...',
|
||||||
|
humi3: '数据加载中...',
|
||||||
|
humi4: '数据加载中...'
|
||||||
|
},
|
||||||
// 卡片状态(模拟后端返回数据)
|
// 卡片状态(模拟后端返回数据)
|
||||||
show: {
|
show: {
|
||||||
jbk: "暂停",
|
jbk: "暂停",
|
||||||
|
|
@ -157,7 +221,8 @@ export default {
|
||||||
jm2g: 0,
|
jm2g: 0,
|
||||||
jm3k: 0,
|
jm3k: 0,
|
||||||
jm3g: 0
|
jm3g: 0
|
||||||
}
|
},
|
||||||
|
fontStyle: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
|
@ -203,17 +268,35 @@ export default {
|
||||||
if (selectedItem) {
|
if (selectedItem) {
|
||||||
this.selectedText = selectedItem.text; // 获取展示文本
|
this.selectedText = selectedItem.text; // 获取展示文本
|
||||||
this.title= this.selectedText;
|
this.title= this.selectedText;
|
||||||
|
var queryParams = {
|
||||||
|
imei: this.imei
|
||||||
|
}
|
||||||
|
findDtuDataByInfo(queryParams).then(response => {
|
||||||
|
this.liveData = {
|
||||||
|
temp1: response.data.temp1 || '已离线...',
|
||||||
|
temp2: response.data.temp2 || '已离线..',
|
||||||
|
temp3: response.data.temp3 || '已离线..',
|
||||||
|
temp4: response.data.temp4 || '已离线..',
|
||||||
|
humi1: response.data.humi1 || '已离线..',
|
||||||
|
humi2: response.data.humi2 || '已离线..',
|
||||||
|
humi3: response.data.humi3 || '已离线..',
|
||||||
|
humi4: response.data.humi4 || '已离线..'
|
||||||
|
}
|
||||||
|
this.temp = "最后更新时间:"+response.data.time;
|
||||||
|
this.fontStyle = 'font-size:16px'
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.selectedText = ''; // 无匹配项时清空
|
this.selectedText = ''; // 无匹配项时清空
|
||||||
this.title='';
|
this.title='';
|
||||||
this.value=1;
|
this.value=1;
|
||||||
}
|
}
|
||||||
this.reset();
|
this.reset();
|
||||||
|
this.style="";
|
||||||
// this.disconnectMqtt();
|
// this.disconnectMqtt();
|
||||||
},
|
},
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.show= {
|
this.show = {
|
||||||
jbk: "暂停",
|
jbk: "暂停",
|
||||||
jbg: "暂停",
|
jbg: "暂停",
|
||||||
jm1k: "暂停",
|
jm1k: "暂停",
|
||||||
|
|
@ -223,8 +306,8 @@ export default {
|
||||||
jm3k: "暂停",
|
jm3k: "暂停",
|
||||||
jm3g: "暂停"
|
jm3g: "暂停"
|
||||||
}
|
}
|
||||||
this.deviceType= '';
|
this.deviceType = '';
|
||||||
this.status= {
|
this.status = {
|
||||||
jbk: 0,
|
jbk: 0,
|
||||||
jbg: 0,
|
jbg: 0,
|
||||||
jm1k: 0,
|
jm1k: 0,
|
||||||
|
|
@ -234,28 +317,38 @@ export default {
|
||||||
jm3k: 0,
|
jm3k: 0,
|
||||||
jm3g: 0
|
jm3g: 0
|
||||||
};
|
};
|
||||||
this.message={};
|
this.message = {};
|
||||||
this.temp='';
|
this.temp = '';
|
||||||
|
this.liveData = {
|
||||||
|
temp1: '数据加载中...',
|
||||||
|
temp2: '数据加载中...',
|
||||||
|
temp3: '数据加载中...',
|
||||||
|
temp4: '数据加载中...',
|
||||||
|
humi1: '数据加载中...',
|
||||||
|
humi2: '数据加载中...',
|
||||||
|
humi3: '数据加载中...',
|
||||||
|
humi4: '数据加载中...'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 卡片点击事件(实际项目中调用接口修改状态) 功能标识
|
// 卡片点击事件(实际项目中调用接口修改状态) 功能标识
|
||||||
handleCardClick(status, type) {
|
handleCardClick(status, type) {
|
||||||
// 校验
|
// 校验
|
||||||
// 定义类型与提示文案的映射关系,减少重复代码
|
// 定义类型与提示文案的映射关系,减少重复代码
|
||||||
const tipMap = {
|
const tipMap = {
|
||||||
'jbk': { opposite: 'jbg', name: '卷被关', op: '卷被开' },
|
'jbk': {opposite: 'jbg', name: '卷被关', op: '卷被开'},
|
||||||
'jbg': { opposite: 'jbk', name: '卷被开', op: '卷被关' },
|
'jbg': {opposite: 'jbk', name: '卷被开', op: '卷被关'},
|
||||||
'jm1k': { opposite: 'jm1g', name: '卷膜1关', op: '卷膜1开' },
|
'jm1k': {opposite: 'jm1g', name: '卷膜1关', op: '卷膜1开'},
|
||||||
'jm1g': { opposite: 'jm1k', name: '卷膜1开', op: '卷膜1关' },
|
'jm1g': {opposite: 'jm1k', name: '卷膜1开', op: '卷膜1关'},
|
||||||
'jm2k': { opposite: 'jm2g', name: '卷膜2关', op: '卷膜2开' },
|
'jm2k': {opposite: 'jm2g', name: '卷膜2关', op: '卷膜2开'},
|
||||||
'jm2g': { opposite: 'jm2k', name: '卷膜2开', op: '卷膜2关' },
|
'jm2g': {opposite: 'jm2k', name: '卷膜2开', op: '卷膜2关'},
|
||||||
'jm3k': { opposite: 'jm3g', name: '卷膜3关', op: '卷膜3开' },
|
'jm3k': {opposite: 'jm3g', name: '卷膜3关', op: '卷膜3开'},
|
||||||
'jm3g': { opposite: 'jm3k', name: '卷膜3开', op: '卷膜3关' }
|
'jm3g': {opposite: 'jm3k', name: '卷膜3开', op: '卷膜3关'}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 先判断类型是否在映射表中,避免无效case
|
// 先判断类型是否在映射表中,避免无效case
|
||||||
if (!tipMap[type]) return;
|
if (!tipMap[type]) return;
|
||||||
|
|
||||||
const { opposite, name, op } = tipMap[type];
|
const {opposite, name, op} = tipMap[type];
|
||||||
// 核心校验逻辑(只写一次,无需重复)
|
// 核心校验逻辑(只写一次,无需重复)
|
||||||
if (status === 1 && this.status[opposite] === 1) {
|
if (status === 1 && this.status[opposite] === 1) {
|
||||||
this.$modal.msgError(`【${this.selectedText}】${name}在运行状态,不能运行${op}操作!`);
|
this.$modal.msgError(`【${this.selectedText}】${name}在运行状态,不能运行${op}操作!`);
|
||||||
|
|
@ -267,17 +360,17 @@ export default {
|
||||||
// 链接mqtt
|
// 链接mqtt
|
||||||
this.connectMqtt()
|
this.connectMqtt()
|
||||||
}
|
}
|
||||||
if (this.value===1) {
|
if (this.value === 1) {
|
||||||
this.$modal.msgError("设备控制失败!");
|
this.$modal.msgError("设备控制失败!");
|
||||||
console.info("大棚选取失败!")
|
console.info("大棚选取失败!")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '操作提示:',
|
title: '操作提示:',
|
||||||
content: '确定'+(status===1?"运行":"暂停")+'【'+this.selectedText+'】设备?',
|
content: '确定' + (status === 1 ? "运行" : "暂停") + '【' + this.selectedText + '】设备?',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
confirmText: '确定',
|
confirmText: '确定',
|
||||||
success: (res) =>{
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
// console.info("操作功能:【"+type+"】,变更状态为:"+ status)
|
// console.info("操作功能:【"+type+"】,变更状态为:"+ status)
|
||||||
|
|
||||||
|
|
@ -287,7 +380,7 @@ export default {
|
||||||
// 控制设备
|
// 控制设备
|
||||||
this.publishMessage();
|
this.publishMessage();
|
||||||
// 设备回执
|
// 设备回执
|
||||||
this.deviceType=type;
|
this.deviceType = type;
|
||||||
//todo
|
//todo
|
||||||
|
|
||||||
// this.status[type] = this.status[type] === 0 ? 1 : 0;
|
// this.status[type] = this.status[type] === 0 ? 1 : 0;
|
||||||
|
|
@ -314,11 +407,11 @@ export default {
|
||||||
|
|
||||||
this.client.on('connect', () => {
|
this.client.on('connect', () => {
|
||||||
this.connected = true
|
this.connected = true
|
||||||
this.client.subscribe('dtu/+/up', { qos: 0 })
|
this.client.subscribe('dtu/+/up', {qos: 0})
|
||||||
this.addMessage('已连接到MQTT服务器')
|
this.addMessage('已连接到MQTT服务器')
|
||||||
})
|
})
|
||||||
|
|
||||||
this.client.on("message",this.ackMessage);
|
this.client.on("message", this.ackMessage);
|
||||||
|
|
||||||
this.client.on('error', (err) => {
|
this.client.on('error', (err) => {
|
||||||
this.addMessage(`控制失败: ${err.message}`)
|
this.addMessage(`控制失败: ${err.message}`)
|
||||||
|
|
@ -385,18 +478,18 @@ export default {
|
||||||
if (msgData.prop && "suc" in msgData) {
|
if (msgData.prop && "suc" in msgData) {
|
||||||
// console.info("处理回执消息")
|
// console.info("处理回执消息")
|
||||||
// 👉 这是“指令回执”
|
// 👉 这是“指令回执”
|
||||||
this.handleCommandAck(msgData,this.deviceType);
|
this.handleCommandAck(msgData, this.deviceType);
|
||||||
} else {
|
} else {
|
||||||
this.handleOtherContent(msgData)
|
this.handleOtherContent(msgData,payload)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addMessage(content) {
|
addMessage(content) {
|
||||||
|
|
||||||
console.info("提示消息:"+content)
|
console.info("提示消息:" + content)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 处理指令回执的函数
|
// 处理指令回执的函数
|
||||||
handleCommandAck(ackData,type) {
|
handleCommandAck(ackData, type) {
|
||||||
// console.info("回执消息11111:"+ackData)
|
// console.info("回执消息11111:"+ackData)
|
||||||
// 拿到指令字段(如jm2k)和执行状态(suc)
|
// 拿到指令字段(如jm2k)和执行状态(suc)
|
||||||
const commandField = Object.keys(ackData.prop)[0]; // 这里是"jm2k"
|
const commandField = Object.keys(ackData.prop)[0]; // 这里是"jm2k"
|
||||||
|
|
@ -407,7 +500,7 @@ export default {
|
||||||
this.status[type] = this.status[type] === 0 ? 1 : 0;
|
this.status[type] = this.status[type] === 0 ? 1 : 0;
|
||||||
this.show[type] = this.status[type] === 0 ? "运行" : "暂停";
|
this.show[type] = this.status[type] === 0 ? "运行" : "暂停";
|
||||||
}
|
}
|
||||||
this.deviceType='';
|
this.deviceType = '';
|
||||||
this.$modal.msgSuccess("设备操作成功!")
|
this.$modal.msgSuccess("设备操作成功!")
|
||||||
|
|
||||||
// 业务逻辑:提示“指令执行成功/失败”
|
// 业务逻辑:提示“指令执行成功/失败”
|
||||||
|
|
@ -416,43 +509,65 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
// 处理其他内容的函数
|
// 处理其他内容的函数
|
||||||
handleOtherContent(msgData) {
|
handleOtherContent(msgData,payload) {
|
||||||
// 业务逻辑:处理传感器数据、设备状态等
|
// 业务逻辑:处理传感器数据、设备状态等
|
||||||
// console.log("收到其他内容:", msgData);
|
// console.log("收到其他内容:", msgData);
|
||||||
// 例如:更新温湿度显示、设备在线状态等
|
// 例如:更新温湿度显示、设备在线状态等
|
||||||
|
|
||||||
// 设备状态展示
|
// 设备状态展示
|
||||||
if (this.value!==1) {
|
if (this.value !== 1) {
|
||||||
var arr=['jbk',"jbg","jm1k","jm1g","jm2k","jm2g","jm3k","jm3g"]
|
var arr = ['jbk', "jbg", "jm1k", "jm1g", "jm2k", "jm2g", "jm3k", "jm3g"]
|
||||||
const allKeysNumeric = Object.keys(msgData).some(key => arr.includes(key));
|
const allKeysNumeric = Object.keys(msgData).some(key => arr.includes(key));
|
||||||
if (allKeysNumeric) {
|
if (allKeysNumeric) {
|
||||||
// console.info(msgData)
|
// console.info(msgData)
|
||||||
this.status={...msgData}
|
this.status = {...msgData}
|
||||||
// console.info("imei: "+this.publishTopic+"copy: ",this.status)
|
// console.info("imei: "+this.publishTopic+"copy: ",this.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 实时温度展示
|
|
||||||
const allKeysNumeric2 = Object.keys(msgData).every(key => /^\d+$/.test(key));
|
const allKeysNumeric2 = Object.keys(msgData).every(key => /^\d+$/.test(key));
|
||||||
if (Object.keys(msgData).length > 0 && allKeysNumeric2) {
|
if (Object.keys(msgData).length > 0 && allKeysNumeric2) {
|
||||||
var avgResult = this.calculateAvg(msgData).averageFixed;
|
|
||||||
this.temp = "当前棚内平均温度:"+avgResult+"℃"
|
// 你的键:温度101~104、湿度201~204(按你之前约定温度/10、湿度/10)
|
||||||
|
const div10 = (v) => (v == null ? null : Math.round((Number(v)/10)*10)/10)
|
||||||
|
|
||||||
|
this.liveData = {
|
||||||
|
temp1: msgData["201"]==null ? "已离线...":div10(msgData["201"])+"℃",
|
||||||
|
humi1: msgData["101"]==null ? "已离线...":div10(msgData["101"])+"%RH",
|
||||||
|
temp2: msgData["202"]==null ? "已离线...":div10(msgData["202"])+"℃",
|
||||||
|
humi2: msgData["102"]==null ? "已离线...":div10(msgData["102"])+"%RH",
|
||||||
|
temp3: msgData["203"]==null ? "已离线...":div10(msgData["203"])+"℃",
|
||||||
|
humi3: msgData["103"]==null ? "已离线...":div10(msgData["103"])+"%RH",
|
||||||
|
temp4: msgData["204"]==null ? "已离线...":div10(msgData["204"])+"℃",
|
||||||
|
humi4: msgData["104"]==null ? "已离线...":div10(msgData["104"])+"%RH"
|
||||||
}
|
}
|
||||||
|
// 调用函数获取并输出格式化后的当前时间
|
||||||
|
this.temp = "最新更新时间:" + this.getCurrentTime();
|
||||||
|
this.fontStyle = 'font-size:16px'
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
|
||||||
calculateAvg(dataObj) {
|
|
||||||
const targetKeys = ['201', '202', '203', '204'];
|
|
||||||
const values = targetKeys.map(key => dataObj[key]).filter(val => typeof val === 'number' && !isNaN(val));
|
|
||||||
if (values.length === 0) return { average: 0, averageFixed: '0.00' };
|
|
||||||
const sum = values.reduce((total, num) => total + num, 0);
|
|
||||||
const avg = sum/10 / values.length;
|
|
||||||
return {
|
|
||||||
average: avg,
|
|
||||||
averageFixed: avg.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取格式化后的当前时间
|
||||||
|
* @returns {string} 格式为 YYYY-MM-DD HH:mm:ss 的当前时间
|
||||||
|
*/
|
||||||
|
getCurrentTime() {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
// 获取年、月、日(补零确保两位数)
|
||||||
|
const year = now.getFullYear();
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,需 +1
|
||||||
|
const day = String(now.getDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
// 获取时、分、秒(补零确保两位数)
|
||||||
|
const hours = String(now.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||||
|
|
||||||
|
// 拼接成标准格式
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
onHide() {
|
onHide() {
|
||||||
this.disconnectMqtt();
|
this.disconnectMqtt();
|
||||||
},
|
},
|
||||||
|
|
@ -541,4 +656,45 @@ export default {
|
||||||
.uni-pb-5 {
|
.uni-pb-5 {
|
||||||
padding-bottom: 40rpx;
|
padding-bottom: 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
width: 50rpx;
|
||||||
|
margin: 10rpx 10rpx 8rpx 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
text-align: center;
|
||||||
|
background:#fff;
|
||||||
|
font-size: 26rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx #bfbec1
|
||||||
|
}
|
||||||
|
|
||||||
|
.text:first-child {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-view {
|
||||||
|
-webkit-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
height: 150rpx;
|
||||||
|
-webkit-justify-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data {
|
||||||
|
font-size: 13px;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 23px;
|
||||||
|
color: #3a3a3a;
|
||||||
|
}
|
||||||
|
.data:nth-child(even) {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 3px;
|
||||||
|
color: #9c9c9c;
|
||||||
|
}
|
||||||
|
/deep/ .uni-section-header__slot-right {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
const state = {
|
||||||
|
dict: new Array()
|
||||||
|
}
|
||||||
|
const mutations = {
|
||||||
|
SET_DICT: (state, { key, value }) => {
|
||||||
|
if (key !== null && key !== "") {
|
||||||
|
state.dict.push({
|
||||||
|
key: key,
|
||||||
|
value: value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
REMOVE_DICT: (state, key) => {
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < state.dict.length; i++) {
|
||||||
|
if (state.dict[i].key == key) {
|
||||||
|
state.dict.splice(i, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CLEAN_DICT: (state) => {
|
||||||
|
state.dict = new Array()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
// 设置字典
|
||||||
|
setDict({ commit }, data) {
|
||||||
|
commit('SET_DICT', data)
|
||||||
|
},
|
||||||
|
// 删除字典
|
||||||
|
removeDict({ commit }, key) {
|
||||||
|
commit('REMOVE_DICT', key)
|
||||||
|
},
|
||||||
|
// 清空字典
|
||||||
|
cleanDict({ commit }) {
|
||||||
|
commit('CLEAN_DICT')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
/**
|
||||||
|
* 通用js方法封装处理
|
||||||
|
* Copyright (c) 2019 agri
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 日期格式化
|
||||||
|
export function parseTime(time, pattern) {
|
||||||
|
if (arguments.length === 0 || !time) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||||
|
let date
|
||||||
|
if (typeof time === 'object') {
|
||||||
|
date = time
|
||||||
|
} else {
|
||||||
|
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||||
|
time = parseInt(time)
|
||||||
|
} else if (typeof time === 'string') {
|
||||||
|
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '')
|
||||||
|
}
|
||||||
|
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||||
|
time = time * 1000
|
||||||
|
}
|
||||||
|
date = new Date(time)
|
||||||
|
}
|
||||||
|
const formatObj = {
|
||||||
|
y: date.getFullYear(),
|
||||||
|
m: date.getMonth() + 1,
|
||||||
|
d: date.getDate(),
|
||||||
|
h: date.getHours(),
|
||||||
|
i: date.getMinutes(),
|
||||||
|
s: date.getSeconds(),
|
||||||
|
a: date.getDay()
|
||||||
|
}
|
||||||
|
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||||
|
let value = formatObj[key]
|
||||||
|
// Note: getDay() returns 0 on Sunday
|
||||||
|
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
|
||||||
|
if (result.length > 0 && value < 10) {
|
||||||
|
value = '0' + value
|
||||||
|
}
|
||||||
|
return value || 0
|
||||||
|
})
|
||||||
|
return time_str
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单重置
|
||||||
|
export function resetForm(refName) {
|
||||||
|
if (this.$refs[refName]) {
|
||||||
|
this.$refs[refName].resetFields()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加日期范围
|
||||||
|
export function addDateRange(params, dateRange, propName) {
|
||||||
|
let search = params
|
||||||
|
search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
|
||||||
|
dateRange = Array.isArray(dateRange) ? dateRange : []
|
||||||
|
if (typeof (propName) === 'undefined') {
|
||||||
|
search.params['beginTime'] = dateRange[0]
|
||||||
|
search.params['endTime'] = dateRange[1]
|
||||||
|
} else {
|
||||||
|
search.params['begin' + propName] = dateRange[0]
|
||||||
|
search.params['end' + propName] = dateRange[1]
|
||||||
|
}
|
||||||
|
return search
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回显数据字典
|
||||||
|
export function selectDictLabel(datas, value) {
|
||||||
|
if (value === undefined) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var actions = []
|
||||||
|
Object.keys(datas).some((key) => {
|
||||||
|
if (datas[key].value == ('' + value)) {
|
||||||
|
actions.push(datas[key].label)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (actions.length === 0) {
|
||||||
|
actions.push(value)
|
||||||
|
}
|
||||||
|
return actions.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回显数据字典(字符串、数组)
|
||||||
|
export function selectDictLabels(datas, value, separator) {
|
||||||
|
if (value === undefined || value.length ===0) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value = value.join(",")
|
||||||
|
}
|
||||||
|
var actions = []
|
||||||
|
var currentSeparator = undefined === separator ? "," : separator
|
||||||
|
var temp = value.split(currentSeparator)
|
||||||
|
Object.keys(value.split(currentSeparator)).some((val) => {
|
||||||
|
var match = false
|
||||||
|
Object.keys(datas).some((key) => {
|
||||||
|
if (datas[key].value == ('' + temp[val])) {
|
||||||
|
actions.push(datas[key].label + currentSeparator)
|
||||||
|
match = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!match) {
|
||||||
|
actions.push(temp[val] + currentSeparator)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return actions.join('').substring(0, actions.join('').length - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字符串格式化(%s )
|
||||||
|
export function sprintf(str) {
|
||||||
|
var args = arguments, flag = true, i = 1
|
||||||
|
str = str.replace(/%s/g, function () {
|
||||||
|
var arg = args[i++]
|
||||||
|
if (typeof arg === 'undefined') {
|
||||||
|
flag = false
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return arg
|
||||||
|
})
|
||||||
|
return flag ? str : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换字符串,undefined,null等转化为""
|
||||||
|
export function parseStrEmpty(str) {
|
||||||
|
if (!str || str == "undefined" || str == "null") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据合并
|
||||||
|
export function mergeRecursive(source, target) {
|
||||||
|
for (var p in target) {
|
||||||
|
try {
|
||||||
|
if (target[p].constructor == Object) {
|
||||||
|
source[p] = mergeRecursive(source[p], target[p])
|
||||||
|
} else {
|
||||||
|
source[p] = target[p]
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
source[p] = target[p]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造树型结构数据
|
||||||
|
* @param {*} data 数据源
|
||||||
|
* @param {*} id id字段 默认 'id'
|
||||||
|
* @param {*} parentId 父节点字段 默认 'parentId'
|
||||||
|
* @param {*} children 孩子节点字段 默认 'children'
|
||||||
|
*/
|
||||||
|
export function handleTree(data, id, parentId, children) {
|
||||||
|
let config = {
|
||||||
|
id: id || 'id',
|
||||||
|
parentId: parentId || 'parentId',
|
||||||
|
childrenList: children || 'children'
|
||||||
|
}
|
||||||
|
|
||||||
|
var childrenListMap = {}
|
||||||
|
var tree = []
|
||||||
|
for (let d of data) {
|
||||||
|
let id = d[config.id]
|
||||||
|
childrenListMap[id] = d
|
||||||
|
if (!d[config.childrenList]) {
|
||||||
|
d[config.childrenList] = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let d of data) {
|
||||||
|
let parentId = d[config.parentId]
|
||||||
|
let parentObj = childrenListMap[parentId]
|
||||||
|
if (!parentObj) {
|
||||||
|
tree.push(d)
|
||||||
|
} else {
|
||||||
|
parentObj[config.childrenList].push(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数处理
|
||||||
|
* @param {*} params 参数
|
||||||
|
*/
|
||||||
|
export function tansParams(params) {
|
||||||
|
let result = ''
|
||||||
|
for (const propName of Object.keys(params)) {
|
||||||
|
const value = params[propName]
|
||||||
|
var part = encodeURIComponent(propName) + "="
|
||||||
|
if (value !== null && value !== "" && typeof (value) !== "undefined") {
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
for (const key of Object.keys(value)) {
|
||||||
|
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
|
||||||
|
let params = propName + '[' + key + ']'
|
||||||
|
var subPart = encodeURIComponent(params) + "="
|
||||||
|
result += subPart + encodeURIComponent(value[key]) + "&"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result += part + encodeURIComponent(value) + "&"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回项目路径
|
||||||
|
export function getNormalPath(p) {
|
||||||
|
if (p.length === 0 || !p || p == 'undefined') {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
let res = p.replace('//', '/')
|
||||||
|
if (res[res.length - 1] === '/') {
|
||||||
|
return res.slice(0, res.length - 1)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证是否为blob格式
|
||||||
|
export function blobValidate(data) {
|
||||||
|
return data.type !== 'application/json'
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import { mergeRecursive } from "@/utils/agri"
|
||||||
|
import DictMeta from './DictMeta'
|
||||||
|
import DictData from './DictData'
|
||||||
|
|
||||||
|
const DEFAULT_DICT_OPTIONS = {
|
||||||
|
types: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc 字典
|
||||||
|
* @property {Object} label 标签对象,内部属性名为字典类型名称
|
||||||
|
* @property {Object} dict 字段数组,内部属性名为字典类型名称
|
||||||
|
* @property {Array.<DictMeta>} _dictMetas 字典元数据数组
|
||||||
|
*/
|
||||||
|
export default class Dict {
|
||||||
|
constructor() {
|
||||||
|
this.owner = null
|
||||||
|
this.label = {}
|
||||||
|
this.type = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(options) {
|
||||||
|
if (options instanceof Array) {
|
||||||
|
options = { types: options }
|
||||||
|
}
|
||||||
|
const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
|
||||||
|
if (opts.types === undefined) {
|
||||||
|
throw new Error('need dict types')
|
||||||
|
}
|
||||||
|
const ps = []
|
||||||
|
this._dictMetas = opts.types.map(t => DictMeta.parse(t))
|
||||||
|
this._dictMetas.forEach(dictMeta => {
|
||||||
|
const type = dictMeta.type
|
||||||
|
Vue.set(this.label, type, {})
|
||||||
|
Vue.set(this.type, type, [])
|
||||||
|
if (dictMeta.lazy) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ps.push(loadDict(this, dictMeta))
|
||||||
|
})
|
||||||
|
return Promise.all(ps)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新加载字典
|
||||||
|
* @param {String} type 字典类型
|
||||||
|
*/
|
||||||
|
reloadDict(type) {
|
||||||
|
const dictMeta = this._dictMetas.find(e => e.type === type)
|
||||||
|
if (dictMeta === undefined) {
|
||||||
|
return Promise.reject(`the dict meta of ${type} was not found`)
|
||||||
|
}
|
||||||
|
return loadDict(this, dictMeta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载字典
|
||||||
|
* @param {Dict} dict 字典
|
||||||
|
* @param {DictMeta} dictMeta 字典元数据
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
function loadDict(dict, dictMeta) {
|
||||||
|
return dictMeta.request(dictMeta)
|
||||||
|
.then(response => {
|
||||||
|
const type = dictMeta.type
|
||||||
|
let dicts = dictMeta.responseConverter(response, dictMeta)
|
||||||
|
if (!(dicts instanceof Array)) {
|
||||||
|
console.error('the return of responseConverter must be Array.<DictData>')
|
||||||
|
dicts = []
|
||||||
|
} else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
|
||||||
|
console.error('the type of elements in dicts must be DictData')
|
||||||
|
dicts = []
|
||||||
|
}
|
||||||
|
dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
|
||||||
|
dicts.forEach(d => {
|
||||||
|
Vue.set(dict.label[type], d.value, d.label)
|
||||||
|
})
|
||||||
|
return dicts
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import DictOptions from './DictOptions'
|
||||||
|
import DictData from './DictData'
|
||||||
|
|
||||||
|
export default function(dict, dictMeta) {
|
||||||
|
const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
|
||||||
|
const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
|
||||||
|
return new DictData(dict[label], dict[value], dict)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确定字典字段
|
||||||
|
* @param {DictData} dict
|
||||||
|
* @param {...String} fields
|
||||||
|
*/
|
||||||
|
function determineDictField(dict, ...fields) {
|
||||||
|
return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* @classdesc 字典数据
|
||||||
|
* @property {String} label 标签
|
||||||
|
* @property {*} value 标签
|
||||||
|
* @property {Object} raw 原始数据
|
||||||
|
*/
|
||||||
|
export default class DictData {
|
||||||
|
constructor(label, value, raw) {
|
||||||
|
this.label = label
|
||||||
|
this.value = value
|
||||||
|
this.raw = raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { mergeRecursive } from "@/utils/agri"
|
||||||
|
import DictOptions from './DictOptions'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc 字典元数据
|
||||||
|
* @property {String} type 类型
|
||||||
|
* @property {Function} request 请求
|
||||||
|
* @property {String} label 标签字段
|
||||||
|
* @property {String} value 值字段
|
||||||
|
*/
|
||||||
|
export default class DictMeta {
|
||||||
|
constructor(options) {
|
||||||
|
this.type = options.type
|
||||||
|
this.request = options.request
|
||||||
|
this.responseConverter = options.responseConverter
|
||||||
|
this.labelField = options.labelField
|
||||||
|
this.valueField = options.valueField
|
||||||
|
this.lazy = options.lazy === true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析字典元数据
|
||||||
|
* @param {Object} options
|
||||||
|
* @returns {DictMeta}
|
||||||
|
*/
|
||||||
|
DictMeta.parse= function(options) {
|
||||||
|
let opts = null
|
||||||
|
if (typeof options === 'string') {
|
||||||
|
opts = DictOptions.metas[options] || {}
|
||||||
|
opts.type = options
|
||||||
|
} else if (typeof options === 'object') {
|
||||||
|
opts = options
|
||||||
|
}
|
||||||
|
opts = mergeRecursive(DictOptions.metas['*'], opts)
|
||||||
|
return new DictMeta(opts)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { mergeRecursive } from "@/utils/agri"
|
||||||
|
import dictConverter from './DictConverter'
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
metas: {
|
||||||
|
'*': {
|
||||||
|
/**
|
||||||
|
* 字典请求,方法签名为function(dictMeta: DictMeta): Promise
|
||||||
|
*/
|
||||||
|
request: (dictMeta) => {
|
||||||
|
console.log(`load dict ${dictMeta.type}`)
|
||||||
|
return Promise.resolve([])
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData
|
||||||
|
*/
|
||||||
|
responseConverter,
|
||||||
|
labelField: 'label',
|
||||||
|
valueField: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 默认标签字段
|
||||||
|
*/
|
||||||
|
DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
|
||||||
|
/**
|
||||||
|
* 默认值字段
|
||||||
|
*/
|
||||||
|
DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 映射字典
|
||||||
|
* @param {Object} response 字典数据
|
||||||
|
* @param {DictMeta} dictMeta 字典元数据
|
||||||
|
* @returns {DictData}
|
||||||
|
*/
|
||||||
|
function responseConverter(response, dictMeta) {
|
||||||
|
const dicts = response.content instanceof Array ? response.content : response
|
||||||
|
if (dicts === undefined) {
|
||||||
|
console.warn(`no dict data of "${dictMeta.type}" found in the response`)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return dicts.map(d => dictConverter(d, dictMeta))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mergeOptions(src) {
|
||||||
|
mergeRecursive(options, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default options
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import Dict from './Dict'
|
||||||
|
import { mergeOptions } from './DictOptions'
|
||||||
|
|
||||||
|
export default function(Vue, options) {
|
||||||
|
mergeOptions(options)
|
||||||
|
Vue.mixin({
|
||||||
|
data() {
|
||||||
|
if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
const dict = new Dict()
|
||||||
|
dict.owner = this
|
||||||
|
return {
|
||||||
|
dict
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!(this.dict instanceof Dict)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
options.onCreated && options.onCreated(this.dict)
|
||||||
|
this.dict.init(this.$options.dicts).then(() => {
|
||||||
|
options.onReady && options.onReady(this.dict)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$emit('dictReady', this.dict)
|
||||||
|
if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
|
||||||
|
this.$options.methods.onDictReady.call(this, this.dict)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue