fix: iot && IconifyIcon
This commit is contained in:
@@ -3,6 +3,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { IoTOtaFirmwareApi } from '#/api/iot/ota/firmware';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
@@ -119,7 +120,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
download
|
||||
class="text-primary cursor-pointer hover:underline"
|
||||
>
|
||||
<Icon icon="ant-design:download-outlined" class="mr-1" />
|
||||
<IconifyIcon icon="ant-design:download-outlined" class="mr-1" />
|
||||
下载固件
|
||||
</a>
|
||||
<span v-else class="text-gray-400">无文件</span>
|
||||
|
||||
@@ -5,10 +5,19 @@ import type { OtaTask } from '#/api/iot/ota/task';
|
||||
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { VbenButton } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { formatDate } from '@vben/utils';
|
||||
|
||||
import { Card, Input, message, Modal, Space, Table, Tag } from 'ant-design-vue';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import * as IoTOtaTaskApi from '#/api/iot/ota/task';
|
||||
import { IoTOtaTaskStatusEnum } from '#/views/iot/utils/constants';
|
||||
@@ -167,10 +176,10 @@ onMounted(() => {
|
||||
<Card title="升级任务管理" class="mb-5">
|
||||
<!-- 搜索栏 -->
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<VbenButton type="primary" @click="openTaskForm">
|
||||
<Icon icon="ant-design:plus-outlined" class="mr-1" />
|
||||
<Button type="primary" @click="openTaskForm">
|
||||
<IconifyIcon icon="ant-design:plus-outlined" class="mr-1" />
|
||||
新增
|
||||
</VbenButton>
|
||||
</Button>
|
||||
<Input
|
||||
v-model:value="queryParams.name"
|
||||
placeholder="请输入任务名称"
|
||||
|
||||
@@ -87,7 +87,7 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
||||
<!-- 空状态 -->
|
||||
<div v-if="!subGroup || subGroup.length === 0" class="py-24px text-center">
|
||||
<div class="gap-12px flex flex-col items-center">
|
||||
<Icon
|
||||
<IconifyIcon
|
||||
icon="ep:plus"
|
||||
class="text-32px text-[var(--el-text-color-placeholder)]"
|
||||
/>
|
||||
@@ -96,7 +96,7 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
||||
<p class="text-12px">点击下方按钮添加第一个条件</p>
|
||||
</div>
|
||||
<Button type="primary" @click="addCondition">
|
||||
<Icon icon="ep:plus" />
|
||||
<IconifyIcon icon="ep:plus" />
|
||||
添加条件
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { VxeGridInstance } from '#/adapter/vxe-table';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { ThingModelApi } from '#/api/iot/thingmodel';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { deleteThingModel, getThingModelPage } from '#/api/iot/thingmodel';
|
||||
@@ -20,6 +22,8 @@ const props = defineProps<{
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {
|
||||
columns: useGridColumns(),
|
||||
height: 'auto',
|
||||
keepSource: true,
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page, form }) => {
|
||||
@@ -32,26 +36,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rowConfig: {
|
||||
keyField: 'id',
|
||||
isHover: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
refresh: true,
|
||||
search: true,
|
||||
},
|
||||
} as VxeTableGridOptions<ThingModelApi.ThingModel>,
|
||||
formOptions: {
|
||||
schema: useGridFormSchema(),
|
||||
},
|
||||
});
|
||||
|
||||
const xGrid = shallowRef<VxeGridInstance>();
|
||||
const formRef = ref();
|
||||
const tslRef = ref();
|
||||
|
||||
// 新增功能
|
||||
const handleCreate = () => {
|
||||
// TODO: 打开物模型表单
|
||||
console.log('新增功能');
|
||||
console.error('新增功能');
|
||||
};
|
||||
|
||||
// 编辑功能
|
||||
const handleEdit = (row: any) => {
|
||||
// TODO: 打开物模型表单
|
||||
console.log('编辑功能:', row);
|
||||
console.error('编辑功能:', row);
|
||||
};
|
||||
|
||||
// 删除功能
|
||||
@@ -68,7 +76,7 @@ const handleDelete = async (row: any) => {
|
||||
// 打开 TSL
|
||||
const handleOpenTSL = () => {
|
||||
// TODO: 打开 TSL 弹窗
|
||||
console.log('打开 TSL');
|
||||
console.error('打开 TSL');
|
||||
};
|
||||
|
||||
// 获取数据类型标签
|
||||
@@ -82,13 +90,13 @@ const getDataTypeLabel = (row: any) => {
|
||||
description="管理产品的物模型定义,包括属性、服务和事件"
|
||||
title="物模型管理"
|
||||
>
|
||||
<Grid ref="xGrid">
|
||||
<Grid>
|
||||
<template #toolbar-tools>
|
||||
<VbenButton @click="handleCreate">
|
||||
<Icon icon="ant-design:plus-outlined" class="mr-1" />
|
||||
<Button @click="handleCreate">
|
||||
<IconifyIcon icon="ant-design:plus-outlined" class="mr-1" />
|
||||
添加功能
|
||||
</VbenButton>
|
||||
<VbenButton type="success" @click="handleOpenTSL"> TSL </VbenButton>
|
||||
</Button>
|
||||
<Button type="primary" @click="handleOpenTSL"> TSL </Button>
|
||||
</template>
|
||||
|
||||
<!-- 数据类型列 -->
|
||||
@@ -99,17 +107,15 @@ const getDataTypeLabel = (row: any) => {
|
||||
<!-- 数据定义列 -->
|
||||
<template #dataDefinition="{ row }">
|
||||
<!-- TODO: 实现数据定义组件 -->
|
||||
<span class="text-gray-400">-</span>
|
||||
<span class="text-gray-400">{{ row }}</span>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template #actions="{ row }">
|
||||
<VbenButton size="small" type="primary" @click="handleEdit(row)">
|
||||
<Button size="small" type="primary" @click="handleEdit(row)">
|
||||
编辑
|
||||
</VbenButton>
|
||||
<VbenButton size="small" type="danger" @click="handleDelete(row)">
|
||||
删除
|
||||
</VbenButton>
|
||||
</Button>
|
||||
<Button size="small" danger @click="handleDelete(row)"> 删除 </Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import type { ThingModelEvent } from '#/api/iot/thingmodel';
|
||||
|
||||
import { watch } from 'vue';
|
||||
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Form, Radio } from 'ant-design-vue';
|
||||
|
||||
import { ThingModelEvent } from '#/api/iot/thingmodel';
|
||||
import {
|
||||
IoTThingModelEventTypeEnum,
|
||||
IoTThingModelParamDirectionEnum,
|
||||
@@ -30,7 +32,7 @@ const thingModelEvent = useVModel(
|
||||
// 默认选中,INFO 信息
|
||||
watch(
|
||||
() => thingModelEvent.value.type,
|
||||
(val: string) =>
|
||||
(val: string | undefined) =>
|
||||
isEmpty(val) &&
|
||||
(thingModelEvent.value.type = IoTThingModelEventTypeEnum.INFO.value),
|
||||
{ immediate: true },
|
||||
@@ -38,32 +40,32 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
:rules="[{ required: true, message: '请选择事件类型', trigger: 'change' }]"
|
||||
label="事件类型"
|
||||
prop="event.type"
|
||||
>
|
||||
<el-radio-group v-model="thingModelEvent.type">
|
||||
<el-radio
|
||||
<Radio.Group v-model="thingModelEvent.type">
|
||||
<Radio
|
||||
v-for="eventType in Object.values(IoTThingModelEventTypeEnum)"
|
||||
:key="eventType.value"
|
||||
:value="eventType.value"
|
||||
>
|
||||
{{ eventType.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="输出参数">
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="输出参数">
|
||||
<ThingModelInputOutputParam
|
||||
v-model="thingModelEvent.outputParams"
|
||||
v-model="thingModelEvent.outputData"
|
||||
:direction="IoTThingModelParamDirectionEnum.OUTPUT"
|
||||
/>
|
||||
</el-form-item>
|
||||
</Form.Item>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item) {
|
||||
.el-form-item {
|
||||
:deep(.ant-form-item) {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,13 @@ import { getDictOptions } from '@vben/hooks';
|
||||
import { $t } from '@vben/locales';
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { Button, Form, Input, message, Radio } from 'ant-design-vue';
|
||||
|
||||
import { createThingModel, updateThingModel } from '#/api/iot/thingmodel';
|
||||
import {
|
||||
createThingModel,
|
||||
getThingModel,
|
||||
updateThingModel,
|
||||
} from '#/api/iot/thingmodel';
|
||||
import {
|
||||
IOT_PROVIDE_KEY,
|
||||
IoTDataSpecsDataTypeEnum,
|
||||
@@ -37,7 +41,7 @@ const dialogTitle = ref(''); // 弹窗的标题
|
||||
const formLoading = ref(false); // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref(''); // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref<ThingModelData>({
|
||||
type: IoTThingModelTypeEnum.PROPERTY,
|
||||
type: IoTThingModelTypeEnum.PROPERTY.toString(),
|
||||
dataType: IoTDataSpecsDataTypeEnum.INT,
|
||||
property: {
|
||||
dataType: IoTDataSpecsDataTypeEnum.INT,
|
||||
@@ -47,7 +51,7 @@ const formData = ref<ThingModelData>({
|
||||
},
|
||||
service: {},
|
||||
event: {},
|
||||
} as ThingModelData);
|
||||
});
|
||||
|
||||
const formRef = ref(); // 表单 Ref
|
||||
|
||||
@@ -176,68 +180,64 @@ function resetForm() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<a-form
|
||||
<Modal v-model="dialogVisible" :title="dialogTitle">
|
||||
<Form
|
||||
ref="formRef"
|
||||
:loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="ThingModelFormRules"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
>
|
||||
<a-form-item label="功能类型" name="type">
|
||||
<a-radio-group v-model:value="formData.type">
|
||||
<a-radio-button
|
||||
v-for="dict in getDictOptions(
|
||||
<Form.Item label="功能类型" name="type">
|
||||
<Radio.Group v-model:value="formData.type">
|
||||
<Radio.Button
|
||||
v-for="(dict, index) in getDictOptions(
|
||||
DICT_TYPE.IOT_THING_MODEL_TYPE,
|
||||
'number',
|
||||
)"
|
||||
:key="dict.value"
|
||||
:key="index"
|
||||
:value="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="功能名称" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入功能名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="标识符" name="identifier">
|
||||
<a-input
|
||||
v-model:value="formData.identifier"
|
||||
placeholder="请输入标识符"
|
||||
/>
|
||||
</a-form-item>
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="功能名称" name="name">
|
||||
<Input v-model:value="formData.name" placeholder="请输入功能名称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="标识符" name="identifier">
|
||||
<Input v-model:value="formData.identifier" placeholder="请输入标识符" />
|
||||
</Form.Item>
|
||||
<!-- 属性配置 -->
|
||||
<ThingModelProperty
|
||||
v-if="formData.type === IoTThingModelTypeEnum.PROPERTY"
|
||||
v-if="formData.type === IoTThingModelTypeEnum.PROPERTY.toString()"
|
||||
v-model="formData.property"
|
||||
/>
|
||||
<!-- 服务配置 -->
|
||||
<ThingModelService
|
||||
v-if="formData.type === IoTThingModelTypeEnum.SERVICE"
|
||||
v-if="formData.type === IoTThingModelTypeEnum.SERVICE.toString()"
|
||||
v-model="formData.service"
|
||||
/>
|
||||
<!-- 事件配置 -->
|
||||
<ThingModelEvent
|
||||
v-if="formData.type === IoTThingModelTypeEnum.EVENT"
|
||||
v-if="formData.type === IoTThingModelTypeEnum.EVENT.toString()"
|
||||
v-model="formData.event"
|
||||
/>
|
||||
<a-form-item label="描述" name="description">
|
||||
<a-textarea
|
||||
v-model:value="formData.description"
|
||||
<Form.Item label="描述" name="desc">
|
||||
<Input.TextArea
|
||||
v-model:value="formData.desc"
|
||||
:maxlength="200"
|
||||
:rows="3"
|
||||
placeholder="请输入属性描述"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
<template #footer>
|
||||
<a-button :disabled="formLoading" type="primary" @click="submitForm">
|
||||
<Button :disabled="formLoading" type="primary" @click="submitForm">
|
||||
确 定
|
||||
</a-button>
|
||||
<a-button @click="dialogVisible = false">取 消</a-button>
|
||||
</Button>
|
||||
<Button @click="dialogVisible = false">取 消</Button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<!-- 产品的物模型表单(event、service 项里的参数) -->
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import { ref, unref } from 'vue';
|
||||
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Button, Divider, Form, Input, Modal } from 'ant-design-vue';
|
||||
|
||||
import { ThingModelFormRules } from '#/api/iot/thingmodel';
|
||||
import { IoTDataSpecsDataTypeEnum } from '#/views/iot/utils/constants';
|
||||
|
||||
import ThingModelProperty from './ThingModelProperty.vue';
|
||||
@@ -29,7 +33,7 @@ const formData = ref<any>({
|
||||
});
|
||||
|
||||
/** 打开 param 表单 */
|
||||
const openParamForm = (val: any) => {
|
||||
function openParamForm(val: any) {
|
||||
dialogVisible.value = true;
|
||||
resetForm();
|
||||
if (isEmpty(val)) {
|
||||
@@ -46,15 +50,15 @@ const openParamForm = (val: any) => {
|
||||
dataSpecsList: val.dataSpecsList,
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/** 删除 param 项 */
|
||||
const deleteParamItem = (index: number) => {
|
||||
function deleteParamItem(index: number) {
|
||||
thingModelParams.value.splice(index, 1);
|
||||
};
|
||||
}
|
||||
|
||||
/** 添加参数 */
|
||||
const submitForm = async () => {
|
||||
async function submitForm() {
|
||||
// 初始化参数列表
|
||||
if (isEmpty(thingModelParams.value)) {
|
||||
thingModelParams.value = [];
|
||||
@@ -93,10 +97,10 @@ const submitForm = async () => {
|
||||
} finally {
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
function resetForm() {
|
||||
formData.value = {
|
||||
dataType: IoTDataSpecsDataTypeEnum.INT,
|
||||
property: {
|
||||
@@ -107,59 +111,46 @@ const resetForm = () => {
|
||||
},
|
||||
};
|
||||
paramFormRef.value?.resetFields();
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-for="(item, index) in thingModelParams"
|
||||
:key="index"
|
||||
class="w-1/1 param-item px-10px mb-10px flex justify-between"
|
||||
class="w-1/1 px-10px mb-10px flex justify-between bg-gray-100"
|
||||
>
|
||||
<span>参数名称:{{ item.name }}</span>
|
||||
<div class="btn">
|
||||
<el-button link type="primary" @click="openParamForm(item)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button link type="danger" @click="deleteParamItem(index)">
|
||||
删除
|
||||
</el-button>
|
||||
<Button link type="primary" @click="openParamForm(item)"> 编辑 </Button>
|
||||
<Divider direction="vertical" />
|
||||
<Button link danger @click="deleteParamItem(index)"> 删除 </Button>
|
||||
</div>
|
||||
</div>
|
||||
<el-button link type="primary" @click="openParamForm(null)">
|
||||
+新增参数
|
||||
</el-button>
|
||||
<Button link type="primary" @click="openParamForm(null)"> +新增参数 </Button>
|
||||
|
||||
<!-- param 表单 -->
|
||||
<Dialog v-model="dialogVisible" title="新增参数" append-to-body>
|
||||
<el-form
|
||||
<Modal v-model="dialogVisible" title="新增参数" append-to-body>
|
||||
<Form
|
||||
ref="paramFormRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="ThingModelFormRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="参数名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入功能名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标识符" prop="identifier">
|
||||
<el-input v-model="formData.identifier" placeholder="请输入标识符" />
|
||||
</el-form-item>
|
||||
<Form.Item label="参数名称" prop="name">
|
||||
<Input v-model="formData.name" placeholder="请输入功能名称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="标识符" prop="identifier">
|
||||
<Input v-model="formData.identifier" placeholder="请输入标识符" />
|
||||
</Form.Item>
|
||||
<!-- 属性配置 -->
|
||||
<ThingModelProperty v-model="formData.property" is-params />
|
||||
</el-form>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">
|
||||
<Button :disabled="formLoading" type="primary" @click="submitForm">
|
||||
确 定
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</Button>
|
||||
<Button @click="dialogVisible = false">取 消</Button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.param-item {
|
||||
background-color: #e4f2fd;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
<!-- 产品的物模型表单(property 项) -->
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import type { ThingModelProperty } from '#/api/iot/thingmodel';
|
||||
|
||||
import { computed, watch } from 'vue';
|
||||
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Form, Input, Radio, Select } from 'ant-design-vue';
|
||||
|
||||
import { ThingModelProperty, validateBoolName } from '#/api/iot/thingmodel';
|
||||
import { validateBoolName } from '#/api/iot/thingmodel';
|
||||
import {
|
||||
getDataTypeOptions,
|
||||
IoTDataSpecsDataTypeEnum,
|
||||
@@ -46,7 +53,7 @@ const getDataTypeOptions2 = computed(() => {
|
||||
}); // 获得数据类型列表
|
||||
|
||||
/** 属性值的数据类型切换时初始化相关数据 */
|
||||
const handleChange = (dataType: any) => {
|
||||
function handleChange(dataType: any) {
|
||||
property.value.dataSpecs = {};
|
||||
property.value.dataSpecsList = [];
|
||||
// 不是列表型数据才设置 dataSpecs.dataType
|
||||
@@ -75,12 +82,12 @@ const handleChange = (dataType: any) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** 默认选中读写 */
|
||||
watch(
|
||||
() => property.value.accessMode,
|
||||
(val: string) => {
|
||||
(val: string | undefined) => {
|
||||
if (props.isStructDataSpecs || props.isParams) {
|
||||
return;
|
||||
}
|
||||
@@ -93,25 +100,25 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
:rules="[{ required: true, message: '请选择数据类型', trigger: 'change' }]"
|
||||
label="数据类型"
|
||||
prop="property.dataType"
|
||||
>
|
||||
<el-select
|
||||
<Select
|
||||
v-model="property.dataType"
|
||||
placeholder="请选择数据类型"
|
||||
@change="handleChange"
|
||||
>
|
||||
<!-- ARRAY 和 STRUCT 类型数据相互嵌套时,最多支持递归嵌套 2 层(父和子) -->
|
||||
<el-option
|
||||
<Select.Option
|
||||
v-for="option in getDataTypeOptions2"
|
||||
:key="option.value"
|
||||
:label="`${option.value}(${option.label})`"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<!-- 数值型配置 -->
|
||||
<ThingModelNumberDataSpecs
|
||||
v-if="
|
||||
@@ -129,7 +136,7 @@ watch(
|
||||
v-model="property.dataSpecsList"
|
||||
/>
|
||||
<!-- 布尔型配置 -->
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
v-if="property.dataType === IoTDataSpecsDataTypeEnum.BOOL"
|
||||
label="布尔值"
|
||||
>
|
||||
@@ -137,7 +144,7 @@ watch(
|
||||
<div class="w-1/1 mb-5px flex items-center justify-start">
|
||||
<span>{{ item.value }}</span>
|
||||
<span class="mx-2">-</span>
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
:prop="`property.dataSpecsList[${index}].name`"
|
||||
:rules="[
|
||||
{ required: true, message: '枚举描述不能为空' },
|
||||
@@ -145,41 +152,41 @@ watch(
|
||||
]"
|
||||
class="mb-0 flex-1"
|
||||
>
|
||||
<el-input
|
||||
<Input
|
||||
v-model="item.name"
|
||||
:placeholder="`如:${item.value === 0 ? '关' : '开'}`"
|
||||
class="w-255px!"
|
||||
/>
|
||||
</el-form-item>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</Form.Item>
|
||||
<!-- 文本型配置 -->
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
v-if="property.dataType === IoTDataSpecsDataTypeEnum.TEXT"
|
||||
label="数据长度"
|
||||
prop="property.dataSpecs.length"
|
||||
>
|
||||
<el-input
|
||||
<Input
|
||||
v-model="property.dataSpecs.length"
|
||||
class="w-255px!"
|
||||
placeholder="请输入文本字节长度"
|
||||
>
|
||||
<template #append>字节</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</Input>
|
||||
</Form.Item>
|
||||
<!-- 时间型配置 -->
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
v-if="property.dataType === IoTDataSpecsDataTypeEnum.DATE"
|
||||
label="时间格式"
|
||||
prop="date"
|
||||
>
|
||||
<el-input
|
||||
<Input
|
||||
class="w-255px!"
|
||||
disabled
|
||||
placeholder="String 类型的 UTC 时间戳(毫秒)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</Form.Item>
|
||||
<!-- 数组型配置-->
|
||||
<ThingModelArrayDataSpecs
|
||||
v-if="property.dataType === IoTDataSpecsDataTypeEnum.ARRAY"
|
||||
@@ -190,26 +197,26 @@ watch(
|
||||
v-if="property.dataType === IoTDataSpecsDataTypeEnum.STRUCT"
|
||||
v-model="property.dataSpecsList"
|
||||
/>
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
v-if="!isStructDataSpecs && !isParams"
|
||||
label="读写类型"
|
||||
prop="property.accessMode"
|
||||
>
|
||||
<el-radio-group v-model="property.accessMode">
|
||||
<el-radio
|
||||
<Radio.Group v-model="property.accessMode">
|
||||
<Radio
|
||||
v-for="accessMode in Object.values(IoTThingModelAccessModeEnum)"
|
||||
:key="accessMode.value"
|
||||
:label="accessMode.value"
|
||||
>
|
||||
{{ accessMode.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item) {
|
||||
.el-form-item {
|
||||
:deep(.ant-form-item) {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<!-- 产品的物模型表单(service 项) -->
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import type { ThingModelService } from '#/api/iot/thingmodel';
|
||||
|
||||
import { watch } from 'vue';
|
||||
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Form, Radio } from 'ant-design-vue';
|
||||
|
||||
import { ThingModelService } from '#/api/iot/thingmodel';
|
||||
import {
|
||||
IoTThingModelParamDirectionEnum,
|
||||
IoTThingModelServiceCallTypeEnum,
|
||||
@@ -22,7 +28,7 @@ const service = useVModel(props, 'modelValue', emits) as Ref<ThingModelService>;
|
||||
/** 默认选中,ASYNC 异步 */
|
||||
watch(
|
||||
() => service.value.callType,
|
||||
(val: string) =>
|
||||
(val: string | undefined) =>
|
||||
isEmpty(val) &&
|
||||
(service.value.callType = IoTThingModelServiceCallTypeEnum.ASYNC.value),
|
||||
{ immediate: true },
|
||||
@@ -30,38 +36,38 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form-item
|
||||
<Form.Item
|
||||
:rules="[{ required: true, message: '请选择调用方式', trigger: 'change' }]"
|
||||
label="调用方式"
|
||||
prop="service.callType"
|
||||
>
|
||||
<el-radio-group v-model="service.callType">
|
||||
<el-radio
|
||||
<Radio.Group v-model="service.callType">
|
||||
<Radio
|
||||
v-for="callType in Object.values(IoTThingModelServiceCallTypeEnum)"
|
||||
:key="callType.value"
|
||||
:value="callType.value"
|
||||
>
|
||||
{{ callType.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="输入参数">
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="输入参数">
|
||||
<ThingModelInputOutputParam
|
||||
v-model="service.inputParams"
|
||||
v-model="service.inputData"
|
||||
:direction="IoTThingModelParamDirectionEnum.INPUT"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="输出参数">
|
||||
</Form.Item>
|
||||
<Form.Item label="输出参数">
|
||||
<ThingModelInputOutputParam
|
||||
v-model="service.outputParams"
|
||||
v-model="service.outputData"
|
||||
:direction="IoTThingModelParamDirectionEnum.OUTPUT"
|
||||
/>
|
||||
</el-form-item>
|
||||
</Form.Item>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item) {
|
||||
.el-form-item {
|
||||
:deep(.ant-form-item) {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import type { ProductVO } from '#/api/iot/product/product';
|
||||
import type { IotProductApi } from '#/api/iot/product/product';
|
||||
|
||||
import { inject, onMounted, ref } from 'vue';
|
||||
|
||||
import { Modal, Radio } from 'ant-design-vue';
|
||||
import hljs from 'highlight.js'; // 导入代码高亮文件
|
||||
import json from 'highlight.js/lib/languages/json';
|
||||
|
||||
@@ -17,7 +18,7 @@ defineOptions({ name: 'ThingModelTSL' });
|
||||
|
||||
const dialogVisible = ref(false); // 弹窗的是否展示
|
||||
const dialogTitle = ref('物模型 TSL'); // 弹窗的标题
|
||||
const product = inject<Ref<ProductVO>>(IOT_PROVIDE_KEY.PRODUCT); // 注入产品信息
|
||||
const product = inject<Ref<IotProductApi.Product>>(IOT_PROVIDE_KEY.PRODUCT); // 注入产品信息
|
||||
const viewMode = ref('code'); // 查看模式:code-代码视图,editor-编辑器视图
|
||||
|
||||
/** 打开弹窗 */
|
||||
@@ -43,17 +44,17 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<Modal v-model="dialogVisible" :title="dialogTitle">
|
||||
<JsonEditor
|
||||
v-model="thingModelTSL"
|
||||
:mode="viewMode === 'editor' ? 'code' : 'view'"
|
||||
height="600px"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-radio-group v-model="viewMode" size="small">
|
||||
<el-radio-button label="code">代码视图</el-radio-button>
|
||||
<el-radio-button label="editor">编辑器视图</el-radio-button>
|
||||
</el-radio-group>
|
||||
<Radio.Group v-model="viewMode" size="small">
|
||||
<Radio.Button label="code">代码视图</Radio.Button>
|
||||
<Radio.Button label="editor">编辑器视图</Radio.Button>
|
||||
</Radio.Group>
|
||||
</template>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
@@ -155,7 +155,6 @@ onMounted(async () => {
|
||||
ref="structFormRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="ThingModelFormRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<Form.Item label="参数名称" prop="name">
|
||||
|
||||
Reference in New Issue
Block a user