fix: bug#16459、16434、16453、16452、10936

* fix: bug#16459、16434、16453、16452

* feat: 数据解析添加代码提示

* fix: bug#16451

* fix: 兼容物模型旧版数据

* fix: 优化物模型规则窗口长度

* fix: providerName

* fix: bug#10936
This commit is contained in:
XieYongHong 2023-07-18 18:03:38 +08:00 committed by GitHub
parent bd966849c6
commit e3ef99cbe1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 236 additions and 142 deletions

View File

@ -25,7 +25,7 @@
"event-source-polyfill": "^1.0.31",
"global": "^4.4.0",
"jetlinks-store": "^0.0.3",
"jetlinks-ui-components": "^1.0.24",
"jetlinks-ui-components": "^1.0.25",
"js-cookie": "^3.0.1",
"jsencrypt": "^3.3.2",
"less": "^4.1.3",

View File

@ -607,3 +607,6 @@ export const saveDeviceVirtualProperty = (productId: string, deviceId: string, d
export const queryDeviceVirtualProperty = (productId: string, deviceId: string, propertyId: string) => server.get(`/virtual/property/device/${productId}/${deviceId}/${propertyId}`)
export const queryByParent = (deviceId: string) => server.get(`/device/gateway/${deviceId}/parent`)
export const queryCodeTips = (productId: string, deviceId: string) => server.get(`/device/transparent-codec/${productId}/${deviceId}.d.ts`)
export const queryProductCodeTips = (productId: string) => server.get(`/device/transparent-codec/${productId}.d.ts`)

View File

@ -105,7 +105,7 @@ const handleSearch = async () => {
);
});
if (_item) {
info.value = _item?.providerName || _item?.provider
info.value = _item?.providerName || _item?.thirdPartyUserId
}
}
};

View File

@ -11,35 +11,27 @@
编辑
</PermissionButton>
</template>
<j-descriptions-item label="设备ID">{{
instanceStore.current?.id
}}</j-descriptions-item>
<j-descriptions-item v-if='instanceStore.current?.accessProvider === "plugin_gateway"'>
<template #label>
<div>
第三方系统设备ID
<j-tooltip>
<template #title>
<p>通过调用SDK或HTTP请求的方式接入第三方系统设备数据时第三方系统与平台当前设备对应的设备ID</p>
如双方ID值一致则无需填写
</template>
<a-icon type='QuestionCircleOutlined' />
</j-tooltip>
</div>
</template>
<j-button v-if='!inklingDeviceId' type="link" @click='giveAnInkling'>映射</j-button>
<div v-else style='display: flex;justify-content: space-between;align-items: center;'>
<div style='flex: 1 1 auto;'>
<j-ellipsis>{{ inklingDeviceId }}</j-ellipsis>
</div>
<j-button type='link'>
<a-icon
type='EditOutlined'
@click='inkingVisible = true'
/>
</j-button>
<j-descriptions-item label="设备ID">
<div style="display: flex">
<div style="flex: 1">
<j-ellipsis> {{ instanceStore.current?.id }} </j-ellipsis>
</div>
<div v-if='instanceStore.current?.accessProvider === "plugin_gateway"'>
<j-tooltip>
<template #title>
<p>通过调用SDK或HTTP请求的方式接入第三方系统设备数据时第三方系统与平台当前设备对应的设备ID</p>
如双方ID值一致则无需填写
</template>
<a v-if="!inklingDeviceId" type='link' @click='giveAnInkling'>
未映射
</a>
<a v-else type='link' @click='inkingVisible = true'>
已映射
</a>
</j-tooltip>
</div>
</div>
</j-descriptions-item>
<j-descriptions-item label="产品名称">{{
instanceStore.current?.productName

View File

@ -68,6 +68,7 @@
style="height: 100%"
theme="vs"
v-model:modelValue="editorValue"
:registrationTypescript="typescriptTip"
/>
</div>
<div class="bottom">
@ -151,11 +152,11 @@ import PermissionButton from '@/components/PermissionButton/index.vue';
import { useFullscreen } from '@vueuse/core';
import { useInstanceStore } from '@/store/instance';
import {
deviceCode,
getProtocal,
testCode,
saveDeviceCode,
delDeviceCode,
deviceCode,
getProtocal,
testCode,
saveDeviceCode,
delDeviceCode, queryCodeTips, queryProductCodeTips,
} from '@/api/device/instance';
import { message } from 'jetlinks-ui-components';
import { isBoolean } from 'lodash';
@ -179,6 +180,11 @@ const loading = ref<boolean>(false);
const isTest = ref<boolean>(false);
const editorValue = ref<string>('');
const typescriptTip = reactive({
typescript: ''
})
const color = computed(() => ({
color: readOnly.value ? '#415ed1' : '#a6a6a6',
}));
@ -228,12 +234,24 @@ const getTopic = async () => {
topicList.value = item;
}
};
const queryCode = () => {
queryCodeTips(instanceStore.current.productId,
instanceStore.current.id,).then(res => {
if (res.success) {
typescriptTip.typescript = res.result
}
})
}
//
const getDeviceCode = async () => {
const res: any = await deviceCode(
instanceStore.current.productId,
instanceStore.current.id,
);
if (res.status === 200) {
const item = res.result?.configuration?.script
? res.result?.configuration?.script
@ -261,6 +279,7 @@ const test = async (dataTest: any) => {
}
};
//
const save = async () => {
const item = {
@ -328,6 +347,7 @@ watch(() => instanceStore.current?.id, () => {
if (instanceStore.current?.id) {
getDeviceCode();
getTopic();
queryCode()
}
}, { immediate: true })
</script>

View File

@ -25,6 +25,7 @@
style="height: 100%"
theme="vs"
v-model:modelValue="editorValue"
:registrationTypescript="typescriptTip"
/>
</div>
<div class="bottom">
@ -112,10 +113,10 @@ import PermissionButton from '@/components/PermissionButton/index.vue';
import { useFullscreen } from '@vueuse/core';
import { useProductStore } from '@/store/product';
import {
productCode,
getProtocal,
testCode,
saveProductCode,
productCode,
getProtocal,
testCode,
saveProductCode, queryProductCodeTips,
} from '@/api/device/instance';
import { isBoolean } from 'lodash';
import { onlyMessage } from '@/utils/comm';
@ -135,6 +136,9 @@ const resultValue = ref<any>({});
const loading = ref<boolean>(false);
const isTest = ref<boolean>(false);
const editorValue = ref<string>('');
const typescriptTip = reactive({
typescript: ''
})
const resStyle = computed(() =>
isBoolean(resultValue.value.success)
@ -168,6 +172,16 @@ const getTopic = async () => {
topicList.value = item;
}
};
const queryCodeTips = () => {
queryProductCodeTips(productStore.current.id).then(res => {
if (res.success) {
typescriptTip.typescript = res.result
}
})
}
//
const getProductCode = async () => {
const res: any = await productCode(productStore.current.id);
@ -248,6 +262,7 @@ const debug = () => {
onMounted(() => {
getProductCode();
getTopic();
queryCodeTips()
});
</script>

View File

@ -395,19 +395,22 @@ const handleSaveClick = async (next?: Function) => {
const virtual: any[] = [];
const arr = resp.map((item: any) => {
if(item.expands?.virtualRule) {
const triggerProperties = item.expands.virtualRule.triggerProperties
const rule = omit(item.expands.virtualRule, ['triggerProperties'])
virtual.push({
...item.expands.virtualRule,
triggerProperties,
rule,
type: rule.type,
propertyId: item.id
})
}
// return {
// ...item,
// expands: {
// ...item.expands,
// virtualRule: undefined
// }
// }
return item
return {
...item,
expands: {
...omit(item.expands, ['virtualRule'])
}
}
// return item
})
//
if(virtual.length) {

View File

@ -433,26 +433,46 @@ export const useColumns = (type?: MetadataType, target?: 'device' | 'product', n
required: true,
rules: target !== 'device' ? [
{
validator: async (_: Record<string, any>, value: any) => {
callback: async (rule: any, value: any, dataSource: any[]) => {
console.log('value', value)
if (value.source) {
if(value.source !== 'rule') {
if(value.type?.length) {
return Promise.resolve();
} else {
return Promise.reject('请选择读写类型');
}
} else {
if(value.virtualRule?.rule?.script) {
return Promise.resolve();
}else {
return Promise.reject('请配置规则');
}
const field = rule.field.split('.')
const fieldIndex = Number(field[1])
const values = dataSource.find((item, index) => index === fieldIndex)
const virtualRule = values.elements?.virtualRule
const source = value.source
const ids = (noEdit?.value?.id || []) as any[]
if (source) {
if (source !== 'rule' && !value.type?.length) {
return Promise.reject('请选择读写类型');
} else if(!ids.includes(values.id) && virtualRule){
return Promise.reject('请配置规则');
}
} else {
return Promise.reject('请选择属性来源');
return Promise.resolve()
}
return Promise.reject('请选择属性来源');
}
// if (value.source) {
// if(value.source !== 'rule') {
// if(value.type?.length) {
// return Promise.resolve();
// } else {
// return Promise.reject('请选择读写类型');
// }
// } else {
// if(value.virtualRule?.script) {
// return Promise.resolve();
// }else {
// return Promise.reject('请配置规则');
// }
// }
// } else {
// return Promise.reject('请选择属性来源');
// }
// }
},
]: []
},

View File

@ -0,0 +1,39 @@
<template>
<j-select
v-model:value="myValue"
:options="[
{ label: '固定值', value: 'false' },
{ label: '范围值', value: 'true' },
]"
@select="select"
/>
</template>
<script name="BooleanSelect" setup>
const props = defineProps({
value: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['update:value'])
const myValue = ref()
const select = (e) => {
emit('update:value', {
...props.value,
range: e === 'true',
value: e === 'true' ? [undefined, undefined] : undefined
})
}
watch(() => JSON.stringify(props.value), () => {
myValue.value = `${props.value?.range}`
}, { immediate: true })
</script>
<style scoped>
</style>

View File

@ -33,6 +33,7 @@
import { defineExpose, provide } from 'vue'
import MetricValueItem from './ValueItem.vue'
import {validatorConfig} from "@/views/device/components/Metadata/Base/columns";
import BooleanSelect from "@/views/device/components/Metadata/Base/components/Properties/Metrics/BooleanSelect.vue";
const props = defineProps({
value: {
@ -107,7 +108,6 @@ const columns: any = [
rules: [
{
validator(_: any, value: any) {
console.log('指标配置', value)
if (!value) {
return Promise.reject('请配置指标')
}
@ -132,17 +132,11 @@ const newColumns = computed(() => {
title: '指标值',
dataIndex: 'range',
width: 120,
type: 'booleanSelect',
type: 'components',
components: {
props: {
trueText: '范围值',
trueValue: true,
falseText: '固定值',
falseValue: false,
}
name: BooleanSelect
}
})
console.log(data);
return data
}
return columns

View File

@ -10,18 +10,18 @@
>
<template #content>
<j-form ref="formRef" :model="formData">
<j-form-item v-if="value.range === 'false'" name="value" :rule="[{ required: true, message: '请输入指标值'}]">
<j-form-item v-if="value.range === false" :rules="[{ required: true, message: '请输入指标值'}]" name="value">
<Item v-model:value="formData.value" />
</j-form-item>
<div v-else class="data-table-boolean-item">
<div class="data-table-boolean-item--value">
<j-form-item :name="['rangeValue', 0]" :rule="[{ required: true, message: '请输入指标值'}]">
<j-form-item :name="['rangeValue', 0]" :rules="[{ required: true, message: '请输入指标值'}]">
<Item v-model:value="formData.rangeValue[0]" />
</j-form-item>
</div>
<div>-</div>
<div class="data-table-boolean-item--value">
<j-form-item :name="['rangeValue', 1]" :rule="[{ required: true, message: '请输入指标值'}]">
<j-form-item :name="['rangeValue', 1]" :rules="[{ required: true, message: '请输入指标值'}, { validator: validator}]">
<Item v-model:value="formData.rangeValue[1]" />
</j-form-item>
</div>
@ -38,6 +38,7 @@ import { reactive } from 'vue';
import type { PropType } from 'vue';
import Item from './item.vue'
import {Form} from "jetlinks-ui-components";
import {cloneDeep} from "lodash";
type ValueType = number | Array<number | undefined> | undefined;
@ -56,13 +57,14 @@ const emit = defineEmits<Emit>();
const formItemContext = Form.useInjectFormItemContext();
const formData = reactive<{
value: ValueType;
rangeValue: ValueType;
}>({
value: props.value?.range === false ? props.value?.value : undefined,
rangeValue: props.value?.range === true
? props.value?.value || [undefined, undefined]
? cloneDeep(props.value?.value) || [undefined, undefined]
: [undefined, undefined],
});
@ -76,6 +78,13 @@ const showText = computed(() => {
}
})
const validator = (_: any, value: any) => {
if (props.value.range && formData.rangeValue![0] >= formData.rangeValue![1]) {
return Promise.reject('需大于左侧数值')
}
return Promise.resolve()
}
const confirm = () => {
return new Promise((resolve, reject) => {
formRef.value.validate().then(() => {

View File

@ -10,6 +10,8 @@
v-else-if="['int', 'long', 'float', 'double'].includes(type)"
v-model:value="myValue"
:precision="0"
:max="2147483647"
:min="-2147483647"
style="width: 100%"
placeholder="请输入"
@change="change"
@ -31,6 +33,7 @@
/>
</template>
<script setup name="MetricValueItem">
import { Form } from 'jetlinks-ui-components'
const props = defineProps({
value: {
@ -40,11 +43,13 @@ const props = defineProps({
})
const emit = defineEmits(['update:value'])
const formItemContext = Form.useInjectFormItemContext();
const type = inject('metricsType')
const myValue = ref(props.value)
const change = () => {
// formItemContext.onFieldChange()
emit('update:value', myValue.value)
}

View File

@ -55,8 +55,8 @@
required
>
<Rule
v-model:value="formData.virtualRule.rule.script"
:virtualRule="_virtualRule.virtualRule.rule"
v-model:value="formData.virtualRule.script"
:virtualRule="_virtualRule.virtualRule"
:id="value.id"
:aggList="aggList"
/>
@ -67,7 +67,7 @@
required
>
<j-select
v-model:value="formData.virtualRule.rule.windowType"
v-model:value="formData.virtualRule.windowType"
:options="[
{ label: '无', value: 'undefined' },
{ label: '时间窗口', value: 'time' },
@ -79,26 +79,26 @@
/>
</j-form-item>
<template
v-if="formData.virtualRule?.rule?.windowType !== 'undefined'"
v-if="formData.virtualRule?.windowType !== 'undefined'"
>
<j-form-item
label="聚合函数"
:name="['virtualRule', 'rule', 'aggType']"
:name="['virtualRule', 'aggType']"
required
>
<j-select
v-model:value="formData.virtualRule.rule.aggType"
v-model:value="formData.virtualRule.aggType"
:options="aggList"
placeholder="请选择聚合函数"
/>
</j-form-item>
<j-form-item
:label="
formData.virtualRule?.rule?.windowType === 'time'
formData.virtualRule?.windowType === 'time'
? '窗口长度(s)'
: '窗口长度(次)'
"
:name="['virtualRule', 'rule', 'window', 'span']"
:name="['virtualRule', 'window', 'span']"
required
:rules="[
{
@ -112,20 +112,20 @@
]"
>
<j-input-number
v-model:value="formData.virtualRule.rule.window.span"
placeholder="请输入窗口长度"
style="width: 100%"
v-model:value="formData.virtualRule.window.span"
:max="999999"
:min="1"
placeholder="请输入窗口长度"
style="width: 100%"
/>
</j-form-item>
<j-form-item
:label="
formData.virtualRule?.rule?.windowType === 'time'
formData.virtualRule?.windowType === 'time'
? '步长(s)'
: '步长(次)'
"
:name="['virtualRule', 'rule', 'window', 'every']"
:name="['virtualRule', 'window', 'every']"
required
:rules="[
{
@ -140,7 +140,7 @@
>
<j-input-number
style="width: 100%"
v-model:value="formData.virtualRule.rule.window.every"
v-model:value="formData.virtualRule.window.every"
placeholder="请输入步长"
:max="999999"
:min="1"
@ -182,16 +182,14 @@ const props = defineProps({
const initData = {
triggerProperties: ['*'],
rule: {
type: undefined,
script: '',
isVirtualRule: false,
windowType: 'undefined',
aggType: undefined,
window: {
span: undefined,
every: undefined,
},
type: undefined,
script: '',
isVirtualRule: false,
windowType: 'undefined',
aggType: undefined,
window: {
span: undefined,
every: undefined,
},
};
@ -208,16 +206,14 @@ const formData = reactive<{
type: string[];
virtualRule?: {
triggerProperties: string[];
rule: {
type: 'script' | 'window' | undefined;
script: string | undefined;
isVirtualRule: boolean;
windowType: string;
aggType: string | undefined;
window: {
span: number | undefined;
every: number | undefined;
};
type: 'script' | 'window' | undefined;
script: string | undefined;
isVirtualRule: boolean;
windowType: string;
aggType: string | undefined;
window: {
span: number | undefined;
every: number | undefined;
};
};
}>({
@ -228,7 +224,7 @@ const formData = reactive<{
const dataSource = inject<Ref<any[]>>('_dataSource')
const windowTypeChange = () => {
formData.virtualRule!.rule.window = {
formData.virtualRule!.window = {
span: undefined,
every: undefined
}
@ -253,9 +249,11 @@ const options = computed(() => {
});
const setInitVirtualRule = () => {
console.log(props.value?.expands?.virtualRule);
formData.virtualRule = {
...initData,
...(props.value?.expands?.virtualRule || {}),
triggerProperties: props.value?.expands?.virtualRule?.triggerProperties || ['*'],
rule: props.value?.expands?.virtualRule?.rule || initData.rule
}
}
@ -277,7 +275,7 @@ const handleSearch = async () => {
if (resp && resp.status === 200 && resp.result) {
formData.virtualRule = {
triggerProperties: resp.result.triggerProperties,
rule: resp.result.rule,
...resp.result.rule,
}
} else {
setInitVirtualRule()
@ -308,8 +306,6 @@ watch(
() => props.value,
() => {
formData.type = props.value.expands?.type;
if (props.value.virtualRule) {
}
},
{ immediate: true, deep: true },
);
@ -319,7 +315,7 @@ watch(
(newVal: SourceType) => {
if (newVal === 'rule') {
formData.virtualRule = initData;
console.log(formData.virtualRule);
handleSearch();
} else {
formData.virtualRule = undefined;
@ -332,16 +328,13 @@ watch(
);
const _virtualRule = computed(() => {
const flag = formData?.virtualRule?.rule?.windowType !== 'undefined';
const flag = formData?.virtualRule?.windowType !== 'undefined';
return {
type: formData?.type,
virtualRule: {
type: flag ? 'window' : 'script',
rule: {
...formData?.virtualRule?.rule,
isVirtualRule: flag,
type: flag ? 'window' : 'script',
},
...formData?.virtualRule,
isVirtualRule: flag,
triggerProperties: formData?.virtualRule?.triggerProperties.includes('*')
? []
: formData?.virtualRule?.triggerProperties,

View File

@ -92,7 +92,8 @@ const getCPUEcharts = async (val: any) => {
const _cpuXAxis = new Set();
if (res.result?.length) {
//
const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
const filterArray = res.result
filterArray.forEach((item: any) => {
const value = item.data.value;
const nodeID = item.data.clusterNodeId;

View File

@ -90,7 +90,8 @@ const getJVMEcharts = async (val: any) => {
const _jvmOptions = {};
const _jvmXAxis = new Set();
if (res.result?.length) {
const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
// const filterArray = props.isNoCommunity ? res.result.filter((item : any) => item.data?.clusterNodeId === props.serviceId) : res.result
const filterArray = res.result
filterArray.forEach((item: any) => {
const value = item.data.value;
const memoryJvmHeapFree = value.memoryJvmHeapFree;

View File

@ -250,6 +250,7 @@ const getDashBoard = () => {
},
grid: {
top: '2%',
left: 40,
bottom: 0,
},
tooltip: {
@ -428,7 +429,7 @@ const selectChange = () => {
.filter((item: any) => item.group === 'alarmTrend')
.forEach((item: any) => {
xData.push(item.data.timeString);
sData.push(item.data.value);
sData.push(item.data.value * 100000);
});
const maxY = sData.sort((a,b)=>{
return b-a
@ -451,7 +452,7 @@ const selectChange = () => {
grid: {
top: '2%',
bottom: '5%',
left: maxY > 10000 ? '50px' : '40px',
left: maxY < 1000 ? '40px' : maxY.toString().length * 10,
right: '48px',
},
series: [

View File

@ -268,7 +268,8 @@ watch(
() => props.productDetail,
(newVal) => {
if (newVal?.id) {
if (props.values?.selector === 'fixed') {
console.log(props.values)
if (props.values?.selector === 'fixed' && props.values?.selectorValues?.length === 1) {
const id = props.values?.selectorValues?.[0]?.value;
if (id) {
detail(id).then((resp) => {
@ -276,6 +277,7 @@ watch(
metadata.value = JSON.parse(
resp.result?.metadata || '{}',
);
console.log(metadata.value, resp.result?.metadata)
}
});
}

View File

@ -67,7 +67,7 @@ const checkDeviceDelete = async () => {
if (item!.selectorValues!.length === 1 && hasDevice) {
const deviceDetail = deviceResp?.result?.data?.[0]
metadata = JSON.parse(deviceDetail?.deriveMetadata || '{}') //
metadata = JSON.parse(deviceDetail?.deriveMetadata || productDetail?.metadata || '{}') //
}
}
if (!hasDevice) { //
@ -139,9 +139,8 @@ const checkDeviceDelete = async () => {
}
if (item!.message!.messageType === 'READ_PROPERTY' && item!.message!.properties && metadata.properties) {
if (item!.message!.messageType === 'READ_PROPERTY') {
let hasProperties = false
console.log('checkDeviceDelete',item!.message!.properties, metadata)
if (item!.message!.properties && metadata.properties?.length) {
const propertiesKey = item!.message!.properties?.[0]
hasProperties = metadata.properties?.some((item: any) => item.id === propertiesKey)
@ -154,8 +153,7 @@ const checkDeviceDelete = async () => {
}
}
console.log('WRITE_PROPERTY',item, metadata)
if (item!.message!.messageType === 'WRITE_PROPERTY' && item!.message!.properties && metadata.properties) {
if (item!.message!.messageType === 'WRITE_PROPERTY') {
let hasProperties = false
const propertiesKey = Object.keys(item!.message!.properties!)?.[0]
if (item!.message!.properties && metadata.properties?.length) {
@ -169,7 +167,7 @@ const checkDeviceDelete = async () => {
}
// -
const _value = item!.message!.properties?.[propertiesKey]
console.log('WRITE_PROPERTY',_value)
if(_value.source === 'upper') {
const _params = {
branch: props.thenName,
@ -248,7 +246,6 @@ const checkNoticeDelete = async () => {
const itemType = variableDefinitionsMap.get(variableKey)
let hasUser = false
console.log(itemType, notifyType)
if (itemType === 'user') { //
let resp = undefined;
if (['dingTalk', 'weixin'].includes(notifyType)) {
@ -319,8 +316,7 @@ const checkNoticeDelete = async () => {
}
const check = () => {
const _executor = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.executor
console.log('check', _executor)
const _executor = _data.value.branches![props.branchesName].then[props.thenName].actions?.[props.name]?.executor
if (_executor === 'device' && _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.device) { //
checkDeviceDelete()
} else if (_executor === 'notify' && _data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.notify) {

View File

@ -536,7 +536,7 @@ const onSave = (data: ActionsType, options: any) => {
_data.value.branches![props.branchesName].then[props.thenName].actions.splice(props.name, 1, actionItem)
checkItemRef.value?.formTouchOff?.()
visible.value = false;
EventEmitter.emit(eventEmitterKey.value, data) //
EventEmitter.emit(key!, data) //
};
/**

View File

@ -3835,10 +3835,10 @@ jetlinks-ui-components@^1.0.23:
lodash-es "^4.17.21"
monaco-editor "^0.35.0"
jetlinks-ui-components@^1.0.24:
version "1.0.24"
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.24.tgz#e15551fb114e4cb8752db962423b3ca17d9389c1"
integrity sha512-TGyQ9SmdkoNkZScfYvfBF1/P1oBzXkxMuzR+DiNnof6CbSlYfPrkRsJIpOIZUjqg2o/6dyKLDK8gOxbxWm8wjA==
jetlinks-ui-components@^1.0.25:
version "1.0.25"
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.25.tgz#b783da3fe05c1420b2ee5707868a67baa90559f7"
integrity sha512-4HJM9Wi8gFfBgYFPjCO7JpmEAXVtDUf5u5lnXTQUt1QkGh0QCzFSBGBIStFs6HE5oY3oIIS3ZWoAjvXElpnNZg==
dependencies:
"@vueuse/core" "^9.12.0"
"@vueuse/router" "^9.13.0"