提交: 項目管理 詳情頁 设备管理和 项目信息 代码
This commit is contained in:
parent
11d8226408
commit
3e91c55148
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
|
@ -11,7 +11,7 @@
|
|||
<link rel="stylesheet" href="//at.alicdn.com/t/font_2506643_9w119og75cs.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_2506643_9xrjupanl8d.css">
|
||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_2506643_d5as4r89keo.css">
|
||||
|
||||
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.15&key=aabc97a5e095102787d405719847ecf0"></script>
|
||||
<script src="<%= BASE_URL %>js/config.js"></script>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import request from "@/utils/request";
|
||||
|
||||
// 查询 项目 网关/子设备
|
||||
export function listProjectDevice(query) {
|
||||
return request({
|
||||
url: "/iot/device/getProjectDeviceList",
|
||||
method: "get",
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询 项目 型号
|
||||
export function listProjectModel(query) {
|
||||
return request({
|
||||
url: "/iot/model/getProjectModelList",
|
||||
method: "get",
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询 项目 子设备 表格 列
|
||||
export function listProjectTableFilter(query) {
|
||||
return request({
|
||||
url: "/iot/dev/prod/fun/tableHeader",
|
||||
method: "get",
|
||||
params: query
|
||||
});
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,8 @@
|
|||
|
||||
import ESimpleCard from "./src/ESimpleCard/index"
|
||||
|
||||
ESimpleCard.install = function install(Vue) {
|
||||
Vue.component(ESimpleCard.name, ESimpleCard);
|
||||
};
|
||||
|
||||
export default ESimpleCard
|
|
@ -0,0 +1,84 @@
|
|||
import './style.scss'
|
||||
export default {
|
||||
name: 'ESimpleCard',
|
||||
props: {
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'horizontal'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
extra: {
|
||||
type: [String, Boolean],
|
||||
default: false
|
||||
},
|
||||
labelStyle: {
|
||||
type: Object
|
||||
},
|
||||
contentStyle: {
|
||||
type: Object
|
||||
},
|
||||
labelClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
data: {
|
||||
type: [String, Object, Number, Array]
|
||||
},
|
||||
colon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'el-icon-s-grid'
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
handleExtra() {
|
||||
const { data } = this;
|
||||
this.$emit('click', data)
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { title, extra, $slots, icon, color } = this;
|
||||
return (
|
||||
<div class="e-simple-card">
|
||||
{
|
||||
(title || extra || $slots.cardHeader) ?
|
||||
<div class="e-simple-card__header">
|
||||
{ $slots.cardHeader ||
|
||||
<template class="e-header-template">
|
||||
<div class="template-left">
|
||||
<i class={[ icon ? icon : 'el-icon-s-grid', 'template-icon' ]}></i>
|
||||
<div class="template-title">
|
||||
{ title }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{ extra ?
|
||||
<div class="template__extra">
|
||||
<i class="el-icon-setting icon" onClick={this.handleExtra}></i>
|
||||
</div> : null
|
||||
}
|
||||
</template>
|
||||
}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div class="e-simple-card__body">
|
||||
{
|
||||
$slots.cardBody
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
.e-simple-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #E8E8E8;
|
||||
border-radius: 5px;
|
||||
|
||||
}
|
||||
.e-simple-card__header {
|
||||
border-bottom: 1px solid #E8E8E8;
|
||||
padding: 10px;
|
||||
}
|
||||
.e-simple-card__body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.e-simple-card__header .e-header-template {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
align-items: center;
|
||||
}
|
||||
.e-header-template .template-left {
|
||||
width: 60%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
.e-header-template .template-left .template-title {
|
||||
font-size: 14px;
|
||||
font-family: 'Source Han Sans CN';
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
}
|
||||
.e-header-template .template-left .template-icon {
|
||||
font-size: 14px;
|
||||
margin-right: 5px;
|
||||
color: #344567;
|
||||
}
|
||||
|
||||
.e-header-template .template__extra {
|
||||
width: 40%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.e-header-template .template__extra .icon:hover {
|
||||
color: #1890ff
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import Descriptions from './src/index';
|
||||
import './style.scss'
|
||||
|
||||
/* istanbul ignore next */
|
||||
Descriptions.install = function install(Vue) {
|
||||
Vue.component(Descriptions.name, Descriptions);
|
||||
};
|
||||
|
||||
export default Descriptions;
|
|
@ -0,0 +1,30 @@
|
|||
export default {
|
||||
name: 'ElDescriptionsItem',
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
span: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
contentClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentStyle: {
|
||||
type: Object
|
||||
},
|
||||
labelClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
labelStyle: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,116 @@
|
|||
export default {
|
||||
name: 'ElDescriptionsRow',
|
||||
props: {
|
||||
row: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
inject: ['elDescriptions'],
|
||||
render(h) {
|
||||
const { elDescriptions } = this;
|
||||
const row = (this.row || []).map(item => {
|
||||
return {
|
||||
...item,
|
||||
label: item.slots.label || item.props.label,
|
||||
...['labelClassName', 'contentClassName', 'labelStyle', 'contentStyle'].reduce((res, key) => {
|
||||
res[key] = item.props[key] || elDescriptions[key];
|
||||
return res;
|
||||
}, {})
|
||||
};
|
||||
});
|
||||
if (elDescriptions.direction === 'vertical') {
|
||||
return (
|
||||
<tbody>
|
||||
<tr class="el-descriptions-row">
|
||||
{
|
||||
row.map(item => {
|
||||
return (
|
||||
<th
|
||||
class={{
|
||||
'el-descriptions-item__cell': true,
|
||||
'el-descriptions-item__label': true,
|
||||
'has-colon': elDescriptions.border ? false : elDescriptions.colon,
|
||||
'is-bordered-label': elDescriptions.border,
|
||||
[item.labelClassName]: true
|
||||
}}
|
||||
style={item.labelStyle}
|
||||
colSpan={item.props.span}
|
||||
>{item.label}</th>
|
||||
);
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
<tr class="el-descriptions-row">
|
||||
{
|
||||
row.map(item =>{
|
||||
return (
|
||||
<td
|
||||
class={['el-descriptions-item__cell', 'el-descriptions-item__content', item.contentClassName]}
|
||||
style={item.contentStyle}
|
||||
colSpan={item.props.span}
|
||||
>{item.slots.default}</td>
|
||||
);
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
if (elDescriptions.border) {
|
||||
return (
|
||||
<tbody>
|
||||
<tr class="el-descriptions-row">
|
||||
{
|
||||
row.map(item=> {
|
||||
return ([
|
||||
<th
|
||||
class={{
|
||||
'el-descriptions-item__cell': true,
|
||||
'el-descriptions-item__label': true,
|
||||
'is-bordered-label': elDescriptions.border,
|
||||
[item.labelClassName]: true
|
||||
}}
|
||||
style={item.labelStyle}
|
||||
colSpan="1"
|
||||
>{item.label}</th>,
|
||||
<td
|
||||
class={['el-descriptions-item__cell', 'el-descriptions-item__content', item.contentClassName]}
|
||||
style={item.contentStyle}
|
||||
colSpan={item.props.span * 2 - 1}
|
||||
>{item.slots.default}</td>
|
||||
]);
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<tbody>
|
||||
<tr class="el-descriptions-row">
|
||||
{
|
||||
row.map(item=> {
|
||||
return (
|
||||
<td class="el-descriptions-item el-descriptions-item__cell" colSpan={item.props.span}>
|
||||
<div class="el-descriptions-item__container">
|
||||
<span
|
||||
class={{
|
||||
'el-descriptions-item__label': true,
|
||||
'has-colon': elDescriptions.colon,
|
||||
[item.labelClassName]: true
|
||||
}}
|
||||
style={item.labelStyle}
|
||||
>{item.label}</span>
|
||||
<span
|
||||
class={['el-descriptions-item__content', item.contentClassName]}
|
||||
style={item.contentStyle}
|
||||
>{item.slots.default}</span>
|
||||
</div>
|
||||
</td>);
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,180 @@
|
|||
import DescriptionsRow from './descriptions-row';
|
||||
import { isFunction } from 'element-ui/src/utils/types';
|
||||
|
||||
export default {
|
||||
name: 'ElDescriptions',
|
||||
components: {
|
||||
[DescriptionsRow.name]: DescriptionsRow
|
||||
},
|
||||
props: {
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
column: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'horizontal'
|
||||
},
|
||||
size: {
|
||||
type: String
|
||||
// validator: isValidComponentSize,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
extra: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
labelStyle: {
|
||||
type: Object
|
||||
},
|
||||
contentStyle: {
|
||||
type: Object
|
||||
},
|
||||
labelClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentClassName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
colon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
descriptionsSize() {
|
||||
return this.size || (this.$ELEMENT || {}).size;
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
elDescriptions: this
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getOptionProps(vnode) {
|
||||
if (vnode.componentOptions) {
|
||||
const componentOptions = vnode.componentOptions;
|
||||
const { propsData = {}, Ctor = {} } = componentOptions;
|
||||
const props = (Ctor.options || {}).props || {};
|
||||
const res = {};
|
||||
for (const k in props) {
|
||||
const v = props[k];
|
||||
const defaultValue = v.default;
|
||||
if (defaultValue !== undefined) {
|
||||
res[k] = isFunction(defaultValue) ? defaultValue.call(vnode) : defaultValue;
|
||||
}
|
||||
}
|
||||
return { ...res, ...propsData };
|
||||
}
|
||||
return {};
|
||||
},
|
||||
getSlots(vnode) {
|
||||
let componentOptions = vnode.componentOptions || {};
|
||||
const children = vnode.children || componentOptions.children || [];
|
||||
const slots = {};
|
||||
children.forEach(child => {
|
||||
if (!this.isEmptyElement(child)) {
|
||||
const name = (child.data && child.data.slot) || 'default';
|
||||
slots[name] = slots[name] || [];
|
||||
if (child.tag === 'template') {
|
||||
slots[name].push(child.children);
|
||||
} else {
|
||||
slots[name].push(child);
|
||||
}
|
||||
}
|
||||
});
|
||||
return { ...slots };
|
||||
},
|
||||
isEmptyElement(c) {
|
||||
return !(c.tag || (c.text && c.text.trim() !== ''));
|
||||
},
|
||||
filledNode(node, span, count, isLast = false) {
|
||||
if (!node.props) {
|
||||
node.props = {};
|
||||
}
|
||||
if (span > count) {
|
||||
node.props.span = count;
|
||||
}
|
||||
if (isLast) {
|
||||
// set the max span, cause of the last td
|
||||
node.props.span = count;
|
||||
}
|
||||
return node;
|
||||
},
|
||||
getRows() {
|
||||
const children = ((this.$slots.default || []).filter(vnode => vnode.tag &&
|
||||
vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElDescriptionsItem'));
|
||||
const nodes = children.map(vnode => {
|
||||
return {
|
||||
props: this.getOptionProps(vnode),
|
||||
slots: this.getSlots(vnode),
|
||||
vnode
|
||||
};
|
||||
});
|
||||
const rows = [];
|
||||
let temp = [];
|
||||
let count = this.column;
|
||||
|
||||
nodes.forEach((node, index) => {
|
||||
const span = node.props.span || 1;
|
||||
|
||||
if (index === children.length - 1) {
|
||||
temp.push(this.filledNode(node, span, count, true));
|
||||
rows.push(temp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (span < count) {
|
||||
count -= span;
|
||||
temp.push(node);
|
||||
} else {
|
||||
temp.push(this.filledNode(node, span, count));
|
||||
rows.push(temp);
|
||||
count = this.column;
|
||||
temp = [];
|
||||
}
|
||||
});
|
||||
|
||||
return rows;
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { title, extra, border, descriptionsSize, $slots } = this;
|
||||
const rows = this.getRows();
|
||||
|
||||
return (
|
||||
<div class="el-descriptions">
|
||||
{
|
||||
(title || extra || $slots.title || $slots.extra)
|
||||
? <div class="el-descriptions__header">
|
||||
<div class="el-descriptions__title">
|
||||
{ $slots.title ? $slots.title : title}
|
||||
</div>
|
||||
<div class="el-descriptions__extra">
|
||||
{ $slots.extra ? $slots.extra : extra }
|
||||
</div>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
|
||||
<div class="el-descriptions__body">
|
||||
<table class={['el-descriptions__table', {'is-bordered': border}, descriptionsSize ? `el-descriptions--${descriptionsSize}` : '']}>
|
||||
{rows.map(row => (
|
||||
<DescriptionsRow row={row}></DescriptionsRow>
|
||||
))}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
|
@ -11,6 +11,7 @@ let wsProtocol = 'ws://';
|
|||
let iotWebSocketAlarmBaseUrl = ''
|
||||
let bigWebSocketUrl = ''
|
||||
let port = '8899'
|
||||
let webSocketProjectGatewayUrl = ''
|
||||
|
||||
// window.dasConfig = {
|
||||
// ip: 'http://192.168.10.241:32024'
|
||||
|
@ -41,8 +42,9 @@ if (env.NODE_ENV == 'development') {
|
|||
} else if(env.NODE_ENV == 'test') {
|
||||
}
|
||||
iotWebSocketAlarmBaseUrl = sysWebSocket + hrefHost + ':8899/ws/alarm/live'
|
||||
bigWebSocketUrl = sysWebSocket + hrefHost + ( port ? ':'+ port :'') + '/ws/dev/readData'
|
||||
sysWebSocket = sysWebSocket + hrefHost;
|
||||
sysWebSocket = sysWebSocket + hrefHost + ( port ? ':'+ port :'');
|
||||
bigWebSocketUrl = sysWebSocket + '/ws/dev/readData'
|
||||
webSocketProjectGatewayUrl = sysWebSocket + '/ws/dev/projectDeviceLive'
|
||||
iotWebSocketBaseUrl = sysWebSocket + '/ws/dev/up/'
|
||||
devLiveWebSocketBaseUrl = sysWebSocket + '/ws/dev/live/'
|
||||
iotPlatformUrl = 'http://' + iotHost + prodApi
|
||||
|
@ -54,5 +56,6 @@ export {
|
|||
iotWebSocketAlarmBaseUrl,
|
||||
devLiveWebSocketBaseUrl,
|
||||
prodApi,
|
||||
bigWebSocketUrl
|
||||
bigWebSocketUrl,
|
||||
webSocketProjectGatewayUrl
|
||||
}
|
||||
|
|
|
@ -274,9 +274,9 @@
|
|||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<div class="to-home-wrap2" @click="linkToTable" v-show="componectVal !== ''">
|
||||
<!-- <div class="to-home-wrap2" @click="linkToTable" v-show="componectVal !== ''">
|
||||
<el-button icon="el-icon-d-arrow-left" title="返回列表" circle>返回列表</el-button>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -647,7 +647,7 @@ export default {
|
|||
},
|
||||
handleDetails(row) {
|
||||
this.sourceId = row.projectId;
|
||||
this.componectVal = "DetailsWrap";
|
||||
this.componectVal = "DetailsWrapNew";
|
||||
},
|
||||
// 跳转详情页
|
||||
linkToTable() {
|
||||
|
|
|
@ -0,0 +1,442 @@
|
|||
<template>
|
||||
<div class="e-object-device-children-table">
|
||||
<div class="device-children-header">
|
||||
<div class="left-link-home" @click="handleLinkToHome">
|
||||
<icon class="iconfont iconfanhui_1"></icon>
|
||||
<span class="link-bt-title">返回</span>
|
||||
</div>
|
||||
<div class="lift-gateway-info">
|
||||
<span class="gateway-label">位置:</span>
|
||||
<span class="gateway-adders">{{
|
||||
gatewayDevice.deviceAddress || "--"
|
||||
}}</span>
|
||||
<span class="gateway-label">设备号:</span>
|
||||
<span class="gateway-did">{{ gatewayDevice.deviceId || "--" }}</span>
|
||||
<span class="gateway-label">在线状态:</span>
|
||||
<span
|
||||
:class="
|
||||
gatewayDevice.deviceState === 'ONLINE'
|
||||
? 'gateway-stu'
|
||||
: 'gateway-stu off-line'
|
||||
"
|
||||
>
|
||||
{{ gatewayDevice.deviceState === "ONLINE" ? "在线" : "离线" }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="right-operate">
|
||||
<div class="operate-refresh" @click="handleRefresh">
|
||||
刷新
|
||||
</div>
|
||||
<div :class="tableSelectList && tableSelectList.length > 0 ? 'operate-onekey-on' : 'operate-onekey-on but-disable'" @click="handleChildStatus('true')">
|
||||
一键合闸
|
||||
</div>
|
||||
<div :class="tableSelectList && tableSelectList.length > 0 ? 'operate-onekey-on' : 'operate-onekey-on but-disable'" @click="handleChildStatus('false')">
|
||||
一键分闸
|
||||
</div>
|
||||
<el-select v-model="queryParams.prodKey" style="margin-left: 5xp; width: 120px;" placeholder="请选择项目类型" size="small">
|
||||
<el-option
|
||||
v-for="dict in projectModelList"
|
||||
:key="dict.prodKey"
|
||||
:label="dict.modelName"
|
||||
:value="dict.prodKey"
|
||||
@change="getTableFilterList"
|
||||
></el-option>
|
||||
</el-select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-children-center">
|
||||
<e-dynamic-table
|
||||
:border="false"
|
||||
:loading="tableLoading"
|
||||
:tableTotal="0"
|
||||
:queryParams="queryParams"
|
||||
:tableList="tableList"
|
||||
:filterList="[...defaultFilterList, ...filterList]"
|
||||
:isIndex="true"
|
||||
:isSelect="true"
|
||||
rowKey="deviceId"
|
||||
@tableSelectionChange="handleTableChange"
|
||||
@handleQuery="handleQuery"
|
||||
>
|
||||
<template v-slot:operate="operate">
|
||||
<div>
|
||||
<span>{{ operate }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</e-dynamic-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EDynamicTable from "./EDynamicTable";
|
||||
import { listProjectDevice, listProjectModel, listProjectTableFilter } from '@/api/iot/project_new'
|
||||
import { setSwitchControl } from "@/api/iot/device";
|
||||
import { webSocketProjectGatewayUrl } from "@/config/env";
|
||||
export default {
|
||||
name: "EDeviceChildren",
|
||||
components: {
|
||||
EDynamicTable,
|
||||
},
|
||||
props: {
|
||||
gatewayDevice: {
|
||||
type: Object,
|
||||
require: true,
|
||||
},
|
||||
sourceId: {
|
||||
type: [String, Number],
|
||||
require: true,
|
||||
},
|
||||
deviceType: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
queryParams: {
|
||||
prodKey: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
tableLoading: true,
|
||||
tableList: [],
|
||||
defaultFilterList: [
|
||||
{
|
||||
label: "线路名称",
|
||||
align: "center",
|
||||
prop: "deviceName",
|
||||
width: "150px"
|
||||
},
|
||||
{
|
||||
label: "型号",
|
||||
align: "center",
|
||||
prop: "modelName",
|
||||
width: "150px",
|
||||
},
|
||||
],
|
||||
|
||||
filterList: [],
|
||||
operate: {
|
||||
label: "操作",
|
||||
align: "left",
|
||||
prop: "operate",
|
||||
width: "200px",
|
||||
slot: true,
|
||||
slotName: "operate",
|
||||
},
|
||||
projectModelList: [],
|
||||
tableSelectList: [],
|
||||
stompClient: null,
|
||||
socket_flag: true,
|
||||
timeout_flag: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.tableLoading = true
|
||||
this.getProjectModelList()
|
||||
},
|
||||
methods: {
|
||||
handleLinkToHome() {
|
||||
this.$emit("handleLinkToHome");
|
||||
},
|
||||
// 处理数据 成为表格可用 列数据
|
||||
handleTableFilter(list) {
|
||||
var resultList = [];
|
||||
if (list && list.length > 0) {
|
||||
list.forEach(v => {
|
||||
resultList.push({
|
||||
label: v['unitName'] ? `${v['name']}(${v['unitName']})` : v['name'],
|
||||
align: "center",
|
||||
prop: v['key'],
|
||||
width: list.length > 5 ? '200px' : '',
|
||||
})
|
||||
});
|
||||
};
|
||||
return resultList;
|
||||
},
|
||||
// 获取 项目 型号列表
|
||||
getProjectModelList() {
|
||||
listProjectModel({
|
||||
projectId: this.sourceId,
|
||||
deviceTags: this.deviceType || '',
|
||||
pid: this.gatewayDevice.deviceId || ''
|
||||
}).then(res => {
|
||||
this.projectModelList = res.data
|
||||
if (this.projectModelList && this.projectModelList.length > 0) {
|
||||
this.queryParams.prodKey = this.projectModelList[0]['prodKey']
|
||||
this.getTableFilterList()
|
||||
};
|
||||
})
|
||||
},
|
||||
// 获取 子设备列表
|
||||
getTableFilterList() {
|
||||
this.filterList = []
|
||||
this.getChildrenDeviceList()
|
||||
listProjectTableFilter({
|
||||
prodKey: this.queryParams.prodKey
|
||||
}).then(res => {
|
||||
this.filterList = this.handleTableFilter(res.data)
|
||||
this.$forceUpdate()
|
||||
this.tableLoading = false
|
||||
})
|
||||
},
|
||||
// 查询 子设备列表数据---需要考虑到型号的问题
|
||||
getChildrenDeviceList() {
|
||||
this.tableList = []
|
||||
listProjectDevice(Object.assign({
|
||||
projectId: this.sourceId || '',
|
||||
deviceTags: this.deviceType || '',
|
||||
pid: this.gatewayDevice.deviceId || ''
|
||||
}, this.queryParams)).then(res => {
|
||||
this.tableList = res.data
|
||||
if (this.stompClient) {
|
||||
this.closeSocket()
|
||||
}
|
||||
this.connection()
|
||||
})
|
||||
},
|
||||
// 动态表格 返回的 勾选数据
|
||||
handleTableChange(e) {
|
||||
if (e && e.length > 0) {
|
||||
this.tableSelectList = e.map(v => v['deviceId'])
|
||||
} else {
|
||||
this.tableSelectList = []
|
||||
}
|
||||
},
|
||||
// 点击子设备 线路开关
|
||||
handleChildStatus(type) {
|
||||
this.$prompt("请输入登录密码", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
inputPattern: /^[a-z A-z 0-9 $.]+/,
|
||||
inputType: "password",
|
||||
inputErrorMessage: "登录密码不能为空",
|
||||
}).then(({ value }) => {
|
||||
let params = {
|
||||
data: {
|
||||
cmd: "set_switch",
|
||||
params: {
|
||||
switch: 1
|
||||
},
|
||||
},
|
||||
deviceId: '',
|
||||
verifyKey: value,
|
||||
};
|
||||
|
||||
switch(type) {
|
||||
case 'true':
|
||||
params.data.params.switch = 1;
|
||||
params.deviceId = this.tableSelectList.toString();
|
||||
break;
|
||||
|
||||
case 'false':
|
||||
params.data.params.switch = 0;
|
||||
params.deviceId = this.tableSelectList.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
setSwitchControl(params).then((res) => {
|
||||
this.msgSuccess("修改成功");
|
||||
});
|
||||
});
|
||||
},
|
||||
handleRefresh() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getChildrenDeviceList()
|
||||
},
|
||||
// 表格 分页查询
|
||||
handleQuery(e) {
|
||||
this.queryParams = Object.assign(this.queryParams, e)
|
||||
this.getChildrenDeviceList()
|
||||
},
|
||||
// 处理 socket 数据返回 赋值问题
|
||||
handleDeviceInfo(param) {
|
||||
if (this.tableList && this.tableList.length > 0) {
|
||||
this.tableList = this.tableList.map(v => {
|
||||
if (v['deviceId'] === param['deviceId']) {
|
||||
return Object.assign(v, param)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 创建一个ws 监听获取报警实时数据
|
||||
connection() {
|
||||
if (this.stompClient) {
|
||||
return;
|
||||
}
|
||||
if (!webSocketProjectGatewayUrl) {
|
||||
return;
|
||||
}
|
||||
if (!this.tableList || this.length <= 0) {
|
||||
return;
|
||||
}
|
||||
let deviceIds = this.tableList.map(v => v['deviceId'])
|
||||
this.stompClient = new WebSocket(
|
||||
`${webSocketProjectGatewayUrl}/${this.getGuid()}/${ deviceIds.toString() }`
|
||||
);
|
||||
this.stompClient.onmessage = this.socket_message;
|
||||
this.stompClient.onclose = this.socket_onclose;
|
||||
},
|
||||
socket_message(evt) {
|
||||
console.log("wsljcg:=", evt);
|
||||
const data = JSON.parse(evt.data);
|
||||
// this.actualEnergyCensus = data.params || {};
|
||||
console.log('socket-message:', data)
|
||||
this.handleDeviceInfo(data)
|
||||
this.$forceUpdate();
|
||||
},
|
||||
socket_onclose(e) {
|
||||
this.stompClient = null;
|
||||
if (this.socket_flag) {
|
||||
this.socket_flag = false;
|
||||
let _this = this;
|
||||
this.timeout_flag = setTimeout(function () {
|
||||
_this.socket_flag = true;
|
||||
_this.connection();
|
||||
}, 10000);
|
||||
}
|
||||
},
|
||||
closeSocket() {
|
||||
if (this.stompClient) {
|
||||
this.stompClient.close();
|
||||
}
|
||||
this.socket_flag = false;
|
||||
this.stompClient = null;
|
||||
clearTimeout(this.timeout_flag);
|
||||
},
|
||||
getGuid() {
|
||||
return "xxxxxxx_xxxxx_4xxx_yxxx_xxxxxxxxxxxx".replace(/[xy]/g, function(
|
||||
c
|
||||
) {
|
||||
var r = (Math.random() * 16) | 0,
|
||||
v = c == "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
this.closeSocket()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.e-object-device-children-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.device-children-header {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.left-link-home {
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
background: #f4f5f7;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #6b778c;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.link-bt-title {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.lift-gateway-info {
|
||||
width: calc(100% - 420px);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 10px;
|
||||
justify-content: space-around;
|
||||
.gateway-label {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #6b778c;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gateway-adders {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #344567;
|
||||
width: calc(45% - 60px);
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gateway-did {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #344567;
|
||||
width: calc(55% - 20% - 80px);
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gateway-stu {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #009003;
|
||||
width: calc(18% - 80px);
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.off-line {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
.right-operate {
|
||||
width: 350px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
font-size: 12px;
|
||||
font-family: Source Han Sans CN;
|
||||
cursor: default;
|
||||
.operate-refresh {
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
background: #F4F5F7;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 5px;
|
||||
}
|
||||
.operate-onekey-on {
|
||||
width: 75px;
|
||||
height: 30px;
|
||||
background: #F4F5F7;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 5px;
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
}
|
||||
.but-disable {
|
||||
color: #6B778C;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,512 @@
|
|||
<template>
|
||||
<div class="e-object-device-manage-table">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
v-show="showChildrenView === false"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="型号名称" prop="modelName">
|
||||
<!-- <el-input
|
||||
v-model="queryParams.modelName"
|
||||
placeholder="请输入型号名称"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/> -->
|
||||
<el-select v-model="queryParams.prodKey" placeholder="请选择项目类型" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in projectModelList"
|
||||
:key="dict.prodKey"
|
||||
:label="dict.modelName"
|
||||
:value="dict.prodKey"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="设备名称" prop="deviceName">
|
||||
<el-input
|
||||
v-model="queryParams.deviceName"
|
||||
placeholder="请输入设备名称"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="设备状态" prop="deviceStatus">
|
||||
<el-input
|
||||
v-model="queryParams.deviceStatus"
|
||||
placeholder="请输入设备状态"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="设备类型" prop="deviceStatus">
|
||||
<el-input
|
||||
v-model="queryParams.deviceStatus"
|
||||
placeholder="请输入设备类型"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="4">
|
||||
<el-form-item class="query-foot">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
size="mini"
|
||||
@click="handleQuery"
|
||||
>搜索</el-button
|
||||
>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
|
||||
>重置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="table-container" v-show="showChildrenView === false">
|
||||
<e-simple-card title="" extra="" class="object-device-card" v-for="(devItem, idx) in list" :key="idx">
|
||||
<template slot="cardHeader" class="card-custom-head">
|
||||
<div :class="devItem['deviceState'] == 'ONLINE' ? 'card-left' : 'card-left off-line'">
|
||||
<icon v-if="devItem['deviceState'] == 'ONLINE'" class="iconfont iconSYS_STA_1"/>
|
||||
<icon v-else class="iconfont iconlixian"/>
|
||||
<span style="margin-left: 8px;">{{ devItem['deviceState'] == 'ONLINE' ? '在线' : '离线' }}</span>
|
||||
</div>
|
||||
<div class="card-right">
|
||||
<span class="c-label">线路数:</span>
|
||||
<span class="c-number">{{ devItem.routeCount || 0}}</span>
|
||||
|
||||
<el-dropdown>
|
||||
<icon class="el-icon-s-operation card-opt-i"/>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="handleChildrenDevice(devItem)">查看线路列表</el-dropdown-item>
|
||||
<el-dropdown-item>修改服务指向</el-dropdown-item>
|
||||
<el-dropdown-item>设备巡检记录</el-dropdown-item>
|
||||
<el-dropdown-item>设备参数调整</el-dropdown-item>
|
||||
<el-dropdown-item>内置定时配置</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<template slot="cardBody">
|
||||
<div class="object-device-body">
|
||||
<div class="card-body-info">
|
||||
<div class="card-body-left">
|
||||
<img :src="devItem['deviceImage'] ? devItem['deviceImage'] : '/images/devcie_default.png'" />
|
||||
</div>
|
||||
<div class="card-body-right">
|
||||
<span :title="devItem.deviceId">{{ devItem.deviceId }}</span>
|
||||
<span :title="devItem.deviceSecret">{{ devItem.deviceSecret }}</span>
|
||||
<span :title="devItem.deviceAddress">{{ devItem.deviceAddress }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body-footer">
|
||||
<!-- {{ renderCardFooter(devItem) }} -->
|
||||
<div :class="devItem.alarmProcessStatus == 1 ? 'card-footer' : 'card-footer dev-error'">
|
||||
<icon class="iconfont icontongzhi"></icon>
|
||||
<span stle="margin-left: 10px;" class="footer-title">{{ devItem.alarmProcessStatus == 1 ? '正常' : `时间:${devItem.alarmTime} ${devItem.alarmTypeName || '--'}` }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</e-simple-card>
|
||||
</div>
|
||||
<div v-if="showChildrenView">
|
||||
<e-device-children
|
||||
:gatewayDevice="showGatewayInfo"
|
||||
:sourceId="sourceId"
|
||||
:deviceType="deviceType"
|
||||
@handleLinkToHome="handleLinkToHome"></e-device-children>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ESimpleCard from "@/components/Cards/index";
|
||||
import EDeviceChildren from './EDeviceChildren'
|
||||
import { webSocketProjectGatewayUrl } from "@/config/env";
|
||||
import { listProjectDevice, listProjectModel } from '@/api/iot/project_new'
|
||||
export default {
|
||||
name: "EDeviceTable",
|
||||
components: {
|
||||
ESimpleCard,
|
||||
EDeviceChildren
|
||||
},
|
||||
props: {
|
||||
sourceId: {
|
||||
type: [String, Number],
|
||||
require: true,
|
||||
},
|
||||
deviceType: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
queryParams: {
|
||||
prodKey: undefined,
|
||||
deviceName: undefined,
|
||||
deviceStatus: undefined,
|
||||
},
|
||||
showChildrenView: false,
|
||||
list: [],
|
||||
mockerList: [
|
||||
{
|
||||
createTime: "2022-07-27 16:33:58",
|
||||
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
||||
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
||||
deviceKey: "ceshixinzeng",
|
||||
deviceName: "ceshixinzeng",
|
||||
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
||||
deviceState: "UNACTIVE",
|
||||
deviceStatus: "0",
|
||||
deviceType: "GATEWAY_CONTROLLER",
|
||||
deviceTypeName: "物联网网关",
|
||||
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
||||
modelName: "网关-测试型号0513",
|
||||
prodKey: "testpk220513",
|
||||
updateTime: "2022-07-27 16:33:59",
|
||||
parentId: "0",
|
||||
},
|
||||
{
|
||||
createTime: "2022-07-27 16:33:58",
|
||||
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
||||
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
||||
deviceKey: "ceshixinzeng",
|
||||
deviceName: "ceshixinzeng",
|
||||
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
||||
deviceState: "UNACTIVE",
|
||||
deviceStatus: "1",
|
||||
deviceType: "GATEWAY_CONTROLLER",
|
||||
deviceTypeName: "物联网网关",
|
||||
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
||||
modelName: "网关-测试型号0513",
|
||||
prodKey: "testpk220513",
|
||||
updateTime: "2022-07-27 16:33:59",
|
||||
parentId: "0",
|
||||
},
|
||||
{
|
||||
createTime: "2022-07-27 16:33:58",
|
||||
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
||||
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
||||
deviceKey: "ceshixinzeng",
|
||||
deviceName: "ceshixinzeng",
|
||||
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
||||
deviceState: "ONLINE",
|
||||
deviceStatus: "0",
|
||||
deviceType: "GATEWAY_CONTROLLER",
|
||||
deviceTypeName: "物联网网关",
|
||||
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
||||
modelName: "网关-测试型号0513",
|
||||
prodKey: "testpk220513",
|
||||
updateTime: "2022-07-27 16:33:59",
|
||||
parentId: "0",
|
||||
},
|
||||
],
|
||||
showGatewayInfo: {},
|
||||
projectModelList: [],
|
||||
stompClient: null,
|
||||
socket_flag: true,
|
||||
timeout_flag: null
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
sourceId(val) {
|
||||
if (val) {
|
||||
this.initHTML();
|
||||
}
|
||||
},
|
||||
deviceType(val) {
|
||||
if (val) {
|
||||
this.initHTML();
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initHTML()
|
||||
},
|
||||
methods: {
|
||||
// init html
|
||||
initHTML() {
|
||||
this.getGatewayList();
|
||||
this.getProjectModelList();
|
||||
},
|
||||
// 查看子设备列表信息
|
||||
handleChildrenDevice(gatewayDevice) {
|
||||
this.showChildrenView = true;
|
||||
this.showGatewayInfo = gatewayDevice;
|
||||
this.$forceUpdate()
|
||||
},
|
||||
// 子设备列表 返回 网关设备列表
|
||||
handleLinkToHome() {
|
||||
this.showChildrenView = false;
|
||||
},
|
||||
// 内容部分
|
||||
renderCardContent(item) {
|
||||
return (
|
||||
<template>
|
||||
<div class="card-body-left">
|
||||
<image src={item['deviceImage'] ? item['deviceImage'] : '/images/devcie_default.png'}></image>
|
||||
</div>
|
||||
<div class="card-body-right">
|
||||
<span>{ item.deviceId }</span>
|
||||
<span>{ item.deviceSecret }</span>
|
||||
<span>{ item.deviceAddress }</span>
|
||||
</div>
|
||||
</template>
|
||||
)
|
||||
},
|
||||
// 卡片 底部 报警状态
|
||||
renderCardFooter(item) {
|
||||
return (
|
||||
<template>
|
||||
<div class={item.deviceStatus == 0 ? 'card-footer' : 'card-footer dev-error'}>
|
||||
<icon class="iconfont icontongzhi"></icon>
|
||||
<span>{item.deviceStatus == 0 ? '正常' : 'card-footer dev-error'}</span>
|
||||
</div>
|
||||
</template>
|
||||
)
|
||||
},
|
||||
handleQuery() {
|
||||
this.getGatewayList();
|
||||
},
|
||||
resetQuery() {
|
||||
this.getGatewayList();
|
||||
},
|
||||
// 获取 项目 型号列表
|
||||
getProjectModelList() {
|
||||
listProjectModel({
|
||||
projectId: this.sourceId,
|
||||
deviceTags: this.deviceType || ''
|
||||
}).then(res => {
|
||||
this.projectModelList = res.data
|
||||
})
|
||||
},
|
||||
// 获取 项目网关设备列表
|
||||
getGatewayList() {
|
||||
this.list = []
|
||||
listProjectDevice(Object.assign({
|
||||
projectId: this.sourceId,
|
||||
deviceTags: this.deviceType || ''
|
||||
}, this.queryParams)).then(res => {
|
||||
this.list = res.data
|
||||
if (this.stompClient) {
|
||||
this.closeSocket()
|
||||
}
|
||||
this.connection()
|
||||
})
|
||||
},
|
||||
// 创建一个ws 监听获取报警实时数据
|
||||
connection() {
|
||||
if (this.stompClient) {
|
||||
return;
|
||||
}
|
||||
if (!webSocketProjectGatewayUrl) {
|
||||
return;
|
||||
}
|
||||
if (!this.list || this.length <= 0) {
|
||||
return;
|
||||
}
|
||||
let deviceIds = this.list.map(v => v['deviceId'])
|
||||
this.stompClient = new WebSocket(
|
||||
`${webSocketProjectGatewayUrl}/${this.getGuid()}/${ deviceIds.toString() }`
|
||||
);
|
||||
this.stompClient.onmessage = this.socket_message;
|
||||
this.stompClient.onclose = this.socket_onclose;
|
||||
},
|
||||
socket_message(evt) {
|
||||
console.log("wsljcg:=", evt);
|
||||
const data = JSON.parse(evt.data);
|
||||
|
||||
// this.actualEnergyCensus = data.params || {};
|
||||
console.log('socket-message:', data)
|
||||
this.handleDeviceInfo(data)
|
||||
this.$forceUpdate();
|
||||
},
|
||||
// 处理 socket 数据返回 赋值问题
|
||||
handleDeviceInfo(param) {
|
||||
if (this.list && this.list.length > 0) {
|
||||
this.list = this.list.map(v => {
|
||||
if (v['deviceId'] === param['deviceId']) {
|
||||
return Object.assign(v, param)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
socket_onclose(e) {
|
||||
this.stompClient = null;
|
||||
if (this.socket_flag) {
|
||||
this.socket_flag = false;
|
||||
let _this = this;
|
||||
this.timeout_flag = setTimeout(function () {
|
||||
_this.socket_flag = true;
|
||||
_this.connection();
|
||||
}, 10000);
|
||||
}
|
||||
},
|
||||
closeSocket() {
|
||||
if (this.stompClient) {
|
||||
this.stompClient.close();
|
||||
}
|
||||
this.socket_flag = false;
|
||||
this.stompClient = null;
|
||||
clearTimeout(this.timeout_flag);
|
||||
},
|
||||
getGuid() {
|
||||
return "xxxxxxx_xxxxx_4xxx_yxxx_xxxxxxxxxxxx".replace(/[xy]/g, function(
|
||||
c
|
||||
) {
|
||||
var r = (Math.random() * 16) | 0,
|
||||
v = c == "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
this.closeSocket()
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.e-object-device-manage-table {
|
||||
.el-form-item--medium .el-form-item__content {
|
||||
width: calc(100% - 70px);
|
||||
}
|
||||
.query-foot.el-form-item--medium .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
.table-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: start;
|
||||
.object-device-card {
|
||||
width: 285px;
|
||||
height: 164px;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #E4EBF4;
|
||||
box-shadow: 0px 0px 8px 0px rgba(17,76,157,0.26);
|
||||
border-radius: 5px;
|
||||
margin: 5px;
|
||||
.card-left {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #00C805;
|
||||
}
|
||||
.off-line {
|
||||
color: #DA2710;
|
||||
}
|
||||
.card-right {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #6B778C;
|
||||
align-items: baseline;
|
||||
.c-label {}
|
||||
.c-number {
|
||||
color: #344567;
|
||||
margin: 0 8px;
|
||||
}
|
||||
.card-opt-i {
|
||||
font-size: 18px;
|
||||
-ms-transform:rotate(90deg); /* IE 9 */
|
||||
-webkit-transform:rotate(90deg); /* Safari and Chrome */
|
||||
transform:rotate(90deg);
|
||||
}
|
||||
.card-opt-i:hover {
|
||||
color: #46a6ff;
|
||||
}
|
||||
}
|
||||
.e-simple-card__header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.e-simple-card__body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.object-device-body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.card-body-info {
|
||||
width: 100%;
|
||||
height: 85px;
|
||||
display: flex;
|
||||
.card-body-left {
|
||||
width: 40%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
> img {
|
||||
width: 93px;
|
||||
height: 52px;
|
||||
}
|
||||
}
|
||||
.card-body-right {
|
||||
width: 60%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 300;
|
||||
color: #344567;
|
||||
>span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
.card-body-footer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.card-footer {
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.footer-title {
|
||||
width: 100%;
|
||||
margin-left: 10px;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.dev-error {
|
||||
color: #DC3520;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<div class="e-dynamic-table">
|
||||
<el-table v-loading="loading" :data="tableList" :row-key="rowKey" :border="border" @selection-change="handleSelectionChange">
|
||||
|
||||
<el-table-column type="selection" v-if="isSelect" width="50" align="center" />
|
||||
|
||||
<el-table-column
|
||||
v-if="isIndex"
|
||||
type="index"
|
||||
label="序号"
|
||||
align="center"
|
||||
:index="
|
||||
(val) => {
|
||||
return (
|
||||
val + 1 + (queryParams.pageNum - 1) * this.queryParams.pageSize
|
||||
);
|
||||
}
|
||||
"
|
||||
width="80px"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
:label="tableItem.label || ''"
|
||||
:align="tableItem.align || 'left'"
|
||||
:prop="tableItem.prop || ''"
|
||||
:width="tableItem.width || ''"
|
||||
v-for="(tableItem, idx) in filterList"
|
||||
:key="idx"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<slot v-if="tableItem.slot" :name="tableItem.slotName" :row="scope.row" ></slot>
|
||||
<span v-else class="lay-table-textarea" :title="scope.row[tableItem.prop || '']">
|
||||
{{ scope.row[tableItem.prop || ''] }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="tableTotal > 0"
|
||||
:total="tableTotal"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="handleQuery2"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "EDynamicTable",
|
||||
props: {
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
tableTotal: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
queryParams: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
},
|
||||
},
|
||||
tableList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
filterList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
isIndex: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rowKey: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filter: [
|
||||
{
|
||||
label: "",
|
||||
align: 'left',
|
||||
prop: '',
|
||||
width: '',
|
||||
slot: true,
|
||||
slotName: 'inst'
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleQuery2() {
|
||||
this.$emit('handleQuery', this.queryParams)
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.$emit('tableSelectionChange', selection)
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<div class="e-object-device-manage">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="tabLabel.dictLabel" :name="tabLabel.dictValue" v-for="(tabLabel, idx) in projectDeviceTagGroup" :key="idx">
|
||||
<e-device-table v-if="tabLabel.dictValue === activeName" :sourceId="projectInfo['projectId']" :deviceType="tabLabel.dictValue" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EDeviceTable from './EDeviceTable'
|
||||
export default {
|
||||
name: 'EObjectDeviceManage',
|
||||
components: {
|
||||
EDeviceTable
|
||||
},
|
||||
props: {
|
||||
projectInfo: {
|
||||
type: Object,
|
||||
require: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: '',
|
||||
projectDeviceTagGroup: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getDicts("project_device_tag_group").then(response => {
|
||||
this.projectDeviceTagGroup = response.data;
|
||||
if (this.projectDeviceTagGroup && this.projectDeviceTagGroup.length > 0) {
|
||||
this.activeName = this.projectDeviceTagGroup[0]['dictValue'] || ''
|
||||
};
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
// 菜单状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.projectDeviceTagGroup, row.industry);
|
||||
},
|
||||
// 获取 网关设备列表
|
||||
getGatewayDeviceList() {
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div class="e-census-cards">
|
||||
<div
|
||||
class="card-foreach"
|
||||
v-for="(item, index) in propList"
|
||||
:key="index"
|
||||
:style="{
|
||||
width: `calc(100% / ${propList.length})`,
|
||||
}"
|
||||
>
|
||||
<div class="card-for-item">
|
||||
<div class="card-item-title">{{ item.label }}</div>
|
||||
<div class="card-item-value">{{ result[item.key] || 222 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "ECensusCards",
|
||||
props: {
|
||||
propList: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
result: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.e-census-cards {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
.card-foreach {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
.card-for-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.card-item-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-family: "Source Han Sans CN";
|
||||
font-weight: 400;
|
||||
color: #6b778c;
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
justify-content: center;
|
||||
}
|
||||
.card-item-value {
|
||||
font-size: 24px;
|
||||
font-family: "Source Han Sans CN";
|
||||
font-weight: 500;
|
||||
color: #344567;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<div class="bigscreen-echarts-gauge">
|
||||
<div :id="eId" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as echarts from 'echarts/core';
|
||||
import { GaugeChart } from 'echarts/charts';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
export default {
|
||||
name: "echartsRadarWrap",
|
||||
props: {
|
||||
eId: {
|
||||
type: String
|
||||
},
|
||||
styles: {
|
||||
type: String
|
||||
},
|
||||
colorList: {
|
||||
type: [Array, String],
|
||||
default: ["#27d0ec"]
|
||||
},
|
||||
option: {
|
||||
stype: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.chart = null;
|
||||
echarts.use([GaugeChart, CanvasRenderer]);
|
||||
},
|
||||
mounted() {
|
||||
this.drawLine();
|
||||
},
|
||||
methods: {
|
||||
drawLine() {
|
||||
if (!this.chart) {
|
||||
this.chart = echarts.init(document.getElementById(this.eId));
|
||||
}
|
||||
const options = {
|
||||
series: [
|
||||
{
|
||||
type: "gauge",
|
||||
color: this.colorList,
|
||||
min: 0,
|
||||
max: 100,
|
||||
progress: {
|
||||
show: true,
|
||||
width: 3
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 3
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
distance: 2,
|
||||
length: '3',
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
color: '#dcdcdc'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
distance: 7,
|
||||
color: '#999',
|
||||
fontSize: 5
|
||||
},
|
||||
pointer: {
|
||||
offsetCenter: [0, '0%'],
|
||||
length: '60%',
|
||||
width: '1',
|
||||
itemStyle: {
|
||||
// color: '#000'
|
||||
}
|
||||
},
|
||||
anchor: {
|
||||
show: true,
|
||||
showAbove: true,
|
||||
size: 6,
|
||||
itemStyle: {
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
title: {
|
||||
show: false,
|
||||
text: "今日报警"
|
||||
},
|
||||
axisLine: {
|
||||
// 坐标轴线
|
||||
lineStyle: {
|
||||
// 属性lineStyle控制线条样式
|
||||
width: 4,
|
||||
// color: [
|
||||
// [1, "#1A3F81"]
|
||||
// ]
|
||||
}
|
||||
},
|
||||
|
||||
detail: {
|
||||
color: this.colorList[0] || "#27d0ec",
|
||||
valueAnimation: true,
|
||||
fontSize: 18,
|
||||
offsetCenter: ['0', '80%']
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: this.option
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
this.chart.setOption(options);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
option(val, oldVal) {
|
||||
this.chart = null;
|
||||
this.drawLine();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.bigscreen-echarts-gauge {
|
||||
height: calc(100% - 30px);
|
||||
height: calc(100% - 15px);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div class="project-e-trend-echart-line">
|
||||
<div :id="eId" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as echarts from "echarts";
|
||||
export default {
|
||||
name: "EEchartsLine",
|
||||
props: {
|
||||
eId: {
|
||||
type: String
|
||||
},
|
||||
styles: {
|
||||
type: String
|
||||
},
|
||||
colorList: {
|
||||
type: [Array, String],
|
||||
default: ""
|
||||
},
|
||||
option: {
|
||||
stype: Object,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.chart = null;
|
||||
},
|
||||
mounted() {
|
||||
this.drawLine();
|
||||
},
|
||||
methods: {
|
||||
updateEchart() {
|
||||
if (this.chart) {
|
||||
this.chart = null;
|
||||
}
|
||||
this.drawLine();
|
||||
},
|
||||
drawLine() {
|
||||
if (!this.chart) {
|
||||
this.chart = echarts.init(document.getElementById(this.eId));
|
||||
}
|
||||
this.chart.setOption(this.option);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
option(val, oldVal) {
|
||||
this.chart = null;
|
||||
this.drawLine();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.project-e-trend-echart-line {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<div class="project-e-echarts-pie">
|
||||
<div :id="eId" :style="styles"></div>
|
||||
<!-- <div v-else>暂无数据</div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as echarts from "echarts";
|
||||
export default {
|
||||
name: "echartsRadarWrap",
|
||||
props: {
|
||||
eId: {
|
||||
type: String,
|
||||
},
|
||||
styles: {
|
||||
type: String,
|
||||
},
|
||||
colorList: {
|
||||
type: [Array, String],
|
||||
default: "",
|
||||
},
|
||||
option: {
|
||||
stype: Object,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.chart = null;
|
||||
},
|
||||
mounted() {
|
||||
this.drawLine();
|
||||
},
|
||||
methods: {
|
||||
updateEchart() {
|
||||
if (this.chart) {
|
||||
this.chart = null;
|
||||
}
|
||||
this.drawLine();
|
||||
},
|
||||
drawLine() {
|
||||
if (!this.chart) {
|
||||
this.chart = echarts.init(document.getElementById(this.eId));
|
||||
}
|
||||
const option = {
|
||||
color: this.colorList,
|
||||
// legend: {
|
||||
// top: "5",
|
||||
// right: "10",
|
||||
// type: "scroll",
|
||||
// // itemWidth: 10, // legend 显示宽度
|
||||
// orient: "vertical",
|
||||
// pageIconColor: "#6495ed", //翻页下一页的三角按钮颜色
|
||||
// pageIconInactiveColor: "#aaa", //翻页(即翻页到头时)
|
||||
// pageIconSize: 10, //翻页按钮大小
|
||||
// pageButtonItemGap: 1, //翻页按钮的两个之间的间距
|
||||
// textStyle: {
|
||||
// color: "#fff",
|
||||
// fontSize: 16,
|
||||
// },
|
||||
// formatter: function (name) {
|
||||
// return name.length > 7 ? name.substr(0, 7) + "..." : name;
|
||||
// },
|
||||
// },
|
||||
toolbox: {
|
||||
show: false,
|
||||
feature: {
|
||||
mark: { show: true },
|
||||
dataView: { show: true, readOnly: false },
|
||||
restore: { show: true },
|
||||
saveAsImage: { show: true },
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "",
|
||||
type: "pie",
|
||||
radius: ["40%", "70%"],
|
||||
center: ["50%", "50%"],
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
itemStyle: {
|
||||
borderRadius: 1,
|
||||
},
|
||||
data: this.option,
|
||||
},
|
||||
],
|
||||
};
|
||||
this.chart.setOption(option);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
option(val, oldVal) {
|
||||
this.chart = null;
|
||||
this.drawLine();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.project-e-echarts-pie {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,91 @@
|
|||
<template>
|
||||
<div class="e-nav-menu">
|
||||
<div
|
||||
:class="value === item[props['key']] ? 'nav-menu-item menu-selected' : 'nav-menu-item'"
|
||||
v-for="(item) in activeList"
|
||||
:key="item[props['key']]"
|
||||
@click="handleClick(item)"
|
||||
>
|
||||
<svg-icon slot="prefix" icon-class="A_yuanjiaodian" class="icon-left" />
|
||||
<div class="nav-item-title">{{ item[props["label"]] }}</div>
|
||||
<i class="el-icon-arrow-right icon-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "ENavMenu",
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: () => {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
label: "label",
|
||||
key: "key",
|
||||
};
|
||||
},
|
||||
},
|
||||
activeList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [
|
||||
{
|
||||
label: "项目管理",
|
||||
key: "projectOt"
|
||||
},
|
||||
{
|
||||
label: "设备管理",
|
||||
key: "projectOt"
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleClick(row) {
|
||||
this.$emit('input', row[this.props['key']]);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.e-nav-menu {
|
||||
width: 150px;
|
||||
height: 100%;
|
||||
padding-top: 15px;
|
||||
border-right: 1px solid #E8E8E8;
|
||||
.nav-menu-item {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
.nav-item-title {
|
||||
font-size: 14px;
|
||||
font-family: 'Source Han Sans CN';
|
||||
font-weight: 300;
|
||||
color: #344567;
|
||||
}
|
||||
.icon-left {
|
||||
font-size: 18px;
|
||||
}
|
||||
.icon-right {
|
||||
font-size: 18px
|
||||
}
|
||||
}
|
||||
.menu-selected {
|
||||
background: #F4F5F7;
|
||||
.nav-item-title {
|
||||
color: #1890FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div class="e-object-container">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="项目信息" name="info">
|
||||
<e-object-info v-if="activeName === 'info'" :infoData="projectInfo || {}" :projectTypeOptions="projectTypeOptions"></e-object-info>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="租户" name="tenant">
|
||||
<e-object-tenant v-if="activeName === 'tenant'" :infoData="projectInfo || {}"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="空间" name="space">
|
||||
<e-object-space v-if="activeName === 'space'" :infoData="projectInfo || {}"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EObjectInfo from './EObjectInfo'
|
||||
import EObjectSpace from './EObjectSpace'
|
||||
import EObjectTenant from './EObjectTenant'
|
||||
export default {
|
||||
name: 'EObjectContainer',
|
||||
components: {
|
||||
EObjectInfo,
|
||||
EObjectSpace,
|
||||
EObjectTenant
|
||||
},
|
||||
props: {
|
||||
projectInfo: {
|
||||
type: Object,
|
||||
require: true
|
||||
},
|
||||
projectTypeOptions: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'info'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,426 @@
|
|||
<template>
|
||||
<div class="e-object-info">
|
||||
<div class="group-list-info">
|
||||
<div class="top">
|
||||
<div class="top-label">
|
||||
<svg-icon
|
||||
icon-class="A_product1"
|
||||
style="margin-right: 2px; height: 20px; width: 20px"
|
||||
/>项目信息
|
||||
<span
|
||||
v-if="updateState === false"
|
||||
style="margin: 0px 15px 0 10px; font-weight: 200; font-size: 14px"
|
||||
>项目名称:{{ infoData.projectName }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group-list-table">
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目ID</div>
|
||||
<div class="content">
|
||||
<span class="name">{{ infoData.projectId }}</span>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click.stop="copyText(infoData.projectId)"
|
||||
>复制</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目编号</div>
|
||||
<div class="content">
|
||||
<span class="group-id" :title="infoData.projectCode">{{
|
||||
infoData.projectCode
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目类型</div>
|
||||
<div class="content">
|
||||
<span class="group-id">{{ statusFormat(infoData) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目纬度</div>
|
||||
<div class="content">{{ infoData.projectLat }}</div>
|
||||
</div>
|
||||
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目经度</div>
|
||||
<div class="content">{{ infoData.projectLng }}</div>
|
||||
</div>
|
||||
|
||||
<div class="table-row-col">
|
||||
<div class="title">项目状态</div>
|
||||
<div class="content">
|
||||
{{ infoData.projectStatus === "0" ? "启用" : "禁用" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title">总路设备</div>
|
||||
<div class="content">{{ infoData.projectDeviceName || "--" }}</div>
|
||||
</div>
|
||||
|
||||
<div class="table-row-col" style="flex: 2 0 0%">
|
||||
<div class="title">项目地址</div>
|
||||
<div class="content">
|
||||
<span class="centent">{{ infoData.projectAddress }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title">创建时间</div>
|
||||
<div class="content">{{ infoData.createTime || "--" }}</div>
|
||||
</div>
|
||||
<div class="table-row-col" style="flex: 2 0 0%">
|
||||
<div class="title">行政区划</div>
|
||||
<div class="content">{{ infoData.regionalismFullName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ---- -->
|
||||
|
||||
<div class="group-list-info" style="margin-top: 20px">
|
||||
<div class="top">
|
||||
<div class="top-label">
|
||||
<svg-icon
|
||||
icon-class="A_product1"
|
||||
style="margin-right: 2px; height: 20px; width: 20px"
|
||||
/>电价合同
|
||||
<span
|
||||
v-if="updateState === false"
|
||||
style="margin: 0px 15px 0 10px; font-weight: 200; font-size: 14px"
|
||||
>{{ contrctInfo.contractName }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group-list-table">
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title">合同ID</div>
|
||||
<div class="content">
|
||||
<span class="name">{{ contrctInfo.contractId }}</span>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click.stop="copyText(contrctInfo.contractId)"
|
||||
>复制</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row-col">
|
||||
<div class="title">合同类型</div>
|
||||
<div class="content">
|
||||
<span class="group-id">{{ contrctInfo.contractTypeName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-row-col">
|
||||
<div class="title">合同状态</div>
|
||||
<div class="content">
|
||||
<span class="group-id">{{
|
||||
contrctInfo.status === "0" ? "启用" : "禁用"
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-row">
|
||||
<div class="table-row-col">
|
||||
<div class="title" style="height: 160px">合同规则</div>
|
||||
<div class="content" style="overflow: auto">
|
||||
<div
|
||||
class="crat-warp"
|
||||
v-for="item in contrctInfo.priceContractRuleList"
|
||||
:key="item.ruleNum"
|
||||
>
|
||||
<div class="title-span">{{ item.ruleName }}</div>
|
||||
<div
|
||||
class="time-wrap"
|
||||
v-if="contrctInfo.contractType === 'PEAK_VALLEY'"
|
||||
>
|
||||
<span class="time-title">时间:</span>
|
||||
<div class="time-val">
|
||||
<span style="color: #3300ff">{{ item.minTime }}</span>
|
||||
<span>~</span>
|
||||
<span style="color: #3300ff">{{ item.maxTime }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="time-wrap" v-else>
|
||||
<div class="vlue-warp">
|
||||
<span>最小值:</span>
|
||||
<span>{{ item.minVal }}</span>
|
||||
</div>
|
||||
<div class="vlue-warp">
|
||||
<span>最大值:</span>
|
||||
<span>{{ item.maxVal }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dj-wrap">
|
||||
<span class="dj-title">单价:</span>
|
||||
<span class="dj-value">{{ item.unitPrice }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script >
|
||||
import { getContract } from "@/api/iot/contract";
|
||||
import ElDescriptions from "@/components/Edescriptions";
|
||||
import ElDescriptionsItem from "@/components/Edescriptions/src/descriptions-item";
|
||||
|
||||
export default {
|
||||
name: "EObjectInfo",
|
||||
components: {
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
},
|
||||
props: {
|
||||
infoData: {
|
||||
type: Object,
|
||||
require: true,
|
||||
},
|
||||
projectTypeOptions: {
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
infoData(val) {
|
||||
if (val) {
|
||||
this.getContractById();
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
updateState: false,
|
||||
contrctInfo: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getContractById()
|
||||
},
|
||||
methods: {
|
||||
// 菜单状态字典翻译
|
||||
statusFormat(row) {
|
||||
return this.selectDictLabel(this.projectTypeOptions, row.industry);
|
||||
},
|
||||
copyText(val) {
|
||||
this.copeFu(val, this);
|
||||
},
|
||||
getContractById() {
|
||||
if (!this.infoData.contractId && this.infoData.contractId !== 0) {
|
||||
return;
|
||||
}
|
||||
getContract(this.infoData.contractId).then((response) => {
|
||||
this.contrctInfo = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.e-object-info {
|
||||
.group-list-info {
|
||||
.top {
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
float: left;
|
||||
height: 40px;
|
||||
.top-label {
|
||||
float: left;
|
||||
width: calc(100% - 200px);
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #373d41;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
.el-input--medium {
|
||||
width: 150px;
|
||||
}
|
||||
.el-button--text {
|
||||
padding: 8px 12px;
|
||||
color: #333;
|
||||
}
|
||||
.el-button--text:hover {
|
||||
background-color: #d1dbe6;
|
||||
border-radius: 0;
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
.top-button {
|
||||
float: left;
|
||||
text-align: right;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 6px;
|
||||
flex: 1;
|
||||
.title {
|
||||
line-height: 30px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #373d41;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.group-list-table {
|
||||
border-top: 1px solid #d4d4d4;
|
||||
border-left: 1px solid #d4d4d4;
|
||||
.table-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
.table-row-col {
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
.title {
|
||||
width: 180px;
|
||||
height: 48px;
|
||||
color: rgb(116, 119, 122);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgb(250, 250, 252);
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-right: 1px solid #d4d4d4;
|
||||
padding: 0px 12px;
|
||||
margin-bottom: 0px;
|
||||
font-size: 15px;
|
||||
font-weight: 100;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex: 1 1 0%;
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-right: 1px solid #d4d4d4;
|
||||
padding: 0px 12px;
|
||||
.name {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
.group-id {
|
||||
margin-right: 8px;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.notice-item {
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 6px;
|
||||
background: #d3d5d5;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.n {
|
||||
background: #0fc18a;
|
||||
}
|
||||
.secret {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.crat-warp {
|
||||
height: 100px;
|
||||
width: 200px;
|
||||
border: 1px solid #333;
|
||||
padding: 5px;
|
||||
border: 1px dotted #898989;
|
||||
height: 120px;
|
||||
width: 250px;
|
||||
margin: 5px;
|
||||
.title-span {
|
||||
height: 30px;
|
||||
font-size: 18px;
|
||||
border-bottom: 1px dotted #333;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.time-wrap {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
.time-title {
|
||||
display: block;
|
||||
width: 40px;
|
||||
text-align: end;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.time-val {
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
width: calc(100% - 45px);
|
||||
justify-content: space-around;
|
||||
}
|
||||
.vlue-warp {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
> span:nth-child(1) {
|
||||
display: block;
|
||||
text-align: left;
|
||||
margin-right: 5px;
|
||||
width: 55px;
|
||||
}
|
||||
> span:nth-child(2) {
|
||||
display: block;
|
||||
width: calc(100% - 55px);
|
||||
text-align: center;
|
||||
color: #3300ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dj-wrap {
|
||||
height: 35px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
.dj-title {
|
||||
display: block;
|
||||
width: 40px;
|
||||
text-align: end;
|
||||
}
|
||||
.dj-value {
|
||||
display: block;
|
||||
width: calc(100% - 45px);
|
||||
text-align: center;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,371 @@
|
|||
<template>
|
||||
<div class="app-container e-project-space">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="上级空间" prop="parentId">
|
||||
<treeselect
|
||||
style="width: 200px;"
|
||||
v-model="queryParams.parentId"
|
||||
:options="querySpaceOptions"
|
||||
:normalizer="normalizer"
|
||||
placeholder="请选择上级空间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="空间名称" prop="spaceName">
|
||||
<el-input
|
||||
v-model="queryParams.spaceName"
|
||||
placeholder="空间名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="空间类型" prop="spaceType">
|
||||
<el-select v-model="queryParams.spaceType" placeholder="空间类型" clearable>
|
||||
<el-option
|
||||
v-for="dict in spaceTypeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="spaceList"
|
||||
row-key="spaceId"
|
||||
default-expand-all
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" :index="indexFormatter" width="80px"></el-table-column>
|
||||
<el-table-column label="空间名称" align="left" prop="spaceName" />
|
||||
<!-- <el-table-column label="空间ID" align="left" prop="spaceId" />
|
||||
<el-table-column label="空间编码" align="left" prop="spaceCode" />-->
|
||||
<el-table-column label="空间类型" align="center" prop="spaceType" :formatter="statusFormat" />
|
||||
<el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-search"
|
||||
@click="handleDetails(scope.row)"
|
||||
>空间设备</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改项目空间对话框 -->
|
||||
<el-dialog class="eldialog-wrap" :close-on-click-modal="false" :title="title" :visible.sync="open" width="500px">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="上级空间:" prop="parentId">
|
||||
<treeselect v-model="form.parentId" :options="spaceOptions" placeholder="请选择上级空间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="空间名称:" prop="spaceName">
|
||||
<el-input v-model="form.spaceName" placeholder="请输入空间名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型:" prop="spaceType">
|
||||
<el-select v-model="form.spaceType" style="width: 100%;" placeholder="请选择空间类型">
|
||||
<el-option
|
||||
v-for="dict in spaceTypeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button size="mini" @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
class="eldialog-wrap"
|
||||
:title="spaceDeviceTitle"
|
||||
:visible.sync="selectTableShow"
|
||||
width="75%"
|
||||
top="10vh"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<e-object-space-device
|
||||
v-if="selectTableShow"
|
||||
:sourceId="sourceId"
|
||||
:projectId="infoData.projectId"
|
||||
/>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="() =>{selectTableShow = false}">确 定</el-button>
|
||||
<el-button size="mini" @click="() =>{selectTableShow = false}">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listSpace,
|
||||
getSpace,
|
||||
delSpace,
|
||||
addSpace,
|
||||
updateSpace,
|
||||
exportSpace,
|
||||
listSpaceDevice,
|
||||
listSpaceTree
|
||||
} from "@/api/iot/space";
|
||||
import EObjectSpaceDevice from "./EObjectSpaceDevice";
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
|
||||
export default {
|
||||
name: "EObjectSpace",
|
||||
components: {
|
||||
Treeselect,
|
||||
EObjectSpaceDevice
|
||||
},
|
||||
props: ["infoData"],
|
||||
data() {
|
||||
return {
|
||||
selectTableShow: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 项目空间表格数据
|
||||
spaceList: [],
|
||||
// 项目空间树选项
|
||||
spaceOptions: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
parentId: null,
|
||||
projectId: null,
|
||||
spaceName: null,
|
||||
spaceCode: null,
|
||||
spaceType: null
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {},
|
||||
spaceTypeOptions: [],
|
||||
querySpaceOptions: [],
|
||||
sourceId: "",
|
||||
spaceDeviceTitle: ""
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getDicts("space_type").then(response => {
|
||||
this.spaceTypeOptions = response.data;
|
||||
});
|
||||
this.getQueryTreeselect();
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
indexFormatter(val) {
|
||||
return val + 1;
|
||||
},
|
||||
// 打开厂商选择窗口 ——表格
|
||||
handleDetails(row) {
|
||||
this.sourceId = row.spaceId;
|
||||
this.spaceDeviceTitle = `[ ${row.spaceName} ] 空间--设备管理`;
|
||||
this.selectTableShow = true;
|
||||
},
|
||||
// 菜单状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.spaceTypeOptions, row.spaceType);
|
||||
},
|
||||
/** 查询项目空间列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.queryParams.projectId = this.infoData.projectId;
|
||||
listSpace(this.queryParams).then(response => {
|
||||
this.spaceList = this.handleTree(response.data, "spaceId", "parentId");
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 转换项目空间数据结构 */
|
||||
normalizer(node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children;
|
||||
}
|
||||
return {
|
||||
id: node.spaceId,
|
||||
label: node.spaceName,
|
||||
children: node.children
|
||||
};
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
getTreeselect(param) {
|
||||
listSpaceTree(param).then(response => {
|
||||
this.spaceOptions = [];
|
||||
const data = { id: 0, label: "顶级节点", children: [] };
|
||||
// data.children = this.handleTree(response.data, "spaceId", "parentId");
|
||||
data.children = response.data;
|
||||
this.spaceOptions.push(data);
|
||||
});
|
||||
},
|
||||
/** 查询部门下拉树结构 */
|
||||
getQueryTreeselect() {
|
||||
let param = {
|
||||
projectId: this.infoData.projectId
|
||||
};
|
||||
listSpace(param).then(response => {
|
||||
this.querySpaceOptions = [];
|
||||
const data = { spaceId: 0, spaceName: "顶级节点", children: [] };
|
||||
data.children = this.handleTree(response.data, "spaceId", "parentId");
|
||||
this.querySpaceOptions.push(data);
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
parentId: null,
|
||||
projectId: this.infoData.projectId,
|
||||
spaceName: null,
|
||||
spaceType: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
let param = {
|
||||
projectId: this.infoData.projectId
|
||||
};
|
||||
this.getTreeselect(param);
|
||||
this.open = true;
|
||||
this.title = "添加项目空间";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
let param = {
|
||||
projectId: this.infoData.projectId,
|
||||
spaceId: row.spaceId
|
||||
};
|
||||
this.getTreeselect(param);
|
||||
if (row != null) {
|
||||
this.form.parentId = row.spaceId;
|
||||
}
|
||||
getSpace(row.spaceId).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改项目空间";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.spaceId != null) {
|
||||
updateSpace(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addSpace(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
this.$confirm(
|
||||
'是否确认删除项目空间编号为"' + row.spaceId + '"的数据项?',
|
||||
"警告",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}
|
||||
)
|
||||
.then(function() {
|
||||
return delSpace(row.spaceId);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.e-project-space {
|
||||
.eldialog-wrap {
|
||||
.el-dialog__header {
|
||||
border-bottom: 1px solid #747373;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 0px;
|
||||
height: calc(100vh - 200px);
|
||||
overflow: auto;
|
||||
}
|
||||
.el-form {
|
||||
padding: 20px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
.el-dialog__footer {
|
||||
height: 60px;
|
||||
border-top: 1px solid #747373;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
padding-top: 15px;
|
||||
.el-button + .el-button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.el-button {
|
||||
padding-top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,353 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="space_deviceList"
|
||||
:default-sort="{prop: 'createTime', order: 'descending'}"
|
||||
@sort-change="sortChange"
|
||||
>
|
||||
<el-table-column type="index" label="序号" align="center" :index="indexFormatter" width="80px"></el-table-column>
|
||||
<el-table-column label="设备名称" align="left" width="200px" prop="deviceName" />
|
||||
<el-table-column label="所属型号" align="left" prop="modelName" />
|
||||
<el-table-column label="设备key" align="left" prop="deviceKey" />
|
||||
<el-table-column label="设备类型" align="left" width="120px" prop="deviceTypeName" />
|
||||
<el-table-column label="创建时间" sortable="custom" align="center" width="200" prop="createTime" />
|
||||
<el-table-column label="操作" width="150" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
v-if="scope.row.deviceType !== 'MINIATURE_BREAKER'"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改空间设备对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px"></el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button size="mini" @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="选择设备"
|
||||
:visible.sync="selectTableShow"
|
||||
width="75%"
|
||||
top="10vh"
|
||||
class="select-table-dialog"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
>
|
||||
<select-table-wrap
|
||||
v-if="selectTableShow"
|
||||
:tableOption="tableSelectOption.tableOpt"
|
||||
:queryOption="tableSelectOption.queryOpt"
|
||||
:tableList="tableSelectOption.tableList"
|
||||
@parentGetList="childGetList($event)"
|
||||
:otherOption="tableSelectOption.otherOption"
|
||||
@returnEvent="returnEvent($event)"
|
||||
/>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button size="mini" @click="() =>{selectTableShow = false}">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listSpace_device,
|
||||
getSpace_device,
|
||||
delSpace_device,
|
||||
addSpace_device,
|
||||
updateSpace_device,
|
||||
exportSpace_device,
|
||||
listProjectDevice
|
||||
} from "@/api/iot/spaceDevice";
|
||||
import { listSpaceDevice } from "@/api/iot/space";
|
||||
import SelectTableWrap from "@/components/SelectTable/index";
|
||||
|
||||
export default {
|
||||
name: "SpaceDeviceWrap",
|
||||
props: ["sourceId", "projectId"],
|
||||
components: {
|
||||
SelectTableWrap
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectTableShow: false,
|
||||
tableSelectOption: {},
|
||||
selectResult: {},
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 空间设备表格数据
|
||||
space_deviceList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
spaceId: "",
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
orderByColumn: "createTime",
|
||||
isAsc: "desc"
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
sortChange(column) {
|
||||
const sort = {
|
||||
isAsc: column.order === "descending" ? "desc" : "asc",
|
||||
orderByColumn: column.prop
|
||||
};
|
||||
this.queryParams = Object.assign(this.queryParams, sort);
|
||||
this.handleQuery();
|
||||
},
|
||||
indexFormatter(val) {
|
||||
return (
|
||||
val + 1 + (this.queryParams.pageNum - 1) * this.queryParams.pageSize
|
||||
);
|
||||
},
|
||||
// 打开厂商选择窗口 ——表格
|
||||
handleDetails() {
|
||||
this.selectResult = {};
|
||||
this.tableSelectOption = {
|
||||
otherOption: {
|
||||
tableType: "device"
|
||||
},
|
||||
queryOpt: {
|
||||
disable: false,
|
||||
labelWidth: "68px",
|
||||
params: {
|
||||
deviceName: "",
|
||||
modelId: "",
|
||||
parentId: 0,
|
||||
deviceType: "GATEWAY_CONTROLLER"
|
||||
},
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
total: 0
|
||||
},
|
||||
inline: true,
|
||||
queryChilds: [
|
||||
{
|
||||
style: "",
|
||||
placeholder: "设备名称",
|
||||
clearable: true,
|
||||
label: "设备名称",
|
||||
type: "input",
|
||||
key: "deviceName",
|
||||
size: "small",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
tableOpt: {
|
||||
loading: false,
|
||||
rowKey: "deviceId",
|
||||
selection: false,
|
||||
maxHeight: "45vh",
|
||||
childs: [
|
||||
{
|
||||
style: "",
|
||||
label: "所属型号",
|
||||
type: "",
|
||||
prop: "modelName",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "设备名称",
|
||||
type: "",
|
||||
prop: "deviceName",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "设备Key",
|
||||
type: "",
|
||||
prop: "deviceKey",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "设备类型",
|
||||
type: "",
|
||||
prop: "deviceTypeName",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "创建时间",
|
||||
type: "time",
|
||||
prop: "createTime",
|
||||
align: "center",
|
||||
width: "180",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
}
|
||||
],
|
||||
tableList: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
tableList: []
|
||||
};
|
||||
this.selectTableShow = true;
|
||||
},
|
||||
childGetList(data) {
|
||||
console.log(data.param)
|
||||
listProjectDevice(data.param).then(response => {
|
||||
this.tableSelectOption.tableList = response.data;
|
||||
// this.tableSelectOption.queryOpt.page.total = Number(response.total);
|
||||
});
|
||||
},
|
||||
returnEvent(data) {
|
||||
if (data.type === "dblclick") {
|
||||
this.form.deviceId = data.value.deviceId;
|
||||
this.submitForm();
|
||||
} else if (data.type === "click") {
|
||||
this.form.deviceId = data.value.deviceId;
|
||||
}
|
||||
},
|
||||
|
||||
/** 查询空间设备列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.queryParams.spaceId = this.sourceId;
|
||||
listSpace_device(this.queryParams).then(response => {
|
||||
this.space_deviceList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
spaceId: this.sourceId,
|
||||
deviceId: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.spaceId);
|
||||
this.single = selection.length !== 1;
|
||||
this.multiple = !selection.length;
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.handleDetails();
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
addSpace_device(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.selectTableShow = false;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const spaceIds = row.deviceId;
|
||||
this.$confirm("是否删除该选项?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(function() {
|
||||
return delSpace_device(spaceIds);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm("是否确认导出所有空间设备数据项?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(function() {
|
||||
return exportSpace_device(queryParams);
|
||||
})
|
||||
.then(response => {
|
||||
this.download(response.msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,386 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="project_tenantList" :default-sort="{prop: 'expirationTime', order: 'descending'}"
|
||||
@sort-change="sortChange">
|
||||
<el-table-column type="index" label="序号" align="center" :index="indexFormatter" width="80px"></el-table-column>
|
||||
<el-table-column label="企业名称" align="center" prop="tenantName" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span v-text="scope.row.status === '0' ? '正常' : '停用'"></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="有效期" align="center" sortable="custom" prop="expirationTime" width="160" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="200px"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>解除租户</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改项目租户关系对话框 -->
|
||||
<!-- <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px"></el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button size="mini" @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog> -->
|
||||
|
||||
<el-dialog
|
||||
title="选择租户"
|
||||
:visible.sync="selectTableShow"
|
||||
width="50%"
|
||||
top="10vh"
|
||||
class="select-table-dialog"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
>
|
||||
<select-table-wrap
|
||||
v-if="selectTableShow"
|
||||
:tableOption="tableSelectOption.tableOpt"
|
||||
:queryOption="tableSelectOption.queryOpt"
|
||||
:tableList="tableSelectOption.tableList"
|
||||
@parentGetList="childGetList($event)"
|
||||
:otherOption="tableSelectOption.otherOption"
|
||||
@returnEvent="returnEvent($event)"
|
||||
/>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button size="mini" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button size="mini" @click="() =>{selectTableShow = false}">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listProject_tenant,
|
||||
getProject_tenant,
|
||||
delProject_tenant,
|
||||
addProject_tenant,
|
||||
updateProject_tenant,
|
||||
exportProject_tenant,
|
||||
listUserdByProjectId
|
||||
} from "@/api/iot/projectTenant";
|
||||
import SelectTableWrap from "@/components/SelectTable/index";
|
||||
export default {
|
||||
name: "EObjectTenant",
|
||||
components: {
|
||||
SelectTableWrap
|
||||
},
|
||||
props: ["infoData"],
|
||||
data() {
|
||||
return {
|
||||
selectTableShow: false,
|
||||
tableSelectOption: {},
|
||||
selectResult: {},
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 项目租户关系表格数据
|
||||
project_tenantList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
orderByColumn: "expirationTime",
|
||||
isAsc: "desc"
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {},
|
||||
// 租户状态
|
||||
statusOptions: [],
|
||||
tenantTypeOptions: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getDicts("sys_tenant_type").then(response => {
|
||||
this.tenantTypeOptions = response.data;
|
||||
});
|
||||
this.getDicts("sys_normal_disable").then(response => {
|
||||
this.statusOptions = response.data;
|
||||
});
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
sortChange(column) {
|
||||
const sort = {
|
||||
isAsc: column.order === "descending" ? "desc" : "asc",
|
||||
orderByColumn: column.prop
|
||||
};
|
||||
this.queryParams = Object.assign(this.queryParams, sort);
|
||||
this.handleQuery();
|
||||
},
|
||||
indexFormatter(val) {
|
||||
return (
|
||||
val + 1 + (this.queryParams.pageNum - 1) * this.queryParams.pageSize
|
||||
);
|
||||
},
|
||||
// 打开厂商选择窗口 ——表格
|
||||
handleDetails() {
|
||||
this.selectResult = {};
|
||||
this.tableSelectOption = {
|
||||
otherOption: {
|
||||
tableType: "device"
|
||||
},
|
||||
queryOpt: {
|
||||
disable: false,
|
||||
labelWidth: "68px",
|
||||
params: {
|
||||
projectId: this.infoData.projectId,
|
||||
tenantName: ""
|
||||
},
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
total: 0
|
||||
},
|
||||
inline: true,
|
||||
queryChilds: [
|
||||
{
|
||||
style: "",
|
||||
placeholder: "企业名称",
|
||||
clearable: true,
|
||||
label: "企业名称",
|
||||
type: "input",
|
||||
key: "tenantName",
|
||||
size: "small",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
tableOpt: {
|
||||
loading: false,
|
||||
rowKey: "deviceId",
|
||||
selection: false,
|
||||
maxHeight: "45vh",
|
||||
childs: [
|
||||
{
|
||||
style: "",
|
||||
label: "企业名称",
|
||||
type: "",
|
||||
prop: "tenantName",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "企业法人",
|
||||
type: "",
|
||||
prop: "corporation",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "状态",
|
||||
type: "",
|
||||
prop: "status",
|
||||
align: "left",
|
||||
width: "",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "text1"
|
||||
},
|
||||
{
|
||||
style: "",
|
||||
label: "有效期",
|
||||
type: "time",
|
||||
prop: "expirationTime",
|
||||
align: "center",
|
||||
width: "180",
|
||||
"show-overflow-tooltip": false,
|
||||
tempType: "span"
|
||||
}
|
||||
],
|
||||
tableList: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
tableList: []
|
||||
};
|
||||
this.selectTableShow = true;
|
||||
},
|
||||
childGetList(data) {
|
||||
listUserdByProjectId(Object.assign(data.page, data.param)).then(
|
||||
response => {
|
||||
this.tableSelectOption.tableList = response.rows;
|
||||
this.tableSelectOption.queryOpt.page.total = Number(response.total);
|
||||
}
|
||||
);
|
||||
},
|
||||
returnEvent(data) {
|
||||
if (data.type === "dblclick") {
|
||||
this.form.tenantId = data.value.tenantId;
|
||||
this.submitForm();
|
||||
} else if (data.type === "click") {
|
||||
this.form.tenantId = data.value.tenantId;
|
||||
}
|
||||
},
|
||||
// 租户状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
var rulesStr = "";
|
||||
this.statusOptions.forEach(v => {
|
||||
if (v.dictValue === row.status) {
|
||||
rulesStr = v.dictLabel;
|
||||
}
|
||||
});
|
||||
return rulesStr;
|
||||
},
|
||||
tenantTypeFormat(row, column) {
|
||||
var rulesStr = "";
|
||||
this.tenantTypeOptions.forEach(v => {
|
||||
if (v.dictValue === row.status) {
|
||||
rulesStr = v.dictLabel;
|
||||
}
|
||||
});
|
||||
return rulesStr;
|
||||
},
|
||||
/** 查询项目租户关系列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.queryParams.projectId = this.infoData.projectId;
|
||||
listProject_tenant(this.queryParams).then(response => {
|
||||
this.project_tenantList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
projectId: this.infoData.projectId,
|
||||
tenantId: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.projectId);
|
||||
this.single = selection.length !== 1;
|
||||
this.multiple = !selection.length;
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.handleDetails();
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const projectId = row.projectId || this.ids;
|
||||
getProject_tenant(projectId).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改项目租户关系";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
addProject_tenant(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.selectTableShow = false;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const projectIds = row.projectId;
|
||||
const tenantId = row.tenantId;
|
||||
this.$confirm("是否删除该选项?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(function() {
|
||||
return delProject_tenant(projectIds, tenantId);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm("是否确认导出所有项目租户关系数据项?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(function() {
|
||||
return exportProject_tenant(queryParams);
|
||||
})
|
||||
.then(response => {
|
||||
this.download(response.msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div class="e-project-manage">
|
||||
项目管理
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'EProjectManage',
|
||||
props: {
|
||||
projectInfo: {
|
||||
type: Object,
|
||||
require: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,169 @@
|
|||
<template>
|
||||
<div class="project-e-today-ratio">
|
||||
<div class="bd-conter">
|
||||
<div class="echarts-list-wrap">
|
||||
<div v-for="item in rchartsList" :key="item.valueKeys">
|
||||
<echarts-gauge-wrap
|
||||
:styles="item.styles"
|
||||
:colorList="item.colorList"
|
||||
:eId="item.valueKeys"
|
||||
:option="tempResult[item.valueKeys]"
|
||||
></echarts-gauge-wrap>
|
||||
<div class="title">{{ item.title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-tb-block">
|
||||
<div>
|
||||
<div style="font-weight: 600;">{{ alarmTB }}%</div>
|
||||
<div>同比</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 600;">{{ warningTB }}%</div>
|
||||
<div>同比</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EchartsGaugeWrap from "./EEchartsGauge";
|
||||
export default {
|
||||
name: "ETodayRatio",
|
||||
components: {
|
||||
EchartsGaugeWrap,
|
||||
},
|
||||
props: ["result"],
|
||||
data() {
|
||||
return {
|
||||
tempResult: {
|
||||
q1: 0,
|
||||
q2: 0,
|
||||
q3: 0,
|
||||
q4: 0,
|
||||
},
|
||||
alarmTB: 0,
|
||||
warningTB: 0,
|
||||
rchartsList: [
|
||||
{
|
||||
styles: "width: 100%; height: 100%;",
|
||||
colorList: ["#27d0ec"],
|
||||
valueKeys: "q1",
|
||||
title: "今日报警",
|
||||
},
|
||||
{
|
||||
styles: "width: 100%; height: 100%;",
|
||||
colorList: ["#fdc46e"],
|
||||
valueKeys: "q2",
|
||||
title: "昨日报警 ",
|
||||
},
|
||||
{
|
||||
styles: "width: 100%; height: 100%;",
|
||||
colorList: ["#27d0ec"],
|
||||
valueKeys: "q3",
|
||||
title: "今日预警",
|
||||
},
|
||||
{
|
||||
styles: "width: 100%; height: 100%;",
|
||||
colorList: ["#fdc46e"],
|
||||
valueKeys: "q4",
|
||||
title: "昨日预警",
|
||||
},
|
||||
],
|
||||
title: "最近2天警情同比",
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
result: {
|
||||
handler: function (val, oldVal) {
|
||||
if (val) {
|
||||
this.tempResult = {};
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i]["alarmDivide"] === "ALARM") {
|
||||
this.tempResult["q1"] = val[i]["todayAlarm"];
|
||||
this.tempResult["q2"] = val[i]["yesterdayAlarm"];
|
||||
this.alarmTB = val[i]["dayOnDay"];
|
||||
} else if (val[i]["alarmDivide"] === "WARNING") {
|
||||
this.tempResult["q3"] = val[i]["todayAlarm"];
|
||||
this.tempResult["q4"] = val[i]["yesterdayAlarm"];
|
||||
this.warningTB = val[i]["dayOnDay"];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.project-e-today-ratio {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.bd-conter {
|
||||
width: 100%;
|
||||
height: 220px;
|
||||
background-size: contain;
|
||||
padding-top: 10px;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
.echarts-list-wrap {
|
||||
width: 80%;
|
||||
height: 200px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
> div {
|
||||
width: 50%;
|
||||
height: calc(100% / 2);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-family: "Source Han Sans CN";
|
||||
font-weight: 400;
|
||||
> .title {
|
||||
position: relative;
|
||||
top: -10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
height: 15px;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
}
|
||||
}
|
||||
}
|
||||
.info-tb-block {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
width: 20%;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
cursor: default;
|
||||
> div {
|
||||
width: 100%;
|
||||
// height: 50%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: inherit;
|
||||
justify-content: center;
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-family: Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
color: #344567;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,205 @@
|
|||
<template>
|
||||
<div class="project-e-trend-census">
|
||||
<div class="trend-conter">
|
||||
<e-echarts-line
|
||||
ref="echartsLineTrend"
|
||||
:styles="echartsOption.styles"
|
||||
:colorList="echartsOption.colorList"
|
||||
:eId="echartsOption.eId"
|
||||
:option="resultOption"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EEchartsLine from "@/components/Echarts/EEchartsLine";
|
||||
import * as echarts from "echarts";
|
||||
export default {
|
||||
name: "ETrendCensus",
|
||||
components: {
|
||||
EEchartsLine
|
||||
},
|
||||
props: ["result"],
|
||||
data() {
|
||||
return {
|
||||
echartsOption: {
|
||||
styles: "width: 100%; height: 100%;",
|
||||
colorList: ["#FC6A16", "#1EEEFF"],
|
||||
eId: "trendEchartsLine",
|
||||
},
|
||||
typeName: "alarm",
|
||||
resultOption: {
|
||||
color: ["#FC6A16", "#1EEEFF"],
|
||||
title: {
|
||||
text: "",
|
||||
show: false,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
legend: {
|
||||
top: 5,
|
||||
right: 5,
|
||||
data: ["报警", "预警"],
|
||||
// icon: "circle",
|
||||
textStyle: {
|
||||
color: "#344567",
|
||||
fontSize: 12,
|
||||
fontWeight: 400
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: "20",
|
||||
right: "20",
|
||||
bottom: "5",
|
||||
top: 30,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
show: true,
|
||||
data: [],
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
// color: "#E8E8E8",
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
// color: "#E8E8E8",
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "报警",
|
||||
type: "line",
|
||||
smooth: true,
|
||||
symbolSize: 2,
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(252,106,22,0.8)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(252,106,22,0.1)",
|
||||
},
|
||||
]),
|
||||
},
|
||||
markPoint: {
|
||||
symbolSize: 35,
|
||||
data: [
|
||||
{ type: 'max', name: 'Max' },
|
||||
{ type: 'min', name: 'Min' }
|
||||
]
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
formatter: function (params) {
|
||||
return echarts.format.formatTime("yyyy-MM-dd", params.value);
|
||||
},
|
||||
backgroundColor: "#7581BD",
|
||||
},
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
name: "预警",
|
||||
type: "line",
|
||||
markPoint: {
|
||||
symbolSize: 35,
|
||||
data: [
|
||||
{ type: 'max', name: 'Max' },
|
||||
{ type: 'min', name: 'Min' }
|
||||
]
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgba(30,238,255,0.8)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgba(30,238,255,0.1)",
|
||||
},
|
||||
]),
|
||||
},
|
||||
smooth: true,
|
||||
symbolSize: 2,
|
||||
data: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
result: {
|
||||
handler: function (val, oldVal) {
|
||||
this.resultOption.xAxis.data = val["name"];
|
||||
this.resultOption.series[0].data = val["alarm"];
|
||||
this.resultOption.series[1].data = val["warning"];
|
||||
this.updateEcharts();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 类型发生变化根据新数据刷新 图表信息
|
||||
updateEcharts() {
|
||||
this.$refs.echartsLineTrend.updateEchart();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.project-e-trend-census {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.trend-conter {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
background-size: contain;
|
||||
padding: 0;
|
||||
.tabs-block {
|
||||
width: 305px;
|
||||
height: 38px;
|
||||
background: #bfbfbf94;
|
||||
display: flex;
|
||||
color: #fff;
|
||||
> div {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 18px;
|
||||
letter-spacing: 7px;
|
||||
cursor: default;
|
||||
}
|
||||
.div-select {
|
||||
background: #0010ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,258 @@
|
|||
<template>
|
||||
<div class="project-e-type-census">
|
||||
<div class="conter-block">
|
||||
<div class="tabs-block">
|
||||
<div
|
||||
@click="typeName = 'alarm'"
|
||||
:class="typeName === 'alarm' ? 'div-select' : ''"
|
||||
>
|
||||
报警
|
||||
</div>
|
||||
<div
|
||||
@click="typeName = 'waraing'"
|
||||
:class="typeName === 'waraing' ? 'div-select' : ''"
|
||||
>
|
||||
预警
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="!(templist[typeName] && templist[typeName].length > 0)">
|
||||
暂无数据
|
||||
</div>
|
||||
<echarts-pie-wrap
|
||||
v-show="(templist[typeName] && templist[typeName].length > 0)"
|
||||
ref="echartsPieType"
|
||||
style="height: calc(100% - 38px);"
|
||||
:styles="echartsOption.styles"
|
||||
:colorList="echartsOption.colorList"
|
||||
:eId="echartsOption.eId"
|
||||
:option="templist[typeName]"
|
||||
></echarts-pie-wrap>
|
||||
<div v-show="(templist[typeName] && templist[typeName].length > 0)" class="echarts-legend-c">
|
||||
<div class="legend-for">
|
||||
<div
|
||||
class="legend-item"
|
||||
v-for="(item, idx) in templist[typeName]"
|
||||
:key="idx"
|
||||
>
|
||||
<div
|
||||
class="color-block"
|
||||
:style="`background: ${echartsOption.colorList[idx]};`"
|
||||
></div>
|
||||
<span class="title-block" :title="item.name" style="
|
||||
color: #6B778C;
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
">
|
||||
{{
|
||||
item.name.length > 10
|
||||
? item.name.substr(0, 10) + "..."
|
||||
: item.name
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EchartsPieWrap from "./EEchartsPie";
|
||||
export default {
|
||||
name: "ETypeCensus",
|
||||
components: {
|
||||
EchartsPieWrap
|
||||
},
|
||||
props: ["result"],
|
||||
data() {
|
||||
return {
|
||||
resultList: [
|
||||
{ value: 40, name: "rose 1" },
|
||||
{ value: 38, name: "rose 2" },
|
||||
{ value: 32, name: "rose 3" },
|
||||
{ value: 30, name: "rose 4" },
|
||||
],
|
||||
templist: {
|
||||
alarm: [],
|
||||
waraing: [],
|
||||
},
|
||||
echartsOption: {
|
||||
styles: "width: 80%; height: calc(100%);",
|
||||
colorList: [
|
||||
"#00deff",
|
||||
"#ff643e",
|
||||
"#8882f7",
|
||||
"#01b3d0",
|
||||
"#ff9724",
|
||||
"#168efe",
|
||||
"#00c279",
|
||||
"#ffce2a",
|
||||
"#ff88a7",
|
||||
"#3785b3",
|
||||
"#2e966b",
|
||||
"#8d68d8",
|
||||
"#c77856",
|
||||
"#ff4df9",
|
||||
"#0066ff",
|
||||
"#788a00",
|
||||
"#73c0de",
|
||||
"#91cc75",
|
||||
"#5470c6",
|
||||
"#ff69d6",
|
||||
"#d9815c",
|
||||
"#00b604",
|
||||
"#b2942e",
|
||||
"#b2942e",
|
||||
"#0656da",
|
||||
"#ff4e00",
|
||||
"#387289",
|
||||
"#5aa1bd",
|
||||
"#5443f9",
|
||||
"#708694",
|
||||
"#cd1fc7",
|
||||
"#ff00ae",
|
||||
"#a26f00",
|
||||
"#277900",
|
||||
"#00b604",
|
||||
"#ac29ff",
|
||||
"#ff3737",
|
||||
"#eae700",
|
||||
"#b1af01",
|
||||
],
|
||||
eId: "typeEchartsPie",
|
||||
},
|
||||
title: "类型分布统计",
|
||||
typeName: "alarm",
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
typeName(val, old) {
|
||||
if (val) {
|
||||
this.updateEcharts();
|
||||
}
|
||||
},
|
||||
result: {
|
||||
handler: function (list, oldVal) {
|
||||
this.templist = {
|
||||
alarm: [],
|
||||
waraing: [],
|
||||
};
|
||||
if (list) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
// console.log(list[i]['typeCode'].indexOf('a'))
|
||||
if (list[i]["typeCode"].indexOf("a") === 0) {
|
||||
this.templist["alarm"].push({
|
||||
value: list[i].alarmTotal,
|
||||
name: list[i].typeName,
|
||||
});
|
||||
} else if (list[i]["typeCode"].indexOf("w") === 0) {
|
||||
this.templist["waraing"].push({
|
||||
value: list[i].alarmTotal,
|
||||
name: list[i].typeName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.updateEcharts();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 类型发生变化根据新数据刷新 图表信息
|
||||
updateEcharts() {
|
||||
if(this.$refs.echartsPieType) {
|
||||
this.$refs.echartsPieType.updateEchart();
|
||||
} else {
|
||||
console.log('err_log:--', 'this.$refs.echartsPieType 组件未找到!')
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.project-e-type-census {
|
||||
width: 100%;
|
||||
height: 238px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.conter-block {
|
||||
width: 100%;
|
||||
height: 238px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
// padding-top: 10px;
|
||||
background-size: contain;
|
||||
.tabs-block {
|
||||
width: 305px;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
background: #efefef;
|
||||
color: #344567;
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
> div {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
letter-spacing: 7px;
|
||||
cursor: default;
|
||||
}
|
||||
.div-select {
|
||||
color: #fff;
|
||||
background: #1890ff;
|
||||
}
|
||||
}
|
||||
.echarts-legend-c {
|
||||
width: 40%;
|
||||
height: calc(100% - 38px);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.legend-for {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
height: calc(100% - 25px);
|
||||
overflow: auto;
|
||||
.legend-item {
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 24px;
|
||||
.color-block {
|
||||
width: 9px;
|
||||
height: 8px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.echarts-legend-c .legend-for::-webkit-scrollbar {
|
||||
/*滚动条整体样式*/
|
||||
width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
|
||||
height: 3px;
|
||||
}
|
||||
.echarts-legend-c .legend-for::-webkit-scrollbar-thumb {
|
||||
/*滚动条里面小方块*/
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 5px #004eb0;
|
||||
background: #004eb0;
|
||||
}
|
||||
.echarts-legend-c .legend-for::-webkit-scrollbar-track {
|
||||
/*滚动条里面轨道*/
|
||||
box-shadow: inset 0 0 5px #042764;
|
||||
border-radius: 10px;
|
||||
background: #042764;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,451 @@
|
|||
<template>
|
||||
<div class="project-detail-v2"
|
||||
id="project-detail-v2-id"
|
||||
ref="project-detail-v2-id"
|
||||
:style="{
|
||||
transformOrigin: 'center top',
|
||||
transform: `scale(${scalseNumX}, ${scalseNumY})`,
|
||||
opacity: 1,
|
||||
transition: `all 0.5s ease 0s`,
|
||||
}"
|
||||
>
|
||||
<div :class="isFoldRight ? 'block-lift block-right-fold':'block-lift'">
|
||||
<div class="container-title">
|
||||
<div class="title-left">
|
||||
<span>{{ infoData.projectName }}</span>
|
||||
<i class="el-icon-arrow-left icon-c"></i>
|
||||
<i class="el-icon-arrow-right icon-c"></i>
|
||||
</div>
|
||||
<div class="title-but">
|
||||
<div class="but-home" @click="handleLinkToTable">
|
||||
<i class="el-icon-d-arrow-left icon-c"></i>
|
||||
<span class="but-title">返回列表</span>
|
||||
</div>
|
||||
<div class="but-tz" @click="handleFoldRight">
|
||||
<i class="el-icon-back icon-c"></i>
|
||||
<i class="el-icon-right icon-c"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-info">
|
||||
<div class="info-left">
|
||||
<el-descriptions class="margin-top" title="" :column="2">
|
||||
<el-descriptions-item label="行业类型:">{{
|
||||
statusFormat(infoData)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人1:">{{
|
||||
infoData.contractName
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人2:"
|
||||
>林工1586000000</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item label="联系人2:">
|
||||
{{ infoData["projectDeviceName"] }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="项目地址:">{{
|
||||
infoData.projectAddress
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div class="info-divider"></div>
|
||||
<div class="info-right">
|
||||
<div>
|
||||
<e-census-cards :propList="censusCardList" :result="censusResult" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-main">
|
||||
<e-nav-menu
|
||||
v-model="activeName"
|
||||
:activeList="activeList"
|
||||
@input="
|
||||
(data) => {
|
||||
activeName = data;
|
||||
}
|
||||
"
|
||||
/>
|
||||
<div class="main-block">
|
||||
<component :is="activeName" :projectInfo="infoData" :projectTypeOptions="projectTypeOptions"></component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block-right" v-if="!isFoldRight">
|
||||
<e-simple-card title="最近2 天警情同比" class="today-ratio-card">
|
||||
<template slot="cardBody">
|
||||
<e-today-ratio :result="resultInfo['warningAnalysisStatisticsVo']"/>
|
||||
</template>
|
||||
</e-simple-card>
|
||||
|
||||
<e-simple-card
|
||||
title="类型分布统计"
|
||||
class="type-census-card"
|
||||
>
|
||||
<template slot="cardBody">
|
||||
<e-type-census
|
||||
:result="resultInfo['alarmCategoriesList'] || []"
|
||||
/>
|
||||
</template>
|
||||
</e-simple-card>
|
||||
|
||||
<e-simple-card
|
||||
title="报警预警趋势"
|
||||
class="trend-census-card"
|
||||
>
|
||||
<template slot="cardBody">
|
||||
<e-trend-census :result="resultInfo['alarmChartDataVo'] || []"/>
|
||||
</template>
|
||||
</e-simple-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getProject } from "@/api/iot/project";
|
||||
import { getWarningAnalysis, appProjectList } from "@/api/app";
|
||||
import ECensusCards from "./ECensusCards";
|
||||
import ElDescriptions from "@/components/Edescriptions";
|
||||
import ElDescriptionsItem from "@/components/Edescriptions/src/descriptions-item";
|
||||
import ESimpleCard from "@/components/Cards/index";
|
||||
import ENavMenu from "./ENavMenu";
|
||||
import EProjectManage from "./EProjectManage";
|
||||
import ETodayRatio from "./ETodayRatio";
|
||||
import ETypeCensus from './ETypeCensus'
|
||||
import ETrendCensus from './ETrendCensus'
|
||||
import EObjectContainer from './EObjectContainer'
|
||||
import EDeviceManage from './DeviceManage/index'
|
||||
|
||||
export default {
|
||||
name: "projectDetailV2",
|
||||
components: {
|
||||
ECensusCards,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ENavMenu,
|
||||
EProjectManage,
|
||||
ESimpleCard,
|
||||
ETodayRatio,
|
||||
ETypeCensus,
|
||||
ETrendCensus,
|
||||
EObjectContainer,
|
||||
EDeviceManage
|
||||
},
|
||||
props: {
|
||||
sourceId: {
|
||||
type: [String, Number],
|
||||
require: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
stateSourceId: null,
|
||||
resultInfo: {},
|
||||
activeName: "EObjectContainer",
|
||||
activeList: [
|
||||
{
|
||||
label: "项目信息",
|
||||
key: "EObjectContainer",
|
||||
},
|
||||
{
|
||||
label: "设备管理",
|
||||
key: "EDeviceManage",
|
||||
},
|
||||
],
|
||||
projectTypeOptions: [],
|
||||
infoData: {},
|
||||
censusResult: {
|
||||
device: 3555,
|
||||
},
|
||||
censusCardList: [
|
||||
{
|
||||
label: "设备总数",
|
||||
key: "device",
|
||||
},
|
||||
{
|
||||
label: "在线设备数",
|
||||
key: "device",
|
||||
},
|
||||
{
|
||||
label: "离线设备数",
|
||||
key: "device",
|
||||
},
|
||||
{
|
||||
label: "今日报警数",
|
||||
key: "device",
|
||||
},
|
||||
{
|
||||
label: "本月报警数",
|
||||
key: "device",
|
||||
},
|
||||
],
|
||||
isFoldRight: false,
|
||||
scalseNumX: 1,
|
||||
scalseNumY: 1,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.stateSourceId = this.sourceId;
|
||||
this.getInfoByProjectId();
|
||||
this.activeName = "EObjectContainer";
|
||||
this.getDicts("project_industry").then((response) => {
|
||||
this.projectTypeOptions = response.data;
|
||||
});
|
||||
this.warningAnalysisList();
|
||||
},
|
||||
switch: {
|
||||
sourceId(val) {
|
||||
console.log(val);
|
||||
this.stateSourceId = this.sourceId;
|
||||
this.getInfoByProjectId();
|
||||
this.warningAnalysisList();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// 计算缩放比例
|
||||
// this.resize_window();
|
||||
// this.thisScrollTopY = document.getElementById("con_lf_top_div").scrollTop;
|
||||
// document.getElementById("con_lf_top_div").style.background = "#010e45";
|
||||
// document.getElementById("con_lf_top_div").style.height =
|
||||
// "calc(100vh - 0px)";
|
||||
// document.getElementById("con_lf_top_div").style.minHeight =
|
||||
// "calc(100vh - 0px)";
|
||||
// document.getElementById("con_lf_top_div").style.overflow = "hidden";
|
||||
// document.getElementById("con_lf_top_div").scrollTop = 0;
|
||||
// window.addEventListener("resize", () => {
|
||||
// this.resize_window();
|
||||
// });
|
||||
},
|
||||
methods: {
|
||||
resize_window() {
|
||||
// if (this.fullscreen) {
|
||||
// this.scalseNumX = Number(document.documentElement.clientWidth / 1682);
|
||||
// this.scalseNumY = Number(document.documentElement.clientHeight / 812);
|
||||
// } else {
|
||||
// if (document.documentElement.clientWidth < 993) {
|
||||
// this.scalseNumX =
|
||||
// Number(document.documentElement.clientWidth / 1682) -
|
||||
// (Cookies.get("sidebarStatus") !== "0" ? Number(200 / 1920) : 0);
|
||||
// } else {
|
||||
// this.scalseNumX =
|
||||
// Number(document.documentElement.clientWidth / 1920) -
|
||||
// (Cookies.get("sidebarStatus") !== "0"
|
||||
// ? Number(200 / 1920)
|
||||
// : Number(54 / 1920));
|
||||
// }
|
||||
// this.scalseNumY = Number(document.documentElement.clientHeight / 1080);
|
||||
// }
|
||||
},
|
||||
// 返回列表
|
||||
handleLinkToTable() {
|
||||
this.$emit('linkToTable')
|
||||
},
|
||||
// 折叠开启右侧数据
|
||||
handleFoldRight() {
|
||||
this.isFoldRight = !this.isFoldRight
|
||||
this.$forceUpdate()
|
||||
},
|
||||
// 查询获取告警分析等数据
|
||||
warningAnalysisList() {
|
||||
getWarningAnalysis({
|
||||
projectId: this.stateSourceId,
|
||||
}).then((res) => {
|
||||
this.resultInfo = res.data;
|
||||
});
|
||||
},
|
||||
// 菜单状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.projectTypeOptions, row.industry);
|
||||
},
|
||||
getInfoByProjectId() {
|
||||
getProject(this.stateSourceId).then((response) => {
|
||||
this.infoData = response.data;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.project-detail-v2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100vh - 125px);
|
||||
display: flex;
|
||||
.block-lift {
|
||||
width: calc(100% - 300px - 20px);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.container-title {
|
||||
height: 45px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.title-left {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
> span {
|
||||
font-size: 24px;
|
||||
font-family: "Source Han Sans CN";
|
||||
font-weight: 600;
|
||||
color: #172b4d;
|
||||
}
|
||||
.icon-c {
|
||||
font-size: 18px;
|
||||
color: #6b778c;
|
||||
font-weight: 600;
|
||||
margin-top: 2px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
.title-but {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
.but-home {
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
background: #f4f5f7;
|
||||
border-radius: 5px;
|
||||
color: #6b778c;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-right: 10px;
|
||||
.icon-c {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.but-title {
|
||||
font-size: 12px;
|
||||
font-family: "Source Han Sans CN";
|
||||
font-weight: 600;
|
||||
margin-left: 5px;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
.but-home:hover {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
.but-tz {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: #f4f5f7;
|
||||
border-radius: 5px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-right: 0px;
|
||||
font-weight: 600;
|
||||
color: #6b778c;
|
||||
.icon-c {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
.but-tz:hover {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.container-info {
|
||||
height: 104px;
|
||||
width: 100%;
|
||||
background: #f4f5f7;
|
||||
border-radius: 5px;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
.info-left {
|
||||
width: calc(40%);
|
||||
padding: 8px 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.margin-top {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.info-divider {
|
||||
width: 1px;
|
||||
height: 105px;
|
||||
background: #e8e8e8;
|
||||
}
|
||||
.info-right {
|
||||
width: calc(100% - 1px - 40%);
|
||||
display: flex;
|
||||
height: 104px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.container-main {
|
||||
width: calc(100% - 10px);
|
||||
height: calc(100vh - 286px);
|
||||
margin-left: 10px;
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 5px;
|
||||
.main-block {
|
||||
padding: 15px;
|
||||
width: calc(100% - 150px);
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.block-right-fold {
|
||||
width: 100%;
|
||||
}
|
||||
.block-right {
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
padding: 5px 0;
|
||||
margin-left: 20px;
|
||||
.today-ratio-card {
|
||||
height: 270px;
|
||||
margin-bottom: 20px;
|
||||
.e-simple-card__body {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
.type-census-card {
|
||||
height: 245px;
|
||||
margin-bottom: 20px;
|
||||
.e-simple-card__body {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
.trend-census-card {
|
||||
height: 260px;
|
||||
margin-bottom: 20px;
|
||||
.e-simple-card__body {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-descriptions__body {
|
||||
background-color: #fff0;
|
||||
}
|
||||
.margin-top {
|
||||
margin-top: 0;
|
||||
}
|
||||
.el-descriptions .el-descriptions-item__cell {
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
.el-descriptions .is-bordered .el-descriptions-item__cell {
|
||||
padding: 5px 5px;
|
||||
// border: 0px solid #ebeef5;
|
||||
}
|
||||
.el-descriptions-item__label.is-bordered-label {
|
||||
background: #fafafa00;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -113,7 +113,7 @@ import ModelOat from "./modelOat";
|
|||
import ChildDevice from "./childDevice";
|
||||
export default {
|
||||
name: "DetailsWrap",
|
||||
props: ["sourceId", "isTenant"],
|
||||
props: ["sourceId", "isTenant", 'isPersonal'],
|
||||
components: {
|
||||
InfoWrap,
|
||||
DeviceLog,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
>
|
||||
<el-input v-if="updateState === true" v-model="temp.deviceName" />
|
||||
<el-button
|
||||
v-if="updateState === false && !isTenant"
|
||||
v-if="updateState === false"
|
||||
type="text"
|
||||
@click.stop="handleUpdate(infoData)"
|
||||
>编辑</el-button
|
||||
|
|
Loading…
Reference in New Issue