smart-power-ui/src/views/tenant/device/index.vue

784 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--我的设备页-->
<template>
<div class="app-container iot-device">
<component
:is="componectVal"
:isTenant="true"
:sourceId="sourceId"
@toTableClick="toTableClick"
></component>
<div v-show="componectVal === ''">
<el-form
v-show="showSearch"
ref="queryForm"
:inline="true"
:model="queryParams"
class="main-search-card"
label-width="68px"
>
<el-form-item label="所属项目" prop="inProject">
<el-select
v-model="queryParams.inProject"
clearable
placeholder="请选择所属项目"
size="small"
@change="changeProject"
>
<el-option
v-for="(item, index) in inProjectList"
:key="item.projectId"
:label="item.projectName"
:value="item.projectId"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="queryParams.inProject"
label="设备组"
prop="groupId"
>
<el-select
v-model="queryParams.groupId"
clearable
placeholder="请选择设备组"
size="small"
>
<el-option
v-for="(item, index) in projectGroupList"
:key="item.id"
:label="item.groupName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input
v-model="queryParams.deviceName"
clearable
placeholder="请输入设备名称"
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="设备状态" prop="deviceState">
<el-select
v-model="queryParams.deviceState"
clearable
placeholder="请选择设备状态"
size="small"
>
<el-option
v-for="(keys, vals) in deviceStatusOpt"
:key="vals"
:label="keys"
:value="vals"
/>
</el-select>
</el-form-item>
<el-form-item label="设备类型" prop="deviceType">
<el-select
v-model="queryParams.deviceType"
clearable
placeholder="请选择设备类型"
size="small"
>
<el-option
v-for="(keys, vals) in deviceTypeList"
:key="vals"
:label="keys"
:value="vals"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
icon="el-icon-search"
size="mini"
type="primary"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<div class="main-content-card">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
icon="el-icon-download"
plain
size="mini"
type="warning"
@click="handleExport"
>导出</el-button
>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
:view-type="viewType"
@changeViewType="changeViewType"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-if="viewType!='card'"
v-loading="loading"
:data="deviceList"
:default-sort="{ prop: 'createTime', order: 'descending' }"
@sort-change="sortChange"
>
<el-table-column
:index="indexFormatter"
align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column align="center" label="设备key" prop="deviceKey" />
<el-table-column align="center" label="设备名称" prop="deviceName">
<template slot-scope="scope">
<el-link
:underline="false"
type="primary"
@click="handleDetails(scope.row)"
>{{ scope.row.deviceName }}</el-link
>
</template>
</el-table-column>
<el-table-column align="center" label="所属型号" prop="modelName" />
<el-table-column align="center" label="所属项目" prop="inProjectName" />
<el-table-column
align="center"
label="设备码"
min-width="120"
prop="deviceState"
width="60"
>
<template slot-scope="scope">
<svg-icon
icon-class="qrcode"
style="color: #1890FF;cursor: pointer"
@click="lookQrCode(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
align="center"
label="设备类型"
prop="deviceTypeName"
width="120px"
/>
<el-table-column
align="center"
label="设备状态"
prop="deviceState"
width="120"
>
<template slot-scope="scope">
<el-tag v-if="scope.row.deviceState === 'ONLINE'" type="success"
>在线</el-tag
>
<el-tag
v-else-if="scope.row.deviceState === 'OFFLINE'"
type="danger"
>离线</el-tag
>
<el-tag
v-else-if="scope.row.deviceState === 'OUTLINE'"
type="warning"
>脱线</el-tag
>
<el-tag v-else-if="scope.row.deviceState === 'UNACTIVE'" type="warning"
>未激活</el-tag
>
</template>
</el-table-column>
<el-table-column align="center" label="设备组" prop="groupName" />
<el-table-column align="center" label="设备标签" prop="deviceLabel">
<template slot-scope="scope">
<el-tag
v-for="(val, i) in scope.row.deviceLabel"
:key="i"
size="mini"
style="margin-right: 5px;margin-bottom: 5px"
>{{ val }}</el-tag
>
</template>
</el-table-column>
<el-table-column
align="center"
label="创建时间"
prop="createTime"
sortable="custom"
width="160px"
/>
<el-table-column
align="center"
class-name="small-padding fixed-width"
label="操作"
width="200px"
>
<template slot-scope="scope">
<el-button
icon="el-icon-search"
size="mini"
type="text"
@click="handleDetails(scope.row)"
>详情</el-button
>
</template>
</el-table-column>
</el-table>
<div v-else class="card-list-box">
<el-row :gutter="20">
<el-col v-for="(item, index) in deviceList" :key="index" :lg="8" :md="12" :sm="12" :xs="24" class="card-item-col">
<div class="device-card">
<div class="card-header">
<div class="device-img-box">
<el-image
:preview-src-list="item.deviceImage?[imgPath+item.deviceImage]:['http://static.drgyen.com/pc/smart-power-ui/device/device-card.png']"
:src="item.deviceImage?imgPath+item.deviceImage:'http://static.drgyen.com/pc/smart-power-ui/device/device-card.png'"
style="width: 100%; height: 100%">
</el-image>
</div>
<div class="card-header-right">
<div class="card-header-right-top">
<div class="device-name">{{ item.deviceName }}</div>
<div>
<svg-icon
icon-class="qrcode"
style="color: #1890FF;cursor: pointer;width: 18px;height: 18px"
@click="lookQrCode(item)"
/>
</div>
</div>
<div class="card-header-right-content">
<el-tag :type="item.deviceState === 'ONLINE' ? 'success' : item.deviceState === 'OFFLINE' ? 'danger' :'warning'" class="status-tag" size="mini">
{{ item.deviceState === 'ONLINE' ? '在线' : (item.deviceState === 'OFFLINE' ? '离线' : (item.deviceState === 'OUTLINE' ? '脱线' : '未激活')) }}
</el-tag>
<el-tag
v-for="(val, i) in item.deviceLabel"
:key="i"
class="status-tag"
size="mini"
type="info"
>{{ val }}</el-tag
>
</div>
</div>
</div>
<div class="card-content">
<div class="info-item">
<span class="label">Key</span>
<span class="value">{{ item.deviceKey }}</span>
</div>
<div class="info-item">
<span class="label">设备组:</span>
<el-tooltip :content="item.groupName" effect="dark" placement="top">
<span class="value">{{ item.groupName }}</span>
</el-tooltip>
</div>
<div class="info-item">
<span class="label">型号:</span>
<el-tooltip :content="item.modelName" effect="dark" placement="top">
<span class="value">{{ item.modelName }}</span>
</el-tooltip>
</div>
<div class="info-item">
<span class="label">所属项目:</span>
<el-tooltip v-if="item.inProjectName" :content="item.inProjectName" effect="dark" placement="top">
<span class="value">{{ item.inProjectName || '-' }}</span>
</el-tooltip>
<span v-else class="value">{{ item.inProjectName || '-' }}</span>
</div>
<div class="info-item">
<span class="label">类型:</span>
<span class="value">{{ item.deviceTypeName }}</span>
</div>
<div class="info-item">
<span class="label">创建时间:</span>
<el-tooltip :content="item.createTime" effect="dark" placement="top">
<span class="value">{{ item.createTime }}</span>
</el-tooltip>
</div>
</div>
<div class="card-footer">
<el-button icon="el-icon-search" type="text" @click="handleDetails(item)">查看详情</el-button>
<el-button v-hasPermi="['iot:device:edit']" type="text"><el-divider direction="vertical"></el-divider></el-button>
<el-button v-hasPermi="['iot:device:edit']" icon="el-icon-edit" type="text" @click="handleUpdate(item)">修改</el-button>
<el-button v-hasPermi="['iot:device:edit','iot:device:remove']" type="text"><el-divider direction="vertical"></el-divider></el-button>
<el-button v-if="item['parentId'] && item['parentId'] !== '0'" v-hasPermi="['iot:device:edit']" icon="el-icon-error" type="text" @click="handleDisassociate(item)">解绑</el-button>
<el-button v-else v-hasPermi="['iot:device:remove']" icon="el-icon-delete" type="text" @click="handleDelete(item)">删除</el-button>
</div>
</div>
</el-col>
</el-row>
<el-empty v-if="total === 0"></el-empty>
</div>
<pagination
v-show="total > 0"
:limit.sync="queryParams.pageSize"
:page-sizes="[12, 24, 36, 60]"
:page.sync="queryParams.pageNum"
:total="total"
@pagination="getList"
/>
</div>
</div>
<!-- <div-->
<!-- v-show="componectVal !== ''"-->
<!-- :class="-->
<!-- componectVal === 'GatewayDetail'-->
<!-- ? 'to-home-wrap2 gateway-wrap'-->
<!-- : 'to-home-wrap2 '-->
<!-- "-->
<!-- @click="toTableClick"-->
<!-- >-->
<!-- <el-button circle icon="el-icon-d-arrow-left" title="返回列表"-->
<!-- >返回列表</el-button-->
<!-- >-->
<!-- </div>-->
<el-dialog :visible.sync="imgModelShow" title="设备二维码" width="400px">
<img ref="qrCode" height="100%" width="100%" />
</el-dialog>
</div>
</template>
<script>
import {
listDevice,
getDevice,
exportDevice,
listDeviceTypeList
} from "@/api/tenant/device";
import DetailsWrap from "./profile/details";
import GatewayDetail from "@/views/profile/DeviceDetailsView/index";
import JsBarcode from "jsbarcode";
import { getProjectGroupList, listProject } from "@/api/tenant/project";
const deviceStatusOpt = {
ONLINE: "在线",
OFFLINE: "离线",
OUTLINE: "脱线",
UNACTIVE: "未激活"
};
const lineTypeOpt = {
MAIN: "总路",
BRANCH: "支路"
};
export default {
name: "Device",
components: {
DetailsWrap,
GatewayDetail
},
data() {
return {
//列表显示视图
viewType: "card",
deviceStatusOpt,
lineTypeOpt,
imgModelShow: false,
qrCodeUrl: "",
sourceId: "",
componectVal: "",
selectTableShow: false,
tableSelectOption: {},
selectResult: {},
queryModelOpt: [],
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 设备表格数据
deviceList: [],
// 弹出层标题
inProjectList: [],
// 设备组列表
projectGroupList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 12,
modelId: null,
parentId: null,
deviceName: null,
deviceState: null,
inProject: null,
groupId: null,
deviceType: null,
orderByColumn: "createTime",
isAsc: "desc"
},
// 表单校验
deviceTypeList: {},
imgPath: "",
};
},
created() {
this.imgPath = (process.env.NODE_ENV === "production") ? `${window.dasConfig.protocol}${window.dasConfig.ip}${window.dasConfig.port ? ':'+window.dasConfig.port : ''}${window.dasConfig.prodApi ? window.dasConfig.prodApi : ''}` : process.env.VUE_APP_BASE_API;''
if (this.$route.query["deviceId"]) {
this.handleDetails(this.$route.query);
}
this.getDeviceTypeList();
this.getInProjectList();
this.getList();
},
methods: {
changeProject(e) {
console.log("changeProject", e);
this.queryParams.groupId = null;
this.projectGroupList = [];
if (e) {
this.getInProjectGroupList();
}
},
changeViewType(type) {
this.viewType=type;
},
// 查询所属项目列表
getInProjectGroupList() {
getProjectGroupList({
projectId: this.queryParams.inProject
}).then(response => {
this.projectGroupList = response.rows || [];
});
},
lookQrCode(item) {
this.imgModelShow = true;
this.$nextTick(() => {
JsBarcode(this.$refs.qrCode, item.deviceKey, {
format: "CODE128", //条形码的格式
width: 2, //线宽
height: 65, //条码高度
lineColor: "#000", //线条颜色
displayValue: true, //是否显示文字
margin: 3 //设置条形码周围的空白区域
});
});
},
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(row) {
this.sourceId = row.deviceId;
// this.componectVal = "DetailsWrap";
this.componectVal =
row.deviceType === "GATEWAY_CONTROLLER"
? "GatewayDetail"
: "DetailsWrap";
},
// 跳转详情页
toTableClick() {
if (this.$route.query["deviceId"]) {
this.$router.push("/device_tenant/device_tenant");
}
this.componectVal = "";
},
deviceTypeChange(val) {
if (val !== "MINIATURE_BREAKER") {
this.form.parentId = 0;
this.form.parentName = "";
} else if (!val) {
this.form.parentId = "";
this.form.parentName = "";
}
},
// 查询所属项目列表
getInProjectList() {
listProject({
pageNum: 1,
pageSize: 100,
orderByColumn: "createTime",
isAsc: "desc"
}).then(response => {
this.inProjectList = response.rows;
if (this.$route.query.projectId) {
this.queryParams.inProject = parseInt(this.$route.query.projectId);
this.getList();
}
});
},
// 查询设备类型列表
getDeviceTypeList() {
listDeviceTypeList().then(response => {
this.deviceTypeList = response.data;
});
},
/** 查询设备列表 */
getList() {
this.loading = true;
listDevice(this.queryParams).then(response => {
let list = response.rows.map(item => {
item.deviceImage = item.deviceImage || "";
return item;
});
this.deviceList = list;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 导出按钮操作 */
handleExport() {
const queryParams = this.queryParams;
this.$confirm("是否确认导出所有设备数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(function() {
return exportDevice(queryParams);
})
.then(response => {
this.download(response.msg);
});
}
}
};
</script>
<style lang="scss">
.iot-device {
.eldialog-wrap {
.el-dialog__header {
border-bottom: 1px solid #747373;
}
.el-dialog__body {
padding: 0px;
}
.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;
}
}
.form-params-wrap {
height: 100%;
width: calc(100% + 110px);
position: relative;
top: 35px;
left: -90px;
max-height: 250px;
overflow: auto;
padding: 10px;
border: 1px solid #009688;
border-radius: 5px;
}
}
.to-home-wrap2 {
width: 100px;
height: 20px;
position: absolute;
right: 30px;
top: 50px;
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
color: #656363;
font-size: 20px;
cursor: default;
.el-button--medium.is-circle {
width: 25px;
height: 20px;
padding: 0;
background: #f26a6a;
color: #fff;
font-size: 16px;
border-radius: 5px;
height: 30px;
width: 100%;
font-size: 14px;
}
}
.to-home-wrap2:hover {
color: #1890ff;
font-size: 30px;
}
.gateway-wrap {
top: 220px;
display: none;
}
}
.form-params-wrap::-webkit-scrollbar {
/*滚动条整体样式*/
width: 8px; /*高宽分别对应横竖滚动条的尺寸*/
height: 5px;
}
.form-params-wrap::-webkit-scrollbar-thumb {
/*滚动条里面小方块*/
border-radius: 10px;
box-shadow: inset 0 0 5px #c4c4c4;
background: #dededea6;
}
.form-params-wrap::-webkit-scrollbar-track {
/*滚动条里面轨道*/
box-shadow: inset 0 0 5px #f6f6f6;
border-radius: 10px;
background: #ffffff;
}
// 卡片视图样式
.card-list-box {
.card-item-col {
margin-top: 15px;
}
.device-card {
height: 100%;
border-radius: 10px;
border: 1px solid #ebeef5;
background-color: #fff;
overflow: hidden;
color: #303133;
transition: 0.3s;
cursor: pointer;
&:hover {
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2);
//border: 1px solid #409EFF;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
.device-img-box{
width: 60px;
height: 60px;
img{
width: 100%;
height: 100%;
}
}
.card-header-right{
width: calc(100% - 110px);
flex: 1;
padding-left: 10px;
.card-header-right-top{
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 5px;
.device-name {
font-size: 16px;
line-height: 16px;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc(100% - 30px);
}
}
.card-header-right-content{
.status-tag {
margin-right: 5px;
}
}
}
.device-title {
display: flex;
flex-direction: column;
.device-id {
font-size: 12px;
color: #909399;
cursor: pointer;
}
}
}
.card-content {
padding: 10px 20px;
display: flex;
flex-wrap: wrap;
.info-item {
display: flex;
align-items: center;
margin-bottom: 5px;
font-size: 11px;
width: 50%;
.label {
color: #909399;
width: 35px;
}
.value {
width: calc(100% - 35px);
color: #606266;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&:nth-child(2n){
width: 50%;
.label {
width: 70px;
}
}
}
}
.card-footer {
display: flex;
justify-content: space-around;
align-items: center;
padding: 10px 15px;
border-top: 1px solid #ebeef5;
.el-button {
padding: 5px 8px;
&:hover {
color: #409EFF;
}
}
}
}
}
</style>