fix: iot warn
This commit is contained in:
@@ -101,6 +101,7 @@ export interface Action {
|
|||||||
identifier?: string;
|
identifier?: string;
|
||||||
value?: any;
|
value?: any;
|
||||||
alertConfigId?: number;
|
alertConfigId?: number;
|
||||||
|
params?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询场景联动规则分页 */
|
/** 查询场景联动规则分页 */
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '关联场景联动规则',
|
label: '关联场景联动规则',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleRuleSceneList,
|
api: () => getSimpleRuleSceneList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -76,7 +76,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '接收的用户',
|
label: '接收的用户',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleUserList,
|
api: () => getSimpleUserList(),
|
||||||
labelField: 'nickname',
|
labelField: 'nickname',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '告警配置',
|
label: '告警配置',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleAlertConfigList,
|
api: () => getSimpleAlertConfigList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择告警配置',
|
placeholder: '请选择告警配置',
|
||||||
@@ -40,7 +40,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -53,7 +53,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备',
|
label: '设备',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeviceList,
|
api: () => getSimpleDeviceList(),
|
||||||
labelField: 'deviceName',
|
labelField: 'deviceName',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择设备',
|
placeholder: '请选择设备',
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ async function handleProcess(row: AlertRecord) {
|
|||||||
try {
|
try {
|
||||||
await processAlertRecord(row.id as number, processRemark);
|
await processAlertRecord(row.id as number, processRemark);
|
||||||
message.success('处理成功');
|
message.success('处理成功');
|
||||||
onRefresh();
|
handleRefresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('处理失败:', error);
|
console.error('处理失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { DICT_TYPE } from '@vben/constants';
|
|||||||
import { getDictOptions } from '@vben/hooks';
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
|
import { getSimpleDeviceList } from '#/api/iot/device/device';
|
||||||
import { getSimpleDeviceGroupList } from '#/api/iot/device/group';
|
import { getSimpleDeviceGroupList } from '#/api/iot/device/group';
|
||||||
import {
|
import {
|
||||||
DeviceTypeEnum,
|
DeviceTypeEnum,
|
||||||
@@ -27,7 +28,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -55,12 +56,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '网关设备',
|
label: '网关设备',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: async () => {
|
api: () => getSimpleDeviceList(DeviceTypeEnum.GATEWAY),
|
||||||
const { getSimpleDeviceList } = await import(
|
|
||||||
'#/api/iot/device/device'
|
|
||||||
);
|
|
||||||
return getSimpleDeviceList(DeviceTypeEnum.GATEWAY);
|
|
||||||
},
|
|
||||||
labelField: 'nickname',
|
labelField: 'nickname',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '子设备可选择父设备',
|
placeholder: '子设备可选择父设备',
|
||||||
@@ -93,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeviceGroupList,
|
api: () => getSimpleDeviceGroupList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -160,7 +156,7 @@ export function useGroupFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeviceGroupList,
|
api: () => getSimpleDeviceGroupList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -203,7 +199,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -253,7 +249,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeviceGroupList,
|
api: () => getSimpleDeviceGroupList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择设备分组',
|
placeholder: '请选择设备分组',
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import { getSimpleProductList } from '#/api/iot/product/product';
|
|||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns } from './data';
|
import { useGridColumns } from './data';
|
||||||
// @ts-ignore
|
|
||||||
import DeviceCardView from './modules/DeviceCardView.vue';
|
import DeviceCardView from './modules/DeviceCardView.vue';
|
||||||
import DeviceForm from './modules/DeviceForm.vue';
|
import DeviceForm from './modules/DeviceForm.vue';
|
||||||
import DeviceGroupForm from './modules/DeviceGroupForm.vue';
|
import DeviceGroupForm from './modules/DeviceGroupForm.vue';
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { IotDeviceApi } from '#/api/iot/device/device';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import { useVbenForm, useVbenModal } from '@vben/common-ui';
|
import { useVbenForm, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import {
|
import { message } from 'ant-design-vue';
|
||||||
createDevice,
|
|
||||||
getDevice,
|
import { createDevice, getDevice, updateDevice } from '#/api/iot/device/device';
|
||||||
updateDevice,
|
|
||||||
} from '#/api/iot/device/device';
|
|
||||||
import type { IotDeviceApi } from '#/api/iot/device/device';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useFormSchema } from '../data';
|
import { useFormSchema } from '../data';
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
await modalApi.close();
|
await modalApi.close();
|
||||||
emit('success');
|
emit('success');
|
||||||
message.success($t('common.updateSuccess'));
|
message.success($t('ui.actionMessage.operationSuccess'));
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ async function saveConfig() {
|
|||||||
try {
|
try {
|
||||||
config.value = JSON.parse(configString.value);
|
config.value = JSON.parse(configString.value);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('JSON格式错误:', error);
|
||||||
message.error({ content: 'JSON格式错误,请修正后再提交!' });
|
message.error({ content: 'JSON格式错误,请修正后再提交!' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -176,33 +177,31 @@ async function updateDeviceConfig() {
|
|||||||
placeholder="请输入 JSON 格式的配置信息"
|
placeholder="请输入 JSON 格式的配置信息"
|
||||||
class="json-editor"
|
class="json-editor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.json-viewer-container {
|
.json-viewer-container {
|
||||||
|
max-height: 600px;
|
||||||
|
padding: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 12px;
|
|
||||||
max-height: 600px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-code {
|
.json-code {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
|
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #333;
|
color: #333;
|
||||||
white-space: pre-wrap;
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-editor {
|
.json-editor {
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
|
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
|
import {
|
||||||
|
computed,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
import { ContentWrap } from '@vben/common-ui';
|
import { ContentWrap } from '@vben/common-ui';
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { formatDate } from '@vben/utils';
|
import { formatDate } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Form, Pagination, Select, Switch, Table, Tag } from 'ant-design-vue';
|
import {
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
Pagination,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
import { getDeviceMessagePage } from '#/api/iot/device/device';
|
import { getDeviceMessagePage } from '#/api/iot/device/device';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import type { ThingModelData } from '#/api/iot/thingmodel';
|
|||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { ContentWrap } from '@vben/common-ui';
|
import { ContentWrap } from '@vben/common-ui';
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -19,16 +20,14 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
Textarea,
|
Textarea,
|
||||||
} from 'ant-design-vue';
|
} from 'ant-design-vue';
|
||||||
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
import { DeviceStateEnum, sendDeviceMessage } from '#/api/iot/device/device';
|
import { DeviceStateEnum, sendDeviceMessage } from '#/api/iot/device/device';
|
||||||
|
import DataDefinition from '#/views/iot/thingmodel/modules/components/DataDefinition.vue';
|
||||||
import {
|
import {
|
||||||
IotDeviceMessageMethodEnum,
|
IotDeviceMessageMethodEnum,
|
||||||
IoTThingModelTypeEnum,
|
IoTThingModelTypeEnum,
|
||||||
} from '#/views/iot/utils/constants';
|
} from '#/views/iot/utils/constants';
|
||||||
|
|
||||||
import DataDefinition from '#/views/iot/thingmodel/modules/components/DataDefinition.vue';
|
|
||||||
|
|
||||||
import DeviceDetailsMessage from './DeviceDetailsMessage.vue';
|
import DeviceDetailsMessage from './DeviceDetailsMessage.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -340,7 +339,7 @@ async function handleServiceInvoke(row: ThingModelData) {
|
|||||||
<template>
|
<template>
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<!-- 上方:指令调试区域 -->
|
<!-- 上方:指令调试区域 -->
|
||||||
<Card class="mb-4 simulator-tabs">
|
<Card class="simulator-tabs mb-4">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span>指令调试</span>
|
<span>指令调试</span>
|
||||||
@@ -349,8 +348,8 @@ async function handleServiceInvoke(row: ThingModelData) {
|
|||||||
size="small"
|
size="small"
|
||||||
@click="debugCollapsed = !debugCollapsed"
|
@click="debugCollapsed = !debugCollapsed"
|
||||||
>
|
>
|
||||||
<UpOutlined v-if="!debugCollapsed" />
|
<IconifyIcon icon="lucide:chevron-up" v-if="!debugCollapsed" />
|
||||||
<DownOutlined v-if="debugCollapsed" />
|
<IconifyIcon icon="lucide:chevron-down" v-if="debugCollapsed" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -587,8 +586,8 @@ async function handleServiceInvoke(row: ThingModelData) {
|
|||||||
size="small"
|
size="small"
|
||||||
@click="messageCollapsed = !messageCollapsed"
|
@click="messageCollapsed = !messageCollapsed"
|
||||||
>
|
>
|
||||||
<UpOutlined v-if="!messageCollapsed" />
|
<IconifyIcon icon="lucide:chevron-down" v-if="!messageCollapsed" />
|
||||||
<DownOutlined v-if="messageCollapsed" />
|
<IconifyIcon icon="lucide:chevron-down" v-if="messageCollapsed" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -41,4 +41,3 @@ onMounted(() => {
|
|||||||
<!-- TODO: 实现子设备列表展示和管理功能 -->
|
<!-- TODO: 实现子设备列表展示和管理功能 -->
|
||||||
</Card>
|
</Card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,9 @@ async function getList() {
|
|||||||
try {
|
try {
|
||||||
const data = await getHistoryDevicePropertyList(queryParams);
|
const data = await getHistoryDevicePropertyList(queryParams);
|
||||||
// 后端直接返回数组,不是 { list: [] } 格式
|
// 后端直接返回数组,不是 { list: [] } 格式
|
||||||
list.value = (Array.isArray(data) ? data : (data?.list || [])) as IotDeviceApi.DevicePropertyDetail[];
|
list.value = (
|
||||||
|
Array.isArray(data) ? data : data?.list || []
|
||||||
|
) as IotDeviceApi.DevicePropertyDetail[];
|
||||||
total.value = list.value.length;
|
total.value = list.value.length;
|
||||||
|
|
||||||
// 如果是图表模式且不是复杂数据类型,渲染图表
|
// 如果是图表模式且不是复杂数据类型,渲染图表
|
||||||
|
|||||||
@@ -34,11 +34,9 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '父级分组',
|
label: '父级分组',
|
||||||
component: 'ApiTreeSelect',
|
component: 'ApiTreeSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeviceGroupList,
|
api: () => getSimpleDeviceGroupList(),
|
||||||
fieldNames: {
|
labelField: 'name',
|
||||||
label: 'name',
|
valueField: 'id',
|
||||||
value: 'id',
|
|
||||||
},
|
|
||||||
placeholder: '请选择父级分组',
|
placeholder: '请选择父级分组',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '所属产品',
|
label: '所属产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -85,7 +85,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '所属产品',
|
label: '所属产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -86,7 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
|
|||||||
@@ -34,11 +34,9 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '父级分类',
|
label: '父级分类',
|
||||||
component: 'ApiTreeSelect',
|
component: 'ApiTreeSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductCategoryList,
|
api: () => getSimpleProductCategoryList(),
|
||||||
fieldNames: {
|
labelField: 'name',
|
||||||
label: 'name',
|
valueField: 'id',
|
||||||
value: 'id',
|
|
||||||
},
|
|
||||||
placeholder: '请选择父级分类',
|
placeholder: '请选择父级分类',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
label: '产品分类',
|
label: '产品分类',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductCategoryList,
|
api: () => getSimpleProductCategoryList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品分类',
|
placeholder: '请选择产品分类',
|
||||||
@@ -246,7 +246,7 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
label: '产品分类',
|
label: '产品分类',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductCategoryList,
|
api: () => getSimpleProductCategoryList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品分类',
|
placeholder: '请选择产品分类',
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ import { downloadFileFromBlobPart } from '@vben/utils';
|
|||||||
import { Button, Card, Image, Input, message, Space } from 'ant-design-vue';
|
import { Button, Card, Image, Input, message, Space } from 'ant-design-vue';
|
||||||
|
|
||||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getSimpleProductCategoryList } from '#/api/iot/product/category';
|
||||||
import {
|
import {
|
||||||
deleteProduct,
|
deleteProduct,
|
||||||
exportProduct,
|
exportProduct,
|
||||||
getProductPage,
|
getProductPage,
|
||||||
} from '#/api/iot/product/product';
|
} from '#/api/iot/product/product';
|
||||||
import { getSimpleProductCategoryList } from '#/api/iot/product/category';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns, useImagePreview } from './data';
|
import { useGridColumns, useImagePreview } from './data';
|
||||||
// @ts-ignore
|
|
||||||
import ProductCardView from './modules/ProductCardView.vue';
|
import ProductCardView from './modules/ProductCardView.vue';
|
||||||
import ProductForm from './modules/ProductForm.vue';
|
import ProductForm from './modules/ProductForm.vue';
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,18 @@ import {
|
|||||||
} from '#/api/iot/product/product';
|
} from '#/api/iot/product/product';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { generateProductKey, useBasicFormSchema, useAdvancedFormSchema } from '../data';
|
import {
|
||||||
|
generateProductKey,
|
||||||
|
useAdvancedFormSchema,
|
||||||
|
useBasicFormSchema,
|
||||||
|
} from '../data';
|
||||||
|
|
||||||
defineOptions({ name: 'IoTProductForm' });
|
defineOptions({ name: 'IoTProductForm' });
|
||||||
|
|
||||||
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const CollapsePanel = Collapse.Panel;
|
const CollapsePanel = Collapse.Panel;
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
|
||||||
const formData = ref<any>();
|
const formData = ref<any>();
|
||||||
const getTitle = computed(() => {
|
const getTitle = computed(() => {
|
||||||
return formData.value?.id ? '编辑产品' : '新增产品';
|
return formData.value?.id ? '编辑产品' : '新增产品';
|
||||||
@@ -84,7 +89,10 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const values = { ...basicValues, ...advancedValues } as IotProductApi.Product;
|
const values = {
|
||||||
|
...basicValues,
|
||||||
|
...advancedValues,
|
||||||
|
} as IotProductApi.Product;
|
||||||
const data = formData.value?.id
|
const data = formData.value?.id
|
||||||
? { ...values, id: formData.value.id }
|
? { ...values, id: formData.value.id }
|
||||||
: values;
|
: values;
|
||||||
@@ -132,7 +140,11 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 如果有图标、图片或描述,自动展开折叠面板以便显示
|
// 如果有图标、图片或描述,自动展开折叠面板以便显示
|
||||||
if (formData.value.icon || formData.value.picUrl || formData.value.description) {
|
if (
|
||||||
|
formData.value.icon ||
|
||||||
|
formData.value.picUrl ||
|
||||||
|
formData.value.description
|
||||||
|
) {
|
||||||
activeKey.value = ['advanced'];
|
activeKey.value = ['advanced'];
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ interface Props {
|
|||||||
defineProps<Props>();
|
defineProps<Props>();
|
||||||
|
|
||||||
/** 格式化日期 */
|
/** 格式化日期 */
|
||||||
const formatDate = (date?: Date | string) => {
|
function formatDate(date?: Date | string) {
|
||||||
if (!date) return '-';
|
if (!date) return '-';
|
||||||
return new Date(date).toLocaleString('zh-CN');
|
return new Date(date).toLocaleString('zh-CN');
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleProductList,
|
api: () => getSimpleProductList(),
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
|
|||||||
@@ -210,7 +210,8 @@ function handleOperatorChange() {
|
|||||||
<!-- 设备状态条件配置 -->
|
<!-- 设备状态条件配置 -->
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
|
condition.type ===
|
||||||
|
IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS.toString()
|
||||||
"
|
"
|
||||||
class="gap-16px flex flex-col"
|
class="gap-16px flex flex-col"
|
||||||
>
|
>
|
||||||
@@ -222,7 +223,7 @@ function handleOperatorChange() {
|
|||||||
<Select
|
<Select
|
||||||
:model-value="condition.operator"
|
:model-value="condition.operator"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(value) => updateConditionField('operator', value)
|
(value: any) => updateConditionField('operator', value)
|
||||||
"
|
"
|
||||||
placeholder="请选择操作符"
|
placeholder="请选择操作符"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ const timeValue2 = computed(() => {
|
|||||||
* @param value 字段值
|
* @param value 字段值
|
||||||
*/
|
*/
|
||||||
function updateConditionField(field: any, value: any) {
|
function updateConditionField(field: any, value: any) {
|
||||||
condition.value[field] = value;
|
(condition.value as any)[field] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
options: getDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE, 'number'),
|
options: getDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE, 'number'),
|
||||||
placeholder: '请选择功能类型',
|
placeholder: '请选择功能类型',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, provide, ref } from 'vue';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
|
||||||
import { Page } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import { deleteThingModel, getThingModelPage } from '#/api/iot/thingmodel';
|
|
||||||
import { getProduct } from '#/api/iot/product/product';
|
|
||||||
import type { IotProductApi } from '#/api/iot/product/product';
|
import type { IotProductApi } from '#/api/iot/product/product';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { onMounted, provide, ref } from 'vue';
|
||||||
|
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getProduct } from '#/api/iot/product/product';
|
||||||
|
import { deleteThingModel, getThingModelPage } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
import { getDataTypeOptionsLabel, IOT_PROVIDE_KEY } from '../utils/constants';
|
import { getDataTypeOptionsLabel, IOT_PROVIDE_KEY } from '../utils/constants';
|
||||||
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
import { DataDefinition } from './modules/components';
|
||||||
import ThingModelForm from './modules/ThingModelForm.vue';
|
import ThingModelForm from './modules/ThingModelForm.vue';
|
||||||
import ThingModelTSL from './modules/ThingModelTSL.vue';
|
import ThingModelTSL from './modules/ThingModelTSL.vue';
|
||||||
import { DataDefinition } from './modules/components';
|
|
||||||
|
|
||||||
defineOptions({ name: 'IoTThingModel' });
|
defineOptions({ name: 'IoTThingModel' });
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ onMounted(async () => {
|
|||||||
description="管理产品的物模型定义,包括属性、服务和事件"
|
description="管理产品的物模型定义,包括属性、服务和事件"
|
||||||
title="物模型管理"
|
title="物模型管理"
|
||||||
>
|
>
|
||||||
<Grid ref="xGrid">
|
<Grid>
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<TableAction
|
<TableAction
|
||||||
:actions="[
|
:actions="[
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ defineOptions({ name: 'ThingModelEvent' });
|
|||||||
|
|
||||||
const props = defineProps<{ isStructDataSpecs?: boolean; modelValue: any }>();
|
const props = defineProps<{ isStructDataSpecs?: boolean; modelValue: any }>();
|
||||||
const emits = defineEmits(['update:modelValue']);
|
const emits = defineEmits(['update:modelValue']);
|
||||||
const thingModelEvent = useVModel(
|
const thingModelEvent = useVModel(props, 'modelValue', emits) as Ref<any>;
|
||||||
props,
|
|
||||||
'modelValue',
|
|
||||||
emits,
|
|
||||||
) as Ref<any>;
|
|
||||||
|
|
||||||
// 默认选中,INFO 信息
|
// 默认选中,INFO 信息
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ const formRef = ref(); // 表单 Ref
|
|||||||
async function open(type: string, id?: number) {
|
async function open(type: string, id?: number) {
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
// 设置标题:create -> 新增,update -> 编辑
|
// 设置标题:create -> 新增,update -> 编辑
|
||||||
dialogTitle.value = type === 'create' ? $t('page.action.add') : $t('page.action.edit');
|
dialogTitle.value =
|
||||||
|
type === 'create' ? $t('page.action.add') : $t('page.action.edit');
|
||||||
formType.value = type;
|
formType.value = type;
|
||||||
resetForm();
|
resetForm();
|
||||||
if (id) {
|
if (id) {
|
||||||
|
|||||||
@@ -42,8 +42,13 @@ const getDataTypeOptions2 = computed(() => {
|
|||||||
if (!props.isStructDataSpecs) {
|
if (!props.isStructDataSpecs) {
|
||||||
return getDataTypeOptions();
|
return getDataTypeOptions();
|
||||||
}
|
}
|
||||||
const excludedTypes = [IoTDataSpecsDataTypeEnum.STRUCT, IoTDataSpecsDataTypeEnum.ARRAY];
|
const excludedTypes = new Set([
|
||||||
return getDataTypeOptions().filter((item: any) => !excludedTypes.includes(item.value));
|
IoTDataSpecsDataTypeEnum.ARRAY,
|
||||||
|
IoTDataSpecsDataTypeEnum.STRUCT,
|
||||||
|
]);
|
||||||
|
return getDataTypeOptions().filter(
|
||||||
|
(item: any) => !excludedTypes.has(item.value),
|
||||||
|
);
|
||||||
}); // 获得数据类型列表
|
}); // 获得数据类型列表
|
||||||
|
|
||||||
/** 属性值的数据类型切换时初始化相关数据 */
|
/** 属性值的数据类型切换时初始化相关数据 */
|
||||||
@@ -52,19 +57,11 @@ function handleChange(dataType: any) {
|
|||||||
property.value.dataSpecsList = [];
|
property.value.dataSpecsList = [];
|
||||||
// 不是列表型数据才设置 dataSpecs.dataType
|
// 不是列表型数据才设置 dataSpecs.dataType
|
||||||
![
|
![
|
||||||
IoTDataSpecsDataTypeEnum.ENUM,
|
|
||||||
IoTDataSpecsDataTypeEnum.BOOL,
|
IoTDataSpecsDataTypeEnum.BOOL,
|
||||||
|
IoTDataSpecsDataTypeEnum.ENUM,
|
||||||
IoTDataSpecsDataTypeEnum.STRUCT,
|
IoTDataSpecsDataTypeEnum.STRUCT,
|
||||||
].includes(dataType) && (property.value.dataSpecs.dataType = dataType);
|
].includes(dataType) && (property.value.dataSpecs.dataType = dataType);
|
||||||
switch (dataType) {
|
switch (dataType) {
|
||||||
case IoTDataSpecsDataTypeEnum.ENUM: {
|
|
||||||
property.value.dataSpecsList.push({
|
|
||||||
dataType: IoTDataSpecsDataTypeEnum.ENUM,
|
|
||||||
name: '', // 枚举项的名称
|
|
||||||
value: undefined, // 枚举值
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IoTDataSpecsDataTypeEnum.BOOL: {
|
case IoTDataSpecsDataTypeEnum.BOOL: {
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
property.value.dataSpecsList.push({
|
property.value.dataSpecsList.push({
|
||||||
@@ -75,6 +72,14 @@ function handleChange(dataType: any) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IoTDataSpecsDataTypeEnum.ENUM: {
|
||||||
|
property.value.dataSpecsList.push({
|
||||||
|
dataType: IoTDataSpecsDataTypeEnum.ENUM,
|
||||||
|
name: '', // 枚举项的名称
|
||||||
|
value: undefined, // 枚举值
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// useVModel 会自动同步数据到父组件,不需要手动 emit
|
// useVModel 会自动同步数据到父组件,不需要手动 emit
|
||||||
}
|
}
|
||||||
@@ -95,9 +100,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Form.Item
|
<Form.Item label="数据类型">
|
||||||
label="数据类型"
|
|
||||||
>
|
|
||||||
<Select
|
<Select
|
||||||
v-model:value="property.dataType"
|
v-model:value="property.dataType"
|
||||||
placeholder="请选择数据类型"
|
placeholder="请选择数据类型"
|
||||||
@@ -135,7 +138,7 @@ watch(
|
|||||||
label="布尔值"
|
label="布尔值"
|
||||||
>
|
>
|
||||||
<template v-for="item in property.dataSpecsList" :key="item.value">
|
<template v-for="item in property.dataSpecsList" :key="item.value">
|
||||||
<div class="flex items-center justify-start w-1/1 mb-5px">
|
<div class="w-1/1 mb-5px flex items-center justify-start">
|
||||||
<span>{{ item.value }}</span>
|
<span>{{ item.value }}</span>
|
||||||
<span class="mx-2">-</span>
|
<span class="mx-2">-</span>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
|
|||||||
@@ -92,26 +92,26 @@ watch(tslString, (newValue) => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.json-viewer-container {
|
.json-viewer-container {
|
||||||
|
max-height: 600px;
|
||||||
|
padding: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 12px;
|
|
||||||
max-height: 600px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-code {
|
.json-code {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
|
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #333;
|
color: #333;
|
||||||
white-space: pre-wrap;
|
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-editor {
|
.json-editor {
|
||||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
|
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -19,22 +19,30 @@ const props = defineProps<{ data: ThingModelData }>();
|
|||||||
|
|
||||||
// 格式化布尔值和枚举值列表为字符串
|
// 格式化布尔值和枚举值列表为字符串
|
||||||
const formattedDataSpecsList = computed(() => {
|
const formattedDataSpecsList = computed(() => {
|
||||||
if (!props.data.property?.dataSpecsList || props.data.property.dataSpecsList.length === 0) {
|
if (
|
||||||
|
!props.data.property?.dataSpecsList ||
|
||||||
|
props.data.property.dataSpecsList.length === 0
|
||||||
|
) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return props.data.property.dataSpecsList
|
return props.data.property.dataSpecsList
|
||||||
.map(item => `${item.value}-${item.name}`)
|
.map((item) => `${item.value}-${item.name}`)
|
||||||
.join('、');
|
.join('、');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 显示的简短文本(第一个值)
|
// 显示的简短文本(第一个值)
|
||||||
const shortText = computed(() => {
|
const shortText = computed(() => {
|
||||||
if (!props.data.property?.dataSpecsList || props.data.property.dataSpecsList.length === 0) {
|
if (
|
||||||
|
!props.data.property?.dataSpecsList ||
|
||||||
|
props.data.property.dataSpecsList.length === 0
|
||||||
|
) {
|
||||||
return '-';
|
return '-';
|
||||||
}
|
}
|
||||||
const first = props.data.property.dataSpecsList[0];
|
const first = props.data.property.dataSpecsList[0];
|
||||||
const count = props.data.property.dataSpecsList.length;
|
const count = props.data.property.dataSpecsList.length;
|
||||||
return count > 1 ? `${first.value}-${first.name} 等${count}项` : `${first.value}-${first.name}`;
|
return count > 1
|
||||||
|
? `${first.value}-${first.name} 等${count}项`
|
||||||
|
: `${first.value}-${first.name}`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -108,8 +116,8 @@ const shortText = computed(() => {
|
|||||||
border-bottom: 1px dashed #d9d9d9;
|
border-bottom: 1px dashed #d9d9d9;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-bottom-color: #1890ff;
|
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
|
border-bottom-color: #1890ff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ function handleChange(val: any) {
|
|||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="元素个数" name="property.dataSpecs.size">
|
<Form.Item label="元素个数" name="property.dataSpecs.size">
|
||||||
<Input v-model:value="dataSpecs.size" placeholder="请输入数组中的元素个数" />
|
<Input
|
||||||
|
v-model:value="dataSpecs.size"
|
||||||
|
placeholder="请输入数组中的元素个数"
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<!-- Struct 型配置-->
|
<!-- Struct 型配置-->
|
||||||
<ThingModelStructDataSpecs
|
<ThingModelStructDataSpecs
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ function deleteEnum(index: number) {
|
|||||||
}
|
}
|
||||||
dataSpecsList.value.splice(index, 1);
|
dataSpecsList.value.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -41,7 +40,7 @@ function deleteEnum(index: number) {
|
|||||||
<div
|
<div
|
||||||
v-for="(item, index) in dataSpecsList"
|
v-for="(item, index) in dataSpecsList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="flex items-center justify-between mb-5px"
|
class="mb-5px flex items-center justify-between"
|
||||||
>
|
>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<Input v-model:value="item.value" placeholder="请输入枚举值,如'0'" />
|
<Input v-model:value="item.value" placeholder="请输入枚举值,如'0'" />
|
||||||
|
|||||||
@@ -1,4 +1,35 @@
|
|||||||
<!-- dataType:number 数组类型 -->
|
<!-- dataType:number 数组类型 -->
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
|
import type { DataSpecsNumberData } from '#/api/iot/thingmodel';
|
||||||
|
|
||||||
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { useVModel } from '@vueuse/core';
|
||||||
|
import { Form, Input, Select } from 'ant-design-vue';
|
||||||
|
|
||||||
|
/** 数值型的 dataSpecs 配置组件 */
|
||||||
|
defineOptions({ name: 'ThingModelNumberDataSpecs' });
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: any }>();
|
||||||
|
const emits = defineEmits(['update:modelValue']);
|
||||||
|
const dataSpecs = useVModel(
|
||||||
|
props,
|
||||||
|
'modelValue',
|
||||||
|
emits,
|
||||||
|
) as Ref<DataSpecsNumberData>;
|
||||||
|
|
||||||
|
/** 单位发生变化时触发 */
|
||||||
|
const unitChange = (UnitSpecs: any) => {
|
||||||
|
if (!UnitSpecs) return;
|
||||||
|
const [unitName, unit] = String(UnitSpecs).split('-');
|
||||||
|
dataSpecs.value.unitName = unitName;
|
||||||
|
dataSpecs.value.unit = unit;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Form.Item label="取值范围">
|
<Form.Item label="取值范围">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
@@ -38,38 +69,6 @@
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import type { Ref } from 'vue';
|
|
||||||
|
|
||||||
import type { DataSpecsNumberData } from '#/api/iot/thingmodel';
|
|
||||||
|
|
||||||
import { useVModel } from '@vueuse/core';
|
|
||||||
|
|
||||||
import { Form, Input, Select } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
|
||||||
import { getDictOptions } from '@vben/hooks';
|
|
||||||
|
|
||||||
/** 数值型的 dataSpecs 配置组件 */
|
|
||||||
defineOptions({ name: 'ThingModelNumberDataSpecs' });
|
|
||||||
|
|
||||||
const props = defineProps<{ modelValue: any }>();
|
|
||||||
const emits = defineEmits(['update:modelValue']);
|
|
||||||
const dataSpecs = useVModel(
|
|
||||||
props,
|
|
||||||
'modelValue',
|
|
||||||
emits,
|
|
||||||
) as Ref<DataSpecsNumberData>;
|
|
||||||
|
|
||||||
/** 单位发生变化时触发 */
|
|
||||||
const unitChange = (UnitSpecs: any) => {
|
|
||||||
if (!UnitSpecs) return;
|
|
||||||
const [unitName, unit] = String(UnitSpecs).split('-');
|
|
||||||
dataSpecs.value.unitName = unitName;
|
|
||||||
dataSpecs.value.unit = unit;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
:deep(.ant-form-item) {
|
:deep(.ant-form-item) {
|
||||||
.ant-form-item {
|
.ant-form-item {
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ function resetForm() {
|
|||||||
structFormRef.value?.resetFields();
|
structFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 组件初始化 */
|
/** 组件初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await nextTick();
|
await nextTick();
|
||||||
@@ -134,18 +133,14 @@ onMounted(async () => {
|
|||||||
>
|
>
|
||||||
<span>参数:{{ item.name }}</span>
|
<span>参数:{{ item.name }}</span>
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<Button type="link" @click="openStructForm(item)">
|
<Button type="link" @click="openStructForm(item)"> 编辑 </Button>
|
||||||
编辑
|
|
||||||
</Button>
|
|
||||||
<Divider type="vertical" />
|
<Divider type="vertical" />
|
||||||
<Button type="link" danger @click="deleteStructItem(index)">
|
<Button type="link" danger @click="deleteStructItem(index)">
|
||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button type="link" @click="openStructForm(null)">
|
<Button type="link" @click="openStructForm(null)"> +新增参数 </Button>
|
||||||
+新增参数
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<!-- struct 表单 -->
|
<!-- struct 表单 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user