fix: 修复 iot 模块 ele 端迁移阻塞的类型 / 字段问题(P0)
- ele property-selector / device-control-config,改用 ThingModelApi 命名空间引用 - ele api/iot/thingmodel,补 ThingModelTSL 类型,收敛 getThingModelTSLByProductId 返回值 - ele api/iot/rule/scene,SceneRule 补 lastTriggeredTime 字段 - ele views/iot/rule/scene/data.ts,useGridColumns 对齐 antd 的 5 列结构 - ele views/iot/home/modules/message-trend-card,ElSelect 改用 ElOption 子节点 - ele / antd api/iot/rule/scene,Action.params 类型 Record<string, any> 改为 string Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>pull/345/head
parent
f02a5975b8
commit
0d175cbe9c
|
|
@ -46,7 +46,7 @@ export namespace RuleSceneApi {
|
|||
identifier?: string;
|
||||
value?: any;
|
||||
alertConfigId?: number;
|
||||
params?: Record<string, any>;
|
||||
params?: string;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export namespace RuleSceneApi {
|
|||
status?: number;
|
||||
triggers?: Trigger[];
|
||||
actions?: Action[];
|
||||
lastTriggeredTime?: Date;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ export namespace RuleSceneApi {
|
|||
identifier?: string;
|
||||
value?: any;
|
||||
alertConfigId?: number;
|
||||
params?: Record<string, any>;
|
||||
params?: string;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,15 @@ export namespace ThingModelApi {
|
|||
dataSpecsList?: any[];
|
||||
}
|
||||
|
||||
/** IoT 物模型 TSL 响应 */
|
||||
export interface ThingModelTSL {
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
properties?: Property[];
|
||||
events?: Event[];
|
||||
services?: Service[];
|
||||
}
|
||||
|
||||
/** IoT 数据定义(数值型) */
|
||||
export interface DataSpecsNumberData {
|
||||
min?: number | string;
|
||||
|
|
@ -236,7 +245,10 @@ export function deleteThingModel(id: number) {
|
|||
|
||||
/** 获取物模型 TSL */
|
||||
export function getThingModelTSLByProductId(productId: number) {
|
||||
return requestClient.get<any>('/iot/thing-model/get-tsl', {
|
||||
params: { productId },
|
||||
});
|
||||
return requestClient.get<ThingModelApi.ThingModelTSL>(
|
||||
'/iot/thing-model/get-tsl',
|
||||
{
|
||||
params: { productId },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { getDictOptions } from '@vben/hooks';
|
|||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import { ElCard, ElEmpty, ElSelect } from 'element-plus';
|
||||
import { ElCard, ElEmpty, ElOption, ElSelect } from 'element-plus';
|
||||
|
||||
import { getDeviceMessageSummaryByDate } from '#/api/iot/statistics';
|
||||
import ShortcutDateRangePicker from '#/components/shortcut-date-range-picker/shortcut-date-range-picker.vue';
|
||||
|
|
@ -145,11 +145,17 @@ onMounted(() => {
|
|||
<span class="text-sm text-gray-500">时间间隔</span>
|
||||
<ElSelect
|
||||
v-model="queryParams.interval"
|
||||
:options="intervalOptions"
|
||||
placeholder="间隔类型"
|
||||
:style="{ width: '80px' }"
|
||||
@change="handleIntervalChange"
|
||||
/>
|
||||
>
|
||||
<ElOption
|
||||
v-for="opt in intervalOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -89,49 +89,45 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||
return [
|
||||
{ type: 'checkbox', width: 40 },
|
||||
{
|
||||
field: 'id',
|
||||
title: '规则编号',
|
||||
minWidth: 80,
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
title: '规则名称',
|
||||
minWidth: 150,
|
||||
},
|
||||
{
|
||||
field: 'description',
|
||||
title: '规则描述',
|
||||
minWidth: 200,
|
||||
align: 'left',
|
||||
showOverflow: false,
|
||||
slots: { default: 'name' },
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '规则状态',
|
||||
minWidth: 100,
|
||||
cellRender: {
|
||||
name: 'CellDict',
|
||||
props: { type: DICT_TYPE.COMMON_STATUS },
|
||||
},
|
||||
field: 'triggers',
|
||||
title: '触发条件',
|
||||
minWidth: 280,
|
||||
align: 'left',
|
||||
showOverflow: false,
|
||||
slots: { default: 'triggers' },
|
||||
},
|
||||
{
|
||||
field: 'actionCount',
|
||||
title: '执行动作数',
|
||||
minWidth: 100,
|
||||
field: 'actions',
|
||||
title: '执行动作',
|
||||
minWidth: 250,
|
||||
align: 'left',
|
||||
showOverflow: false,
|
||||
slots: { default: 'actionsCol' },
|
||||
},
|
||||
{
|
||||
field: 'executeCount',
|
||||
title: '执行次数',
|
||||
minWidth: 100,
|
||||
field: 'lastTriggeredTime',
|
||||
title: '最近触发',
|
||||
width: 180,
|
||||
slots: { default: 'lastTriggeredTime' },
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
title: '创建时间',
|
||||
minWidth: 180,
|
||||
width: 180,
|
||||
formatter: 'formatDateTime',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 240,
|
||||
width: 210,
|
||||
fixed: 'right',
|
||||
slots: { default: 'actions' },
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<!-- 设备控制配置组件 -->
|
||||
<script setup lang="ts">
|
||||
import type { Action } from '#/api/iot/rule/scene';
|
||||
import type {
|
||||
ThingModelProperty,
|
||||
ThingModelService,
|
||||
} from '#/api/iot/thingmodel';
|
||||
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
||||
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
|
||||
|
|
@ -44,10 +41,10 @@ const emit = defineEmits<{
|
|||
|
||||
const action = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const thingModelProperties = ref<ThingModelProperty[]>([]); // 物模型属性列表
|
||||
const thingModelProperties = ref<ThingModelApi.Property[]>([]); // 物模型属性列表
|
||||
const loadingThingModel = ref(false); // 物模型加载状态
|
||||
const selectedService = ref<null | ThingModelService>(null); // 选中的服务对象
|
||||
const serviceList = ref<ThingModelService[]>([]); // 服务列表
|
||||
const selectedService = ref<null | ThingModelApi.Service>(null); // 选中的服务对象
|
||||
const serviceList = ref<ThingModelApi.Service[]>([]); // 服务列表
|
||||
const loadingServices = ref(false); // 服务加载状态
|
||||
|
||||
// 参数值的计算属性,用于双向绑定
|
||||
|
|
@ -178,7 +175,7 @@ async function loadThingModelProperties(productId: number) {
|
|||
|
||||
// 过滤出可写的属性(accessMode 包含 'w')
|
||||
thingModelProperties.value = tslData.properties.filter(
|
||||
(property: ThingModelProperty) =>
|
||||
(property: ThingModelApi.Property) =>
|
||||
property.accessMode &&
|
||||
(property.accessMode === IoTThingModelAccessModeEnum.READ_WRITE.value ||
|
||||
property.accessMode === IoTThingModelAccessModeEnum.WRITE_ONLY.value),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
<!-- 属性选择器组件 -->
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
ThingModelApi,
|
||||
ThingModelEvent,
|
||||
ThingModelProperty,
|
||||
ThingModelService,
|
||||
} from '#/api/iot/thingmodel';
|
||||
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
||||
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
|
|
@ -61,18 +56,18 @@ interface PropertySelectorItem {
|
|||
range?: string;
|
||||
eventType?: string;
|
||||
callType?: string;
|
||||
inputParams?: ThingModelParam[];
|
||||
outputParams?: ThingModelParam[];
|
||||
property?: ThingModelProperty;
|
||||
event?: ThingModelEvent;
|
||||
service?: ThingModelService;
|
||||
inputParams?: ThingModelApi.Param[];
|
||||
outputParams?: ThingModelApi.Param[];
|
||||
property?: ThingModelApi.Property;
|
||||
event?: ThingModelApi.Event;
|
||||
service?: ThingModelApi.Service;
|
||||
}
|
||||
|
||||
const localValue = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const loading = ref(false); // 加载状态
|
||||
const propertyList = ref<ThingModelApi.Property[]>([]); // 属性列表
|
||||
const thingModelTSL = ref<null | ThingModelApi.ThingModel>(null); // 物模型TSL数据
|
||||
const propertyList = ref<PropertySelectorItem[]>([]); // 属性列表
|
||||
const thingModelTSL = ref<null | ThingModelApi.ThingModelTSL>(null); // 物模型 TSL 数据
|
||||
|
||||
// 计算属性:属性分组
|
||||
const propertyGroups = computed(() => {
|
||||
|
|
@ -169,10 +164,10 @@ function parseThingModelData() {
|
|||
if (tsl.properties && Array.isArray(tsl.properties)) {
|
||||
tsl.properties.forEach((prop) => {
|
||||
properties.push({
|
||||
identifier: prop.identifier,
|
||||
name: prop.name,
|
||||
identifier: prop.identifier!,
|
||||
name: prop.name!,
|
||||
description: prop.description,
|
||||
dataType: prop.dataType,
|
||||
dataType: prop.dataType!,
|
||||
type: IoTThingModelTypeEnum.PROPERTY,
|
||||
accessMode: prop.accessMode,
|
||||
required: prop.required,
|
||||
|
|
@ -187,8 +182,8 @@ function parseThingModelData() {
|
|||
if (tsl.events && Array.isArray(tsl.events)) {
|
||||
tsl.events.forEach((event) => {
|
||||
properties.push({
|
||||
identifier: event.identifier,
|
||||
name: event.name,
|
||||
identifier: event.identifier!,
|
||||
name: event.name!,
|
||||
description: event.description,
|
||||
dataType: 'struct',
|
||||
type: IoTThingModelTypeEnum.EVENT,
|
||||
|
|
@ -204,8 +199,8 @@ function parseThingModelData() {
|
|||
if (tsl.services && Array.isArray(tsl.services)) {
|
||||
tsl.services.forEach((service) => {
|
||||
properties.push({
|
||||
identifier: service.identifier,
|
||||
name: service.name,
|
||||
identifier: service.identifier!,
|
||||
name: service.name!,
|
||||
description: service.description,
|
||||
dataType: 'struct',
|
||||
type: IoTThingModelTypeEnum.SERVICE,
|
||||
|
|
|
|||
Loading…
Reference in New Issue