fix: 修复公网host多次校验提示
* fix: 修改bug * feat: 修改bug优化ui * fix: 修改bug * fix: 修改bug * fix: 修改bug * fix: 修改物模型导入bug * fix: 修改bug * fix: 修改bug * fix: 修改bug * fix: 设备功能 * fix: 设备功能删除console.log * fix: 修改onenet和ctwing * fix: 修改bug * fix: 修改首页视图 * fix: 修复产品跳转设备接口异常 * fix: 17008、16996 * fix: 修复Iframe页面无法访问 * fix: bug#17006 * fix: 修改bug * feat: 17019 * fix: 修改文档 * fix: ctwing右侧提示 * fix: bug#16975 * fix: 修改17021 * fix: bug#17018 * fix: 优化oauth页面跳转逻辑 * fix: 产品导入提示bug * fix: 产品导入bug * fix: bug#17035 * fix: bug#17041 * fix: bug#17041 * fix: bug#17041 * fix: bug#17051 * fix: 初始化页面添加菜单控制 * fix: 修复公网host多次校验提示
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 307 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<div class="view-content">
|
||||||
|
<div
|
||||||
|
class="select-item"
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.id"
|
||||||
|
@click="onChange(item.id)"
|
||||||
|
:class="{
|
||||||
|
active: currentView === item.id,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<img :src="getImage(`/home/home-view/${item.id}${currentView === item.id ? '-active' : ''}.png`)" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { getImage } from '@/utils/comm';
|
||||||
|
|
||||||
|
const list = [
|
||||||
|
{
|
||||||
|
id: 'device',
|
||||||
|
name: '设备接入视图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ops',
|
||||||
|
name: '运营管理视图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'comprehensive',
|
||||||
|
name: '综合管理视图',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:value', 'change'])
|
||||||
|
|
||||||
|
const currentView = ref<string>('');
|
||||||
|
|
||||||
|
const onChange = (id: string) => {
|
||||||
|
emits('change', id);
|
||||||
|
emits('update:value', id)
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
currentView.value = (props.value || '') as string
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.view-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.select-item {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 30%;
|
||||||
|
border-radius: 14px;
|
||||||
|
color: #333333;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||||
|
0px 6px 16px 0px rgba(0, 0, 0, 0.08),
|
||||||
|
0px 9px 16px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<j-form-item name="type" label="读写类型" required>
|
<j-form-item name="type" label="读写类型" :rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择读写类型'
|
||||||
|
}
|
||||||
|
]">
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
|
|
|
@ -369,7 +369,7 @@ const findComponents = (code: string, level: number, isApp: boolean, components:
|
||||||
if (level === 1) { // BasicLayoutPage
|
if (level === 1) { // BasicLayoutPage
|
||||||
return myComponents ? () => myComponents() : BasicLayoutPage
|
return myComponents ? () => myComponents() : BasicLayoutPage
|
||||||
} else if (isApp){ // iframe
|
} else if (isApp){ // iframe
|
||||||
return () => Iframe
|
return Iframe
|
||||||
} else if (level === 2) { // BlankLayoutPage or components
|
} else if (level === 2) { // BlankLayoutPage or components
|
||||||
return myComponents ? () => myComponents() : BlankLayoutPage
|
return myComponents ? () => myComponents() : BlankLayoutPage
|
||||||
} else if(myComponents) { // components
|
} else if(myComponents) { // components
|
||||||
|
|
|
@ -215,11 +215,17 @@ const _channelListAll = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const channelList = computed(() => {
|
const channelList = computed(() => {
|
||||||
return _channelListAll.value.map((item: any) => ({
|
const list:any = [];
|
||||||
|
_channelListAll.value.forEach((item: any) => {
|
||||||
|
if(item?.state?.value !== 'disabled'){
|
||||||
|
list.push({
|
||||||
provider: item.provider,
|
provider: item.provider,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
}));
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list
|
||||||
})
|
})
|
||||||
|
|
||||||
const channelSelect = (key: string, detail: any) => {
|
const channelSelect = (key: string, detail: any) => {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
class="tree-left-tag"
|
class="tree-left-tag"
|
||||||
v-if="data.id !== '*'"
|
v-if="data.id !== '*'"
|
||||||
:color="colorMap.get(data?.uniformState?.value)"
|
:color="colorMap.get(data?.uniformState?.value)"
|
||||||
>{{ data?.pointNumber === 0 ? '--' : (data?.uniformState?.value === 'normal' ? '运行中' : data?.uniformState?.text) }}</j-tag
|
>{{ data?.uniformState?.text }}</j-tag
|
||||||
>
|
>
|
||||||
<j-tag
|
<j-tag
|
||||||
class="tree-left-tag2"
|
class="tree-left-tag2"
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
data?.state?.value === 'disabled' ? '禁用' : '运行中'
|
data?.state?.value === 'disabled' ? data?.state?.text : data?.runningState?.text
|
||||||
}}
|
}}
|
||||||
</j-tag
|
</j-tag
|
||||||
>
|
>
|
||||||
|
@ -94,6 +94,7 @@
|
||||||
? '启用'
|
? '启用'
|
||||||
: '禁用',
|
: '禁用',
|
||||||
}"
|
}"
|
||||||
|
:disabled="data?.runningState?.value === 'stopped' && data?.state?.value!== 'disabled'"
|
||||||
hasPermission="DataCollect/Collector:action"
|
hasPermission="DataCollect/Collector:action"
|
||||||
:popConfirm="{
|
:popConfirm="{
|
||||||
title:
|
title:
|
||||||
|
|
|
@ -1,65 +1,105 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="doc">
|
<div class="doc">
|
||||||
<div class="url">
|
<div class="url">
|
||||||
小度智能家居开放平台:
|
小度智能家居开放平台:
|
||||||
<a
|
<a
|
||||||
href="https://dueros.baidu.com/dbp/bot/index#/iotopenplatform"
|
href="https://dueros.baidu.com/dbp/bot/index#/iotopenplatform"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
https://dueros.baidu.com/dbp/bot/index#/iotopenplatform
|
https://dueros.baidu.com/dbp/bot/index#/iotopenplatform
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
<h1>1. 概述</h1>
|
|
||||||
<div>
|
|
||||||
DuerOS支持家居场景下的云端控制,该页面主要将平台的产品与DuerOS支持语音控制的产品进行映射,以到达小度平台控制本平台设备的目的。
|
|
||||||
</div>
|
|
||||||
<h1>2. 操作步骤</h1>
|
|
||||||
<div>
|
|
||||||
<h2>1、在百度小度技能平台创建技能,并授权。完成物联网平台与DuerOS的关联。</h2>
|
|
||||||
<div class="image">
|
|
||||||
<j-image width="100%" :src="getImage('/cloud/dueros-doc.jpg')" />
|
|
||||||
</div>
|
</div>
|
||||||
<h1>授权地址</h1>
|
<h1>1. 概述</h1>
|
||||||
<div>物联网平台的登录地址。注意需要为https。</div>
|
<div>
|
||||||
<div>请复制并填写: https://{location.host}/#/user/login</div>
|
DuerOS支持在家居场景下进行云端控制,该页面主要将平台的产品与DuerOS支持语音控制的产品进行映射,达到小度平台控制本平台设备的目的。
|
||||||
<h1>Client_Id</h1>
|
|
||||||
<div>请填写系统管理-应用管理中的clientId。</div>
|
|
||||||
<div class="image">
|
|
||||||
<j-image width="100%" :src="getImage('/cloud/dueros-doc1.png')" />
|
|
||||||
</div>
|
</div>
|
||||||
<h1>回调地址</h1>
|
<h1>2. 操作步骤</h1>
|
||||||
<div>请复制DuerOS平台中的值,填写到系统管理-应用管理中-redirectUrl中。</div>
|
<div>
|
||||||
<div class="image">
|
<div>1、在百度小度技能平台创建技能,并授权。</div>
|
||||||
<j-image width="100%" :src="getImage('/cloud/dueros-doc2.png')" />
|
<div>
|
||||||
|
2、在物联网平台 系统管理--应用管理中配置应用完成与DuerOS的关联。
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image
|
||||||
|
width="100%"
|
||||||
|
:src="getImage('/cloud/dueros-doc.jpg')"
|
||||||
|
/>
|
||||||
|
<div class="desc">新建DuerOS</div>
|
||||||
|
</div>
|
||||||
|
<j-descriptions
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
:column="1"
|
||||||
|
:labelStyle="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="参数">说明</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="授权地址"
|
||||||
|
>物联网平台的登录地址http://host:port/JetLinks.cn</j-descriptions-item
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="Client_Id">
|
||||||
|
请复制并填写物联网平台的appId
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="Scope">
|
||||||
|
以空格分割的权限列表,若不传递此参数,代表请求用户的默认权限
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="Token地址">
|
||||||
|
请复制并填写:HTTPS://host:port/api/v1/token
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="ClientSecret">
|
||||||
|
请复制并填写物联网平台的secureKey
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="WebService">
|
||||||
|
请复制并填写:/dueros/product/_query
|
||||||
|
</j-descriptions-item>
|
||||||
|
</j-descriptions>
|
||||||
|
<div class="image">
|
||||||
|
<j-image
|
||||||
|
width="100%"
|
||||||
|
:src="getImage('/cloud/dueros-doc1.png')"
|
||||||
|
/>
|
||||||
|
<div class="desc">新建应用</div>
|
||||||
|
</div>
|
||||||
|
<j-descriptions
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
:column="1"
|
||||||
|
:labelStyle="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="参数">说明</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="appId">
|
||||||
|
第三方应用唯一标识,物联网平台的自动生成
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="secureKey">
|
||||||
|
secureKey 第三方应用唯一标识匹配的秘钥,物联网平台的自动生成
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="角色">
|
||||||
|
为应用用户分配角色,根据绑定的角色,进行系统菜单赋权
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="组织">
|
||||||
|
为应用用户分配所属组织,根据绑定的组织,进行数据隔离
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="redirectUrl">
|
||||||
|
请复制并填写小度平台的回调地址
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="IP白名单">
|
||||||
|
允许指定IP地址访问
|
||||||
|
</j-descriptions-item>
|
||||||
|
</j-descriptions>
|
||||||
|
<div>3、登录物联网平台,进行平台内产品与DuerOS产品的数据映射。</div>
|
||||||
|
<div>
|
||||||
|
4、智能家居用户通过物联网平台中的用户,登录小度APP,获取平台内当前用户的所属设备。获取后即可进行语音控制。
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1>Token地址</h1>
|
<h1>配置说明</h1>
|
||||||
<div>请复制并填写:HTTPS://{location.host}/api/v1/token</div>
|
<div>
|
||||||
<h1>ClientSecret</h1>
|
“设备类型”为DuerOS平台拟定的标准规范,设备类型将决定【动作映射】中“动作”的下拉选项,以及【属性映射】中“Dueros属性”的下拉选项
|
||||||
<div>请复制系统管理-应用管理中的secureKey,填写到DuerOS平台。</div>
|
|
||||||
<div class="image">
|
|
||||||
<j-image width="100%" :src="getImage('/cloud/dueros-doc3.png')" />
|
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
|
||||||
<h1>WebService</h1>
|
|
||||||
<div>请复制并填写:/dueros/product/_query</div>
|
|
||||||
<h2>2、登录物联网平台,进行平台内产品与DuerOS产品的数据映射。</h2>
|
|
||||||
<h2>
|
|
||||||
3、智能家居用户通过物联网平台中的用户,登录小度APP,获取平台内当前用户的所属设备。获取后即可进行语音控制。
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<h1>3. 配置说明</h1>
|
|
||||||
<div>
|
|
||||||
<h2>
|
|
||||||
1、“设备类型”为DuerOS平台拟定的标准规范,设备类型将决定【动作映射】中“动作”的下拉选项,以及【属性映射】中“Dueros属性”的下拉选项
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -72,31 +112,38 @@ import { getImage } from '@/utils/comm';
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
|
||||||
.url {
|
.url {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
color: #2f54eb;
|
color: #2f54eb;
|
||||||
background-color: rgba(#a7bdf7, 0.2);
|
background-color: rgba(#a7bdf7, 0.2);
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
color: rgba(#000, 0.85);
|
color: rgba(#000, 0.85);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
color: rgba(0, 0, 0, 0.8);
|
color: rgba(0, 0, 0, 0.8);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: rgb(138, 143, 141);
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,22 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="choose-view">
|
<div class="choose-view">
|
||||||
<div class="view-content">
|
<HomeView v-model:value="currentView" />
|
||||||
<div
|
|
||||||
:span="8"
|
|
||||||
class="select-item"
|
|
||||||
v-for="item in list"
|
|
||||||
:key="item.id"
|
|
||||||
@click="currentView = item.id"
|
|
||||||
:class="{
|
|
||||||
active: currentView === item.id,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div class="select-item-box">
|
|
||||||
<div class="title">{{ item.name }}</div>
|
|
||||||
</div>
|
|
||||||
<img :src="getImage(`/home/home-view/${item.id}.png`)" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<j-button type="primary" @click="confirm">保存修改</j-button>
|
<j-button type="primary" @click="confirm">保存修改</j-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,24 +9,11 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getMe_api, getView_api, setView_api } from '@/api/home';
|
import { getMe_api, getView_api, setView_api } from '@/api/home';
|
||||||
import { getImage, onlyMessage } from '@/utils/comm';
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
import HomeView from '@/components/HomeView/index.vue';
|
||||||
|
|
||||||
const currentView = ref<string>('');
|
const currentView = ref<string>('');
|
||||||
const isApiUser = ref<boolean>();
|
const isApiUser = ref<boolean>();
|
||||||
const list = [
|
|
||||||
{
|
|
||||||
id: 'device',
|
|
||||||
name: '设备接入视图',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ops',
|
|
||||||
name: '运营管理视图',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'comprehensive',
|
|
||||||
name: '综合管理视图',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function getViews() {
|
function getViews() {
|
||||||
// 判断是否是api用户 不是则获取选中的视图
|
// 判断是否是api用户 不是则获取选中的视图
|
||||||
|
@ -59,10 +30,13 @@ function getViews() {
|
||||||
})
|
})
|
||||||
.then((resp: any) => {
|
.then((resp: any) => {
|
||||||
if (resp?.status === 200) {
|
if (resp?.status === 200) {
|
||||||
if (resp.result) currentView.value = resp.result?.content;
|
if (resp.result) {
|
||||||
else if (resp.result?.username === 'admin') {
|
currentView.value = resp.result?.content;
|
||||||
|
} else if (resp.result?.username === 'admin') {
|
||||||
currentView.value = 'comprehensive';
|
currentView.value = 'comprehensive';
|
||||||
} else currentView.value = 'init';
|
} else {
|
||||||
|
currentView.value = 'device';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -84,45 +58,6 @@ onMounted(() => {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 4% 9% 0 9%;
|
padding: 4% 9% 0 9%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
.view-content {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
.select-item {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 30%;
|
|
||||||
border-radius: 14px;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #333333;
|
|
||||||
|
|
||||||
.select-item-box {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
.title {
|
|
||||||
position: absolute;
|
|
||||||
top: 36px;
|
|
||||||
left: 36px;
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 1px solid @primary-color-active;
|
|
||||||
color: @primary-color-active;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0px 3px 6px -4px rgba(0, 0, 0, 0.12),
|
|
||||||
0px 6px 16px 0px rgba(0, 0, 0, 0.08),
|
|
||||||
0px 9px 16px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -109,7 +109,7 @@ const query = reactive({
|
||||||
type: 'number',
|
type: 'number',
|
||||||
componentProps:{
|
componentProps:{
|
||||||
precision:0,
|
precision:0,
|
||||||
min:0
|
min:1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
|
|
|
@ -101,7 +101,9 @@
|
||||||
<j-col
|
<j-col
|
||||||
:span="24"
|
:span="24"
|
||||||
v-if="
|
v-if="
|
||||||
modelRef.type === 'INVOKE_FUNCTION' && modelRef.function && modelRef.inputs.length
|
modelRef.type === 'INVOKE_FUNCTION' &&
|
||||||
|
modelRef.function &&
|
||||||
|
modelRef.inputs.length
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- <j-form-item
|
<!-- <j-form-item
|
||||||
|
@ -169,7 +171,7 @@ const funcChange = (val: string) => {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
value: undefined,
|
value: undefined,
|
||||||
valueType: item?.valueType?.type,
|
valueType: item?.valueType?.type,
|
||||||
required: item?.expands?.required
|
required: item?.expands?.required,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
modelRef.inputs = list;
|
modelRef.inputs = list;
|
||||||
|
@ -177,46 +179,38 @@ const funcChange = (val: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveBtn = async () => {
|
const saveBtn = async () => {
|
||||||
const _inputs = await inputsRef.value?.onSave();
|
const _data = await formRef.value?.validate();
|
||||||
console.log(_inputs)
|
if (!_data) return;
|
||||||
if(!_inputs){
|
const values = toRaw(modelRef);
|
||||||
return
|
if (values.type === 'READ_PROPERTY') {
|
||||||
}
|
await readProperties(instanceStore.current?.id || '', [
|
||||||
formRef.value.validate().then(async () => {
|
values.properties,
|
||||||
const values = toRaw(modelRef);
|
]);
|
||||||
let _inputs: any[] = [];
|
} else if (values.type === 'WRITE_PROPERTY') {
|
||||||
|
await settingProperties(instanceStore.current?.id || '', {
|
||||||
|
[values.properties || '']: values.propertyValue,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
if (modelRef.inputs.length) {
|
if (modelRef.inputs.length) {
|
||||||
_inputs = modelRef.inputs.filter((i: any) => !i.value && i?.required);
|
const _inputs = await inputsRef.value?.onSave();
|
||||||
if (_inputs.length) {
|
if (!_inputs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.type === 'INVOKE_FUNCTION') {
|
const list = (modelRef?.inputs || [])?.filter((it: any) => !!it.value);
|
||||||
const list = (modelRef?.inputs || [])?.filter((it: any) => !!it.value);
|
const obj = {};
|
||||||
const obj = {};
|
list.map((it: any) => {
|
||||||
list.map((it: any) => {
|
obj[it.id] = it.value;
|
||||||
obj[it.id] = it.value;
|
});
|
||||||
});
|
await executeFunctions(
|
||||||
await executeFunctions(
|
instanceStore.current.id || '',
|
||||||
instanceStore.current.id || '',
|
values?.function || '',
|
||||||
values?.function || '',
|
{
|
||||||
{
|
...obj,
|
||||||
...obj,
|
},
|
||||||
},
|
);
|
||||||
);
|
}
|
||||||
} else {
|
|
||||||
if (values.type === 'READ_PROPERTY') {
|
|
||||||
await readProperties(instanceStore.current?.id || '', [
|
|
||||||
values.properties,
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
await settingProperties(instanceStore.current?.id || '', {
|
|
||||||
[values.properties || '']: values.propertyValue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose({ saveBtn });
|
defineExpose({ saveBtn });
|
||||||
|
|
|
@ -8,47 +8,68 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
<div>
|
<div>
|
||||||
<div style="display: flex; align-items: center">
|
<div style="display: flex; align-items: center">
|
||||||
<a-tooltip>
|
<j-tooltip>
|
||||||
<template #title>{{
|
<template #title>{{
|
||||||
productStore.current.name
|
productStore.current.name
|
||||||
}}</template>
|
}}</template>
|
||||||
<div class="productDetailHead">
|
<div class="productDetailHead">
|
||||||
{{ productStore.current.name }}
|
{{ productStore.current.name }}
|
||||||
</div>
|
</div>
|
||||||
</a-tooltip>
|
</j-tooltip>
|
||||||
<div style="margin: -5px 0 0 20px">
|
<div style="margin: -5px 0 0 20px" v-if="permissionStore.hasPermission('device/Product:action')">
|
||||||
<j-popconfirm
|
<j-popconfirm
|
||||||
title="确认禁用"
|
title="确认禁用"
|
||||||
@confirm="handleUndeploy"
|
@confirm="handleUndeploy"
|
||||||
v-if="productStore.current.state === 1"
|
v-if="productStore.current.state === 1"
|
||||||
okText="确定"
|
okText="确定"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
|
||||||
>
|
|
||||||
<j-switch
|
|
||||||
:checked="productStore.current.state === 1"
|
|
||||||
checked-children="正常"
|
|
||||||
un-checked-children="禁用"
|
|
||||||
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
/>
|
>
|
||||||
</j-popconfirm>
|
<j-switch
|
||||||
<j-popconfirm
|
:checked="productStore.current.state === 1"
|
||||||
title="确认启用"
|
checked-children="正常"
|
||||||
@confirm="handleDeploy"
|
un-checked-children="禁用"
|
||||||
v-if="productStore.current.state === 0"
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
okText="确定"
|
/>
|
||||||
cancelText="取消"
|
</j-popconfirm>
|
||||||
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
<j-popconfirm
|
||||||
>
|
title="确认启用"
|
||||||
<j-switch
|
@confirm="handleDeploy"
|
||||||
:unCheckedValue="
|
v-if="productStore.current.state === 0"
|
||||||
productStore.current.state === 0
|
okText="确定"
|
||||||
"
|
cancelText="取消"
|
||||||
checked-children="正常"
|
|
||||||
un-checked-children="禁用"
|
|
||||||
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
/>
|
>
|
||||||
</j-popconfirm>
|
<j-switch
|
||||||
|
:unCheckedValue="
|
||||||
|
productStore.current.state === 0
|
||||||
|
"
|
||||||
|
checked-children="正常"
|
||||||
|
un-checked-children="禁用"
|
||||||
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
|
/>
|
||||||
|
</j-popconfirm>
|
||||||
|
</div>
|
||||||
|
<div style="margin: -5px 0 0 20px" v-else>
|
||||||
|
<j-tooltip>
|
||||||
|
<template #title>暂无权限,请联系管理员</template>
|
||||||
|
<j-switch
|
||||||
|
v-if="productStore.current.state === 1"
|
||||||
|
:checked="productStore.current.state === 1"
|
||||||
|
checked-children="正常"
|
||||||
|
un-checked-children="禁用"
|
||||||
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
|
/>
|
||||||
|
<j-switch
|
||||||
|
v-if="productStore.current.state === 0"
|
||||||
|
:unCheckedValue="
|
||||||
|
productStore.current.state === 0
|
||||||
|
"
|
||||||
|
checked-children="正常"
|
||||||
|
un-checked-children="禁用"
|
||||||
|
:disabled="!permissionStore.hasPermission('device/Product:action')"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -176,7 +197,7 @@ const tabs = {
|
||||||
watch(
|
watch(
|
||||||
() => route.params.id,
|
() => route.params.id,
|
||||||
(newId) => {
|
(newId) => {
|
||||||
if (newId) {
|
if (newId && route.name === 'device/Product/Detail') {
|
||||||
productStore.reSet();
|
productStore.reSet();
|
||||||
productStore.tabActiveKey = 'Info';
|
productStore.tabActiveKey = 'Info';
|
||||||
productStore.refresh(newId as string);
|
productStore.refresh(newId as string);
|
||||||
|
|
|
@ -389,29 +389,37 @@ const beforeUpload = (file: any) => {
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
reader.onload = async (result) => {
|
reader.onload = async (result) => {
|
||||||
const text = result.target?.result;
|
const text = result.target?.result;
|
||||||
console.log('text: ', text);
|
// console.log('text: ', text);
|
||||||
console.log(file);
|
// console.log(file);
|
||||||
if (!file.type.includes('json')) {
|
if (!file.type.includes('json')) {
|
||||||
onlyMessage('请上传json格式文件', 'error');
|
onlyMessage('请上传json格式文件', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(!text){
|
||||||
|
onlyMessage('文件内容不能为空','error')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text || '{}');
|
const data = JSON.parse(text);
|
||||||
// 设置导入的产品状态为未发布
|
// 设置导入的产品状态为未发布
|
||||||
data.state = 0;
|
data.state = 0;
|
||||||
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
onlyMessage('文件内容不能为空', 'error');
|
onlyMessage('请上传正确格式文件', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
delete data.state;
|
delete data.state;
|
||||||
|
if(!data?.name){
|
||||||
|
data.name = "产品" + Date.now();
|
||||||
|
}
|
||||||
const res = await updateDevice(data);
|
const res = await updateDevice(data);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
onlyMessage('操作成功');
|
onlyMessage('操作成功');
|
||||||
tableRef.value?.reload();
|
tableRef.value?.reload();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch(e) {
|
||||||
onlyMessage('请上传json格式文件', 'error');
|
onlyMessage('请上传正确格式文件', 'error');
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
title: hasOperate('add', type)
|
title: hasOperate('add', type)
|
||||||
? '当前的存储方式不支持新增'
|
? '当前的存储方式不支持新增'
|
||||||
: '新增',
|
: '新增',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
}"
|
}"
|
||||||
@click="handleAddClick()"
|
@click="handleAddClick()"
|
||||||
placement="topRight"
|
placement="topRight"
|
||||||
|
@ -43,8 +44,10 @@
|
||||||
? '当前的存储方式不支持新增'
|
? '当前的存储方式不支持新增'
|
||||||
: !editStatus ? '暂无改动数据': '保存',
|
: !editStatus ? '暂无改动数据': '保存',
|
||||||
placement: hasOperate('add', type) ? 'topRight' : 'top',
|
placement: hasOperate('add', type) ? 'topRight' : 'top',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
}"
|
}"
|
||||||
@click="handleSaveClick()"
|
@click="handleSaveClick()"
|
||||||
|
placement="topRight"
|
||||||
>
|
>
|
||||||
保存
|
保存
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
|
@ -91,13 +94,14 @@
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
<OtherSetting
|
<OtherSetting
|
||||||
v-else
|
v-else
|
||||||
v-model:value="data.record.expands"
|
v-model:value="data.record.expands"
|
||||||
:id="data.record.id"
|
:id="data.record.id"
|
||||||
:type="data.record.valueType.type"
|
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex)"
|
||||||
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex)"
|
:record="data.record"
|
||||||
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex) ? {
|
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex) ? {
|
||||||
title: '继承自产品物模型的数据不支持删除',
|
title: '继承自产品物模型的数据不支持删除',
|
||||||
} : undefined"
|
} : undefined"
|
||||||
|
:type="data.record.valueType.type"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #action="{data}">
|
<template #action="{data}">
|
||||||
|
@ -111,6 +115,7 @@
|
||||||
@click="copyItem(data.record, data.index)"
|
@click="copyItem(data.record, data.index)"
|
||||||
:tooltip="{
|
:tooltip="{
|
||||||
title: operateLimits('add', type) ? '当前的存储方式不支持复制' : '复制',
|
title: operateLimits('add', type) ? '当前的存储方式不支持复制' : '复制',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<AIcon type="CopyOutlined" />
|
<AIcon type="CopyOutlined" />
|
||||||
|
@ -124,6 +129,7 @@
|
||||||
@click="handleAddClick(null, data.index)"
|
@click="handleAddClick(null, data.index)"
|
||||||
:tooltip="{
|
:tooltip="{
|
||||||
title: operateLimits('add', type) ? '当前的存储方式不支持新增' : '新增',
|
title: operateLimits('add', type) ? '当前的存储方式不支持新增' : '新增',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<AIcon type="PlusSquareOutlined" />
|
<AIcon type="PlusSquareOutlined" />
|
||||||
|
@ -136,6 +142,7 @@
|
||||||
@click="showDetail(data.record)"
|
@click="showDetail(data.record)"
|
||||||
:tooltip="{
|
:tooltip="{
|
||||||
title: '详情',
|
title: '详情',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<AIcon type="FileSearchOutlined" />
|
<AIcon type="FileSearchOutlined" />
|
||||||
|
@ -152,9 +159,11 @@
|
||||||
onConfirm: async () => {
|
onConfirm: async () => {
|
||||||
await removeItem(data.index);
|
await removeItem(data.index);
|
||||||
},
|
},
|
||||||
|
getPopupContainer: getPopupContainer
|
||||||
}"
|
}"
|
||||||
:tooltip="{
|
:tooltip="{
|
||||||
placement: 'topRight',
|
placement: 'topRight',
|
||||||
|
getPopupContainer: getPopupContainer,
|
||||||
title: target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex) ? '继承自产品物模型的数据不支持删除' :'删除',
|
title: target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex) ? '继承自产品物模型的数据不支持删除' :'删除',
|
||||||
}"
|
}"
|
||||||
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex)"
|
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record._sortIndex)"
|
||||||
|
@ -167,21 +176,25 @@
|
||||||
<PropertiesModal
|
<PropertiesModal
|
||||||
v-if="type === 'properties' && detailData.visible"
|
v-if="type === 'properties' && detailData.visible"
|
||||||
:data="detailData.data"
|
:data="detailData.data"
|
||||||
|
:getPopupContainer="getPopupContainer"
|
||||||
@cancel="cancelDetailModal"
|
@cancel="cancelDetailModal"
|
||||||
/>
|
/>
|
||||||
<FunctionModal
|
<FunctionModal
|
||||||
v-else-if="type === 'functions' && detailData.visible"
|
v-else-if="type === 'functions' && detailData.visible"
|
||||||
:data="detailData.data"
|
:data="detailData.data"
|
||||||
|
:getPopupContainer="getPopupContainer"
|
||||||
@cancel="cancelDetailModal"
|
@cancel="cancelDetailModal"
|
||||||
/>
|
/>
|
||||||
<EventModal
|
<EventModal
|
||||||
v-else-if="type === 'events' && detailData.visible"
|
v-else-if="type === 'events' && detailData.visible"
|
||||||
:data="detailData.data"
|
:data="detailData.data"
|
||||||
|
:getPopupContainer="getPopupContainer"
|
||||||
@cancel="cancelDetailModal"
|
@cancel="cancelDetailModal"
|
||||||
/>
|
/>
|
||||||
<TagsModal
|
<TagsModal
|
||||||
v-else-if="type === 'tags' && detailData.visible"
|
v-else-if="type === 'tags' && detailData.visible"
|
||||||
:data="detailData.data"
|
:data="detailData.data"
|
||||||
|
:getPopupContainer="getPopupContainer"
|
||||||
@cancel="cancelDetailModal"
|
@cancel="cancelDetailModal"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -210,10 +223,11 @@ import {omit} from "lodash-es";
|
||||||
import { PropertiesModal, FunctionModal, EventModal, TagsModal } from './DetailModal'
|
import { PropertiesModal, FunctionModal, EventModal, TagsModal } from './DetailModal'
|
||||||
import { Modal } from 'jetlinks-ui-components'
|
import { Modal } from 'jetlinks-ui-components'
|
||||||
import {EventEmitter} from "@/utils/utils";
|
import {EventEmitter} from "@/utils/utils";
|
||||||
import {watch} from "vue";
|
import {computed, watch} from "vue";
|
||||||
import {cloneDeep} from "lodash";
|
import {cloneDeep} from "lodash";
|
||||||
import {useSystem} from "store/system";
|
import {useSystem} from "store/system";
|
||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
|
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
target: {
|
target: {
|
||||||
|
@ -256,13 +270,23 @@ const detailData = reactive({
|
||||||
visible:false
|
visible:false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const showSave = ref(metadata.value.length !== 0)
|
const showSave = ref(metadata.value.length !== 0)
|
||||||
|
|
||||||
const showLastDelete = ref(false)
|
|
||||||
const dataSourceCache = ref<any[]>(metadata.value)
|
const dataSourceCache = ref<any[]>(metadata.value)
|
||||||
|
const fullRef = inject(FULL_CODE);
|
||||||
|
|
||||||
|
const getPopupContainer = (node: any) => {
|
||||||
|
const fullDom = tableRef.value?.fullRef?.()
|
||||||
|
return fullDom || node
|
||||||
|
}
|
||||||
|
|
||||||
|
const showLastDelete = computed(() => {
|
||||||
|
return dataSourceCache.value.length === 1
|
||||||
|
})
|
||||||
|
|
||||||
provide('_dataSource', dataSourceCache)
|
provide('_dataSource', dataSourceCache)
|
||||||
|
|
||||||
const showDetail = (data: any) => {
|
const showDetail = (data: any) => {
|
||||||
detailData.data = data
|
detailData.data = data
|
||||||
detailData.visible = true
|
detailData.visible = true
|
||||||
|
@ -345,15 +369,15 @@ const handleAddClick = async (_data?: any, index?: number) => {
|
||||||
const newObject = _data || getDataByType()
|
const newObject = _data || getDataByType()
|
||||||
|
|
||||||
const _addData = await tableRef.value.addItem(newObject, index)
|
const _addData = await tableRef.value.addItem(newObject, index)
|
||||||
if (_addData.length === 1) {
|
// if (_addData.length === 1) {
|
||||||
showLastDelete.value = true
|
// showLastDelete.value = true
|
||||||
}
|
// }
|
||||||
showSave.value = true
|
showSave.value = true
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyItem = (record: any, index: number) => {
|
const copyItem = (record: any, index: number) => {
|
||||||
const copyData = cloneDeep(omit(record, ['_uuid', '_sortIndex']))
|
const copyData = cloneDeep(omit(record, ['_uuid', '_sortIndex']))
|
||||||
copyData.id = `copy_${copyData.id}`.slice(0,64)
|
copyData.id = `copy_${copyData.id}`
|
||||||
handleAddClick(copyData, index)
|
handleAddClick(copyData, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,9 +386,9 @@ const removeItem = (index: number) => {
|
||||||
// data.splice(index, 1);
|
// data.splice(index, 1);
|
||||||
// dataSource.value = data
|
// dataSource.value = data
|
||||||
const _data = tableRef.value.removeItem(index)
|
const _data = tableRef.value.removeItem(index)
|
||||||
if (_data.length === 1) {
|
// if (_data.length === 1) {
|
||||||
showLastDelete.value = true
|
// showLastDelete.value = true
|
||||||
}
|
// }
|
||||||
if (_data.length === 0) {
|
if (_data.length === 0) {
|
||||||
showSave.value = false
|
showSave.value = false
|
||||||
|
|
||||||
|
@ -373,6 +397,7 @@ const removeItem = (index: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const editStatusChange = (status: boolean) => {
|
const editStatusChange = (status: boolean) => {
|
||||||
|
console.log('editStatusChange',status)
|
||||||
editStatus.value = status
|
editStatus.value = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,6 +457,7 @@ const handleSaveClick = async (next?: Function) => {
|
||||||
if(result.success) {
|
if(result.success) {
|
||||||
dataSource.value = resp
|
dataSource.value = resp
|
||||||
tableRef.value.cleanEditStatus()
|
tableRef.value.cleanEditStatus()
|
||||||
|
editStatus.value = false
|
||||||
onlyMessage('操作成功!')
|
onlyMessage('操作成功!')
|
||||||
next?.()
|
next?.()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
title="事件详情"
|
title="事件详情"
|
||||||
width="650px"
|
width="650px"
|
||||||
|
:getContainer="getPopupContainer"
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
>
|
>
|
||||||
|
@ -36,6 +37,10 @@ const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
|
},
|
||||||
|
getPopupContainer: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
title="功能详情"
|
title="功能详情"
|
||||||
width="650px"
|
width="650px"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:getContainer="getPopupContainer"
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
>
|
>
|
||||||
|
@ -40,6 +41,10 @@ const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
|
},
|
||||||
|
getPopupContainer: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
visible
|
visible
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
title="属性详情"
|
title="属性详情"
|
||||||
|
:getContainer="getPopupContainer"
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
>
|
>
|
||||||
|
@ -67,6 +68,10 @@ const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
|
},
|
||||||
|
getPopupContainer: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
visible
|
visible
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
title="标签详情"
|
title="标签详情"
|
||||||
|
:getContainer="getPopupContainer"
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
>
|
>
|
||||||
|
@ -47,6 +48,10 @@ const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
|
},
|
||||||
|
getPopupContainer: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -439,7 +439,7 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
|
||||||
const virtualRule = values.expands?.virtualRule
|
const virtualRule = values.expands?.virtualRule
|
||||||
const source = value.source
|
const source = value.source
|
||||||
const ids = (noEdit?.value?.id || []) as any[]
|
const ids = (noEdit?.value?.id || []) as any[]
|
||||||
|
console.log(source, value)
|
||||||
if (source) {
|
if (source) {
|
||||||
if (source === 'device' && !value.type?.length) {
|
if (source === 'device' && !value.type?.length) {
|
||||||
return Promise.reject('请选择读写类型');
|
return Promise.reject('请选择读写类型');
|
||||||
|
@ -542,13 +542,11 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请选择读写类型' },
|
|
||||||
{
|
{
|
||||||
callback(rule:any,value: any, dataSource: any[]) {
|
callback(rule:any,value: any, dataSource: any[]) {
|
||||||
const field = rule.field.split('.')
|
const field = rule.field.split('.')
|
||||||
const fieldIndex = Number(field[1])
|
const fieldIndex = Number(field[1])
|
||||||
const values = dataSource.find((item, index) => index === fieldIndex)
|
const values = dataSource.find((item, index) => index === fieldIndex)
|
||||||
|
|
||||||
if (!values?.expands?.type?.length) {
|
if (!values?.expands?.type?.length) {
|
||||||
return Promise.reject('请选择读写类型')
|
return Promise.reject('请选择读写类型')
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,7 @@ const columns = [
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
width: 100,
|
width: 100,
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [
|
rules: [
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<j-select-boolean
|
<j-select
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
tureTitle="必填"
|
|
||||||
falseTitle='不必填'
|
|
||||||
style="width: 100%;"
|
style="width: 100%;"
|
||||||
|
:options="[
|
||||||
|
{ label: '不必填', value: 'false'},
|
||||||
|
{ label: '必填', value: 'true'},
|
||||||
|
]"
|
||||||
@change="change"
|
@change="change"
|
||||||
>
|
>
|
||||||
|
|
||||||
</j-select-boolean>
|
</j-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="ConstraintSelect">
|
<script setup name="ConstraintSelect">
|
||||||
|
@ -32,14 +34,14 @@ const myValue = ref()
|
||||||
|
|
||||||
const change = (e) => {
|
const change = (e) => {
|
||||||
const newData = { ...props.value }
|
const newData = { ...props.value }
|
||||||
set(newData, props.name, myValue.value)
|
set(newData, props.name, myValue.value === 'true')
|
||||||
console.log(newData, e);
|
console.log(newData, e);
|
||||||
emit('update:value', newData)
|
emit('update:value', newData)
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => JSON.stringify(props.data), () => {
|
watch(() => JSON.stringify(props.data), () => {
|
||||||
console.log(props.value, props.name);
|
console.log(props.value, props.name);
|
||||||
myValue.value = get(props.value, props.name) || false
|
myValue.value = get(props.value, props.name) === true ? 'true' : 'false'
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -86,6 +86,7 @@ const columns = [{
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
width: 100,
|
width: 100,
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [{
|
rules: [{
|
||||||
|
@ -191,6 +192,7 @@ watch(
|
||||||
() => {
|
() => {
|
||||||
type.value = props.value?.valueType?.type;
|
type.value = props.value?.valueType?.type;
|
||||||
_valueType.value = props.value?.valueType
|
_valueType.value = props.value?.valueType
|
||||||
|
console.log(props.value)
|
||||||
// elements.value = props.value?.valueType.elements;
|
// elements.value = props.value?.valueType.elements;
|
||||||
// if (['float', 'double', 'int', 'long'].includes(type.value)) {
|
// if (['float', 'double', 'int', 'long'].includes(type.value)) {
|
||||||
// const res = getUnit().then((res) => {
|
// const res = getUnit().then((res) => {
|
||||||
|
|
|
@ -27,6 +27,7 @@ const columns = [
|
||||||
title: '参数标识',
|
title: '参数标识',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [{
|
rules: [{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<span>{{ TypeStringMap[data.record.valueType?.type] }}</span>
|
<span>{{ TypeStringMap[data.record.valueType?.type] }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #required="{ data }">
|
<template #required="{ data }">
|
||||||
<span>{{ data.record.expands?.required ? "是": '否' }}</span>
|
<span>{{ data.record.expands?.required ? "必填": '不必填' }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #config="{ data }">
|
<template #config="{ data }">
|
||||||
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
<ConfigModal v-model:value="data.record.valueType" :showOther="false" />
|
||||||
|
@ -64,6 +64,7 @@ const columns = ref([
|
||||||
title: '参数标识',
|
title: '参数标识',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [
|
rules: [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="metadata-type">
|
<div class="metadata-type">
|
||||||
<div class="metadata-type-select">
|
<div class="metadata-type-select">
|
||||||
<DataTableTypeSelect v-model:value="type" @change="typeChange" />
|
<DataTableTypeSelect v-model:value="type" :allowClear="true" @change="typeChange" />
|
||||||
</div>
|
</div>
|
||||||
<DataTableArray
|
<DataTableArray
|
||||||
v-if="type === 'array'"
|
v-if="type === 'array'"
|
||||||
|
@ -101,6 +101,7 @@ const columns = [
|
||||||
title: '参数标识',
|
title: '参数标识',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [{
|
rules: [{
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
{{ data.record.range === true ? '范围值' : '固定值'}}
|
{{ data.record.range === true ? '范围值' : '固定值'}}
|
||||||
</template>
|
</template>
|
||||||
<template #value="{data}">
|
<template #value="{data}">
|
||||||
{{ data.record.range === true ? data.record.value?.join('-') : data.record.value }}
|
<j-ellipsis>
|
||||||
|
{{ data.record.range === true ? data.record.value?.join('-') : showText(data.record.value) }}
|
||||||
|
</j-ellipsis>
|
||||||
</template>
|
</template>
|
||||||
<template #action="{data}">
|
<template #action="{data}">
|
||||||
<j-button
|
<j-button
|
||||||
|
@ -43,6 +45,10 @@ const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: undefined
|
default: undefined
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,12 +59,31 @@ const tableRef = ref()
|
||||||
|
|
||||||
provide('metricsType', props.type)
|
provide('metricsType', props.type)
|
||||||
|
|
||||||
|
const showText = (value: any) => {
|
||||||
|
switch (props.type) {
|
||||||
|
case 'date':
|
||||||
|
return value;
|
||||||
|
case 'boolean':
|
||||||
|
const item = props.options.find(item => item.value === value)
|
||||||
|
if (item) {
|
||||||
|
return item.label
|
||||||
|
}else if (value) {
|
||||||
|
return value === 'true' ? '是' : '否'
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const columns: any = [
|
const columns: any = [
|
||||||
{
|
{
|
||||||
title: '指标标识',
|
title: '指标标识',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
width: 120,
|
width: 120,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
placement: 'Left',
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
rules: [{
|
rules: [{
|
||||||
|
@ -109,7 +134,10 @@ const columns: any = [
|
||||||
width: 100,
|
width: 100,
|
||||||
type: 'components',
|
type: 'components',
|
||||||
components: {
|
components: {
|
||||||
name: MetricValueItem
|
name: MetricValueItem,
|
||||||
|
props: {
|
||||||
|
options: props.options
|
||||||
|
}
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="metrics-item-value">
|
<div class="metrics-item-value">
|
||||||
<div class="metrics-item-text">
|
<div class="metrics-item-text">
|
||||||
{{ showText }}
|
<j-ellipsis>
|
||||||
|
{{ showText }}
|
||||||
|
</j-ellipsis>
|
||||||
</div>
|
</div>
|
||||||
<j-popconfirm-modal
|
<j-popconfirm-modal
|
||||||
:show-cancel="false"
|
:show-cancel="false"
|
||||||
|
@ -11,8 +13,8 @@
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<j-form ref="formRef" :model="formData">
|
<j-form ref="formRef" :model="formData">
|
||||||
<j-form-item v-if="value.range === false" :rules="[{ required: true, message: '请输入指标值'}]" name="value">
|
<j-form-item v-if="value.range === false" :rules="[{ validator: typeValidator}]" name="value">
|
||||||
<Item v-model:value="formData.value" />
|
<Item v-model:value="formData.value" :options="options" />
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<div v-else class="data-table-boolean-item">
|
<div v-else class="data-table-boolean-item">
|
||||||
<div class="data-table-boolean-item--value">
|
<div class="data-table-boolean-item--value">
|
||||||
|
@ -41,6 +43,7 @@ import Item from './item.vue'
|
||||||
import {Form} from "jetlinks-ui-components";
|
import {Form} from "jetlinks-ui-components";
|
||||||
import {cloneDeep} from "lodash";
|
import {cloneDeep} from "lodash";
|
||||||
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
type ValueType = number | Array<number | undefined> | undefined;
|
type ValueType = number | Array<number | undefined> | undefined;
|
||||||
|
|
||||||
|
@ -53,12 +56,16 @@ const props = defineProps({
|
||||||
type: Object as PropType<any>,
|
type: Object as PropType<any>,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
},
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<Emit>();
|
const emit = defineEmits<Emit>();
|
||||||
const formItemContext = Form.useInjectFormItemContext();
|
const formItemContext = Form.useInjectFormItemContext();
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
const type = inject<string>('metricsType')
|
||||||
|
|
||||||
const formData = reactive<{
|
const formData = reactive<{
|
||||||
value: ValueType;
|
value: ValueType;
|
||||||
|
@ -72,26 +79,81 @@ const formData = reactive<{
|
||||||
|
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
|
|
||||||
|
|
||||||
const showText = computed(() => {
|
const showText = computed(() => {
|
||||||
if (props.value.range === false) {
|
if (props.value.range === false) {
|
||||||
return props.value?.value || ''
|
switch (type) {
|
||||||
|
case 'date':
|
||||||
|
return props.value?.value;
|
||||||
|
case 'boolean':
|
||||||
|
const _value = props.value?.value
|
||||||
|
const item = props.options.find(item => item.value === props.value?.value)
|
||||||
|
if (item) {
|
||||||
|
return item.label
|
||||||
|
}else if (_value) {
|
||||||
|
return _value === 'true' ? '是' : '否'
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return props.value?.value
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return props.value?.value?.[0] ? props.value.value.join('-') : ''
|
return props.value?.value?.[0] ? props.value.value.join('-') : ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const validatorTip = () =>{
|
||||||
|
let tip = '请输入'
|
||||||
|
if (['boolean', 'date'].includes(type!)) {
|
||||||
|
tip = '请选择'
|
||||||
|
}
|
||||||
|
return `${tip}指标值`
|
||||||
|
}
|
||||||
|
|
||||||
const validator = (_: any, value: any) => {
|
const validator = (_: any, value: any) => {
|
||||||
|
|
||||||
if (props.value.range && formData.rangeValue![0] >= formData.rangeValue![1]) {
|
if (props.value.range && formData.rangeValue![0] >= formData.rangeValue![1]) {
|
||||||
return Promise.reject('需大于左侧数值')
|
return Promise.reject('需大于左侧数值')
|
||||||
}
|
}
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const typeValidator = (_: any, value: any) => {
|
||||||
|
if (value === undefined) {
|
||||||
|
return Promise.reject(validatorTip())
|
||||||
|
}
|
||||||
|
if (type === 'string' && value?.length > 64) {
|
||||||
|
return Promise.reject('最多可输入64个字符')
|
||||||
|
}
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleValueByType = (value: any, isRange: boolean = false) => {
|
||||||
|
if (isRange) {
|
||||||
|
return (value as number[]).map(item => {
|
||||||
|
const itemStr = String(item)
|
||||||
|
const index = String(item).indexOf('.')
|
||||||
|
|
||||||
|
return index === -1 ? item : Number(itemStr.substring(0, index))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const itemStr = String(value)
|
||||||
|
const index = String(value).indexOf('.')
|
||||||
|
return index === -1 ? value : Number(itemStr.substring(0, index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
formRef.value.validate().then(() => {
|
formRef.value.validate().then(() => {
|
||||||
const value = props.value.range === true ? formData.rangeValue : formData.value
|
let value = props.value.range === true ? formData.rangeValue : formData.value
|
||||||
console.log('confirm',value, props.value)
|
|
||||||
|
if (['int', 'long'].includes(type)) {
|
||||||
|
value = handleValueByType(value, props.value.range)
|
||||||
|
console.log('confirm',value, type)
|
||||||
|
}
|
||||||
|
|
||||||
emit('update:value', {
|
emit('update:value', {
|
||||||
...props.value,
|
...props.value,
|
||||||
value: value
|
value: value
|
||||||
|
@ -121,6 +183,7 @@ watch(() => props.value.range,(value, oldValue) => {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.metrics-item-text {
|
.metrics-item-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
<j-input
|
<j-input
|
||||||
v-if="type === 'string'"
|
v-if="type === 'string'"
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
:maxLength="64"
|
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@change="change"
|
@change="change"
|
||||||
/>
|
/>
|
||||||
|
@ -11,7 +10,7 @@
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
:max="2147483647"
|
:max="2147483647"
|
||||||
:min="-2147483647"
|
:min="-2147483648"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@change="change"
|
@change="change"
|
||||||
|
@ -19,8 +18,8 @@
|
||||||
<j-input-number
|
<j-input-number
|
||||||
v-else-if="type === 'long'"
|
v-else-if="type === 'long'"
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
:max="9223372036854775807"
|
:max="999999999999999"
|
||||||
:min="-9223372036854775808"
|
:min="-999999999999999"
|
||||||
:precision="0"
|
:precision="0"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@ -29,8 +28,8 @@
|
||||||
<j-input-number
|
<j-input-number
|
||||||
v-else-if="['float', 'double'].includes(type)"
|
v-else-if="['float', 'double'].includes(type)"
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
:max="9999999999999999"
|
:max="999999999999999"
|
||||||
:min="-9999999999999999"
|
:min="-999999999999999"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
@change="change"
|
@change="change"
|
||||||
|
@ -38,18 +37,21 @@
|
||||||
<j-select
|
<j-select
|
||||||
v-else-if="type === 'boolean'"
|
v-else-if="type === 'boolean'"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
:options="[
|
v-model:value="myValue"
|
||||||
{ label: '否', value: 'false'},
|
style="width: 100%"
|
||||||
{ label: '是', value: 'true'},
|
:options="options"
|
||||||
]"
|
|
||||||
:get-popup-container="(node) => fullRef || node"
|
:get-popup-container="(node) => fullRef || node"
|
||||||
|
@change="change"
|
||||||
/>
|
/>
|
||||||
<j-date-picker
|
<j-date-picker
|
||||||
v-else-if="type === 'date' "
|
v-else-if="type === 'date' "
|
||||||
v-model:value="myValue"
|
v-model:value="myValue"
|
||||||
show-time
|
show-time
|
||||||
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
:get-popup-container="(node) => fullRef || node"
|
:get-popup-container="(node) => fullRef || node"
|
||||||
|
valueFormat="YYYY-MM-DD HH:mm:ss"
|
||||||
@change="change"
|
@change="change"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -61,6 +63,10 @@ const props = defineProps({
|
||||||
value: {
|
value: {
|
||||||
type: [String, Number, Array],
|
type: [String, Number, Array],
|
||||||
default: undefined
|
default: undefined
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -72,8 +78,8 @@ const myValue = ref(props.value)
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
|
||||||
const change = () => {
|
const change = () => {
|
||||||
// formItemContext.onFieldChange()
|
|
||||||
emit('update:value', myValue.value)
|
emit('update:value', myValue.value)
|
||||||
|
formItemContext.onFieldChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.value, () => {
|
watch(() => props.value, () => {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@visibleChange="visibleChange"
|
@visibleChange="visibleChange"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template v-if="visible" #content>
|
||||||
<j-scrollbar height="350" v-if="showMetrics || config.length > 0">
|
<j-scrollbar height="350" v-if="showMetrics || config.length > 0">
|
||||||
<j-collapse v-model:activeKey="activeKey">
|
<j-collapse v-model:activeKey="activeKey">
|
||||||
<j-collapse-panel v-for="(item, index) in config" :key="'store_'+index" :header="item.name">
|
<j-collapse-panel v-for="(item, index) in config" :key="'store_'+index" :header="item.name">
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
<AIcon type="ExclamationCircleOutlined" style="padding-left: 12px;padding-top: 4px;" />
|
<AIcon type="ExclamationCircleOutlined" style="padding-left: 12px;padding-top: 4px;" />
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<Metrics ref="metricsRef" :value="myValue.metrics" :type="props.type"/>
|
<Metrics ref="metricsRef" :options="booleanOptions" :type="props.type" :value="myValue.metrics"/>
|
||||||
</j-collapse-panel>
|
</j-collapse-panel>
|
||||||
</j-collapse>
|
</j-collapse>
|
||||||
|
|
||||||
|
@ -84,6 +84,10 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: undefined
|
default: undefined
|
||||||
},
|
},
|
||||||
|
record: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const fullRef = inject(FULL_CODE);
|
const fullRef = inject(FULL_CODE);
|
||||||
|
@ -109,6 +113,11 @@ const showMetrics = computed(() => {
|
||||||
return ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(props.type as any)
|
return ['int', 'long', 'float', 'double', 'string', 'boolean', 'date'].includes(props.type as any)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const booleanOptions = ref([
|
||||||
|
{ label: '否', value: 'false'},
|
||||||
|
{ label: '是', value: 'true'},
|
||||||
|
])
|
||||||
|
|
||||||
const columns = ref([
|
const columns = ref([
|
||||||
{
|
{
|
||||||
title: '参数名称',
|
title: '参数名称',
|
||||||
|
@ -129,9 +138,16 @@ const columns = ref([
|
||||||
|
|
||||||
const getConfig = async () => {
|
const getConfig = async () => {
|
||||||
const id = type === 'product' ? productStore.current?.id : deviceStore.current.id
|
const id = type === 'product' ? productStore.current?.id : deviceStore.current.id
|
||||||
console.log(props.id, id, props.type)
|
console.log(props.id, id, props)
|
||||||
|
|
||||||
if(!props.id || !id || !props.type) return
|
if(!props.id || !id || !props.type) return
|
||||||
|
|
||||||
|
if (props.type === 'boolean') {
|
||||||
|
const booleanValue = props.record.valueType
|
||||||
|
booleanOptions.value[0] = { label: booleanValue.falseText || '否', value: booleanValue.falseValue || 'false'}
|
||||||
|
booleanOptions.value[1] = { label: booleanValue.trueText || '是', value: booleanValue.trueValue || 'true'}
|
||||||
|
}
|
||||||
|
|
||||||
const params: any = {
|
const params: any = {
|
||||||
deviceId: id,
|
deviceId: id,
|
||||||
metadata: {
|
metadata: {
|
||||||
|
@ -189,6 +205,7 @@ const confirm = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const visibleChange = (e: boolean) => {
|
const visibleChange = (e: boolean) => {
|
||||||
|
visible.value = e
|
||||||
if (e) {
|
if (e) {
|
||||||
configValue.value = omit(props.value, ['source', 'type', 'metrics', 'required'])
|
configValue.value = omit(props.value, ['source', 'type', 'metrics', 'required'])
|
||||||
getConfig()
|
getConfig()
|
||||||
|
@ -200,6 +217,7 @@ const cancel = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.value, () => {
|
watch(() => props.value, () => {
|
||||||
|
console.log(props.value)
|
||||||
myValue.value = cloneDeep(props.value)
|
myValue.value = cloneDeep(props.value)
|
||||||
}, {immediate: true, deep: true})
|
}, {immediate: true, deep: true})
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,6 @@ const cancel = () => {
|
||||||
myValue.value = props.value?.expands?.source || '';
|
myValue.value = props.value?.expands?.source || '';
|
||||||
}
|
}
|
||||||
type.value = props.value?.expands?.type || [];
|
type.value = props.value?.expands?.type || [];
|
||||||
console.log('取消', myValue.value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
:options="typeOptions"
|
:options="typeOptions"
|
||||||
/>
|
/>
|
||||||
<template v-if="source === 'rule'">
|
<template v-if="source === 'rule'">
|
||||||
<j-form-item :name="['virtualRule', 'triggerProperties']" required>
|
<j-form-item :name="['virtualRule', 'triggerProperties']" :rules="[{
|
||||||
|
required: true,
|
||||||
|
message: '请选择触发属性'
|
||||||
|
}]">
|
||||||
<template #label>
|
<template #label>
|
||||||
触发属性
|
触发属性
|
||||||
<j-tooltip>
|
<j-tooltip>
|
||||||
|
@ -23,7 +26,7 @@
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="formData.virtualRule.triggerProperties"
|
v-model:value="formData.virtualRule.triggerProperties"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
placeholder="请选择属性"
|
placeholder="请选择触发属性"
|
||||||
show-search
|
show-search
|
||||||
max-tag-count="responsive"
|
max-tag-count="responsive"
|
||||||
>
|
>
|
||||||
|
@ -65,7 +68,10 @@
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="窗口"
|
label="窗口"
|
||||||
:name="['virtualRule', 'windowType']"
|
:name="['virtualRule', 'windowType']"
|
||||||
required
|
:rules="[{
|
||||||
|
required: true,
|
||||||
|
message: '请选择窗口类型'
|
||||||
|
}]"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="formData.virtualRule.windowType"
|
v-model:value="formData.virtualRule.windowType"
|
||||||
|
@ -85,7 +91,10 @@
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="聚合函数"
|
label="聚合函数"
|
||||||
:name="['virtualRule', 'aggType']"
|
:name="['virtualRule', 'aggType']"
|
||||||
required
|
:rules="[{
|
||||||
|
required: true,
|
||||||
|
message: '请选择聚合函数'
|
||||||
|
}]"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value="formData.virtualRule.aggType"
|
v-model:value="formData.virtualRule.aggType"
|
||||||
|
@ -108,7 +117,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /^\d+$/,
|
pattern: /^\d+$/,
|
||||||
message: '请输入0-999999之间的正整数',
|
message: '请输入1-999999之间的正整数',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
@ -135,7 +144,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /^\d+$/,
|
pattern: /^\d+$/,
|
||||||
message: '请输入0-999999之间的正整数',
|
message: '请输入1-999999之间的正整数',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
@ -250,11 +259,10 @@ const options = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const setInitVirtualRule = () => {
|
const setInitVirtualRule = () => {
|
||||||
console.log(props.value?.expands?.virtualRule);
|
|
||||||
formData.virtualRule = {
|
formData.virtualRule = {
|
||||||
...initData,
|
...initData,
|
||||||
...(props.value?.expands?.virtualRule || {}),
|
...(props.value?.expands?.virtualRule || {}),
|
||||||
triggerProperties: props.value?.expands?.virtualRule?.triggerProperties || ['*'],
|
triggerProperties: props.value?.expands?.virtualRule?.triggerProperties?.length ? props.value?.expands?.virtualRule?.triggerProperties : ['*']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,8 +282,9 @@ const handleSearch = async () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (resp && resp.status === 200 && resp.result) {
|
if (resp && resp.status === 200 && resp.result) {
|
||||||
|
const _triggerProperties = props.value?.expands?.virtualRule?.triggerProperties?.length ? props.value?.expands?.virtualRule?.triggerProperties : resp.result.triggerProperties
|
||||||
formData.virtualRule = {
|
formData.virtualRule = {
|
||||||
triggerProperties: resp.result.triggerProperties,
|
triggerProperties: _triggerProperties?.length ? _triggerProperties : ['*'],
|
||||||
...resp.result.rule,
|
...resp.result.rule,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -318,6 +327,7 @@ watch(
|
||||||
formData.virtualRule = initData;
|
formData.virtualRule = initData;
|
||||||
|
|
||||||
handleSearch();
|
handleSearch();
|
||||||
|
setInitVirtualRule()
|
||||||
} else {
|
} else {
|
||||||
formData.virtualRule = undefined;
|
formData.virtualRule = undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ import { useProductStore } from '@/store/product';
|
||||||
import { FILE_UPLOAD } from '@/api/comm';
|
import { FILE_UPLOAD } from '@/api/comm';
|
||||||
import { getToken, onlyMessage } from '@/utils/comm';
|
import { getToken, onlyMessage } from '@/utils/comm';
|
||||||
import { useMetadataStore } from '@/store/metadata';
|
import { useMetadataStore } from '@/store/metadata';
|
||||||
import { omit, uniqBy } from 'lodash-es';
|
import { omit } from 'lodash-es';
|
||||||
import { Modal } from 'jetlinks-ui-components';
|
import { Modal } from 'jetlinks-ui-components';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -258,11 +258,20 @@ const loadData = async () => {
|
||||||
loadData();
|
loadData();
|
||||||
|
|
||||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||||
const reader = new FileReader();
|
if(file.type === 'application/json') {
|
||||||
reader.readAsText(file);
|
const reader = new FileReader();
|
||||||
reader.onload = (json) => {
|
reader.readAsText(file);
|
||||||
formModel.import = json.target?.result;
|
reader.onload = (json) => {
|
||||||
};
|
if(json.target?.result){
|
||||||
|
onlyMessage('操作成功!')
|
||||||
|
formModel.import = json.target?.result;
|
||||||
|
} else {
|
||||||
|
onlyMessage('文件内容不能为空', 'error')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
onlyMessage('请上传json格式的文件', 'error')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const fileChange = (info: UploadChangeParam) => {
|
const fileChange = (info: UploadChangeParam) => {
|
||||||
if (info.file.status === 'done') {
|
if (info.file.status === 'done') {
|
||||||
|
@ -273,10 +282,18 @@ const fileChange = (info: UploadChangeParam) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uniqArray = (arr: any[]) => {
|
||||||
|
const _map = new Map();
|
||||||
|
for(let item of arr) {
|
||||||
|
_map.set(item.id, item)
|
||||||
|
}
|
||||||
|
return [..._map.values()]
|
||||||
|
}
|
||||||
|
|
||||||
const operateLimits = (mdata: DeviceMetadata) => {
|
const operateLimits = (mdata: DeviceMetadata) => {
|
||||||
hasVirtualRule.value = false;
|
hasVirtualRule.value = false;
|
||||||
const obj: DeviceMetadata = { ...mdata };
|
const obj: DeviceMetadata = { ...mdata };
|
||||||
const old = JSON.parse(instanceStore.detail?.metadata || '{}');
|
const old = JSON.parse((props.type === 'device' ? instanceStore.detail?.metadata : productStore.detail?.metadata) || '{}');
|
||||||
const fid = instanceStore.detail?.features?.map((item) => item.id);
|
const fid = instanceStore.detail?.features?.map((item) => item.id);
|
||||||
const _data: DeviceMetadata = {
|
const _data: DeviceMetadata = {
|
||||||
properties: [],
|
properties: [],
|
||||||
|
@ -284,10 +301,10 @@ const operateLimits = (mdata: DeviceMetadata) => {
|
||||||
functions: [],
|
functions: [],
|
||||||
tags: []
|
tags: []
|
||||||
}
|
}
|
||||||
_data.properties = uniqBy([...(obj?.properties || []), ...(old?.properties || [])], 'id')
|
_data.properties = uniqArray([...(old?.properties || []), ...uniqArray(obj?.properties || [])])
|
||||||
_data.events = uniqBy([...(obj?.events || []), ...(old?.events || [])], 'id')
|
_data.events = uniqArray([...(old?.events || []), ...uniqArray(obj?.events || [])])
|
||||||
_data.functions = uniqBy([...(obj?.functions || []), ...(old?.functions || [])], 'id')
|
_data.functions = uniqArray([...(old?.functions || []), ...uniqArray(obj?.functions || [])])
|
||||||
_data.tags = uniqBy([...(obj?.tags || []), ...(old?.tags || [])], 'id')
|
_data.tags = uniqArray([...(old?.tags || []), ...uniqArray(obj?.tags || [])])
|
||||||
|
|
||||||
if (fid?.includes('eventNotModifiable')) {
|
if (fid?.includes('eventNotModifiable')) {
|
||||||
_data.events = old?.events || [];
|
_data.events = old?.events || [];
|
||||||
|
|
|
@ -3,26 +3,7 @@
|
||||||
<div class="title">请选择首页视图</div>
|
<div class="title">请选择首页视图</div>
|
||||||
|
|
||||||
<div class="choose-view">
|
<div class="choose-view">
|
||||||
<div class="view-content">
|
<HomeView v-model:value="selectValue"/>
|
||||||
<div
|
|
||||||
:span="8"
|
|
||||||
class="select-item"
|
|
||||||
v-for="item in list"
|
|
||||||
:key="item.id"
|
|
||||||
@click="selectValue = item.id"
|
|
||||||
:class="{
|
|
||||||
active: selectValue === item.id,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div class="select-item-box">
|
|
||||||
<div class="select-title">{{ item.name }}</div>
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
:src="getImage(`/home/home-view/${item.id}.png`)"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<j-button type="primary" @click="confirm">保存修改</j-button>
|
<j-button type="primary" @click="confirm">保存修改</j-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,23 +13,8 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { setView_api } from '@/api/home';
|
import { setView_api } from '@/api/home';
|
||||||
import { getImage } from '@/utils/comm';
|
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
|
import HomeView from '@/components/HomeView/index.vue';
|
||||||
const list = [
|
|
||||||
{
|
|
||||||
id: 'device',
|
|
||||||
name: '设备接入视图',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ops',
|
|
||||||
name: '运营管理视图',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'comprehensive',
|
|
||||||
name: '综合管理视图',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const user = useUserInfo();
|
const user = useUserInfo();
|
||||||
const emits = defineEmits(['refresh']);
|
const emits = defineEmits(['refresh']);
|
||||||
|
@ -95,45 +61,6 @@ watch(
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 9%;
|
padding: 0 9%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
.view-content {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
.select-item {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 30%;
|
|
||||||
border-radius: 14px;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #333333;
|
|
||||||
|
|
||||||
.select-item-box {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
.select-title {
|
|
||||||
position: absolute;
|
|
||||||
top: 36px;
|
|
||||||
left: 36px;
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border: 1px solid @primary-color-active;
|
|
||||||
color: @primary-color-active;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0px 3px 6px -4px rgba(0, 0, 0, 0.12),
|
|
||||||
0px 6px 16px 0px rgba(0, 0, 0, 0.08),
|
|
||||||
0px 9px 16px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -16,6 +16,8 @@ import BaseMenu, { USER_CENTER_MENU_DATA } from '../data/baseMenu'
|
||||||
import { getSystemPermission, updateMenus } from '@/api/initHome';
|
import { getSystemPermission, updateMenus } from '@/api/initHome';
|
||||||
import { protocolList } from '@/utils/consts';
|
import { protocolList } from '@/utils/consts';
|
||||||
import { getProviders } from '@/api/data-collect/channel';
|
import { getProviders } from '@/api/data-collect/channel';
|
||||||
|
import { isNoCommunity } from '@/utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取菜单数据
|
* 获取菜单数据
|
||||||
*/
|
*/
|
||||||
|
@ -28,9 +30,13 @@ const menuDatas = reactive({
|
||||||
* 查询支持的协议
|
* 查询支持的协议
|
||||||
*/
|
*/
|
||||||
const getProvidersFn = async () => {
|
const getProvidersFn = async () => {
|
||||||
const res: any = await getProviders();
|
if (!isNoCommunity) {
|
||||||
const ids = res.result?.map?.(item => item.id) || []
|
return undefined
|
||||||
return protocolList.some(item => ids.includes(item.value))
|
} else {
|
||||||
|
const res: any = await getProviders();
|
||||||
|
const ids = res.result?.map?.(item => item.id) || []
|
||||||
|
return protocolList.some(item => ids.includes(item.value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input
|
<j-input
|
||||||
disabled
|
|
||||||
v-model:value="
|
v-model:value="
|
||||||
formState.apiAddress
|
formState.apiAddress
|
||||||
"
|
"
|
||||||
|
@ -113,48 +112,78 @@
|
||||||
<div class="doc">
|
<div class="doc">
|
||||||
<h1>操作指引:</h1>
|
<h1>操作指引:</h1>
|
||||||
<div>
|
<div>
|
||||||
1、CTWing端创建产品、设备,以及一个第三方应用
|
1、CTWing端创建应用、产品、设备;配置完成后查看产品详情。其中产品ID以及Master-APIkey在JetLinks平台配置时会使用。
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img1" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
2、CTWing端配置产品/设备/分组级订阅,订阅方URL地址请填写:
|
2、IOT端创建类型为CTWing的设备接入网关
|
||||||
<div
|
<!-- <div
|
||||||
class="url"
|
class="url"
|
||||||
style="word-wrap: break-word"
|
style="word-wrap: break-word"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
`${origin}/api/ctwing/${randomString()}/notify`
|
`${origin}/api/ctwing/${randomString()}/notify`
|
||||||
}}
|
}}
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
|
||||||
<div class="image">
|
|
||||||
<j-image width="100%" :src="img1" />
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
3、IOT端创建类型为CTWing的设备接入网关
|
3、IOT端创建产品,选中接入方式为CTWing,填写CTWing平台中的产品ID、Master-APIkey。
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
4、IOT端创建产品,选中接入方式为CTWing,填写CTWing平台中的产品ID、Master-APIkey。
|
|
||||||
</div>
|
</div>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<j-image width="100%" :src="img2" />
|
<j-image width="100%" :src="img2" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
5、IOT端添加设备,为每一台设备设置唯一的IMEI(需与CTWing平台中填写的值一致)
|
4、IOT端添加设备,设备ID需要配置真实设备的IMEI号,配置完成后启用设备(如果启用设备提示错误,请检查CTWing网关参数是否配置正确)。
|
||||||
</div>
|
</div>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<j-image width="100%" :src="img3" />
|
<j-image width="100%" :src="img3" />
|
||||||
</div>
|
</div>
|
||||||
<h1>设备接入网关配置说明</h1>
|
|
||||||
<div>
|
|
||||||
1.请将CTWing的AEP平台-应用管理中的App
|
|
||||||
Key和App Secret复制到当前页面
|
|
||||||
</div>
|
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<j-image width="100%" :src="img4" />
|
<j-image width="100%" :src="img4" />
|
||||||
</div>
|
</div>
|
||||||
<h1>其他说明</h1>
|
<j-descriptions
|
||||||
|
bordered
|
||||||
|
size="small"
|
||||||
|
:column="1"
|
||||||
|
:labelStyle="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="参数"
|
||||||
|
>说明</j-descriptions-item
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="IMEI"
|
||||||
|
>真实设备的IMEI号,需要填写正确,否则推送数据会接收失败</j-descriptions-item
|
||||||
|
>
|
||||||
|
<j-descriptions-item label="SN">
|
||||||
|
真实设备的SN号
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="IMSI">
|
||||||
|
真实设备的IMSI号
|
||||||
|
</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="PSK">
|
||||||
|
真实设备的PSK,非必填
|
||||||
|
</j-descriptions-item>
|
||||||
|
</j-descriptions>
|
||||||
<div>
|
<div>
|
||||||
1.在IOT端启用设备时,若CTWing平台没有与之对应的设备,则将在CTWing端自动创建新设备
|
5、CTWing端配置产品/设备/分组级订阅,订阅方URL地址请填写: {{
|
||||||
|
`${origin}/api/ctwing/${randomString()}/notify`
|
||||||
|
}}(此处订阅地址可以在JetLinks平台中配置完成CTWing网关后再填写)。
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img5" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
6、以上步骤配置完成后,可以触发真实设备进行上数,在平台对应设备详情页查看设备状态。
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img6" />
|
||||||
|
</div>
|
||||||
|
<h1>
|
||||||
|
其他说明
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
在IOT端启用设备时,若CTWing平台没有与之对应的设备,则将在CTWing端自动创建新设备
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</j-scrollbar>
|
</j-scrollbar>
|
||||||
|
@ -330,6 +359,8 @@ const img1 = getImage('/network/01.png');
|
||||||
const img2 = getImage('/network/02.jpg');
|
const img2 = getImage('/network/02.jpg');
|
||||||
const img3 = getImage('/network/03.png');
|
const img3 = getImage('/network/03.png');
|
||||||
const img4 = getImage('/network/04.jpg');
|
const img4 = getImage('/network/04.jpg');
|
||||||
|
const img5 = getImage('/network/05-Ctwing.png')
|
||||||
|
const img6 = getImage('/network/06-Ctwing.png')
|
||||||
|
|
||||||
interface FormState {
|
interface FormState {
|
||||||
apiAddress: string;
|
apiAddress: string;
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<j-input
|
<j-input
|
||||||
disabled
|
|
||||||
v-model:value="
|
v-model:value="
|
||||||
formState.apiAddress
|
formState.apiAddress
|
||||||
"
|
"
|
||||||
|
@ -163,29 +162,42 @@
|
||||||
<div class="doc">
|
<div class="doc">
|
||||||
<h1>操作指引:</h1>
|
<h1>操作指引:</h1>
|
||||||
<div>
|
<div>
|
||||||
1、OneNet端创建产品、设备,并配置HTTP推送
|
1、登录OneNet平台创建产品、设备,并配置HTTP的全局推送
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
2、IOT端创建类型为OneNet的设备接入网关
|
2、获取OneNet平台的产品Key
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
3、IOT端创建产品,选中接入方式为OneNet类型的设备接入网关,填写Master-APIkey(OneNet端的产品Key)
|
|
||||||
</div>
|
</div>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<j-image width="100%" :src="img5" />
|
<j-image width="100%" :src="img5" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
4、IOT端添加设备,在设备实例页面为每一台设备设置唯一的IMEI、IMSI码(需与OneNet平台中的值一致)
|
3、IOT端创建类型为OneNet的设备接入网关
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
4、IOT端创建产品,选中接入方式为OneNet类型的设备接入网关,填写Master-APIkey(OneNet端的产品Key)
|
||||||
</div>
|
</div>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<j-image width="100%" :src="img6" />
|
<j-image width="100%" :src="img6" />
|
||||||
</div>
|
<div class="desc">填写OneNet网关相关参数</div>
|
||||||
<h1>HTTP推送配置说明</h1>
|
|
||||||
<div class="image">
|
|
||||||
<j-image width="100%" :src="img" />
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
HTTP推送配置路径:应用开发>数据推送
|
5、IOT端添加设备,在设备实例页面为每一台设备设置唯一的IMEI、IMSI码(需与OneNet平台中的值一致)
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img7" />
|
||||||
|
</div>
|
||||||
|
<h1>HTTP推送配置说明</h1>
|
||||||
|
<div>
|
||||||
|
1、点击<b>数据推送>HTTP推送>添加全局推送</b>
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img8" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
2、填写全局推送相关参数
|
||||||
|
</div>
|
||||||
|
<div class="image">
|
||||||
|
<j-image width="100%" :src="img9" />
|
||||||
</div>
|
</div>
|
||||||
<j-descriptions
|
<j-descriptions
|
||||||
bordered
|
bordered
|
||||||
|
@ -196,11 +208,8 @@
|
||||||
<j-descriptions-item label="参数"
|
<j-descriptions-item label="参数"
|
||||||
>说明</j-descriptions-item
|
>说明</j-descriptions-item
|
||||||
>
|
>
|
||||||
<j-descriptions-item label="实例名称"
|
<j-descriptions-item label="推送地址url">
|
||||||
>推送实例的名称</j-descriptions-item
|
用于接收OneNet推送设备数据的物联网平台地址:
|
||||||
>
|
|
||||||
<j-descriptions-item label="推送地址">
|
|
||||||
用于接收OneNet推送设备数据的地址物联网平台地址:
|
|
||||||
<div style="word-wrap: break-word">
|
<div style="word-wrap: break-word">
|
||||||
{{
|
{{
|
||||||
`${origin}/api/one-net/${randomString()}/notify`
|
`${origin}/api/one-net/${randomString()}/notify`
|
||||||
|
@ -210,12 +219,26 @@
|
||||||
<j-descriptions-item label="Token">
|
<j-descriptions-item label="Token">
|
||||||
自定义token,可用于验证请求是否来自OneNet
|
自定义token,可用于验证请求是否来自OneNet
|
||||||
</j-descriptions-item>
|
</j-descriptions-item>
|
||||||
<j-descriptions-item label="消息加密">
|
<j-descriptions-item label="AESKey">
|
||||||
采用AES加密算法对推送的数据进行数据加密,AesKey为加密秘钥
|
采用AES加密算法对推送的数据进行数据加密,AesKey为加密秘钥
|
||||||
</j-descriptions-item>
|
</j-descriptions-item>
|
||||||
</j-descriptions>
|
</j-descriptions>
|
||||||
|
|
||||||
|
<j-alert
|
||||||
|
message="注意:"
|
||||||
|
style="margin-top: 15px;"
|
||||||
|
type="warning"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
<span>
|
||||||
|
开发者在OneNet物联网平台添加全局推送参数前,需要在JetLinks物联网平台添加OneNet接入网关且OneNet接入网关中的通知Token参数需要和OneNet物联网平台全局推送参数中的Token保持一致,否则OneNet物联网平台添加全局推送检验不通过,提示
|
||||||
|
<span style="color: red">validate fail: validate token fail.</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</j-alert>
|
||||||
|
|
||||||
<h1>设备接入网关配置说明</h1>
|
<h1>设备接入网关配置说明</h1>
|
||||||
|
|
||||||
<j-descriptions
|
<j-descriptions
|
||||||
bordered
|
bordered
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -226,13 +249,13 @@
|
||||||
>说明</j-descriptions-item
|
>说明</j-descriptions-item
|
||||||
>
|
>
|
||||||
<j-descriptions-item label="apiKey"
|
<j-descriptions-item label="apiKey"
|
||||||
>OneNet平台中具体产品的Key</j-descriptions-item
|
>OneNet平台中具体产品的Master-APIkey</j-descriptions-item
|
||||||
>
|
>
|
||||||
<j-descriptions-item label="通知Token">
|
<j-descriptions-item label="通知Token">
|
||||||
填写OneNet数据推送配置中设置的Token
|
填写OneNet数据推送配置中设置的Token
|
||||||
</j-descriptions-item>
|
</j-descriptions-item>
|
||||||
<j-descriptions-item label="aesKey">
|
<j-descriptions-item label="aesKey">
|
||||||
若OneNet数据推送配置了消息加密,此处填写OneNet端数据推送配置中设置的aesKey
|
若OneNet数据推送配置了消息加密,此处填写OneNet端数据推送配置中设置的AESkey
|
||||||
</j-descriptions-item>
|
</j-descriptions-item>
|
||||||
</j-descriptions>
|
</j-descriptions>
|
||||||
<h1>其他说明</h1>
|
<h1>其他说明</h1>
|
||||||
|
@ -411,9 +434,11 @@ import { useMenuStore } from 'store/menu';
|
||||||
|
|
||||||
const menuStory = useMenuStore();
|
const menuStory = useMenuStore();
|
||||||
const origin = window.location.origin;
|
const origin = window.location.origin;
|
||||||
const img5 = getImage('/network/05.jpg');
|
const img5 = getImage('/network/05.jpeg');
|
||||||
const img6 = getImage('/network/06.jpg');
|
const img6 = getImage('/network/06.png');
|
||||||
const img = getImage('/network/OneNet.jpg');
|
const img7 = getImage('/network/07.jpeg');
|
||||||
|
const img8 = getImage('/network/08.png');
|
||||||
|
const img9 = getImage('/network/09.png');
|
||||||
|
|
||||||
interface FormState {
|
interface FormState {
|
||||||
apiAddress: string;
|
apiAddress: string;
|
||||||
|
@ -450,7 +475,7 @@ const formRef1 = ref<FormInstance>();
|
||||||
const formRef2 = ref<FormInstance>();
|
const formRef2 = ref<FormInstance>();
|
||||||
|
|
||||||
const formState = ref<FormState>({
|
const formState = ref<FormState>({
|
||||||
apiAddress: 'https://api.heclouds.com/',
|
apiAddress: 'http://api.zj.cmcconenet.com/',
|
||||||
apiKey: '',
|
apiKey: '',
|
||||||
validateToken: '',
|
validateToken: '',
|
||||||
aesKey: '',
|
aesKey: '',
|
||||||
|
@ -627,4 +652,11 @@ watch(
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: rgb(138, 143, 141);
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -333,6 +333,7 @@
|
||||||
index,
|
index,
|
||||||
'publicHost',
|
'publicHost',
|
||||||
]"
|
]"
|
||||||
|
:validateFirst="true"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
@ -63,6 +63,8 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['refresh'])
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '序号',
|
title: '序号',
|
||||||
|
@ -101,6 +103,7 @@ const handleSearch = async (id: string, arr: Item[]) => {
|
||||||
if (_item) {
|
if (_item) {
|
||||||
return {
|
return {
|
||||||
..._item,
|
..._item,
|
||||||
|
name: item.name,
|
||||||
flag: true,
|
flag: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -125,7 +128,7 @@ const saveInfo = async (preset: Item[]) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
console.log(resp);
|
emits('refresh')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@
|
||||||
</template>
|
</template>
|
||||||
</MediaTool>
|
</MediaTool>
|
||||||
</div>
|
</div>
|
||||||
<Preset :data="data" />
|
<Preset :data="data" @refresh="onRefresh" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -151,6 +151,7 @@ import Preset from './Preset.vue';
|
||||||
|
|
||||||
type Emits = {
|
type Emits = {
|
||||||
(e: 'update:visible', data: boolean): void;
|
(e: 'update:visible', data: boolean): void;
|
||||||
|
(e: 'refresh'): void;
|
||||||
};
|
};
|
||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
@ -315,6 +316,10 @@ const onShare = () => {
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onRefresh = () => {
|
||||||
|
emit('refresh')
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => _vis.value,
|
() => _vis.value,
|
||||||
(val: boolean) => {
|
(val: boolean) => {
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
:channelData="channelData"
|
:channelData="channelData"
|
||||||
@submit="listRef.reload()"
|
@submit="listRef.reload()"
|
||||||
/>
|
/>
|
||||||
<Live v-model:visible="playerVis" :data="playData" />
|
<Live v-model:visible="playerVis" :data="playData" @refresh="listRef.reload()" />
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -151,13 +151,14 @@ const changeAccount = () => {
|
||||||
const getLoginUser = async (data?: any) => {
|
const getLoginUser = async (data?: any) => {
|
||||||
if (getToken()) { // 未登录
|
if (getToken()) { // 未登录
|
||||||
const res = await getMe_api()
|
const res = await getMe_api()
|
||||||
|
console.log(params.value, data)
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
userName.value = res.result?.user.name
|
userName.value = res.result?.user?.name
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
getApplication(data?.client_id || params.value.client_id)
|
getApplication(data?.client_id || params.value.client_id)
|
||||||
if (data?.internal === 'true' || internal.value === 'true') { // 是否走oauth2
|
// if (data?.internal === 'true' || internal.value === 'true') { // 是否走oauth2
|
||||||
goOAuth2Fn(data)
|
goOAuth2Fn(data)
|
||||||
}
|
// }
|
||||||
} else if (res.status === 401) {
|
} else if (res.status === 401) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
spinning.value = false
|
spinning.value = false
|
||||||
|
@ -177,16 +178,19 @@ const getLoginUser = async (data?: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getQueryVariable = (variable: any) => {
|
const getQueryVariable = (): Map<string, string> => {
|
||||||
const query = window.location.search.substring(1);
|
const index = window.location.href.indexOf('?')
|
||||||
const vars = query.split('&');
|
const paramsUrl = window.location.href.substr(index + 1)
|
||||||
|
const paramsArr = paramsUrl.split('#')?.[0] || ''
|
||||||
|
|
||||||
|
const vars = paramsArr.split('&');
|
||||||
|
const maps = new Map()
|
||||||
for (let i = 0; i < vars.length; i++) {
|
for (let i = 0; i < vars.length; i++) {
|
||||||
const pair = vars[i].split('=');
|
const pair = vars[i].split('=');
|
||||||
if (pair[0] === variable) {
|
const [key, value] = pair
|
||||||
return pair[1];
|
maps.set(key, value)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return '';
|
return maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
const doLogin = () => {
|
const doLogin = () => {
|
||||||
|
@ -210,33 +214,35 @@ const initPage = async () => {
|
||||||
let redirectUrl
|
let redirectUrl
|
||||||
// 获取url中的配置信息
|
// 获取url中的配置信息
|
||||||
const paramsIndex = location.hash.indexOf('?')
|
const paramsIndex = location.hash.indexOf('?')
|
||||||
const params = new URLSearchParams(location.hash.slice(paramsIndex))
|
const _params = getQueryVariable()
|
||||||
const items = {
|
const items = {
|
||||||
client_id: params.get('client_id'),
|
client_id: _params.get('client_id'),
|
||||||
state: params.get('state'),
|
state: _params.get('state'),
|
||||||
redirect_uri: decodeURIComponent(params.get('redirect_uri')!),
|
redirect_uri: decodeURIComponent(_params.get('redirect_uri')!),
|
||||||
response_type: params.get('response_type'),
|
response_type: _params.get('response_type'),
|
||||||
scope: params.get('scope'),
|
scope: _params.get('scope'),
|
||||||
}
|
}
|
||||||
const item = params.get('internal');
|
const item = _params.get('internal');
|
||||||
if (items.redirect_uri) {
|
if (items.redirect_uri) {
|
||||||
const origin = items.redirect_uri.split('/').slice(0, 3)
|
const origin = items.redirect_uri.split('/').slice(0, 3)
|
||||||
const url = `${origin.join('/')}${items.redirect_uri?.split('redirect=')[1]}`
|
const url = `${origin.join('/')}${items.redirect_uri?.split('redirect=')[1]}`
|
||||||
// redirectUrl = `${items.redirect_uri?.split('redirect_uri=')[0]}?redirect=${url}`
|
// redirectUrl = `${items.redirect_uri?.split('redirect_uri=')[0]}?redirect=${url}`
|
||||||
redirectUrl = items.redirect_uri
|
redirectUrl = items.redirect_uri
|
||||||
}
|
}
|
||||||
// 获取用户信息
|
|
||||||
getLoginUser({
|
|
||||||
...items,
|
|
||||||
internal: params.get('internal'),
|
|
||||||
redirect_uri: redirectUrl,
|
|
||||||
})
|
|
||||||
|
|
||||||
internal.value = item!
|
console.log(params)
|
||||||
|
internal.value = item
|
||||||
params.value = {
|
params.value = {
|
||||||
...items,
|
...items,
|
||||||
redirect_uri: redirectUrl,
|
redirect_uri: redirectUrl,
|
||||||
}
|
}
|
||||||
|
console.log(params.value)
|
||||||
|
// 获取用户信息
|
||||||
|
getLoginUser({
|
||||||
|
...items,
|
||||||
|
internal: _params.get('internal'),
|
||||||
|
redirect_uri: redirectUrl,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSettingDetail = () => {
|
const getSettingDetail = () => {
|
||||||
|
|
|
@ -60,6 +60,10 @@ const onSelect = (v: any, _label: string, index: number) => {
|
||||||
const tabChange = (e: string) => {
|
const tabChange = (e: string) => {
|
||||||
emit('update:source', e)
|
emit('update:source', e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(() => props.value, () => {
|
||||||
|
myValue.value = props.value
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -175,7 +175,7 @@ watchEffect(() => {
|
||||||
treeOpenKeys.value = openKeysByTree(_options, props.value, props.valueName)
|
treeOpenKeys.value = openKeysByTree(_options, props.value, props.valueName)
|
||||||
} else {
|
} else {
|
||||||
if (isMetric) { // 处理指标值回显
|
if (isMetric) { // 处理指标值回显
|
||||||
label.value = props.metric !== undefined ? props.value : props.placeholder
|
label.value = props.metric !== undefined ? props.value || props.placeholder : props.placeholder
|
||||||
} else {
|
} else {
|
||||||
label.value = props.value !== undefined ? props.value : props.placeholder
|
label.value = props.value !== undefined ? props.value : props.placeholder
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ import { ContextKey, arrayParamsKey, timeTypeKeys } from './util'
|
||||||
import { useSceneStore } from 'store/scene'
|
import { useSceneStore } from 'store/scene'
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { Form } from 'jetlinks-ui-components'
|
import { Form } from 'jetlinks-ui-components'
|
||||||
import { isArray, isObject, pick } from 'lodash-es'
|
import {indexOf, isArray, isObject, isString, pick} from 'lodash-es'
|
||||||
import {cloneDeep} from "lodash";
|
import {cloneDeep} from "lodash";
|
||||||
|
|
||||||
const sceneStore = useSceneStore()
|
const sceneStore = useSceneStore()
|
||||||
|
@ -267,7 +267,8 @@ const columnSelect = (option: any) => {
|
||||||
termTypeChange = true
|
termTypeChange = true
|
||||||
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
|
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
|
||||||
}
|
}
|
||||||
if (hasTypeChange) { // 类型发生变化
|
console.log('hasTypeChange', paramsValue.value.source, tabsOptions.value)
|
||||||
|
if (hasTypeChange || !tabsOptions.value.every(a => a.key === paramsValue.value.source )) { // 类型发生变化
|
||||||
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
|
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
|
||||||
paramsValue.value = {
|
paramsValue.value = {
|
||||||
source: tabsOptions.value[0].key,
|
source: tabsOptions.value[0].key,
|
||||||
|
@ -289,6 +290,7 @@ const columnSelect = (option: any) => {
|
||||||
|
|
||||||
paramsValue.value = newValue
|
paramsValue.value = newValue
|
||||||
}
|
}
|
||||||
|
console.log(paramsValue, hasTypeChange)
|
||||||
handOptionByColumn(option)
|
handOptionByColumn(option)
|
||||||
emit('update:value', { ...paramsValue })
|
emit('update:value', { ...paramsValue })
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
@ -322,8 +324,13 @@ const termsTypeSelect = (e: { key: string, name: string }) => {
|
||||||
|
|
||||||
if (_source === 'metric') {
|
if (_source === 'metric') {
|
||||||
newValue.metric = paramsValue.value?.metric
|
newValue.metric = paramsValue.value?.metric
|
||||||
|
const isArray = isString(paramsValue.value!.value) ? paramsValue.value!.value?.includes?.(',') : false
|
||||||
|
if (arrayParamsKey.includes(e.key) !== isArray) { // 有变化
|
||||||
|
newValue.value = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
paramsValue.value = newValue
|
paramsValue.value = newValue
|
||||||
|
|
||||||
emit('update:value', { ...paramsValue })
|
emit('update:value', { ...paramsValue })
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][1] = e.name
|
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][1] = e.name
|
||||||
|
|
|
@ -95,8 +95,8 @@ export default defineConfig(({ mode}) => {
|
||||||
// target: 'http://192.168.32.226:8844',
|
// target: 'http://192.168.32.226:8844',
|
||||||
// target: 'http://192.168.32.244:8881',
|
// target: 'http://192.168.32.244:8881',
|
||||||
// target: 'http://192.168.32.163:8844', //张季本地
|
// target: 'http://192.168.32.163:8844', //张季本地
|
||||||
target: 'http://120.77.179.54:8844', // 120测试
|
// target: 'http://120.77.179.54:8844', // 120测试
|
||||||
// target: 'http://47.109.52.230:8844', // 本地开发环境
|
target: 'http://192.168.33.46:8844', // 本地开发环境
|
||||||
ws: 'ws://192.168.33.46:8844',
|
ws: 'ws://192.168.33.46:8844',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, '')
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
|
|
@ -3755,8 +3755,8 @@ jetlinks-ui-components@^1.0.23:
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.28:
|
jetlinks-ui-components@^1.0.28:
|
||||||
version "1.0.28"
|
version "1.0.28"
|
||||||
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.28.tgz#f409bdb62769947bf026a32b98899417d2352d0e"
|
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.28.tgz#5b26937f9a0dc7e02006d230944d9044ea9fb4ee"
|
||||||
integrity sha512-SO/04K//MHJ4lAK1KPYf8q+FNaXCnSVsAOhr8YIcaPWlgHuitj9sxdso8xHwypCvNBMEUzTx+kDXB9HAlFqGMA==
|
integrity sha512-yuxOswVTAcR5hevPoxtfdZnosiGy+KmoPMWxShr3B2UDAMybNjps10nKKMsn70Tdvm5VnYZFw5GvTktRxyr/JA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "^9.12.0"
|
"@vueuse/core" "^9.12.0"
|
||||||
"@vueuse/router" "^9.13.0"
|
"@vueuse/router" "^9.13.0"
|
||||||
|
|