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