Browse Source

feat(设备参数添加;统计图表等修改): 设备参数添加;统计图表等修改

master
wally 4 years ago
parent
commit
a32a3fc7f1
  1. 1
      .eslintrc.js
  2. 2
      .vscode/settings.json
  3. 2
      src/apis/index.js
  4. 9
      src/components/device-select-and-status.vue
  5. 150
      src/components/function-config-applied.vue
  6. 239
      src/components/function-config-pending.vue
  7. 34
      src/components/history-data.vue
  8. 19
      src/components/network-config-applied.vue
  9. 19
      src/components/network-config-pending.vue
  10. 42
      src/components/realtime-data.vue
  11. 8
      src/components/search-bar-data.vue
  12. 2
      src/components/search-bar.vue
  13. 49
      src/config/config.js
  14. 16
      src/utils/time.js
  15. 9
      src/views/data-history.vue
  16. 270
      src/views/function-config.vue
  17. 4
      src/views/network-config.vue
  18. 2
      src/views/statistical-history.vue
  19. 10
      src/views/statistical-realtime.vue

1
.eslintrc.js

@ -13,6 +13,7 @@ module.exports = {
'import/no-unresolved': 0,
'import/extensions': 0,
'no-plusplus': 0,
'consistent-return': 0,
'vue/html-self-closing': 'off',
'no-unused-expressions': 'off',
'vue/no-mutating-props': 'off',

2
.vscode/settings.json

@ -1,4 +1,4 @@
{
"cSpell.words": ["browserslist", "commitlint", "unplugin", "windi", "windicss"],
"cSpell.words": ["browserslist", "commitlint", "datas", "unplugin", "windi", "windicss"],
"vue3snippets.enable-compile-vue-file-on-did-save-code": true
}

2
src/apis/index.js

@ -44,7 +44,7 @@ export const createConfigNetwork = data => http.post(`${corrosion}/config/networ
export const createConfigFunction = data => http.post(`${corrosion}/config/function`, data);
// 查历史数据
export const getHistories = params => http.post(`${corrosion}/histories`, params);
export const getHistories = params => http.post(`${corrosion}/datas`, params);
// 导出历史数据
export const exportHistory = params => http.post(`${corrosion}/export`, params);

9
src/components/device-select-and-status.vue

@ -2,7 +2,7 @@
import { computed, ref, watch, defineProps } from 'vue';
import { useStore } from 'vuex';
const props = defineProps({ status: Object });
const props = defineProps({ status: String });
const store = useStore();
const devices = computed(() => store.state.device.devices); // /
@ -57,8 +57,9 @@ function onChange(event) {
<!-- <span class="text-sm text-gray-500 ml-10">获取状态</span>
<el-tag type="success">{{ get }}</el-tag>-->
<span class="text-sm text-gray-500 ml-10">设置状态</span>
<el-tag :type="statusType">{{ props.status || 'PENDING' }}</el-tag>
<template v-if="props.status">
<span class="text-sm text-gray-500 ml-10">设置状态</span>
<el-tag :type="statusType">{{ props.status }}</el-tag>
</template>
</div>
</template>

150
src/components/function-config-applied.vue

@ -0,0 +1,150 @@
<template>
<el-row :gutter="10">
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置金属腐蚀采样频率(分钟)</span>
<span>{{ data.frequency.metal }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置温湿度采样频率(分钟)</span>
<span>{{ data.frequency.th }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置SO2采样频率(分钟)</span>
<span>{{ data.frequency.so2 }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置盐雾采样频率(分钟)</span>
<span>{{ data.frequency.salt }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置时间</span>
<span>{{ formatMsTime(data.time) }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置金属腐蚀采集个数</span>
<span>{{ data.count }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置电池电压低阈值</span>
<span>{{ data.batteryLow }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置电池电压高阈值</span>
<span>{{ data.batteryHigh }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置太阳能电压高阈值</span>
<span>{{ data.sunHigh }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置湿度高阈值</span>
<span>{{ data.humidityHigh }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置温度低阈值</span>
<span>{{ data.temperatureLow }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>设置温度高阈值</span>
<span>{{ data.temperatureHigh }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>选择金属通道1类型</span>
<span>{{ formatCorrosiveType(data.corrosiveType1) }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>选择金属通道2类型</span>
<span>{{ formatCorrosiveType(data.corrosiveType2) }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>选择金属通道3类型</span>
<span>{{ formatCorrosiveType(data.corrosiveType3) }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>选择金属通道4类型</span>
<span>{{ formatCorrosiveType(data.corrosiveType4) }}</span>
</el-col>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>安全模式</span>
<span>{{ formatMode(data.securityMode) }}</span>
</el-col>
</el-row>
<el-row>
<el-col :xs="24" :md="12" :lg="8" :xl="6" class="text-sm text-gray-500 py-3">
<span>上报类型</span>
<span class="mr-8">{{ formatReportType(data.report.type) }}</span>
<span v-if="data.report.type === 'POINT'">{{ data.report.reportTimePoints }}</span>
<span v-else>{{ data.report.cycle }}分钟</span>
</el-col>
</el-row>
<!-- 刷新下发按钮 -->
<!-- <Refresh @refresh="onSearch(currentDeviceI, 1)" /> -->
</template>
<script setup>
import { computed, ref, watch, defineEmits, defineProps } from 'vue';
import { useStore } from 'vuex';
import { getConfigAppliedNetwork } from 'apis/index';
import { formatMsTime } from 'utils/time';
import { functionConfig, corrosiveTypes } from '@/config/config';
const store = useStore();
const currentDeviceId = computed(() => store.state.device.currentDeviceId);
const data = ref(functionConfig); //
const emit = defineEmits(['status']);
const props = defineProps({ activeName: String });
/**
* 查询网络参数配置 设备真实参数
* @param {string} deviceId 设备id
*/
const onSearch = async deviceId => {
try {
const params = { deviceId };
const resData = await getConfigAppliedNetwork(params);
data.value = resData || functionConfig;
if (resData && resData.status) {
emit('status', resData.status);
}
} catch (error) {
throw new Error(error);
}
};
watch(
currentDeviceId,
newDeviceId => {
newDeviceId && props.activeName === 'applied' && onSearch(newDeviceId);
},
{ immediate: true },
);
/**
* 转化安全模式
* @param {string|number} time 时间ms
*/
function formatMode(mode) {
return mode === 'OPEN' ? '不加密' : '加密';
}
/**
* 转化上报类型显示
* @param {string} reportType 上报类型
*/
function formatReportType(reportType) {
return reportType === 'POINT' ? '按时间点上报' : '按周期上报';
}
/**
* 格式化金属腐蚀类型
* @param {string} type 服务端返回的类型
* @return {string} type 对应的文字名称
*/
function formatCorrosiveType(type) {
const target = corrosiveTypes.find(item => item.value === type);
return target.label;
}
</script>

239
src/components/function-config-pending.vue

@ -0,0 +1,239 @@
<template>
<el-form label-position="top" :model="data" ref="functionForm">
<el-row :gutter="20">
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置金属腐蚀采样频率(分钟)" prop="frequency.metal">
<el-input-number :min="0" v-model="data.frequency.metal" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温湿度采样频率(分钟)" prop="frequency.th">
<el-input-number :min="0" v-model="data.frequency.th" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置SO2采样频率(分钟)" prop="frequency.so2">
<el-input-number :min="0" v-model="data.frequency.so2" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置盐雾采样频率(分钟)" prop="frequency.salt">
<el-input-number :min="0" v-model="data.frequency.salt" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置时间" prop="time">
<!-- <el-input v-model="data.time"></el-input> -->
<el-date-picker v-model="data.time" type="datetime" placeholder="设置时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置金属腐蚀采集个数" prop="count">
<el-input-number :min="0" v-model="data.count" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置电池电压低阈值" prop="batteryLow">
<el-input-number :min="0" v-model="data.batteryLow" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置电池电压高阈值" prop="batteryHigh">
<el-input-number :min="0" v-model="data.batteryHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置太阳能电压高阈值" prop="sunHigh">
<el-input-number :min="0" v-model="data.sunHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置湿度高阈值" prop="humidityHigh">
<el-input-number :min="0" v-model="data.humidityHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温度低阈值" prop="temperatureLow">
<el-input-number :min="0" v-model="data.temperatureLow" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温度高阈值" prop="temperatureHigh">
<el-input-number :min="0" v-model="data.temperatureHigh" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道1类型" prop="securityMode">
<el-select v-model="data.corrosiveType1" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道2类型" prop="corrosiveType">
<el-select v-model="data.corrosiveType2" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道3类型" prop="securityMode">
<el-select v-model="data.corrosiveType3" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道4类型" prop="corrosiveType">
<el-select v-model="data.corrosiveType4" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设置安全模式" prop="securityMode">
<!-- <el-input v-model="data.securityMode"></el-input> -->
<el-radio v-model="data.securityMode" label="OPEN">不加密</el-radio>
<el-radio v-model="data.securityMode" label="ENCRYPTION">加密</el-radio>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设置上报时间" prop="report.type" style="margin-bottom: 0 !important">
<el-radio-group v-model="data.report.type">
<el-radio label="POINT">按设定时间点上报</el-radio>
<el-radio label="CYCLE">按设定周期上报(分钟)</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-if="data.report.type === 'POINT'">
<el-col :lg="6" :xl="4" :md="8" :sm="12" v-for="(item, index) in data.report.timePoints" :key="index">
<el-form-item prop="report.timePoints" style="margin-bottom: 10px !important">
<el-time-picker format="HH:mm" v-model="data.report.timePoints[index]" :placeholder="`上报时间点${index + 1}`"></el-time-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-else>
<el-col :span="12">
<el-form-item prop="report.cycle">
<el-input-number :min="0" v-model="data.report.cycle" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="mt-5 pl-2">
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button @click="onReset">重置</el-button>
</el-form-item>
</el-row>
</el-form>
<!-- 刷新下发按钮 -->
<Refresh @refresh="onSearch(currentDeviceId, 1)" />
</template>
<script setup>
import { computed, ref, watch, defineEmits, defineProps } from 'vue';
import { useStore } from 'vuex';
import { ElMessage } from 'element-plus';
import cloneDeep from 'lodash/cloneDeep';
import isDate from 'lodash/isDate';
import { getConfigFunction, createConfigFunction } from 'apis/index';
import Refresh from 'components/refresh.vue';
import { functionConfig, corrosiveTypes } from '@/config/config';
const data = ref(functionConfig);
//
const types = ref(corrosiveTypes);
const functionForm = ref(null); // form
const store = useStore();
const currentDeviceId = computed(() => store.state.device.currentDeviceId);
const emit = defineEmits(['status']);
const props = defineProps({ activeName: String });
/**
* 格式化时间
*/
const formatTime = date => {
const hour = date.getHours();
const minute = date.getMinutes();
return `${hour}:${minute}`;
};
/**
* 查询网络参数配置
* @param {string} deviceId 设备id
* @param {number} type 0数据库查询 1刷新查询
*/
async function onSearch(deviceId, type = 0) {
const params = { deviceId, type };
const resData = await getConfigFunction(params);
data.value = resData || functionConfig;
if (resData && resData.time) {
resData.time = new Date(+resData.time);
}
if (resData && resData.status) {
emit('status', resData.status);
}
}
watch(
currentDeviceId,
newDeviceId => {
newDeviceId && props.activeName === 'pending' && onSearch(newDeviceId);
},
{ immediate: true },
);
//
const onSubmit = () => {
functionForm.value.validate(async () => {
try {
if (!currentDeviceId.value) {
return ElMessage.error('请选择站点');
}
const param = cloneDeep({ ...data.value, deviceId: currentDeviceId.value });
param.time = new Date(param.time).getTime();
if (param.report.type === 'POINT') {
//
const points = [...param.report.timePoints];
for (let i = 0; i < points.length; i++) {
if (points[i] && isDate(points[i])) {
points[i] = formatTime(points[i]);
}
}
param.report.timePoints = points;
}
await createConfigFunction(param);
ElMessage.success('提交成功');
} catch (error) {
throw new Error(error);
}
});
};
//
const onReset = () => {
functionForm.value.resetFields();
};
// currentDeviceId && onSearch(currentDeviceId.value);
</script>

34
src/components/history-data.vue

@ -8,6 +8,7 @@
<script setup>
import { onMounted, ref, defineExpose } from 'vue';
import { Line } from '@antv/g2plot';
import { formatChartTime } from 'utils/time';
const show = ref(false);
const noData = ref(true);
@ -16,12 +17,10 @@ let bar = null;
//
onMounted(() => {
show.value = true;
noData.value = false;
});
//
const setDate = data => {
noData.value = false;
if (bar) {
bar.destroy();
}
@ -32,8 +31,8 @@ const setDate = data => {
yField: 'value',
seriesField: 'category',
slider: {
start: 0.1,
end: 0.2,
start: 0.5,
end: 1,
},
height: 700,
// smooth: true,
@ -52,7 +51,12 @@ const setDate = data => {
//
const changeDate = value => {
if (!value.length) return;
if (!value || !value.length) {
noData.value = true;
return;
}
noData.value = false;
const arr = [];
value.forEach(element => {
const item = { ...element };
@ -68,43 +72,43 @@ const changeDate = value => {
const corrosion3Item = { category: '腐流3' };
const corrosion4Item = { category: '腐流4' };
so2Item.time = item.time;
so2Item.time = formatChartTime(item.time);
so2Item.value = item.so2;
arr.push(so2Item);
saltItem.time = item.time;
saltItem.time = formatChartTime(item.time);
saltItem.value = item.salt;
arr.push(saltItem);
environmentTemperatureItem.time = item.time;
environmentTemperatureItem.time = formatChartTime(item.time);
environmentTemperatureItem.value = item.environmentTemperature;
arr.push(environmentTemperatureItem);
environmentHumidityItem.time = item.time;
environmentHumidityItem.time = formatChartTime(item.time);
environmentHumidityItem.value = item.environmentHumidity;
arr.push(environmentHumidityItem);
deviceTemperatureItem.time = item.time;
deviceTemperatureItem.time = formatChartTime(item.time);
deviceTemperatureItem.value = item.deviceTemperature;
arr.push(deviceTemperatureItem);
deviceHumidityItem.time = item.time;
deviceHumidityItem.time = formatChartTime(item.time);
deviceHumidityItem.value = item.deviceHumidity;
arr.push(deviceHumidityItem);
corrosion1Item.time = item.time;
corrosion1Item.time = formatChartTime(item.time);
corrosion1Item.value = item.corrosion1;
arr.push(corrosion1Item);
corrosion2Item.time = item.time;
corrosion2Item.time = formatChartTime(item.time);
corrosion2Item.value = item.corrosion2;
arr.push(corrosion2Item);
corrosion3Item.time = item.time;
corrosion3Item.time = formatChartTime(item.time);
corrosion3Item.value = item.corrosion3;
arr.push(corrosion3Item);
corrosion4Item.time = item.time;
corrosion4Item.time = formatChartTime(item.time);
corrosion4Item.value = item.corrosion4;
arr.push(corrosion4Item);
});

19
src/components/network-config-applied.vue

@ -62,24 +62,11 @@
import { computed, ref, watch, defineEmits, defineProps } from 'vue';
import { useStore } from 'vuex';
import { getConfigAppliedNetwork } from 'apis/index';
import { networkConfig } from '@/config/config';
const originData = {
ip1: '',
port1: '',
ip2: '',
port2: '',
ip3: '',
port3: '',
ipBackup: '',
portBackup: '',
account: '',
password: '',
apn: '',
status: 'PENDING',
};
const store = useStore();
const currentDeviceId = computed(() => store.state.device.currentDeviceId);
const appliedData = ref(originData); //
const appliedData = ref(networkConfig); //
const emit = defineEmits(['status']);
const props = defineProps({ activeName: String });
@ -91,7 +78,7 @@ const onSearch = async deviceId => {
try {
const params = { deviceId };
const resData = await getConfigAppliedNetwork(params);
appliedData.value = resData || originData;
appliedData.value = resData || networkConfig;
if (resData && resData.status) {
emit('status', resData.status);
}

19
src/components/network-config-pending.vue

@ -81,22 +81,9 @@ import { useStore } from 'vuex';
import { ElMessage } from 'element-plus';
import { getConfigNetwork, createConfigNetwork } from 'apis/index';
import Refresh from 'components/refresh.vue';
import { networkConfig } from '@/config/config';
const originData = {
ip1: '',
port1: '',
ip2: '',
port2: '',
ip3: '',
port3: '',
ipBackup: '',
portBackup: '',
account: '',
password: '',
apn: '',
status: 'PENDING',
};
const data = ref(originData);
const data = ref(networkConfig);
const networkForm = ref(null); // form
const store = useStore();
const currentDeviceId = computed(() => store.state.device.currentDeviceId);
@ -112,7 +99,7 @@ async function onSearch(deviceId, type = 0) {
try {
const params = { deviceId, type };
const resData = await getConfigNetwork(params);
data.value = resData || originData;
data.value = resData || networkConfig;
if (resData && resData.status) {
emit('status', resData.status);
}

42
src/components/realtime-data.vue

@ -1,13 +1,14 @@
<template>
<el-card class="box-card">
<el-empty description="暂无数据" v-if="noData"></el-empty>
<div id="realtimeContainer"></div>
<div id="realtimeContainer" v-show="!noData"></div>
</el-card>
</template>
<script setup>
import { onMounted, ref, defineExpose } from 'vue';
import { Line } from '@antv/g2plot';
import { formatChartTime } from 'utils/time';
const show = ref(false);
const noData = ref(true);
@ -16,14 +17,12 @@ let bar = null;
//
onMounted(() => {
show.value = true;
noData.value = false;
});
//
const setDate = data => {
noData.value = false;
if (bar) {
console.log('change data');
bar.changeData(data);
return;
}
@ -35,8 +34,8 @@ const setDate = data => {
yField: 'value',
seriesField: 'category',
slider: {
start: 0.1,
end: 0.2,
start: 0.5,
end: 1,
},
height: 700,
// smooth: true,
@ -50,12 +49,21 @@ const setDate = data => {
},
});
// bar.on('slider:drag', function (event) {
// console.log('event: ', event);
// });
bar.render();
};
//
const changeDate = value => {
if (!value.length) return;
if (!value || !value.length) {
noData.value = true;
return;
}
noData.value = false;
const arr = [];
value.forEach(element => {
const item = { ...element };
@ -71,43 +79,43 @@ const changeDate = value => {
const corrosion3Item = { category: '腐流3' };
const corrosion4Item = { category: '腐流4' };
so2Item.time = item.time;
so2Item.time = formatChartTime(item.time);
so2Item.value = item.so2;
arr.push(so2Item);
saltItem.time = item.time;
saltItem.time = formatChartTime(item.time);
saltItem.value = item.salt;
arr.push(saltItem);
environmentTemperatureItem.time = item.time;
environmentTemperatureItem.time = formatChartTime(item.time);
environmentTemperatureItem.value = item.environmentTemperature;
arr.push(environmentTemperatureItem);
environmentHumidityItem.time = item.time;
environmentHumidityItem.time = formatChartTime(item.time);
environmentHumidityItem.value = item.environmentHumidity;
arr.push(environmentHumidityItem);
deviceTemperatureItem.time = item.time;
deviceTemperatureItem.time = formatChartTime(item.time);
deviceTemperatureItem.value = item.deviceTemperature;
arr.push(deviceTemperatureItem);
deviceHumidityItem.time = item.time;
deviceHumidityItem.time = formatChartTime(item.time);
deviceHumidityItem.value = item.deviceHumidity;
arr.push(deviceHumidityItem);
corrosion1Item.time = item.time;
corrosion1Item.time = formatChartTime(item.time);
corrosion1Item.value = item.corrosion1;
arr.push(corrosion1Item);
corrosion2Item.time = item.time;
corrosion2Item.time = formatChartTime(item.time);
corrosion2Item.value = item.corrosion2;
arr.push(corrosion2Item);
corrosion3Item.time = item.time;
corrosion3Item.time = formatChartTime(item.time);
corrosion3Item.value = item.corrosion3;
arr.push(corrosion3Item);
corrosion4Item.time = item.time;
corrosion4Item.time = formatChartTime(item.time);
corrosion4Item.value = item.corrosion4;
arr.push(corrosion4Item);
});

8
src/components/search-bar-data.vue

@ -2,7 +2,7 @@
<el-form :inline="true" :model="searchDevice" ref="searchDeviceForm">
<el-form-item label="选择站点">
<el-select v-model="searchDevice.deviceId" placeholder="请选择站点" @change="change">
<el-option label="全部" value></el-option>
<!-- <el-option label="全部" value></el-option> -->
<el-option :label="item.address" :value="item.deviceId" v-for="item in devices" :key="item.deviceId"></el-option>
</el-select>
</el-form-item>
@ -80,14 +80,12 @@ const onSubmit = () => {
});
};
// TODO:
//
async function onExport() {
try {
const params = generateParams();
console.log('params: ', params);
const resData = await exportHistory(params);
console.log('resData: ', resData);
// TODO:
resData && (window.location.href = resData);
} catch (error) {
throw new Error(error);
}

2
src/components/search-bar.vue

@ -2,7 +2,7 @@
<el-form :inline="true" :model="searchDevice" ref="searchDeviceForm">
<el-form-item label="选择站点">
<el-select v-model="searchDevice.deviceId" placeholder="请选择站点" @change="change">
<el-option label="全部" value></el-option>
<!-- <el-option label="全部" value></el-option> -->
<el-option :label="item.address" :value="item.deviceId" v-for="item in devices" :key="item.deviceId"></el-option>
</el-select>
</el-form-item>

49
src/config/config.js

@ -0,0 +1,49 @@
export const networkConfig = {
ip1: '',
port1: '',
ip2: '',
port2: '',
ip3: '',
port3: '',
ipBackup: '',
portBackup: '',
account: '',
password: '',
apn: '',
status: '',
};
export const functionConfig = {
frequency: {
so2: 0, // SO2采样频率
metal: 0, // 金属腐蚀采样频率
th: 0, // 温湿度 采样频率
salt: 0, // 盐雾 采样频率
}, // 采样频率
count: 0, // 采集个数
time: Date.now(), // 设置时间
batteryLow: 0, // 电池电压低阈值
batteryHigh: 0, // 电池电压高阈值
sunHigh: 0, // 太阳能电压高阈值
humidityHigh: 0, // 湿度高阈值
temperatureLow: 0, // 温度低阈值
temperatureHigh: 0, // 温度高阈值
securityMode: 'OPEN', // 安全模式 OPEN->不加密 ENCRYPTION->加密
corrosiveType1: '', // 金属腐蚀类型
corrosiveType2: '', // 金属腐蚀类型
corrosiveType3: '', // 金属腐蚀类型
corrosiveType4: '', // 金属腐蚀类型
report: {
type: 'CYCLE', // 上报周期类型 0->时间点 1->周期
timePoints: [0, 0, 0, 0, 0, 0], // 设置时间点
cycle: 0, // 上报周期分钟数
},
status: '',
};
export const corrosiveTypes = [
{ value: 'XIN', type: '锌' },
{ value: 'LV', type: '铝' },
{ value: 'TONG', type: '铜' },
{ value: 'GANG', type: '钢' },
];

16
src/utils/time.js

@ -0,0 +1,16 @@
import dayjs from 'dayjs';
/**
* 格式化时间
* @param {string | number} time 时间戳字符串或数字
* @param {string} formatStyle
* @returns
*/
export function formatMsTime(time, formatStyle = 'YYYY-MM-DD HH:mm:ss') {
return dayjs(+time).format(formatStyle);
}
// 图表时间轴的时间格式化
export function formatChartTime(time) {
return formatMsTime(time, 'MM/DD HH:mm');
}

9
src/views/data-history.vue

@ -3,6 +3,7 @@ import { computed, onMounted, ref } from 'vue';
import { useStore } from 'vuex';
import SearchBar from 'components/search-bar-data.vue';
import { getHistories } from 'apis/index';
import { ElMessage } from 'element-plus';
const search = ref({});
const page = ref({ page: 1, size: 50 });
@ -17,6 +18,9 @@ const data = ref(null);
const getData = async () => {
try {
if (token) {
if (!currentDeviceId.value) {
return ElMessage.error('请选择站点');
}
const options = { ...search.value };
const date = options && options.date ? options.date : [];
const params = {
@ -37,6 +41,7 @@ const getData = async () => {
}, 20);
}
} catch (error) {
ElMessage.error(error.message || '获取数据失败');
console.log('error: ', error);
}
};
@ -90,8 +95,8 @@ const onPrev = e => {
<template v-if="data">
<el-table :data="data" style="width: 100%" border stripe :style="{ 'max-height': contentHeight + 'px' }">
<el-table-column label="设备编号" fixed prop="deviceNo" min-width="140" align="center" />
<el-table-column label="ICCID" fixed prop="ICCID" min-width="100" align="center" />
<el-table-column label="IMEI" fixed prop="IMEI" min-width="80" align="center" />
<el-table-column label="ICCID" prop="ICCID" min-width="100" align="center" />
<el-table-column label="IMEI" prop="IMEI" min-width="80" align="center" />
<el-table-column label="信号强度" prop="signal" min-width="80" align="center" />
<el-table-column label="基站编号" prop="stationNo" min-width="80" align="center" />
<el-table-column label="版本号" prop="version" min-width="80" align="center" />

270
src/views/function-config.vue

@ -1,260 +1,28 @@
<template>
<!-- 设置站点选择 设备下发状态 -->
<DeviceSelectAndStatus @search="onSearch" :status="data.status" />
<el-form label-position="top" :model="data" ref="functionForm">
<el-row :gutter="20">
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置金属腐蚀采样频率(分钟)" prop="frequency.metal">
<el-input-number :min="0" v-model="data.frequency.metal" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温湿度采样频率(分钟)" prop="frequency.th">
<el-input-number :min="0" v-model="data.frequency.th" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置SO2采样频率(分钟)" prop="frequency.so2">
<el-input-number :min="0" v-model="data.frequency.so2" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置盐雾采样频率(分钟)" prop="frequency.salt">
<el-input-number :min="0" v-model="data.frequency.salt" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置时间" prop="time">
<!-- <el-input v-model="data.time"></el-input> -->
<el-date-picker v-model="data.time" type="datetime" placeholder="设置时间"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置金属腐蚀采集个数" prop="count">
<el-input-number :min="0" v-model="data.count" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置电池电压低阈值" prop="batteryLow">
<el-input-number :min="0" v-model="data.batteryLow" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置电池电压高阈值" prop="batteryHigh">
<el-input-number :min="0" v-model="data.batteryHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置太阳能电压高阈值" prop="sunHigh">
<el-input-number :min="0" v-model="data.sunHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置湿度高阈值" prop="humidityHigh">
<el-input-number :min="0" v-model="data.humidityHigh" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温度低阈值" prop="temperatureLow">
<el-input-number :min="0" v-model="data.temperatureLow" />
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="设置温度高阈值" prop="temperatureHigh">
<el-input-number :min="0" v-model="data.temperatureHigh" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道1类型" prop="securityMode">
<el-select v-model="data.corrosiveType1" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道2类型" prop="corrosiveType">
<el-select v-model="data.corrosiveType2" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道3类型" prop="securityMode">
<el-select v-model="data.corrosiveType3" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" :xs="24" :md="12" :lg="8" :xl="6">
<el-form-item label="选择金属通道4类型" prop="corrosiveType">
<el-select v-model="data.corrosiveType4" placeholder="选择金属腐蚀类型">
<el-option v-for="type in types" :key="type.value" :label="type.type" :value="type.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设置安全模式" prop="securityMode">
<!-- <el-input v-model="data.securityMode"></el-input> -->
<el-radio v-model="data.securityMode" :label="0">不加密</el-radio>
<el-radio v-model="data.securityMode" :label="1">加密</el-radio>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设置上报时间" prop="report.type" style="margin-bottom: 0 !important">
<el-radio-group v-model="data.report.type">
<el-radio :label="0">按设定时间点上报</el-radio>
<el-radio :label="1">按设定周期上报(分钟)</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-if="data.report.type === 0">
<el-col :lg="6" :xl="4" :md="8" :sm="12" v-for="(item, index) in data.report.timePoints" :key="index">
<el-form-item prop="report.timePoints" style="margin-bottom: 10px !important">
<el-time-picker format="HH:mm" v-model="data.report.timePoints[index]" :placeholder="`上报时间点${index + 1}`"></el-time-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-else>
<el-col :span="12">
<el-form-item prop="report.cycle">
<el-input-number :min="0" v-model="data.report.cycle" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" class="mt-5 pl-2">
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button @click="onReset">重置</el-button>
</el-form-item>
</el-row>
</el-form>
<!-- 刷新下发按钮 -->
<Refresh @refresh="onSearch(currentDeviceId, 1)" />
<DeviceSelectAndStatus :status="status" />
<el-tabs v-model="activeName">
<el-tab-pane label="下发参数" name="pending" :lazy="true">
<FunctionConfigPending @status="setStatus" v-if="activeName === 'pending'" :active-name="activeName" />
</el-tab-pane>
<el-tab-pane label="设备参数" name="applied" :lazy="true">
<FunctionConfigApplied @status="setStatus" v-if="activeName === 'applied'" :active-name="activeName" />
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
import { ElMessage } from 'element-plus';
import { cloneDeep, isDate } from 'lodash';
import { getConfigFunction, createConfigFunction } from 'apis/index';
import { ref } from 'vue';
import DeviceSelectAndStatus from 'components/device-select-and-status.vue';
import Refresh from 'components/refresh.vue';
const originData = {
frequency: {
so2: 0, // SO2
metal: 0, //
th: 0, // 湿
salt: 0, //
}, //
count: 0, //
time: new Date(), //
batteryLow: 0, //
batteryHigh: 0, //
sunHigh: 0, //
humidityHigh: 0, // 湿
temperatureLow: 0, //
temperatureHigh: 0, //
securityMode: 0, // 0-> 1->
corrosiveType1: '', //
corrosiveType2: '', //
corrosiveType3: '', //
corrosiveType4: '', //
report: {
type: 0, // 0-> 1->
timePoints: [0, 0, 0, 0, 0, 0], //
cycle: 0, //
},
status: 'PENDING',
};
const data = ref(originData);
//
const types = ref([
{ value: 0, type: '锌' },
{ value: 1, type: '铝' },
{ value: 2, type: '铜' },
{ value: 3, type: '钢' },
]);
const functionForm = ref(null); // form
const store = useStore();
const currentDeviceId = computed(() => store.state.device.currentDeviceId);
/**
* 格式化时间
*/
const formatTime = date => {
const hour = date.getHours();
const minute = date.getMinutes();
return `${hour}:${minute}`;
};
//
const onSubmit = () => {
functionForm.value.validate(async () => {
try {
const param = cloneDeep({ ...data.value, deviceId: currentDeviceId.value });
param.time = new Date(param.time).getTime();
if (param.report.type === 0) {
//
const points = [...param.report.timePoints];
for (let i = 0; i < points.length; i++) {
if (points[i] && isDate(points[i])) {
points[i] = formatTime(points[i]);
}
}
param.report.timePoints = points;
}
await createConfigFunction(param);
ElMessage.success('提交成功');
} catch (error) {
ElMessage.error('提交失败, 请稍后重试');
throw new Error(error);
}
});
};
//
const onReset = () => {
functionForm.value.resetFields();
};
import FunctionConfigPending from 'components/function-config-pending.vue';
import FunctionConfigApplied from 'components/function-config-applied.vue';
/**
* 查询网络参数配置
* @param {string} deviceId 设备id
* @param {number} type 0数据库查询 1刷新查询
*/
const onSearch = async (deviceId, type = 0) => {
const params = { deviceId, type };
store.commit('device/setCurrentDeviceId', deviceId);
const resData = await getConfigFunction(params);
if (resData && resData.time) {
resData.time = new Date(+resData.time);
}
data.value = resData || originData;
};
const activeName = ref('pending');
const status = ref('PENDING');
currentDeviceId && onSearch(currentDeviceId.value);
//
function setStatus(event) {
status.value = event;
}
</script>

4
src/views/network-config.vue

@ -1,6 +1,6 @@
<template>
<!-- 设置站点选择 设备下发状态 -->
<DeviceSelectAndStatus @search="onSearch" :status="status" />
<DeviceSelectAndStatus :status="status" />
<el-tabs v-model="activeName">
<el-tab-pane label="下发参数" name="pending" :lazy="true">
@ -19,7 +19,7 @@ import NetworkConfigPending from 'components/network-config-pending.vue';
import NetworkConfigApplied from 'components/network-config-applied.vue';
const activeName = ref('pending');
const status = ref('PENDING');
const status = ref('');
//
function setStatus(event) {

2
src/views/statistical-history.vue

@ -40,7 +40,7 @@ const getDate = async () => {
await store.dispatch('statistics/getRealtimeData', params);
timer && clearTimeout(timer);
timer = null;
childRef.value.changeDate(realtimeData.value);
childRef.value.changeDate(realtimeData.value.data);
} else {
timer = setTimeout(() => {
getDate();

10
src/views/statistical-realtime.vue

@ -40,12 +40,14 @@ const getDate = async () => {
await store.dispatch('statistics/getRealtimeData', params);
timer && clearTimeout(timer);
timer = null;
childRef.value.changeDate(realtimeData.value);
childRef.value.changeDate(realtimeData.value.data);
//
apiTimer = setInterval(() => {
getDate();
}, 5000);
if (!apiTimer) {
apiTimer = setInterval(() => {
getDate();
}, 5000);
}
} else {
timer = setTimeout(() => {
getDate();

Loading…
Cancel
Save