13 changed files with 608 additions and 949 deletions
@ -1,27 +0,0 @@
|
||||
import request from '@/router/axios'; |
||||
|
||||
/** |
||||
* 获取租户详情 |
||||
* @param{string} tenantId |
||||
*/ |
||||
export const getTenantDetail = (tenantId) => request({ |
||||
url: '/api/iot/tenant/summary', |
||||
params: { |
||||
tenantId, |
||||
}, |
||||
}); |
||||
|
||||
/** |
||||
* 获取在线设备统计数据 |
||||
* @param queryStartTime |
||||
* @param queryEndTime |
||||
* @param productId |
||||
*/ |
||||
export const getOnlineDeviceData = (queryStartTime, queryEndTime, productId) => request({ |
||||
url: '/api/iot/statistics/online', |
||||
params: { |
||||
queryStartTime, |
||||
queryEndTime, |
||||
productId, |
||||
}, |
||||
}); |
@ -1,214 +0,0 @@
|
||||
<template> |
||||
<basic-container> |
||||
<avue-crud :option="option" |
||||
:table-loading="loading" |
||||
:data="data" |
||||
:page.sync="page" |
||||
:permission="permissionList" |
||||
:before-open="beforeOpen" |
||||
v-model="form" |
||||
ref="crud" |
||||
@row-update="rowUpdate" |
||||
@row-save="rowSave" |
||||
@row-del="rowDel" |
||||
@search-change="searchChange" |
||||
@search-reset="searchReset" |
||||
@current-change="currentChange" |
||||
@size-change="sizeChange" |
||||
@refresh-change="refreshChange" |
||||
@on-load="onLoad"> |
||||
</avue-crud> |
||||
</basic-container> |
||||
</template> |
||||
|
||||
<script> |
||||
import {add, getDetail, getList, remove, update} from "@/api/iot/vendor/aliConfig"; |
||||
import {mapGetters} from "vuex"; |
||||
|
||||
export default { |
||||
data() { |
||||
return { |
||||
form: {}, |
||||
query: {}, |
||||
loading: true, |
||||
page: { |
||||
pageSize: 10, |
||||
currentPage: 1, |
||||
total: 0 |
||||
}, |
||||
option: { |
||||
tip: false, |
||||
searchShow: true, |
||||
searchMenuSpan: 6, |
||||
border: true, |
||||
index: true, |
||||
viewBtn: true, |
||||
columnBtn: false, |
||||
selection: false, |
||||
dialogClickModal: false, |
||||
dialogWidth: "45%", |
||||
column: [ |
||||
{ |
||||
label: "配置名称", |
||||
prop: "configName", |
||||
span: 24, |
||||
labelWidth: 120, |
||||
search: true, |
||||
searchLabelWidth: 80, |
||||
searchPlaceholder: "请输入配置名称", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入配置名称", |
||||
trigger: "blur" |
||||
}], |
||||
}, |
||||
{ |
||||
label: "区域", |
||||
prop: "regionId", |
||||
span: 22, |
||||
labelWidth: 120, |
||||
searchPlaceholder: "请输入区域", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入区域", |
||||
trigger: "blur" |
||||
}] |
||||
}, |
||||
{ |
||||
label: "AccessKey", |
||||
prop: "accessKey", |
||||
span: 22, |
||||
labelWidth: 120, |
||||
searchPlaceholder: "请输入 AccessKey", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入 AccessKey", |
||||
trigger: "blur" |
||||
}] |
||||
}, |
||||
{ |
||||
label: "AccessSecret", |
||||
prop: "accessSecret", |
||||
span: 22, |
||||
labelWidth: 120, |
||||
searchPlaceholder: "请输入 AccessSecret", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入 AccessSecret", |
||||
trigger: "blur" |
||||
}] |
||||
}, |
||||
{ |
||||
label: "接入域名", |
||||
prop: "connectionUrl", |
||||
span: 22, |
||||
labelWidth: 120, |
||||
searchPlaceholder: "请输入接入域名", |
||||
rules: [{ |
||||
required: false, |
||||
message: "请输入接入域名", |
||||
trigger: "blur" |
||||
}] |
||||
}, |
||||
] |
||||
}, |
||||
data: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapGetters(["permission"]), |
||||
permissionList() { |
||||
return { |
||||
addBtn: this.vaildData(this.permission.ali_config_add, false), |
||||
viewBtn: this.vaildData(this.permission.ali_config_view, false), |
||||
delBtn: this.vaildData(this.permission.ali_config_delete, false), |
||||
editBtn: this.vaildData(this.permission.ali_config_edit, false) |
||||
}; |
||||
} |
||||
}, |
||||
methods: { |
||||
rowSave(row, done, loading) { |
||||
add(row).then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
done(); |
||||
}, error => { |
||||
loading(); |
||||
window.console.log(error); |
||||
}); |
||||
}, |
||||
rowUpdate(row, index, done, loading) { |
||||
update(row).then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
done(); |
||||
}, error => { |
||||
loading(); |
||||
console.log(error); |
||||
}); |
||||
}, |
||||
rowDel(row) { |
||||
this.$confirm("确定将选择数据删除?", { |
||||
confirmButtonText: "确定", |
||||
cancelButtonText: "取消", |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
return remove(row.id); |
||||
}) |
||||
.then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
}); |
||||
}, |
||||
beforeOpen(done, type) { |
||||
if (["edit", "view"].includes(type)) { |
||||
getDetail(this.form.id).then(res => { |
||||
this.form = res.data.data; |
||||
}); |
||||
} |
||||
done(); |
||||
}, |
||||
searchReset() { |
||||
this.query = {}; |
||||
this.onLoad(this.page); |
||||
}, |
||||
searchChange(params, done) { |
||||
this.query = params; |
||||
this.page.currentPage = 1; |
||||
this.onLoad(this.page, params); |
||||
done(); |
||||
}, |
||||
currentChange(currentPage) { |
||||
this.page.currentPage = currentPage; |
||||
}, |
||||
sizeChange(pageSize) { |
||||
this.page.pageSize = pageSize; |
||||
}, |
||||
refreshChange() { |
||||
this.onLoad(this.page, this.query); |
||||
}, |
||||
onLoad(page, params = {}) { |
||||
this.loading = true; |
||||
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => { |
||||
const data = res.data.data; |
||||
this.page.total = data.total; |
||||
this.data = data.records; |
||||
this.loading = false; |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
@ -1,199 +0,0 @@
|
||||
<template> |
||||
<basic-container> |
||||
<avue-crud :option="option" |
||||
:table-loading="loading" |
||||
:data="data" |
||||
:page.sync="page" |
||||
:permission="permissionList" |
||||
:before-open="beforeOpen" |
||||
v-model="form" |
||||
ref="crud" |
||||
@row-update="rowUpdate" |
||||
@row-save="rowSave" |
||||
@row-del="rowDel" |
||||
@search-change="searchChange" |
||||
@search-reset="searchReset" |
||||
@current-change="currentChange" |
||||
@size-change="sizeChange" |
||||
@refresh-change="refreshChange" |
||||
@on-load="onLoad"> |
||||
</avue-crud> |
||||
</basic-container> |
||||
</template> |
||||
|
||||
<script> |
||||
import {add, getDetail, getList, remove, update} from "@/api/iot/vendor/aliConsumer"; |
||||
import {mapGetters} from "vuex"; |
||||
|
||||
export default { |
||||
data() { |
||||
return { |
||||
form: {}, |
||||
query: {}, |
||||
loading: true, |
||||
page: { |
||||
pageSize: 10, |
||||
currentPage: 1, |
||||
total: 0 |
||||
}, |
||||
option: { |
||||
tip: false, |
||||
searchShow: true, |
||||
searchMenuSpan: 6, |
||||
border: true, |
||||
index: true, |
||||
viewBtn: true, |
||||
columnBtn: false, |
||||
selection: false, |
||||
dialogClickModal: false, |
||||
dialogWidth: "45%", |
||||
column: [ |
||||
{ |
||||
label: "阿里云配置", |
||||
prop: "configId", |
||||
type: "tree", |
||||
dicUrl: "/api/iot/ali/config/select", |
||||
props: { |
||||
label: "configName", |
||||
value: "id" |
||||
}, |
||||
span: 24, |
||||
labelWidth: 110, |
||||
search: true, |
||||
searchLabelWidth: 90, |
||||
searchPlaceholder: "请选择阿里云配置", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请选择阿里云配置", |
||||
trigger: "click" |
||||
}], |
||||
editDisplay: false, |
||||
}, |
||||
{ |
||||
label: "消费组名称", |
||||
prop: "consumerName", |
||||
span: 24, |
||||
labelWidth: 110, |
||||
searchPlaceholder: "请输入消费组名称", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入消费组名称", |
||||
trigger: "blur" |
||||
}] |
||||
}, |
||||
{ |
||||
label: "消费组ID", |
||||
prop: "consumerId", |
||||
labelWidth: 110, |
||||
search: true, |
||||
searchPlaceholder: "请输入消费组ID", |
||||
rules: [{ |
||||
required: true, |
||||
message: "请输入消费组ID", |
||||
trigger: "blur" |
||||
}], |
||||
addDisplay: false, |
||||
editDisplay: false, |
||||
}, |
||||
] |
||||
}, |
||||
data: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapGetters(["permission"]), |
||||
permissionList() { |
||||
return { |
||||
addBtn: this.vaildData(this.permission.ali_config_add, false), |
||||
viewBtn: this.vaildData(this.permission.ali_config_view, false), |
||||
delBtn: this.vaildData(this.permission.ali_config_delete, false), |
||||
editBtn: this.vaildData(this.permission.ali_config_edit, false) |
||||
}; |
||||
} |
||||
}, |
||||
methods: { |
||||
rowSave(row, done, loading) { |
||||
add(row).then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
done(); |
||||
}, error => { |
||||
loading(); |
||||
window.console.log(error); |
||||
}); |
||||
}, |
||||
rowUpdate(row, index, done, loading) { |
||||
update(row).then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
done(); |
||||
}, error => { |
||||
loading(); |
||||
console.log(error); |
||||
}); |
||||
}, |
||||
rowDel(row) { |
||||
this.$confirm("确定将选择数据删除?", { |
||||
confirmButtonText: "确定", |
||||
cancelButtonText: "取消", |
||||
type: "warning" |
||||
}) |
||||
.then(() => { |
||||
return remove(row.id); |
||||
}) |
||||
.then(() => { |
||||
this.onLoad(this.page); |
||||
this.$message({ |
||||
type: "success", |
||||
message: "操作成功!" |
||||
}); |
||||
}); |
||||
}, |
||||
beforeOpen(done, type) { |
||||
if (["edit", "view"].includes(type)) { |
||||
getDetail(this.form.id).then(res => { |
||||
this.form = res.data.data; |
||||
}); |
||||
} |
||||
done(); |
||||
}, |
||||
searchReset() { |
||||
this.query = {}; |
||||
this.onLoad(this.page); |
||||
}, |
||||
searchChange(params, done) { |
||||
this.query = params; |
||||
this.page.currentPage = 1; |
||||
this.onLoad(this.page, params); |
||||
done(); |
||||
}, |
||||
currentChange(currentPage) { |
||||
this.page.currentPage = currentPage; |
||||
}, |
||||
sizeChange(pageSize) { |
||||
this.page.pageSize = pageSize; |
||||
}, |
||||
refreshChange() { |
||||
this.onLoad(this.page, this.query); |
||||
}, |
||||
onLoad(page, params = {}) { |
||||
this.loading = true; |
||||
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => { |
||||
const data = res.data.data; |
||||
this.page.total = data.total; |
||||
this.data = data.records; |
||||
this.loading = false; |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
@ -1,352 +0,0 @@
|
||||
<template> |
||||
<div> |
||||
<div class='infos'> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-tickets'></span> |
||||
租户基本信息 |
||||
</div> |
||||
<div class='content'> |
||||
<div> |
||||
租户ID <span>{{tenantDetail.tenantId}}</span> |
||||
</div> |
||||
<div> |
||||
租户名称 <span>{{tenantDetail.tenantName}}</span> |
||||
</div> |
||||
<div> |
||||
开通时间 <span>{{tenantDetail.tenantCreateTime}}</span> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-cpu'></span> |
||||
设备数 |
||||
</div> |
||||
<div class='content'> |
||||
<Bar |
||||
:current-value='tenantDetail.countStatistics.productCount || 0' |
||||
:total-value='tenantDetail.countStatistics.productLimitNumber || 1' |
||||
> |
||||
<template #title> |
||||
<div class='bar-title'> |
||||
<div class='label'> |
||||
产品 |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<template #currentValue>已添加</template> |
||||
</Bar> |
||||
<Bar |
||||
:current-value='tenantDetail.countStatistics.deviceCount || 0' |
||||
:total-value='(tenantDetail.countStatistics.deviceLimitNumberPerProduct || 1) * (tenantDetail.countStatistics.productLimitNumber || 1)' |
||||
> |
||||
<template #title> |
||||
<div class='bar-title'> |
||||
<div class='label'> |
||||
设备 |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<template #currentValue>已添加</template> |
||||
</Bar> |
||||
</div> |
||||
</el-card> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-coin'></span> |
||||
Open API |
||||
</div> |
||||
<div class='content'> |
||||
<div> |
||||
AppID <span>{{tenantDetail.openApi.appId || '-'}}</span> |
||||
</div> |
||||
<div class='secret'> |
||||
AppSecret |
||||
<span> |
||||
{{tenantDetail.openApi.appSecret || '-'}} |
||||
</span> |
||||
<a class='reset' @click='handleReset'>重置</a> |
||||
</div> |
||||
<div> |
||||
生成时间 <span>{{tenantDetail.openApi.createTime || '-'}}</span> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
<div class='device'> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-cpu'></span> |
||||
实时在线设备数 |
||||
<el-tooltip effect='dark' content='于物联网平台建立长连接的设备数量,数据采集有一定延迟。' placement='top'> |
||||
<span class='tips el-icon-question'></span> |
||||
</el-tooltip> |
||||
</div> |
||||
<div class='content'> |
||||
<Bar |
||||
:current-value='tenantDetail.onlineStatistics.onlineCount || 0' |
||||
:total-value='tenantDetail.onlineStatistics.totalCount || 1' |
||||
> |
||||
<template #title> |
||||
<div class='bar-title'> |
||||
<div class='label'> |
||||
当前在线设备 |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</Bar> |
||||
<div class='not-active'> |
||||
<div> |
||||
占比: {{ |
||||
((tenantDetail.onlineStatistics.onlineCount || 0) / (tenantDetail.onlineStatistics.totalCount || 1) * 100).toFixed(2) |
||||
}}% |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-cpu'></span> |
||||
在线设备数量 |
||||
<DatePicker |
||||
v-model='onLineDeviceQueryDate' |
||||
@change='getOnLineDevice' |
||||
/> |
||||
</div> |
||||
<BasicLine class='line-chart' :data='onLineDeviceList' /> |
||||
</el-card> |
||||
</div> |
||||
<div class='message'> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-chat-dot-square'></span> |
||||
发送到平台的消息量 |
||||
<el-tooltip effect='dark' content='从物联网发送到服务端和设备的消息,数据采集有一定延迟。' placement='top'> |
||||
<span class='tips el-icon-question'></span> |
||||
</el-tooltip> |
||||
</div> |
||||
<BasicLine :height='210'/> |
||||
<div class='month'>本月消息量: 3000</div> |
||||
</el-card> |
||||
<el-card> |
||||
<div class='title'> |
||||
<span class='icon el-icon-chat-dot-square'></span> |
||||
平台发出的消息量 |
||||
<el-tooltip effect='dark' content='从物联网发送到服务端和设备的消息,数据采集有一定延迟。' placement='top'> |
||||
<span class='tips el-icon-question'></span> |
||||
</el-tooltip> |
||||
</div> |
||||
<BasicLine :height='210' /> |
||||
<div class='month'>本月消息量: 3000</div> |
||||
</el-card> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import {mapGetters} from 'vuex'; |
||||
import dayjs from 'dayjs'; |
||||
import Bar from '@/components/Bar/index.vue'; |
||||
import BasicLine from '@/components/Charts/BasicLine'; |
||||
import {getOnlineDeviceData, getTenantDetail} from '@/api/sys'; |
||||
import DatePicker from '@/components/DatePicker/index.vue'; |
||||
|
||||
export default { |
||||
name: 'Sys', |
||||
components: { |
||||
Bar, |
||||
BasicLine, |
||||
DatePicker, |
||||
}, |
||||
data() { |
||||
return { |
||||
tenantDetail: { |
||||
countStatistics: {}, |
||||
onlineStatistics: {}, |
||||
openApi: {}, |
||||
}, |
||||
onLineDeviceQueryDate: [dayjs().subtract(24, 'hour'), dayjs()], |
||||
onLineDeviceList: [], |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapGetters(['userInfo']), |
||||
}, |
||||
methods: { |
||||
// 重置 |
||||
handleReset() { |
||||
this.$confirm('重置后将导致原有AppSecret失效, 是否确定重置?', { type: 'warning' }).then(() => { |
||||
// todo reset |
||||
}).catch(() => {}); |
||||
}, |
||||
|
||||
// 获取在线设备数量 |
||||
getOnLineDevice() { |
||||
let [start, end] = this.onLineDeviceQueryDate; |
||||
const format = 'YYYY-MM-DD HH:mm:ss'; |
||||
start = dayjs(start).format(format); |
||||
end = dayjs(end).format(format); |
||||
getOnlineDeviceData(start, end).then((res) => { |
||||
this.onLineDeviceList = res.data.data.map((item) => ({ |
||||
label: dayjs(item.timeString).format('MM/DD HH:mm'), |
||||
value: item.onlineNum, |
||||
})); |
||||
}); |
||||
}, |
||||
|
||||
initData() { |
||||
getTenantDetail(this.userInfo['tenant_id']).then((res) => { |
||||
this.tenantDetail = res.data.data; |
||||
}); |
||||
this.getOnLineDevice(); |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.initData(); |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang='scss'> |
||||
.infos { |
||||
display: flex; |
||||
|
||||
.el-card { |
||||
flex: 1; |
||||
margin-right: 20px; |
||||
|
||||
&:last-child { |
||||
margin-right: 0; |
||||
} |
||||
|
||||
.content { |
||||
color: #555555; |
||||
font-size: 14px; |
||||
line-height: 3; |
||||
|
||||
span { |
||||
margin-left: 10px; |
||||
} |
||||
|
||||
.reset { |
||||
color: red; |
||||
cursor: pointer; |
||||
margin: 0 20px; |
||||
|
||||
&:hover { |
||||
text-decoration: underline; |
||||
} |
||||
} |
||||
|
||||
.ki-bar:first-child { |
||||
margin-top: 20px; |
||||
} |
||||
|
||||
.ki-bar { |
||||
margin-top: 30px; |
||||
} |
||||
|
||||
.secret { |
||||
display: flex; |
||||
|
||||
span { |
||||
width: 0; |
||||
flex: 1; |
||||
overflow: hidden; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.title { |
||||
color: #000c17; |
||||
font-weight: bold; |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
.icon { |
||||
margin-right: 10px; |
||||
} |
||||
} |
||||
|
||||
.bar-title { |
||||
color: #555555; |
||||
font-size: 14px; |
||||
display: flex; |
||||
align-items: baseline; |
||||
|
||||
.label { |
||||
font-size: 16px; |
||||
font-weight: bold; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
span { |
||||
font-size: 14px; |
||||
font-weight: normal; |
||||
} |
||||
} |
||||
|
||||
.tips { |
||||
color: #cccccc; |
||||
margin-left: 10px; |
||||
} |
||||
|
||||
.el-date-editor { |
||||
margin-left: auto; |
||||
} |
||||
|
||||
.device { |
||||
margin-top: 20px; |
||||
display: flex; |
||||
|
||||
.el-card:first-child { |
||||
flex: 1; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
.el-card:last-child { |
||||
flex: 2; |
||||
padding-right: 20px |
||||
} |
||||
|
||||
.ki-bar, .line-chart { |
||||
margin-top: 25px; |
||||
} |
||||
|
||||
.not-active { |
||||
margin-top: 30px; |
||||
|
||||
span { |
||||
font-size: 14px; |
||||
margin-left: 10px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.message { |
||||
margin-top: 20px; |
||||
display: flex; |
||||
|
||||
.title { |
||||
margin-bottom: 30px; |
||||
} |
||||
|
||||
.el-card { |
||||
flex: 1; |
||||
} |
||||
|
||||
.el-card:first-child { |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
.month { |
||||
font-size: 14px; |
||||
margin-top: 15px; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue