mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-19 01:15:54 +08:00
发布v1.1版本
This commit is contained in:
256
vue/src/views/iot/product/index.vue
Normal file
256
vue/src/views/iot/product/index.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div style="padding:6px;">
|
||||
<el-card style="margin-bottom:6px;">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px" style="margin-bottom:-20px;">
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
<el-input v-model="queryParams.productName" placeholder="请输入产品名称" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="queryParams.categoryName" placeholder="请输入产品分类名称" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
|
||||
<el-option v-for="dict in dict.type.iot_product_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<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-form-item style="float:right;">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleEditProduct(0)" v-hasPermi="['iot:product:add']">新增</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card style="padding-bottom:100px;">
|
||||
<el-row :gutter="30" v-loading="loading" >
|
||||
<el-col :span="6" v-for="(item,index) in productList" :key="index" style="margin-bottom:30px;text-align:center;">
|
||||
<el-card :body-style="{ padding: '20px'}" shadow="always">
|
||||
<el-row type="flex" :gutter="10" justify="space-between">
|
||||
<el-col :span="20" style="text-align:left;">
|
||||
<el-link type="" :underline="false" @click="handleEditProduct(item)" style="font-weight:bold;font-size:16px;line-height:32px;">
|
||||
<svg-icon icon-class="product" /> {{item.productName}}
|
||||
<el-tag type="info" size="mini" style="margin-left:5px;font-weight:200" v-if="item.isSys==1">系统</el-tag>
|
||||
</el-link>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-tooltip class="item" effect="dark" content="取消发布" placement="top-start" v-if="item.status==2">
|
||||
<el-button type="success" size="mini" style="padding:5px;" @click="changeProductStatus(item.productId,1)">已发布</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip class="item" effect="dark" content="现在发布" placement="top-start" v-if="item.status==1">
|
||||
<el-button type="info" size="mini" style="padding:5px;" @click="changeProductStatus(item.productId,2)">未发布</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="14">
|
||||
<el-descriptions :column="1" size="small" style="margin-top:10px;">
|
||||
<el-descriptions-item label="所属分类">
|
||||
<el-link type="primary" :underline="false">{{item.categoryName}}</el-link>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="产品类型">
|
||||
<dict-tag :options="dict.type.iot_device_type" :value="item.deviceType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="联网方式">
|
||||
<dict-tag :options="dict.type.iot_network_method" :value="item.networkMethod" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">
|
||||
<span>{{ parseTime(item.createTime, '{y}-{m}-{d}') }}</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<div style="margin-top:10px;">
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" lazy :preview-src-list="[baseUrl+item.imgUrl]" :src="baseUrl+item.imgUrl" fit="cover" v-if="item.imgUrl!=null && item.imgUrl!=''"></el-image>
|
||||
<!-- 用于显示本地计算机、手机、树莓派等设备图片-->
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/esp8266.jpg')]" :src="require('@/assets/images/esp8266.jpg')" fit="cover" v-else-if="item.productName.indexOf('ESP8266')!=-1"></el-image>
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/esp32.jpg')]" :src="require('@/assets/images/esp32.jpg')" fit="cover" v-else-if="item.productName.indexOf('ESP32')!=-1"></el-image>
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/raspberry.jpg')]" :src="require('@/assets/images/raspberry.jpg')" fit="cover" v-else-if="item.productName.indexOf('Raspberry')!=-1"></el-image>
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/telphone.jpg')]" :src="require('@/assets/images/telphone.jpg')" fit="cover" v-else-if="item.productName.indexOf('Phone')!=-1"></el-image>
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/computer.jpg')]" :src="require('@/assets/images/computer.jpg')" fit="cover" v-else-if="item.productName.indexOf('Computer')!=-1"></el-image>
|
||||
<el-image style="width:100%;height:100px;border:1px solid #ccc;border-radius:5px;" :preview-src-list="[require('@/assets/images/product.jpg')]" :src="require('@/assets/images/product.jpg')" fit="cover" v-else></el-image>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button-group style="margin-top:15px;">
|
||||
<el-button size="mini" type="primary" icon="el-icon-edit" @click="handleEditProduct(item)" v-hasPermi="['iot:product:edit']">详情</el-button>
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="handleDelete(item)" v-hasPermi="['iot:product:remove']" v-if="item.status==1">删除</el-button>
|
||||
<el-button size="mini" type="info" icon="el-icon-download" @click="handleGeneratorSDK(item)" v-hasPermi="['iot:product:edit']" v-if="item.status==2">下载SDK</el-button>
|
||||
<el-button size="mini" type="warning" icon="el-icon-search" @click="handleViewDevice(item.productId)" v-hasPermi="['tool:gen:edit']">查看设备</el-button>
|
||||
</el-button-group>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
|
||||
<!-- 下载SDK -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-link type="danger" style="padding-left:10px;" :underline="false">该功能暂未实现,参考教程和项目的SDK示例</el-link>
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="选择设备">
|
||||
<el-radio-group v-model="form.datatype">
|
||||
<el-radio v-for="dict in dict.type.iot_device_chip" :key="dict.value" :label="dict.value" style="margin-top:15px;width:160px;">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="downloadSdk" disabled>下 载</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listProduct,
|
||||
delProduct,
|
||||
changeProductStatus
|
||||
} from "@/api/iot/product";
|
||||
|
||||
export default {
|
||||
name: "Product",
|
||||
dicts: ['iot_yes_no', 'iot_product_status', 'iot_device_type', 'iot_network_method', 'iot_vertificate_method', 'iot_device_chip'],
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 产品表格数据
|
||||
productList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
productName: null,
|
||||
categoryId: null,
|
||||
categoryName: null,
|
||||
tenantId: null,
|
||||
tenantName: null,
|
||||
isSys: null,
|
||||
status: null,
|
||||
deviceType: null,
|
||||
networkMethod: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
baseUrl: process.env.VUE_APP_BASE_API,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
activated() {
|
||||
const time = this.$route.query.t;
|
||||
if (time != null && time != this.uniqueId) {
|
||||
this.uniqueId = time;
|
||||
this.queryParams.pageNum = Number(this.$route.query.pageNum);
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询产品列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listProduct(this.queryParams).then(response => {
|
||||
this.productList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 更新产品状态 */
|
||||
changeProductStatus(productId,status) {
|
||||
let message="发生错误了";
|
||||
if(status==2){
|
||||
message="产品发布后不能再更改产品内容和对应物模型 !";
|
||||
}else if(status==1){
|
||||
message="产品下不能有已经创建的设备,才能取消发布哦 !"
|
||||
}
|
||||
this.$confirm(message, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let data = {};
|
||||
data.productId = productId;
|
||||
data.status = status;
|
||||
changeProductStatus(data).then(response => {
|
||||
this.getList();
|
||||
this.$modal.alertSuccess(response.msg);
|
||||
}).catch(() => {});
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleViewDevice(productId) {
|
||||
this.$router.push({
|
||||
path: '/iot/device',
|
||||
query: {
|
||||
t: Date.now(),
|
||||
productId: productId,
|
||||
}
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 生成SDK */
|
||||
handleGeneratorSDK(row) {
|
||||
this.title = "生成SDK"
|
||||
this.open = true;
|
||||
},
|
||||
/** 下载SDK */
|
||||
downloadSdk() {
|
||||
this.$download.zip("/iot/tool/genSdk?deviceChip=" + 1, "wumeismart-sdk");
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const productIds = row.productId || this.ids;
|
||||
let msg = "";
|
||||
this.$modal.confirm('是否确认删除产品编号为"' + productIds + '"的数据项?').then(function () {
|
||||
return delProduct(productIds).then(response => {
|
||||
msg = response.msg;
|
||||
});
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess(msg);
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleEditProduct(row) {
|
||||
let productId = 0;
|
||||
if (row != 0) {
|
||||
productId = row.productId || this.ids
|
||||
}
|
||||
this.$router.push({
|
||||
path: '/iot/product-edit',
|
||||
query: {
|
||||
productId: productId,
|
||||
pageNum: this.queryParams.pageNum
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
670
vue/src/views/iot/product/product-alert.vue
Normal file
670
vue/src/views/iot/product/product-alert.vue
Normal file
@@ -0,0 +1,670 @@
|
||||
<template>
|
||||
<div style="padding-left:20px;">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="告警名称" prop="alertName">
|
||||
<el-input v-model="queryParams.alertName" placeholder="请输入告警名称" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="告警级别" prop="alertLevel">
|
||||
<el-select v-model="queryParams.alertLevel" placeholder="请选择告警级别" clearable size="small">
|
||||
<el-option v-for="dict in dict.type.iot_alert_level" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<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-form-item>
|
||||
<el-link type="danger" style="padding-top:5px" :underline="false">该功能,未完成</el-link>
|
||||
</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" v-hasPermi="['iot:alert:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['iot:alert:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['iot:alert:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['iot:alert:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="alertList" @selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="告警ID" align="center" prop="alertId" />
|
||||
<el-table-column label="告警名称" align="center" prop="alertName" />
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success" v-if="scope.row.status==1">启动</el-tag>
|
||||
<el-tag type="danger" v-if="scope.row.status==2">暂停</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="告警级别" align="center" prop="alertLevel">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_alert_level" :value="scope.row.alertLevel" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品ID" align="center" prop="productId" />
|
||||
<el-table-column label="产品名称" align="center" prop="productName" />
|
||||
<el-table-column label="触发器" align="center" prop="triggers" />
|
||||
<el-table-column label="执行动作" align="center" prop="actions" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['iot:alert:edit']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['iot:alert:remove']">删除</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="800px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="15">
|
||||
<el-form-item label="告警名称" prop="alertName">
|
||||
<el-input v-model="form.alertName" placeholder="请输入告警名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="告警级别" prop="alertLevel">
|
||||
<el-select v-model="form.alertLevel" placeholder="请选择告警级别">
|
||||
<el-option v-for="dict in dict.type.iot_alert_level" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<el-form-item label="告警状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in alertType" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<el-form-item label="触发器" prop="griggers">
|
||||
<el-select v-model="form.condition" placeholder="请选择" size="small" style="margin-bottom:10px;">
|
||||
<el-option v-for="item in triggerConditions" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div v-for="(item,index) in form.triggers" :key="index" style="margin-bottom:15px;border:1px solid #ddd;padding:10px;">
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<el-select v-model="item.source" placeholder="请选择" size="small" @change="changeTriggerSource">
|
||||
<el-option v-for="subItem in triggerSource" :key="subItem.value" :label="subItem.label" :value="subItem.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="16" :offset="1" v-if="item.source==2">
|
||||
<el-time-picker v-model="timerTimeValue" size="small" value-format="HH:mm" placeholder="选择执行时间" @change="timeChange" :disabled="item.isAdvance==1"></el-time-picker>
|
||||
</el-col>
|
||||
<el-col :span="2" :offset="item.source==1?17:1" v-if="index!=0"><a style="color:#F56C6C" @click="removeTriggerItem(index)">删除</a></el-col>
|
||||
</el-row>
|
||||
|
||||
<!--定时-->
|
||||
<el-row v-if="item.source==2">
|
||||
<el-col :span="24">
|
||||
<el-row style="margin-bottom:5px;">
|
||||
<el-col :span="4">
|
||||
<el-select v-model="timerWeekRepeatValue" placeholder="请选择" @change="repeatChange" size="small" :disabled="item.isAdvance==1">
|
||||
<el-option v-for="item in timerWeekRepeats" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="15" :offset="1" v-if="timerWeekRepeatValue==3">
|
||||
<el-select v-model="timerWeekValue" placeholder="请选择" multiple style="width:485px" @change="weekChange" size="small" :disabled="item.isAdvance==1">
|
||||
<el-option v-for="item in timerWeeks" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-row>
|
||||
<el-col :span="18">
|
||||
<el-input v-model="item.cronExpression" placeholder="cron执行表达式" :disabled="item.isAdvance==0" size="small">
|
||||
<template slot="append">
|
||||
<el-button type="primary" @click="handleShowCron(item,index)" :disabled="item.isAdvance==0">
|
||||
生成表达式
|
||||
<i class="el-icon-time el-icon--right"></i>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="4" :offset="1">
|
||||
<el-checkbox v-model="item.isAdvance" :true-label="1" :false-label="0" @change="customerCronChange">自定义表达式</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--设备-->
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<el-select v-model="item.modelType" placeholder="请选择" size="small">
|
||||
<el-option v-for="subItem in modelTypes" :key="subItem.value" :label="subItem.label" :value="subItem.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="4" :offset="1">
|
||||
<el-select v-model="item.modelType" placeholder="请选择" size="small">
|
||||
<el-option v-for="subItem in modelTypes" :key="subItem.value" :label="subItem.label" :value="subItem.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="5" :offset="1">
|
||||
<el-select v-model="item.operator" placeholder="请选择操作符" size="small">
|
||||
<el-option key="=" label="等于(=)" value="=" />
|
||||
<el-option key="!=" label="不等于(!=)" value="!=" />
|
||||
<el-option key=">" label="大于(>)" value=">" />
|
||||
<el-option key="<" label="小于(<)" value="<" />
|
||||
<el-option key=">=" label="大于等于(>=)" value=">=" />
|
||||
<el-option key="<=" label="小于等于(<=)" value="<=" />
|
||||
<el-option key="contain" label="包含(contain)" value="contain" />
|
||||
<el-option key="notcontain" label="不包含(not contain)" value="notcontain" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="5" :offset="1">
|
||||
<el-input v-model="item.value" placeholder="值" size="small" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
<div>+ <a style="color:#409EFF" @click="addTriggerItem()">添加触发器</a></div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<el-form-item label="执行动作">
|
||||
<el-row v-for="(item,index) in form.actions" :key="index" style="margin-bottom:10px;">
|
||||
<el-col :span="4">
|
||||
<el-select v-model="item.modelType" placeholder="请选择">
|
||||
<el-option v-for="subItem in modelTypes" :key="subItem.value" :label="subItem.label" :value="subItem.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="4" :offset="1">
|
||||
<el-select v-model="item.modelType" placeholder="请选择">
|
||||
<el-option v-for="subItem in modelTypes" :key="subItem.value" :label="subItem.label" :value="subItem.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="11" :offset="1">
|
||||
<el-input v-model="item.value" placeholder="值" />
|
||||
</el-col>
|
||||
<el-col :span="2" :offset="1" v-if="index!=0"><a style="color:#F56C6C" @click="removeActionItem(index)">删除</a></el-col>
|
||||
</el-row>
|
||||
<div>+ <a style="color:#409EFF" @click="addActionItem()">添加执行动作</a></div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-col :span="16">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm" disabled>确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="Cron表达式生成器" :visible.sync="openCron" append-to-body destroy-on-close class="scrollbar">
|
||||
<crontab @hide="openCron=false" @fill="crontabFill" :expression="expression" style="padding-bottom:80px;"></crontab>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listAlert,
|
||||
getAlert,
|
||||
delAlert,
|
||||
addAlert,
|
||||
updateAlert
|
||||
} from "@/api/iot/alert";
|
||||
import {
|
||||
cacheJsonThingsModel
|
||||
} from "@/api/iot/model";
|
||||
import Crontab from '@/components/Crontab'
|
||||
export default {
|
||||
name: "device-alert",
|
||||
dicts: ['iot_alert_level', 'sys_job_status'],
|
||||
components: {
|
||||
Crontab
|
||||
},
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 获取到父组件传递的productId后,刷新列表
|
||||
product: function (newVal, oldVal) {
|
||||
this.productInfo = newVal;
|
||||
if (this.productInfo && this.productInfo.productId != 0) {
|
||||
this.queryParams.productId = this.productInfo.productId;
|
||||
this.getList();
|
||||
// 获取缓存的Json物模型
|
||||
cacheJsonThingsModel(newVal.productId).then(response => {
|
||||
this.thingsModel = JSON.parse(response.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 物模型JSON
|
||||
thingsModel: {},
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 设备告警表格数据
|
||||
alertList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否显示Cron表达式弹出层
|
||||
openCron: false,
|
||||
// 传入的表达式
|
||||
expression: "",
|
||||
// 触发器的索引,用于接收传入的表达式
|
||||
triggerIndex: 0,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
alertName: null,
|
||||
alertLevel: null,
|
||||
productId: null,
|
||||
productName: null,
|
||||
},
|
||||
// 周
|
||||
timerWeekRepeats: [{
|
||||
value: '1',
|
||||
label: '每天'
|
||||
}, {
|
||||
value: '2',
|
||||
label: '仅此一次'
|
||||
}, {
|
||||
value: '3',
|
||||
label: '指定'
|
||||
}],
|
||||
timerWeekRepeatValue: "1",
|
||||
|
||||
timerWeeks: [{
|
||||
value: 1,
|
||||
label: '周一'
|
||||
}, {
|
||||
value: 2,
|
||||
label: '周二'
|
||||
}, {
|
||||
value: 3,
|
||||
label: '周三'
|
||||
}, {
|
||||
value: 4,
|
||||
label: '周四'
|
||||
}, {
|
||||
value: 5,
|
||||
label: '周五'
|
||||
}, {
|
||||
value: 6,
|
||||
label: '周六'
|
||||
}, {
|
||||
value: 7,
|
||||
label: '周日'
|
||||
}],
|
||||
timerWeekValue: [1, 2, 3, 4, 5, 6, 7],
|
||||
// 时间
|
||||
timerTimeValue: '',
|
||||
// 触发器源 1=设备,2=定时,3=告警输出
|
||||
triggerSource: [{
|
||||
value: 1,
|
||||
label: '设备'
|
||||
}, {
|
||||
value: 2,
|
||||
label: '定时'
|
||||
}],
|
||||
// 执行动作源
|
||||
actionSource: [{
|
||||
value: 1,
|
||||
label: '设备'
|
||||
}, {
|
||||
value: 3,
|
||||
label: '告警输出'
|
||||
}],
|
||||
// 物模型类别
|
||||
modelTypes: [{
|
||||
value: 1,
|
||||
label: '属性'
|
||||
}, {
|
||||
value: 2,
|
||||
label: '功能'
|
||||
}],
|
||||
// 触发器条件
|
||||
triggerConditions: [{
|
||||
value: "all",
|
||||
label: '满足所有条件'
|
||||
}, {
|
||||
value: "any",
|
||||
label: '满足任一条件'
|
||||
}],
|
||||
// 告警状态
|
||||
alertType: [{
|
||||
value: 1,
|
||||
label: '启动'
|
||||
}, {
|
||||
value: 2,
|
||||
label: '停止'
|
||||
}],
|
||||
// 表单参数
|
||||
form: {
|
||||
condition: "all", // 触发器条件
|
||||
triggers: [],
|
||||
actions: []
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
alertName: [{
|
||||
required: true,
|
||||
message: "告警名称不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
alertLevel: [{
|
||||
required: true,
|
||||
message: "告警级别不能为空",
|
||||
trigger: "change"
|
||||
}],
|
||||
productId: [{
|
||||
required: true,
|
||||
message: "产品ID不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
productName: [{
|
||||
required: true,
|
||||
message: "产品名称不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
triggers: [{
|
||||
required: true,
|
||||
message: "触发器不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
actions: [{
|
||||
required: true,
|
||||
message: "执行动作不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
// this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询设备告警列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listAlert(this.queryParams).then(response => {
|
||||
this.alertList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
alertId: null,
|
||||
alertName: null,
|
||||
alertLevel: null,
|
||||
productId: null,
|
||||
productName: null,
|
||||
createBy: null,
|
||||
createTime: null,
|
||||
updateBy: null,
|
||||
updateTime: null,
|
||||
remark: null,
|
||||
status: 1,
|
||||
condition: "all", // 触发器条件
|
||||
triggers: [{
|
||||
id: "",
|
||||
name: "",
|
||||
value: "",
|
||||
deviceId: 0,
|
||||
deviceName: "请选择一个设备",
|
||||
source: 1, //1=设备,2=定时,3=告警输出
|
||||
modelType: 1, // 1=属性,2=功能
|
||||
jobId: 0,
|
||||
cronExpression: "",
|
||||
isAdvance: 0
|
||||
}],
|
||||
actions: [{
|
||||
id: "",
|
||||
name: "",
|
||||
value: "",
|
||||
deviceId: 0,
|
||||
deviceName: "请选择一个设备",
|
||||
source: 1, //1=设备,2=定时,3=告警输出
|
||||
modelType: 1, // 1=属性,2=功能
|
||||
}]
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.alertId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加自定义告警";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const alertId = row.alertId || this.ids
|
||||
getAlert(alertId).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改设备告警";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.alertId != null) {
|
||||
updateAlert(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
addAlert(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const alertIds = row.alertId || this.ids;
|
||||
this.$modal.confirm('是否确认删除设备告警编号为"' + alertIds + '"的数据项?').then(function () {
|
||||
return delAlert(alertIds);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('iot/alert/export', {
|
||||
...this.queryParams
|
||||
}, `alert_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
/** 添加动作 */
|
||||
addActionItem() {
|
||||
this.form.actions.push({
|
||||
id: "",
|
||||
name: "",
|
||||
value: ""
|
||||
})
|
||||
},
|
||||
/** 删除动作 */
|
||||
removeActionItem(index) {
|
||||
this.form.actions.splice(index, 1);
|
||||
},
|
||||
/** 触发器源改变事件 **/
|
||||
changeTriggerSource() {
|
||||
this.setTriggerSource();
|
||||
},
|
||||
/** 设置触发器源 **/
|
||||
setTriggerSource() {
|
||||
// 触发器智能包含一个定时
|
||||
let hasTimer = false;
|
||||
for (let i = 0; i < this.form.triggers.length; i++) {
|
||||
if (this.form.triggers[i].source == 2) {
|
||||
hasTimer = true;
|
||||
}
|
||||
}
|
||||
if (hasTimer) {
|
||||
this.triggerSource = [{
|
||||
value: 1,
|
||||
label: '设备'
|
||||
}];
|
||||
} else {
|
||||
//定时
|
||||
this.triggerSource = [{
|
||||
value: 1,
|
||||
label: '设备'
|
||||
}, {
|
||||
value: 2,
|
||||
label: '定时'
|
||||
}];
|
||||
|
||||
}
|
||||
},
|
||||
/** 添加触发器 */
|
||||
addTriggerItem() {
|
||||
this.setTriggerSource();
|
||||
this.form.triggers.push({
|
||||
id: "",
|
||||
name: "",
|
||||
value: "",
|
||||
deviceId: 0,
|
||||
deviceName: "请选择一个设备",
|
||||
source: 1, //1=设备,2=定时,3=告警输出
|
||||
modelType: 1, // 1=属性,2=功能
|
||||
jobId: 0,
|
||||
cronExpression: "",
|
||||
isAdvance: 0
|
||||
})
|
||||
|
||||
},
|
||||
/** 删除触发器 */
|
||||
removeTriggerItem(index) {
|
||||
this.form.triggers.splice(index, 1);
|
||||
this.setTriggerSource();
|
||||
},
|
||||
/** cron表达式按钮操作 */
|
||||
handleShowCron(item, index) {
|
||||
this.expression = item.cronExpression;
|
||||
this.triggerIndex = index;
|
||||
this.openCron = true;
|
||||
},
|
||||
/** 确定后回传值 */
|
||||
crontabFill(value) {
|
||||
this.form.triggers[this.triggerIndex].cronExpression = value;
|
||||
},
|
||||
/** 修改重复事件 **/
|
||||
repeatChange(data) {
|
||||
if (this.timerWeekRepeatValue == 1) {
|
||||
// 每天
|
||||
this.timerWeekValue = [1, 2, 3, 4, 5, 6, 7];
|
||||
this.form.repeat = 1;
|
||||
} else if (this.timerWeekRepeatValue == 2) {
|
||||
// 仅此一次
|
||||
this.timerWeekValue = [];
|
||||
this.form.isRepeat = 0;
|
||||
} else {
|
||||
// 指定
|
||||
this.form.isRepeat = 1;
|
||||
}
|
||||
this.gentCronExpression();
|
||||
},
|
||||
/** 星期改变事件 **/
|
||||
weekChange(data) {
|
||||
this.gentCronExpression();
|
||||
},
|
||||
/** 时间改变事件 **/
|
||||
timeChange(data) {
|
||||
this.gentCronExpression();
|
||||
},
|
||||
/**自定义cron表达式选项改变事件 */
|
||||
customerCronChange(data) {
|
||||
this.gentCronExpression();
|
||||
},
|
||||
/** 生成cron表达式**/
|
||||
gentCronExpression() {
|
||||
if (this.timerTimeValue == "") {
|
||||
this.$modal.alertError("执行时间不能为空");
|
||||
}
|
||||
let minute = this.timerTimeValue.substring(0, 2);
|
||||
let hour = this.timerTimeValue.substring(3);
|
||||
let week = "*";
|
||||
if (this.timerWeekValue.length > 0) {
|
||||
week = this.timerWeekValue;
|
||||
}
|
||||
this.form.triggers[this.triggerIndex].cronExpression = "0 " + minute + " " + hour + " ? * " + week;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
121
vue/src/views/iot/product/product-app.vue
Normal file
121
vue/src/views/iot/product/product-app.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div style="padding-left:20px;">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="14">
|
||||
<el-link type="danger" style="padding-top:5px" :underline="false">该功能,未完成</el-link>
|
||||
<el-table v-loading="loading" :data="modelList" border style="margin-bottom:60px;margin-top:20px;">
|
||||
<el-table-column label="名称" align="center" prop="modelName" />
|
||||
<el-table-column label="标识符" align="center" prop="identifier" />
|
||||
<el-table-column label="物模型类别" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_things_type" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据类型" align="center" prop="datatype">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_data_type" :value="scope.row.datatype" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="部件" align="center" prop="part">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.part}} 系统定义的部件
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-divider>高级功能</el-divider>
|
||||
<el-form ref="form" :model="form" label-width="100px">
|
||||
<el-form-item label="自定义页面" prop="page">
|
||||
<el-input v-model="form.page" placeholder="请输入自定义页面" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</el-col>
|
||||
<el-col :span="8" :offset="2">
|
||||
<div class="phone">
|
||||
<div class="phone-container"></div>
|
||||
</div>
|
||||
<div style="text-align:center;margin-top:15px;width:370px;">界面展示</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listModel,
|
||||
} from "@/api/iot/model";
|
||||
export default {
|
||||
name: "device-log",
|
||||
dicts: ["iot_things_type", "iot_data_type", "iot_yes_no"],
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 产品物模型表格数据
|
||||
modelList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
productId: 0,
|
||||
// 1-属性,2-功能,3-事件,4-属性和功能
|
||||
type: 4,
|
||||
},
|
||||
form: {},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 获取到父组件传递的productId后,刷新列表
|
||||
product: function (newVal, oldVal) {
|
||||
this.productInfo = newVal;
|
||||
if (this.productInfo && this.productInfo.productId != 0) {
|
||||
this.queryParams.productId = this.productInfo.productId;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
/** 查询产品物模型列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listModel(this.queryParams).then((response) => {
|
||||
this.modelList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.phone {
|
||||
height: 700px;
|
||||
width: 370px;
|
||||
background-image: url("../../../assets/images/phone.jpg");
|
||||
background-size: cover;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.phone-container {
|
||||
height: 620px;
|
||||
width: 345px;
|
||||
border-radius: 20px;
|
||||
position: relative;
|
||||
top: 45px;
|
||||
left: 12px;
|
||||
border: 1px solid #888;
|
||||
background: linear-gradient(23deg, #AFF7FF 0%, #ffc3a0 100%);
|
||||
}
|
||||
</style>
|
||||
288
vue/src/views/iot/product/product-edit.vue
Normal file
288
vue/src/views/iot/product/product-edit.vue
Normal file
@@ -0,0 +1,288 @@
|
||||
<template>
|
||||
<el-card style="margin:6px;padding-bottom:100px;">
|
||||
<el-tabs v-model="activeName" tab-position="left" style="padding:10px;">
|
||||
<el-tab-pane name="basic">
|
||||
<span slot="label"> * 基本信息</span>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-row :gutter="100">
|
||||
<el-col :span="7">
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
<el-input v-model="form.productName" placeholder="请输入产品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品分类" prop="categoryId">
|
||||
<el-select v-model="form.categoryId" placeholder="请选择分类" @change="selectCategory" style="width:100%">
|
||||
<el-option v-for="category in categoryShortList" :key="category.id" :label="category.name" :value="category.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="联网方式" prop="networkMethod">
|
||||
<el-select v-model="form.networkMethod" placeholder="请选择联网方式" style="width:100%;">
|
||||
<el-option v-for="dict in dict.type.iot_network_method" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注信息" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" rows="7" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item label="设备类型" prop="deviceType">
|
||||
<el-select v-model="form.deviceType" placeholder="请选择设备类型" disabled style="width:100%">
|
||||
<el-option v-for="dict in dict.type.iot_device_type" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备认证" prop="vertificateMethod">
|
||||
<el-select v-model="form.vertificateMethod" placeholder="请选择认证方式" disabled style="width:100%">
|
||||
<el-option v-for="dict in dict.type.iot_vertificate_method" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品编号" prop="productId">
|
||||
<el-input v-model="form.productId" placeholder="自动生成" :disabled="!form.mqttAccount" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="Mqtt账号" prop="mqttAccount">
|
||||
<el-input v-model="form.mqttAccount" placeholder="自动生成" :disabled="!form.mqttAccount" readonly :type="accountInputType">
|
||||
<el-button slot="append" icon="el-icon-view" style="font-size:18px;" @click="changeInputType('account')"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Mqtt密码" prop="mqttPassword">
|
||||
<el-input v-model="form.mqttPassword" placeholder="自动生成" :disabled="!form.mqttAccount" readonly :type="passwordInputType">
|
||||
<el-button slot="append" icon="el-icon-view" style="font-size:18px;" @click="changeInputType('password')"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品秘钥" prop="mqttSecret">
|
||||
<el-input v-model="form.mqttSecret" placeholder="自动生成" :disabled="!form.mqttAccount" readonly :type="keyInputType">
|
||||
<el-button slot="append" icon="el-icon-view" style="font-size:18px;" @click="changeInputType('key')"></el-button>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="产品图片">
|
||||
<imageUpload ref="image-upload" :value="form.imgUrl" :limit="1" :fileSize="1" @input="getImagePath($event)"></imageUpload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-col :span="20">
|
||||
<el-form-item style="text-align: center;margin:40px 0px;">
|
||||
<el-button type="primary" @click="submitForm()" v-if="form.status!=2">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="" name="things" :disabled="form.productId==0">
|
||||
<span slot="label">* 定义物模型</span>
|
||||
<product-things-model ref="productThingsModel" :product="form" />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="" name="alert" disabled>
|
||||
<span slot="label"> 告警配置</span>
|
||||
<product-alert ref="productAlert" :product="form"></product-alert>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="" name="productApp" disabled>
|
||||
<span slot="label">自定义APP</span>
|
||||
<product-app ref="productApp" :product="form" />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="" disabled name="product01" />
|
||||
<el-tab-pane label="" disabled name="product02" />
|
||||
<el-tab-pane label="" disabled name="product03" />
|
||||
<el-tab-pane v-if="form.status==1" name="product04">
|
||||
<span slot="label">
|
||||
<el-button type="success" size="mini" @click="changeProductStatus(2)">发布产品</el-button>
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="form.status==2" name="product05">
|
||||
<span slot="label">
|
||||
<el-button type="danger" size="mini" @click="changeProductStatus(1)">取消发布</el-button>
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="product06">
|
||||
<span slot="label">
|
||||
<el-button type="info" size="mini" @click="goBack()">返回列表</el-button>
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import productThingsModel from "./product-things-model";
|
||||
import productApp from "./product-app"
|
||||
import productAlert from "./product-alert"
|
||||
import imageUpload from "../../../components/ImageUpload/index"
|
||||
import {
|
||||
listShortCategory
|
||||
} from "@/api/iot/category";
|
||||
import {
|
||||
getProduct,
|
||||
addProduct,
|
||||
updateProduct,
|
||||
changeProductStatus
|
||||
} from "@/api/iot/product";
|
||||
|
||||
export default {
|
||||
name: "Product-edit",
|
||||
dicts: ['iot_device_type', 'iot_network_method', 'iot_vertificate_method'],
|
||||
components: {
|
||||
productThingsModel,
|
||||
productApp,
|
||||
productAlert,
|
||||
imageUpload,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 输入框类型
|
||||
keyInputType: "password",
|
||||
accountInputType: "text",
|
||||
passwordInputType: "password",
|
||||
// 选中选项卡
|
||||
activeName: 'basic',
|
||||
// 分类短列表
|
||||
categoryShortList: [],
|
||||
// 表单参数
|
||||
form: {
|
||||
networkMethod: 1,
|
||||
deviceType: 1,
|
||||
vertificateMethod: 3,
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
productName: [{
|
||||
required: true,
|
||||
message: "产品名称不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
categoryId: [{
|
||||
required: true,
|
||||
message: "产品分类ID不能为空",
|
||||
trigger: "blur"
|
||||
}]
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 获取产品信息
|
||||
const productId = this.$route.query && this.$route.query.productId;
|
||||
this.form.productId = productId;
|
||||
if (this.form.productId != 0) {
|
||||
this.getProduct();
|
||||
}
|
||||
// 获取简短分类列表
|
||||
listShortCategory().then(response => {
|
||||
this.categoryShortList = response.data;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 返回按钮 */
|
||||
goBack() {
|
||||
const obj = {
|
||||
path: "/iot/product",
|
||||
query: {
|
||||
t: Date.now(),
|
||||
pageNum: this.$route.query.pageNum
|
||||
}
|
||||
};
|
||||
this.$tab.closeOpenPage(obj);
|
||||
this.reset();
|
||||
},
|
||||
/** 获取产品信息 */
|
||||
getProduct() {
|
||||
getProduct(this.form.productId).then(response => {
|
||||
this.form = response.data;
|
||||
});
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
productId: 0,
|
||||
productName: null,
|
||||
categoryId: null,
|
||||
categoryName: null,
|
||||
status: 0,
|
||||
tslJson: null,
|
||||
deviceType: 1,
|
||||
networkMethod: 1,
|
||||
vertificateMethod: 3,
|
||||
mqttAccount: null,
|
||||
mqttPassword: null,
|
||||
mqttSecret: null,
|
||||
remark: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.productId != null && this.form.productId != 0) {
|
||||
updateProduct(this.form).then(response => {
|
||||
this.$modal.alertSuccess("修改成功");
|
||||
});
|
||||
} else {
|
||||
addProduct(this.form).then(response => {
|
||||
this.$modal.alertSuccess("添加成功,可以开始定义物模型了");
|
||||
this.form = response.data;
|
||||
this.activeName = "things";
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 更新产品状态 */
|
||||
changeProductStatus(status) {
|
||||
let message="发生错误了";
|
||||
if(status==2){
|
||||
message="产品发布后不能再更改产品内容和对应物模型 !";
|
||||
}else if(status==1){
|
||||
message="产品下不能有已经创建的设备,才能取消发布哦 !"
|
||||
}
|
||||
this.$confirm(message, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let data = {};
|
||||
data.productId = this.form.productId;
|
||||
data.status = status;
|
||||
changeProductStatus(data).then(response => {
|
||||
this.$modal.alertSuccess(response.msg);
|
||||
this.goBack();
|
||||
}).catch(()=>{
|
||||
if(status==2){
|
||||
this.activeName = "things";
|
||||
}else{
|
||||
this.goBack();
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
this.activeName = "basic";
|
||||
});
|
||||
},
|
||||
/** 选择分类 */
|
||||
selectCategory(val) {
|
||||
for (var i = 0; i < this.categoryShortList.length; i++) {
|
||||
if (this.categoryShortList[i].id == val) {
|
||||
this.form.categoryName = this.categoryShortList[i].name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**获取上传图片的路径 */
|
||||
getImagePath(data) {
|
||||
this.form.imgUrl = data;
|
||||
},
|
||||
/**改变输入框类型**/
|
||||
changeInputType(name) {
|
||||
if (name == "key") {
|
||||
this.keyInputType = this.keyInputType == "password" ? "text" : "password";
|
||||
} else if (name == "account") {
|
||||
this.accountInputType = this.accountInputType == "password" ? "text" : "password";
|
||||
} else if (name == "password") {
|
||||
this.passwordInputType = this.passwordInputType == "password" ? "text" : "password";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
112
vue/src/views/iot/product/product-select-template.vue
Normal file
112
vue/src/views/iot/product/product-select-template.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<div style="margin-top:-35px;">
|
||||
<el-divider></el-divider>
|
||||
<el-form :model="queryParams" ref="product-select-template" :inline="true" label-width="48px">
|
||||
<el-form-item label="名称" prop="templateName">
|
||||
<el-input v-model="queryParams.templateName" placeholder="请输入物模型名称" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类别" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择模型类别" clearable size="small">
|
||||
<el-option v-for="dict in dict.type.iot_things_type" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<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-form>
|
||||
|
||||
<el-table v-loading="loading" :data="templateList" @selection-change="handleSelectionChange" ref="selectTemplateTable" border>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="名称" align="center" prop="templateName" />
|
||||
<el-table-column label="标识符" align="center" prop="identifier" />
|
||||
<el-table-column label="物模型类别" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_things_type" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="首页显示" align="center" prop="isTop">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isTop" :active-value="1" :inactive-value="0" active-color="#81c0fb" disabled></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="监测值" align="center" prop="isMonitor">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isMonitor" :active-value="1" :inactive-value="0" active-color="#81c0fb" disabled></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据类型" align="center" prop="datatype">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_data_type" :value="scope.row.datatype" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listTemplate,
|
||||
} from "@/api/iot/template";
|
||||
export default {
|
||||
name: "product-select-template",
|
||||
dicts: ["iot_things_type", "iot_data_type", "iot_yes_no"],
|
||||
data() {
|
||||
return {
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 通用物模型表格数据
|
||||
templateList: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
templateName: null,
|
||||
type: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.ids = [];
|
||||
},
|
||||
methods: {
|
||||
/** 查询通用物模型列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listTemplate(this.queryParams).then((response) => {
|
||||
this.templateList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map((item) => item.templateId);
|
||||
this.single = selection.length !== 1;
|
||||
this.multiple = !selection.length;
|
||||
// Id数组传递到父组件
|
||||
this.$emit('idsToParentEvent', this.ids)
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
590
vue/src/views/iot/product/product-things-model.vue
Normal file
590
vue/src/views/iot/product/product-things-model.vue
Normal file
@@ -0,0 +1,590 @@
|
||||
<template>
|
||||
<div style="padding-left:20px;">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-if="productInfo.status==1">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-plus" size="mini" @click="handleSelect" v-if="productInfo.status==1">导入通用物模型</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-plus" size="mini" @click="handleOpenThingsModel">查看物模型</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-link type="danger" style="padding-top:5px" :underline="false">注意:标识符不能重复</el-link>
|
||||
</el-col>
|
||||
<right-toolbar @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="modelList" border>
|
||||
<el-table-column label="名称" align="center" prop="modelName" />
|
||||
<el-table-column label="标识符" align="center" prop="identifier" />
|
||||
<el-table-column label="首页显示" align="center" prop="isTop" width="100">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_yes_no" :value="scope.row.isTop" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实时监测" align="center" prop="isMonitor" width="100">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_yes_no" :value="scope.row.isMonitor" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="物模型类别" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_things_type" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据类型" align="center" prop="datatype">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.iot_data_type" :value="scope.row.datatype" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据定义" align="left" prop="specs" min-width="150" class-name="specsColor">
|
||||
<template slot-scope="scope">
|
||||
<div v-html="formatSpecsDisplay(scope.row.specs)"></div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<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 :title="title" :visible.sync="open" width="600px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="名称" prop="modelName">
|
||||
<el-input v-model="form.modelName" placeholder="请输入物模型名称,例如:温度" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标识符" prop="identifier">
|
||||
<el-input v-model="form.identifier" placeholder="请输入标识符,例如:temperature" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模型类别" prop="type">
|
||||
<el-radio-group v-model="form.type" @change="typeChange(form.type)">
|
||||
<el-radio-button label="1">属性</el-radio-button>
|
||||
<el-radio-button label="2">功能</el-radio-button>
|
||||
<el-radio-button label="3">事件</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="首页显示" prop="isTop" v-show="form.type != 3">
|
||||
<el-switch v-model="form.isTop" active-text="" inactive-text="" :active-value="1" :inactive-value="0" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="实时监测" prop="isMonitor" v-show="form.type == 1">
|
||||
<el-switch v-model="form.isMonitor" active-text="" inactive-text="" :active-value="1" :inactive-value="0" active-color="#13ce66" @change="changeMonitor(form.isMonitor)">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-divider></el-divider>
|
||||
<el-form-item label="数据类型" prop="datatype">
|
||||
<el-select v-model="form.datatype" placeholder="请选择数据类型" @change="dataTypeChange">
|
||||
<el-option key="integer" label="整数" value="integer"></el-option>
|
||||
<el-option key="decimal" label="小数" value="decimal"></el-option>
|
||||
<el-option key="bool" label="布尔" value="bool" :disabled="form.isMonitor==1"></el-option>
|
||||
<el-option key="enum" label="枚举" value="enum" :disabled="form.isMonitor==1"></el-option>
|
||||
<el-option key="string" label="字符串" value="string" :disabled="form.isMonitor==1"></el-option>
|
||||
<el-option key="array" label="数组" value="array" :disabled="form.isMonitor==1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="form.datatype == 'integer' || form.datatype == 'decimal'">
|
||||
<el-form-item label="取值范围">
|
||||
<el-row>
|
||||
<el-col :span="9">
|
||||
<el-input v-model="form.specs.min" placeholder="最小值" type="number" />
|
||||
</el-col>
|
||||
<el-col :span="2" align="center">到</el-col>
|
||||
<el-col :span="9">
|
||||
<el-input v-model="form.specs.max" placeholder="最大值" type="number" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="单位">
|
||||
<el-input v-model="form.specs.unit" placeholder="请输入单位,例如:℃" />
|
||||
</el-form-item>
|
||||
<el-form-item label="步长">
|
||||
<el-input v-model="form.specs.step" placeholder="请输入步长,例如:1" type="number" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="form.datatype == 'bool'">
|
||||
<el-form-item label="布尔值" prop="">
|
||||
<el-row style="margin-bottom:10px;">
|
||||
<el-col :span="11">
|
||||
<el-input v-model="form.specs.falseText" placeholder="0 对应的文本,例如:关闭" />
|
||||
</el-col>
|
||||
<el-col :span="10" :offset="1"> 0 对应文本</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-input v-model="form.specs.trueText" placeholder="1 对应的文本,例如:打开" />
|
||||
</el-col>
|
||||
<el-col :span="10" :offset="1"> 1 对应文本</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="form.datatype == 'enum'">
|
||||
<el-form-item label="枚举项" prop="">
|
||||
<el-row v-for="(item,index) in form.specs.enumList" :key="index" style="margin-bottom:10px;">
|
||||
<el-col :span="8">
|
||||
<el-input v-model="item.value" placeholder="参数值,例如:0" type="number" />
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="1">
|
||||
<el-input v-model="item.text" placeholder="参数描述,例如:中速档位" />
|
||||
</el-col>
|
||||
<el-col :span="2" :offset="1" v-if="index!=0"><a style="color:#F56C6C" @click="removeEnumItem(index)">删除</a></el-col>
|
||||
</el-row>
|
||||
<div>+ <a style="color:#409EFF" @click="addEnumItem()">添加枚举项</a></div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="form.datatype == 'string'">
|
||||
<el-form-item label="最大长度" prop="">
|
||||
<el-input v-model="form.specs.maxLength" placeholder="请输入字符串最大长度,例如:1024" type="number" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="form.datatype == 'array'">
|
||||
<el-form-item label="数组类型" prop="">
|
||||
<el-radio-group v-model="form.specs.arrayType">
|
||||
<el-radio label="int">int(整数)</el-radio>
|
||||
<el-radio label="double">double(小数)</el-radio>
|
||||
<el-radio label="string">string(字符串)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入通用物模型对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="openSelect" width="800px" append-to-body>
|
||||
<product-select-template ref="productSelectTemplate" @idsToParentEvent="getChildData($event)" />
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="importSelect">导 入</el-button>
|
||||
<el-button @click="cancelSelect">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 物模型JSON -->
|
||||
<el-dialog :title="title" :visible.sync="openThingsModel" width="600px" append-to-body>
|
||||
<div style="border:1px solid #ccc;margin-top:-15px;height:600px; overflow:scroll;">
|
||||
<json-viewer :value="thingsModel" :expand-depth=10 copyable>
|
||||
<template v-slot:copy>
|
||||
复制
|
||||
</template>
|
||||
</json-viewer>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="info" @click="handleCloseThingsModel">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.specsColor {
|
||||
background-color: #fcfcfc;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import productSelectTemplate from "./product-select-template";
|
||||
import JsonViewer from 'vue-json-viewer'
|
||||
import 'vue-json-viewer/style.css'
|
||||
import {
|
||||
listModel,
|
||||
getModel,
|
||||
delModel,
|
||||
addModel,
|
||||
updateModel,
|
||||
importModel
|
||||
} from "@/api/iot/model";
|
||||
export default {
|
||||
name: "product-things-model",
|
||||
dicts: ["iot_things_type", "iot_data_type", "iot_yes_no"],
|
||||
components: {
|
||||
productSelectTemplate,
|
||||
JsonViewer
|
||||
},
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 获取到父组件传递的productId后,刷新列表
|
||||
product: function (newVal, oldVal) {
|
||||
this.productInfo = newVal;
|
||||
if (this.productInfo && this.productInfo.productId != 0) {
|
||||
this.queryParams.productId = this.productInfo.productId;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 物模型
|
||||
thingsModel: {},
|
||||
// 父组件接收的产品信息
|
||||
productInfo: {},
|
||||
// 子组件选中的id数组
|
||||
templateIds: [],
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 产品物模型表格数据
|
||||
modelList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
openSelect: false,
|
||||
openThingsModel: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
productId: 0,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
modelName: [{
|
||||
required: true,
|
||||
message: "物模型名称不能为空",
|
||||
trigger: "blur"
|
||||
}],
|
||||
identifier: [{
|
||||
required: true,
|
||||
message: "标识符,产品下唯一不能为空",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
type: [{
|
||||
required: true,
|
||||
message: "模型类别不能为空",
|
||||
trigger: "change"
|
||||
}, ],
|
||||
datatype: [{
|
||||
required: true,
|
||||
message: "数据类型不能为空",
|
||||
trigger: "change"
|
||||
}, ],
|
||||
specs: [{
|
||||
required: true,
|
||||
message: "数据定义不能为空",
|
||||
trigger: "blur"
|
||||
}, ],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
/** 查询产品物模型列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listModel(this.queryParams).then((response) => {
|
||||
this.modelList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
modelId: null,
|
||||
modelName: null,
|
||||
productId: null,
|
||||
productName: null,
|
||||
tenantId: null,
|
||||
tenantName: null,
|
||||
identifier: null,
|
||||
type: null,
|
||||
datatype: null,
|
||||
isSys: null,
|
||||
isTop: null,
|
||||
isMonitor: null,
|
||||
delFlag: null,
|
||||
createBy: null,
|
||||
createTime: null,
|
||||
updateBy: null,
|
||||
updateTime: null,
|
||||
remark: null,
|
||||
specs: null,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加物模型";
|
||||
this.form.type = 1;
|
||||
this.form.datatype = "integer"
|
||||
this.form.specs = {
|
||||
enumList: [],
|
||||
};
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const modelId = row.modelId;
|
||||
getModel(modelId).then((response) => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改物模型";
|
||||
// Json转对象
|
||||
this.form.specs = JSON.parse(this.form.specs);
|
||||
});
|
||||
},
|
||||
/**查看物模型 */
|
||||
handleOpenThingsModel() {
|
||||
this.title = "物模型";
|
||||
// 生成物模型
|
||||
this.thingsModel = {
|
||||
properties: [],
|
||||
functions: [],
|
||||
events: []
|
||||
}
|
||||
for (var i = 0; i < this.modelList.length; i++) {
|
||||
let thingsItem = {};
|
||||
thingsItem.id = this.modelList[i].identifier;
|
||||
thingsItem.name = this.modelList[i].modelName;
|
||||
if (this.modelList[i].type == 1) {
|
||||
//属性
|
||||
thingsItem.isTop = this.modelList[i].isTop;
|
||||
thingsItem.isMonitor = this.modelList[i].isMonitor;
|
||||
thingsItem.datatype = JSON.parse(this.modelList[i].specs);
|
||||
this.thingsModel.properties.push(thingsItem);
|
||||
} else if (this.modelList[i].type == 2) {
|
||||
// 功能
|
||||
thingsItem.isTop = this.modelList[i].isTop;
|
||||
thingsItem.datatype = JSON.parse(this.modelList[i].specs);
|
||||
this.thingsModel.functions.push(thingsItem);
|
||||
} else if (this.modelList[i].type == 3) {
|
||||
// 事件
|
||||
thingsItem.datatype = JSON.parse(this.modelList[i].specs);
|
||||
this.thingsModel.events.push(thingsItem);
|
||||
}
|
||||
}
|
||||
|
||||
this.openThingsModel = true;
|
||||
},
|
||||
/**关闭物模型 */
|
||||
handleCloseThingsModel() {
|
||||
this.openThingsModel = false;
|
||||
},
|
||||
/** 选择物模型 */
|
||||
handleSelect() {
|
||||
this.openSelect = true;
|
||||
this.title = "导入通用物模型";
|
||||
this.form.type = 1;
|
||||
this.form.datatype = "integer"
|
||||
this.form.specs = {
|
||||
enumList: [],
|
||||
};
|
||||
},
|
||||
// 取消导入通用物模型按钮
|
||||
cancelSelect() {
|
||||
this.openSelect = false;
|
||||
this.$refs.productSelectTemplate.$refs.selectTemplateTable.clearSelection();
|
||||
},
|
||||
// 获取子组件的值
|
||||
getChildData(data) {
|
||||
this.templateIds = data;
|
||||
},
|
||||
// 导入通用物模型按钮
|
||||
importSelect() {
|
||||
if (this.templateIds != null && this.templateIds.length > 0) {
|
||||
var importData = {
|
||||
productId: this.productInfo.productId,
|
||||
productName: this.productInfo.productName,
|
||||
templateIds: this.templateIds
|
||||
}
|
||||
importModel(importData).then(response => {
|
||||
this.$modal.msgSuccess(response.msg);
|
||||
this.openSelect = false;
|
||||
this.$refs.productSelectTemplate.$refs.selectTemplateTable.clearSelection();
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.form.modelId != null) {
|
||||
// 格式化specs
|
||||
this.form.specs = this.formatThingsSpecs();
|
||||
if (this.form.type == 2) {
|
||||
this.form.isMonitor = 0;
|
||||
} else if (this.form.type == 3) {
|
||||
this.form.isMonitor = 0;
|
||||
this.form.isTop = 0;
|
||||
}
|
||||
updateModel(this.form).then((response) => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
// 格式化specs
|
||||
this.form.specs = this.formatThingsSpecs();
|
||||
this.form.productId = this.productInfo.productId;
|
||||
this.form.productName = this.productInfo.productName;
|
||||
if (this.form.type == 2) {
|
||||
this.form.isMonitor = 0;
|
||||
} else if (this.form.type == 3) {
|
||||
this.form.isMonitor = 0;
|
||||
this.form.isTop = 0;
|
||||
}
|
||||
addModel(this.form).then((response) => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const modelIds = row.modelId;
|
||||
this.$modal
|
||||
.confirm('是否确认删除物模型编号为"' + modelIds + '"的数据项?')
|
||||
.then(function () {
|
||||
return delModel(modelIds);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download(
|
||||
"iot/model/export", {
|
||||
...this.queryParams,
|
||||
},
|
||||
`model_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
},
|
||||
// 类型改变
|
||||
typeChange(label) {
|
||||
if (label == 2 || label == 3) {
|
||||
this.form.isMonitor = 0;
|
||||
}
|
||||
},
|
||||
// 实时监测改变
|
||||
changeMonitor(isMonitor) {
|
||||
if (isMonitor == 1 && this.form.datatype != "integer" && this.form.datatype != "decimal") {
|
||||
this.form.datatype = "integer";
|
||||
}
|
||||
},
|
||||
// 格式化物模型
|
||||
formatThingsSpecs() {
|
||||
var data = {};
|
||||
data.type = this.form.datatype;
|
||||
if (this.form.datatype == "integer" || this.form.datatype == "decimal") {
|
||||
data.min = Number(this.form.specs.min);
|
||||
data.max = Number(this.form.specs.max);
|
||||
data.unit = this.form.specs.unit;
|
||||
data.step = Number(this.form.specs.step);
|
||||
} else if (this.form.datatype == "string") {
|
||||
data.maxLength = Number(this.form.specs.maxLength);
|
||||
} else if (this.form.datatype == "bool") {
|
||||
data.falseText = this.form.specs.falseText;
|
||||
data.trueText = this.form.specs.trueText;
|
||||
} else if (this.form.datatype == "array") {
|
||||
data.arrayType = this.form.specs.arrayType;
|
||||
} else if (this.form.datatype == "enum") {
|
||||
data.enumList = this.form.specs.enumList;
|
||||
}
|
||||
return JSON.stringify(data);
|
||||
},
|
||||
/** 切换为枚举项 */
|
||||
dataTypeChange(val) {
|
||||
if (val == "enum") {
|
||||
this.form.specs.enumList = [{
|
||||
value: "",
|
||||
text: ""
|
||||
}];
|
||||
} else if (val == "array") {
|
||||
this.form.specs.arrayType = "int";
|
||||
}
|
||||
},
|
||||
/** 添加枚举项 */
|
||||
addEnumItem() {
|
||||
this.form.specs.enumList.push({
|
||||
value: "",
|
||||
text: ""
|
||||
})
|
||||
},
|
||||
/** 删除枚举项 */
|
||||
removeEnumItem(index) {
|
||||
this.form.specs.enumList.splice(index, 1);
|
||||
},
|
||||
/** 格式化显示数据定义 */
|
||||
formatSpecsDisplay(json) {
|
||||
let specs = JSON.parse(json);
|
||||
if (specs.type === "integer" || specs.type === "decimal") {
|
||||
return "<span style='width:50%;display:inline-block;'>最大值:<span style=\"color:#F56C6C\">" + specs.max +
|
||||
"</span></span>最小值:<span style=\"color:#F56C6C\">" + specs.min +
|
||||
"</span><br /><span style='width:50%;display:inline-block;'>步长:<span style=\"color:#F56C6C\">" + specs.step +
|
||||
"</span></span>单位:<span style=\"color:#F56C6C\">" + specs.unit;
|
||||
} else if (specs.type === "string") {
|
||||
return "最大长度:<span style=\"color:#F56C6C\">" + specs.maxLength + "</span>";
|
||||
} else if (specs.type === "array") {
|
||||
return "数组类型:<span style=\"color:#F56C6C\">" + specs.arrayType + "</span>";
|
||||
} else if (specs.type === "enum") {
|
||||
let items = "";
|
||||
for (let i = 0; i < specs.enumList.length; i++) {
|
||||
items = items + "<span style='width:50%;display:inline-block;'>" + specs.enumList[i].value + ":<span style='color:#F56C6C'>" + specs.enumList[i].text + "</span></span>"
|
||||
if (i > 0 && i % 2 != 0) {
|
||||
items = items + "<br />"
|
||||
}
|
||||
}
|
||||
return items;
|
||||
} else if (specs.type === "bool") {
|
||||
return "<span style='width:50%;display:inline-block;'>0:<span style=\"color:#F56C6C\">" + specs.falseText +
|
||||
"</span></span>1:<span style=\"color:#F56C6C\">" + specs.trueText
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user