fix: iot warn

This commit is contained in:
xingyu4j
2025-10-20 10:37:23 +08:00
parent 948cb916c4
commit c6ef77694e
35 changed files with 476 additions and 455 deletions

View File

@@ -101,6 +101,7 @@ export interface Action {
identifier?: string;
value?: any;
alertConfigId?: number;
params?: string;
}
/** 查询场景联动规则分页 */

View File

@@ -63,7 +63,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '关联场景联动规则',
component: 'ApiSelect',
componentProps: {
api: getSimpleRuleSceneList,
api: () => getSimpleRuleSceneList(),
labelField: 'name',
valueField: 'id',
mode: 'multiple',
@@ -76,7 +76,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '接收的用户',
component: 'ApiSelect',
componentProps: {
api: getSimpleUserList,
api: () => getSimpleUserList(),
labelField: 'nickname',
valueField: 'id',
mode: 'multiple',

View File

@@ -17,7 +17,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '告警配置',
component: 'ApiSelect',
componentProps: {
api: getSimpleAlertConfigList,
api: () => getSimpleAlertConfigList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择告警配置',
@@ -40,7 +40,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',
@@ -53,7 +53,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '设备',
component: 'ApiSelect',
componentProps: {
api: getSimpleDeviceList,
api: () => getSimpleDeviceList(),
labelField: 'deviceName',
valueField: 'id',
placeholder: '请选择设备',

View File

@@ -101,7 +101,7 @@ async function handleProcess(row: AlertRecord) {
try {
await processAlertRecord(row.id as number, processRemark);
message.success('处理成功');
onRefresh();
handleRefresh();
} catch (error) {
console.error('处理失败:', error);
throw error;

View File

@@ -5,6 +5,7 @@ import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { z } from '#/adapter/form';
import { getSimpleDeviceList } from '#/api/iot/device/device';
import { getSimpleDeviceGroupList } from '#/api/iot/device/group';
import {
DeviceTypeEnum,
@@ -27,7 +28,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',
@@ -55,12 +56,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '网关设备',
component: 'ApiSelect',
componentProps: {
api: async () => {
const { getSimpleDeviceList } = await import(
'#/api/iot/device/device'
);
return getSimpleDeviceList(DeviceTypeEnum.GATEWAY);
},
api: () => getSimpleDeviceList(DeviceTypeEnum.GATEWAY),
labelField: 'nickname',
valueField: 'id',
placeholder: '子设备可选择父设备',
@@ -93,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '设备分组',
component: 'ApiSelect',
componentProps: {
api: getSimpleDeviceGroupList,
api: () => getSimpleDeviceGroupList(),
labelField: 'name',
valueField: 'id',
mode: 'multiple',
@@ -160,7 +156,7 @@ export function useGroupFormSchema(): VbenFormSchema[] {
label: '设备分组',
component: 'ApiSelect',
componentProps: {
api: getSimpleDeviceGroupList,
api: () => getSimpleDeviceGroupList(),
labelField: 'name',
valueField: 'id',
mode: 'multiple',
@@ -203,7 +199,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',
@@ -253,7 +249,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '设备分组',
component: 'ApiSelect',
componentProps: {
api: getSimpleDeviceGroupList,
api: () => getSimpleDeviceGroupList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择设备分组',

View File

@@ -32,7 +32,6 @@ import { getSimpleProductList } from '#/api/iot/product/product';
import { $t } from '#/locales';
import { useGridColumns } from './data';
// @ts-ignore
import DeviceCardView from './modules/DeviceCardView.vue';
import DeviceForm from './modules/DeviceForm.vue';
import DeviceGroupForm from './modules/DeviceGroupForm.vue';

View File

@@ -1,15 +1,13 @@
<script setup lang="ts">
import type { IotDeviceApi } from '#/api/iot/device/device';
import { computed, ref } from 'vue';
import { message } from 'ant-design-vue';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import {
createDevice,
getDevice,
updateDevice,
} from '#/api/iot/device/device';
import type { IotDeviceApi } from '#/api/iot/device/device';
import { message } from 'ant-design-vue';
import { createDevice, getDevice, updateDevice } from '#/api/iot/device/device';
import { $t } from '#/locales';
import { useFormSchema } from '../data';

View File

@@ -44,7 +44,7 @@ const [Modal, modalApi] = useVbenModal({
// 关闭并提示
await modalApi.close();
emit('success');
message.success($t('common.updateSuccess'));
message.success($t('ui.actionMessage.operationSuccess'));
} finally {
modalApi.unlock();
}

View File

@@ -80,6 +80,7 @@ async function saveConfig() {
try {
config.value = JSON.parse(configString.value);
} catch (error) {
console.error('JSON格式错误:', error);
message.error({ content: 'JSON格式错误请修正后再提交' });
return;
}
@@ -176,33 +177,31 @@ async function updateDeviceConfig() {
placeholder="请输入 JSON 格式的配置信息"
class="json-editor"
/>
</div>
</template>
<style scoped>
.json-viewer-container {
max-height: 600px;
padding: 12px;
overflow-y: auto;
background-color: #f5f5f5;
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 12px;
max-height: 600px;
overflow-y: auto;
}
.json-code {
margin: 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
font-size: 13px;
line-height: 1.5;
color: #333;
white-space: pre-wrap;
word-wrap: break-word;
white-space: pre-wrap;
}
.json-editor {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
font-size: 13px;
}
</style>

View File

@@ -1,12 +1,27 @@
<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 { DICT_TYPE } from '@vben/constants';
import { IconifyIcon } from '@vben/icons';
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 { DictTag } from '#/components/dict-tag';

View File

@@ -9,6 +9,7 @@ import type { ThingModelData } from '#/api/iot/thingmodel';
import { computed, ref } from 'vue';
import { ContentWrap } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import {
Button,
@@ -19,16 +20,14 @@ import {
Tabs,
Textarea,
} from 'ant-design-vue';
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue';
import { DeviceStateEnum, sendDeviceMessage } from '#/api/iot/device/device';
import DataDefinition from '#/views/iot/thingmodel/modules/components/DataDefinition.vue';
import {
IotDeviceMessageMethodEnum,
IoTThingModelTypeEnum,
} from '#/views/iot/utils/constants';
import DataDefinition from '#/views/iot/thingmodel/modules/components/DataDefinition.vue';
import DeviceDetailsMessage from './DeviceDetailsMessage.vue';
const props = defineProps<{
@@ -340,7 +339,7 @@ async function handleServiceInvoke(row: ThingModelData) {
<template>
<ContentWrap>
<!-- 上方指令调试区域 -->
<Card class="mb-4 simulator-tabs">
<Card class="simulator-tabs mb-4">
<template #title>
<div class="flex items-center justify-between">
<span>指令调试</span>
@@ -349,8 +348,8 @@ async function handleServiceInvoke(row: ThingModelData) {
size="small"
@click="debugCollapsed = !debugCollapsed"
>
<UpOutlined v-if="!debugCollapsed" />
<DownOutlined v-if="debugCollapsed" />
<IconifyIcon icon="lucide:chevron-up" v-if="!debugCollapsed" />
<IconifyIcon icon="lucide:chevron-down" v-if="debugCollapsed" />
</Button>
</div>
</template>
@@ -587,8 +586,8 @@ async function handleServiceInvoke(row: ThingModelData) {
size="small"
@click="messageCollapsed = !messageCollapsed"
>
<UpOutlined v-if="!messageCollapsed" />
<DownOutlined v-if="messageCollapsed" />
<IconifyIcon icon="lucide:chevron-down" v-if="!messageCollapsed" />
<IconifyIcon icon="lucide:chevron-down" v-if="messageCollapsed" />
</Button>
</div>
</template>

View File

@@ -41,4 +41,3 @@ onMounted(() => {
<!-- TODO: 实现子设备列表展示和管理功能 -->
</Card>
</template>

View File

@@ -137,7 +137,9 @@ async function getList() {
try {
const data = await getHistoryDevicePropertyList(queryParams);
// 后端直接返回数组,不是 { 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;
// 如果是图表模式且不是复杂数据类型,渲染图表

View File

@@ -34,11 +34,9 @@ export function useFormSchema(): VbenFormSchema[] {
label: '父级分组',
component: 'ApiTreeSelect',
componentProps: {
api: getSimpleDeviceGroupList,
fieldNames: {
label: 'name',
value: 'id',
},
api: () => getSimpleDeviceGroupList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择父级分组',
allowClear: true,
},

View File

@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '所属产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',
@@ -85,7 +85,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',

View File

@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: '所属产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',
@@ -86,7 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',

View File

@@ -34,11 +34,9 @@ export function useFormSchema(): VbenFormSchema[] {
label: '父级分类',
component: 'ApiTreeSelect',
componentProps: {
api: getSimpleProductCategoryList,
fieldNames: {
label: 'name',
value: 'id',
},
api: () => getSimpleProductCategoryList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择父级分类',
allowClear: true,
},

View File

@@ -93,7 +93,7 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
label: '产品分类',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductCategoryList,
api: () => getSimpleProductCategoryList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品分类',
@@ -246,7 +246,7 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
label: '产品分类',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductCategoryList,
api: () => getSimpleProductCategoryList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品分类',

View File

@@ -11,16 +11,15 @@ import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, Card, Image, Input, message, Space } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSimpleProductCategoryList } from '#/api/iot/product/category';
import {
deleteProduct,
exportProduct,
getProductPage,
} from '#/api/iot/product/product';
import { getSimpleProductCategoryList } from '#/api/iot/product/category';
import { $t } from '#/locales';
import { useGridColumns, useImagePreview } from './data';
// @ts-ignore
import ProductCardView from './modules/ProductCardView.vue';
import ProductForm from './modules/ProductForm.vue';

View File

@@ -14,13 +14,18 @@ import {
} from '#/api/iot/product/product';
import { $t } from '#/locales';
import { generateProductKey, useBasicFormSchema, useAdvancedFormSchema } from '../data';
import {
generateProductKey,
useAdvancedFormSchema,
useBasicFormSchema,
} from '../data';
defineOptions({ name: 'IoTProductForm' });
const emit = defineEmits(['success']);
const CollapsePanel = Collapse.Panel;
const emit = defineEmits(['success']);
const formData = ref<any>();
const getTitle = computed(() => {
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
? { ...values, id: formData.value.id }
: 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'];
}
} catch (error) {

View File

@@ -15,10 +15,10 @@ interface Props {
defineProps<Props>();
/** 格式化日期 */
const formatDate = (date?: Date | string) => {
function formatDate(date?: Date | string) {
if (!date) return '-';
return new Date(date).toLocaleString('zh-CN');
};
}
</script>
<template>

View File

@@ -24,7 +24,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '产品',
component: 'ApiSelect',
componentProps: {
api: getSimpleProductList,
api: () => getSimpleProductList(),
labelField: 'name',
valueField: 'id',
placeholder: '请选择产品',

View File

@@ -210,7 +210,8 @@ function handleOperatorChange() {
<!-- 设备状态条件配置 -->
<div
v-if="
condition.type === IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS
condition.type ===
IotRuleSceneTriggerConditionTypeEnum.DEVICE_STATUS.toString()
"
class="gap-16px flex flex-col"
>
@@ -222,7 +223,7 @@ function handleOperatorChange() {
<Select
:model-value="condition.operator"
@update:model-value="
(value) => updateConditionField('operator', value)
(value: any) => updateConditionField('operator', value)
"
placeholder="请选择操作符"
class="w-full"

View File

@@ -120,7 +120,7 @@ const timeValue2 = computed(() => {
* @param value 字段值
*/
function updateConditionField(field: any, value: any) {
condition.value[field] = value;
(condition.value as any)[field] = value;
}
/**

View File

@@ -15,7 +15,6 @@ export function useGridFormSchema(): VbenFormSchema[] {
options: getDictOptions(DICT_TYPE.IOT_THING_MODEL_TYPE, 'number'),
placeholder: '请选择功能类型',
allowClear: true,
},
},
];

View File

@@ -1,19 +1,21 @@
<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 { 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 { useGridColumns, useGridFormSchema } from './data';
import { DataDefinition } from './modules/components';
import ThingModelForm from './modules/ThingModelForm.vue';
import ThingModelTSL from './modules/ThingModelTSL.vue';
import { DataDefinition } from './modules/components';
defineOptions({ name: 'IoTThingModel' });
@@ -119,7 +121,7 @@ onMounted(async () => {
description="管理产品的物模型定义,包括属性、服务和事件"
title="物模型管理"
>
<Grid ref="xGrid">
<Grid>
<template #toolbar-tools>
<TableAction
:actions="[

View File

@@ -21,11 +21,7 @@ defineOptions({ name: 'ThingModelEvent' });
const props = defineProps<{ isStructDataSpecs?: boolean; modelValue: any }>();
const emits = defineEmits(['update:modelValue']);
const thingModelEvent = useVModel(
props,
'modelValue',
emits,
) as Ref<any>;
const thingModelEvent = useVModel(props, 'modelValue', emits) as Ref<any>;
// 默认选中INFO 信息
watch(

View File

@@ -64,7 +64,8 @@ const formRef = ref(); // 表单 Ref
async function open(type: string, id?: number) {
dialogVisible.value = true;
// 设置标题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;
resetForm();
if (id) {

View File

@@ -42,8 +42,13 @@ const getDataTypeOptions2 = computed(() => {
if (!props.isStructDataSpecs) {
return getDataTypeOptions();
}
const excludedTypes = [IoTDataSpecsDataTypeEnum.STRUCT, IoTDataSpecsDataTypeEnum.ARRAY];
return getDataTypeOptions().filter((item: any) => !excludedTypes.includes(item.value));
const excludedTypes = new Set([
IoTDataSpecsDataTypeEnum.ARRAY,
IoTDataSpecsDataTypeEnum.STRUCT,
]);
return getDataTypeOptions().filter(
(item: any) => !excludedTypes.has(item.value),
);
}); // 获得数据类型列表
/** 属性值的数据类型切换时初始化相关数据 */
@@ -52,19 +57,11 @@ function handleChange(dataType: any) {
property.value.dataSpecsList = [];
// 不是列表型数据才设置 dataSpecs.dataType
![
IoTDataSpecsDataTypeEnum.ENUM,
IoTDataSpecsDataTypeEnum.BOOL,
IoTDataSpecsDataTypeEnum.ENUM,
IoTDataSpecsDataTypeEnum.STRUCT,
].includes(dataType) && (property.value.dataSpecs.dataType = dataType);
switch (dataType) {
case IoTDataSpecsDataTypeEnum.ENUM: {
property.value.dataSpecsList.push({
dataType: IoTDataSpecsDataTypeEnum.ENUM,
name: '', // 枚举项的名称
value: undefined, // 枚举值
});
break;
}
case IoTDataSpecsDataTypeEnum.BOOL: {
for (let i = 0; i < 2; i++) {
property.value.dataSpecsList.push({
@@ -75,6 +72,14 @@ function handleChange(dataType: any) {
}
break;
}
case IoTDataSpecsDataTypeEnum.ENUM: {
property.value.dataSpecsList.push({
dataType: IoTDataSpecsDataTypeEnum.ENUM,
name: '', // 枚举项的名称
value: undefined, // 枚举值
});
break;
}
}
// useVModel 会自动同步数据到父组件,不需要手动 emit
}
@@ -95,9 +100,7 @@ watch(
</script>
<template>
<Form.Item
label="数据类型"
>
<Form.Item label="数据类型">
<Select
v-model:value="property.dataType"
placeholder="请选择数据类型"
@@ -135,7 +138,7 @@ watch(
label="布尔值"
>
<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 class="mx-2">-</span>
<div class="flex-1">

View File

@@ -92,26 +92,26 @@ watch(tslString, (newValue) => {
<style scoped>
.json-viewer-container {
max-height: 600px;
padding: 12px;
overflow-y: auto;
background-color: #f5f5f5;
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 12px;
max-height: 600px;
overflow-y: auto;
}
.json-code {
margin: 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
font-size: 13px;
line-height: 1.5;
color: #333;
white-space: pre-wrap;
word-wrap: break-word;
white-space: pre-wrap;
}
.json-editor {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, monospace;
font-size: 13px;
}
</style>

View File

@@ -19,22 +19,30 @@ const props = defineProps<{ data: ThingModelData }>();
// 格式化布尔值和枚举值列表为字符串
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 props.data.property.dataSpecsList
.map(item => `${item.value}-${item.name}`)
.map((item) => `${item.value}-${item.name}`)
.join('、');
});
// 显示的简短文本(第一个值)
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 '-';
}
const first = props.data.property.dataSpecsList[0];
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>
@@ -108,8 +116,8 @@ const shortText = computed(() => {
border-bottom: 1px dashed #d9d9d9;
&:hover {
border-bottom-color: #1890ff;
color: #1890ff;
border-bottom-color: #1890ff;
}
}
</style>

View File

@@ -51,7 +51,10 @@ function handleChange(val: any) {
</Radio.Group>
</Form.Item>
<Form.Item label="元素个数" name="property.dataSpecs.size">
<Input v-model:value="dataSpecs.size" placeholder="请输入数组中的元素个数" />
<Input
v-model:value="dataSpecs.size"
placeholder="请输入数组中的元素个数"
/>
</Form.Item>
<!-- Struct 型配置-->
<ThingModelStructDataSpecs

View File

@@ -28,7 +28,6 @@ function deleteEnum(index: number) {
}
dataSpecsList.value.splice(index, 1);
}
</script>
<template>
@@ -41,7 +40,7 @@ function deleteEnum(index: number) {
<div
v-for="(item, index) in dataSpecsList"
:key="index"
class="flex items-center justify-between mb-5px"
class="mb-5px flex items-center justify-between"
>
<div class="flex-1">
<Input v-model:value="item.value" placeholder="请输入枚举值,如'0'" />

View File

@@ -1,4 +1,35 @@
<!-- dataTypenumber 数组类型 -->
<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>
<Form.Item label="取值范围">
<div class="flex items-center justify-between">
@@ -38,38 +69,6 @@
</Form.Item>
</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>
:deep(.ant-form-item) {
.ant-form-item {

View File

@@ -115,7 +115,6 @@ function resetForm() {
structFormRef.value?.resetFields();
}
/** 组件初始化 */
onMounted(async () => {
await nextTick();
@@ -134,18 +133,14 @@ onMounted(async () => {
>
<span>参数{{ item.name }}</span>
<div class="btn">
<Button type="link" @click="openStructForm(item)">
编辑
</Button>
<Button type="link" @click="openStructForm(item)"> 编辑 </Button>
<Divider type="vertical" />
<Button type="link" danger @click="deleteStructItem(index)">
删除
</Button>
</div>
</div>
<Button type="link" @click="openStructForm(null)">
+新增参数
</Button>
<Button type="link" @click="openStructForm(null)"> +新增参数 </Button>
</Form.Item>
<!-- struct 表单 -->