Commit 5c3d3140de0128bbcfbc1aba607585019364dedf

Authored by ww
1 parent 0616ee93

wip: product detail model of matter tsl

Showing 27 changed files with 1000 additions and 955 deletions
@@ -43,7 +43,7 @@ VITE_GLOB_CONFIGURATION = /thingskit-drawio @@ -43,7 +43,7 @@ VITE_GLOB_CONFIGURATION = /thingskit-drawio
43 VITE_CONTENT_SECURITY_POLICY = false 43 VITE_CONTENT_SECURITY_POLICY = false
44 44
45 # Alarm Notify Polling Interval Time 45 # Alarm Notify Polling Interval Time
46 -VITE_ALARM_NOTIFY_POLLING_INTERVAL_TIME = 5000 46 +VITE_ALARM_NOTIFY_POLLING_INTERVAL_TIME = 500000
47 47
48 # Alarm Notify Auto Close Time Unit is Second 48 # Alarm Notify Auto Close Time Unit is Second
49 VITE_ALARM_NOTIFY_DURATION = 5 49 VITE_ALARM_NOTIFY_DURATION = 5
@@ -48,3 +48,40 @@ export interface DeviceProfileModel { @@ -48,3 +48,40 @@ export interface DeviceProfileModel {
48 export type ChildDeviceParams = BasicPageParams & { 48 export type ChildDeviceParams = BasicPageParams & {
49 formId: string; 49 formId: string;
50 }; 50 };
  51 +
  52 +export interface Configuration {
  53 + type: string;
  54 +}
  55 +
  56 +export interface TransportConfiguration {
  57 + type: string;
  58 +}
  59 +
  60 +export interface ProvisionConfiguration {
  61 + type: string;
  62 + provisionDeviceSecret?: any;
  63 +}
  64 +
  65 +export interface ProfileData {
  66 + configuration: Configuration;
  67 + transportConfiguration: TransportConfiguration;
  68 + provisionConfiguration: ProvisionConfiguration;
  69 + alarms?: any;
  70 +}
  71 +
  72 +export interface DeviceRecord {
  73 + id: string;
  74 + creator: string;
  75 + createTime: string;
  76 + name: string;
  77 + tenantId: string;
  78 + transportType: string;
  79 + provisionType: string;
  80 + deviceType: string;
  81 + tbProfileId: string;
  82 + profileData: ProfileData;
  83 + defaultQueueName: string;
  84 + image: string;
  85 + type: string;
  86 + default: boolean;
  87 +}
  1 +import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
  2 +
  3 +export interface Specs {
  4 + min: string;
  5 + max: string;
  6 + unit: string;
  7 + unitName: string;
  8 + step: string;
  9 + length: string;
  10 + boolOpen: string;
  11 + boolClose: string;
  12 +}
  13 +
  14 +export interface FunctionJson {
  15 + type: string;
  16 + specs?: Partial<Specs>;
  17 + specsList?: ModelOfMatterParams[];
  18 +}
  19 +
  20 +export interface ModelOfMatterParams {
  21 + deviceProfileId: string;
  22 + functionJson: FunctionJson;
  23 + functionName: string;
  24 + functionType: FunctionType;
  25 + identifier: string;
  26 + remark: string;
  27 + id?: string;
  28 +}
  29 +
  30 +export interface GetModelTslParams {
  31 + functionType: FunctionType;
  32 + deviceProfileId: string;
  33 +}
  1 +import { BasicPageParams } from '../model/baseModel';
  2 +import { GetModelTslParams, ModelOfMatterParams } from './model/modelOfMatterModel';
  3 +import { defHttp } from '/@/utils/http/axios';
  4 +
  5 +enum ModelOfMatter {
  6 + CREATE = '/things_model',
  7 + UPDATE = '/things_model',
  8 + DELETE = '/things_model',
  9 + TSL = '/things_model',
  10 + LIST = '/things_model/page',
  11 +}
  12 +
  13 +export const getModelList = (params: BasicPageParams) => {
  14 + return defHttp.get({
  15 + url: `${ModelOfMatter.LIST}`,
  16 + params,
  17 + });
  18 +};
  19 +
  20 +export const getModelTsl = (params: GetModelTslParams) => {
  21 + const { functionType, deviceProfileId } = params;
  22 + return defHttp.get({
  23 + url: `${ModelOfMatter.TSL}/${functionType}/${deviceProfileId}`,
  24 + });
  25 +};
  26 +
  27 +export const createModel = (params: Partial<ModelOfMatterParams>) => {
  28 + return defHttp.post({
  29 + url: ModelOfMatter.CREATE,
  30 + params,
  31 + });
  32 +};
  33 +
  34 +export const updateModel = (params: Partial<ModelOfMatterParams>) => {
  35 + return defHttp.put({
  36 + url: ModelOfMatter.UPDATE,
  37 + params,
  38 + });
  39 +};
  40 +
  41 +export const deleteModel = (params: string[]) => {
  42 + return defHttp.delete({
  43 + url: ModelOfMatter.DELETE,
  44 + params: {
  45 + ids: params,
  46 + },
  47 + });
  48 +};
@@ -20,7 +20,7 @@ enum SysDictApi { @@ -20,7 +20,7 @@ enum SysDictApi {
20 * @param code 20 * @param code
21 */ 21 */
22 export const findDictItemByCode = (params?: DictCodeParams) => { 22 export const findDictItemByCode = (params?: DictCodeParams) => {
23 - return defHttp.post<SysDictItemResult>({ 23 + return defHttp.post<SysDictItemResult[]>({
24 url: SysDictApi.CONFIG_ITEM_URL + '/find', 24 url: SysDictApi.CONFIG_ITEM_URL + '/find',
25 params, 25 params,
26 }); 26 });
@@ -12,6 +12,8 @@ export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; @@ -12,6 +12,8 @@ export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
12 export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; 12 export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
13 export { default as ApiUpload } from './src/components/ApiUpload.vue'; 13 export { default as ApiUpload } from './src/components/ApiUpload.vue';
14 14
  15 +export { default as StructForm } from './src/externalCompns/components/StructForm/StructForm.vue';
  16 +
15 //注册自定义组件 17 //注册自定义组件
16 export { 18 export {
17 JEasyCron, 19 JEasyCron,
@@ -35,7 +35,8 @@ import ColorPicker from './components/ColorPicker.vue'; @@ -35,7 +35,8 @@ import ColorPicker from './components/ColorPicker.vue';
35 import IconDrawer from './components/IconDrawer.vue'; 35 import IconDrawer from './components/IconDrawer.vue';
36 import ApiUpload from './components/ApiUpload.vue'; 36 import ApiUpload from './components/ApiUpload.vue';
37 import ApiSearchSelect from './components/ApiSearchSelect.vue'; 37 import ApiSearchSelect from './components/ApiSearchSelect.vue';
38 -import CustomeMinMaxInput from './externalCompns/components/CustomeMinMaxInput.vue'; 38 +import CustomMinMaxInput from './externalCompns/components/CustomMinMaxInput.vue';
  39 +import StructForm from './externalCompns/components/StructForm/StructForm.vue';
39 40
40 const componentMap = new Map<ComponentType, Component>(); 41 const componentMap = new Map<ComponentType, Component>();
41 42
@@ -78,7 +79,8 @@ componentMap.set('ColorPicker', ColorPicker); @@ -78,7 +79,8 @@ componentMap.set('ColorPicker', ColorPicker);
78 componentMap.set('IconDrawer', IconDrawer); 79 componentMap.set('IconDrawer', IconDrawer);
79 componentMap.set('ApiUpload', ApiUpload); 80 componentMap.set('ApiUpload', ApiUpload);
80 componentMap.set('ApiSearchSelect', ApiSearchSelect); 81 componentMap.set('ApiSearchSelect', ApiSearchSelect);
81 -componentMap.set('CustomeMinMaxInput', CustomeMinMaxInput); 82 +componentMap.set('CustomMinMaxInput', CustomMinMaxInput);
  83 +componentMap.set('StructForm', StructForm);
82 84
83 export function add(compName: ComponentType, component: Component) { 85 export function add(compName: ComponentType, component: Component) {
84 componentMap.set(compName, component); 86 componentMap.set(compName, component);
src/components/Form/src/externalCompns/components/CustomMinMaxInput.vue renamed from src/components/Form/src/externalCompns/components/CustomeMinMaxInput.vue
  1 +<script lang="ts">
  2 + export default {
  3 + inheritAttrs: false,
  4 + };
  5 +</script>
  6 +<script lang="ts" setup>
  7 + import StructFormModel from './StructFormModel.vue';
  8 + import { useModal } from '/@/components/Modal';
  9 + import { PlusOutlined } from '@ant-design/icons-vue';
  10 + import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  11 + import { computed, unref } from 'vue';
  12 + import { buildUUID } from '/@/utils/uuid';
  13 + import { Divider, Button } from 'ant-design-vue';
  14 + import { OpenModalMode, OpenModalParams, StructRecord } from './type';
  15 + import { cloneDeep } from 'lodash-es';
  16 +
  17 + const emit = defineEmits(['update:value']);
  18 +
  19 + const props = withDefaults(
  20 + defineProps<{
  21 + value: ModelOfMatterParams[];
  22 + }>(),
  23 + {
  24 + value: () => [],
  25 + }
  26 + );
  27 +
  28 + const getValue = computed<StructRecord[]>(() => {
  29 + const { value } = props;
  30 + return value.map((item) => {
  31 + return {
  32 + ...(item as StructRecord),
  33 + ...((item as StructRecord).id ? {} : { id: buildUUID() }),
  34 + };
  35 + });
  36 + });
  37 +
  38 + const [registerModal, { openModal }] = useModal();
  39 +
  40 + const handleCreateParams = () => {
  41 + openModal(true, {
  42 + mode: OpenModalMode.CREATE,
  43 + } as OpenModalParams);
  44 + };
  45 +
  46 + const handleUpdate = (value: StructRecord) => {
  47 + openModal(true, {
  48 + mode: OpenModalMode.UPDATE,
  49 + record: value,
  50 + } as OpenModalParams);
  51 + };
  52 +
  53 + const handleDelete = (value: StructRecord) => {
  54 + const index = unref(getValue).findIndex((item) => item.id === value.id);
  55 + const _value = cloneDeep(unref(getValue));
  56 + _value.splice(index, 1);
  57 + emit('update:value', _value);
  58 + };
  59 +
  60 + const handleSaveStruct = (mode: OpenModalMode, value: StructRecord) => {
  61 + const _value = cloneDeep(unref(getValue));
  62 +
  63 + if (mode === OpenModalMode.UPDATE) {
  64 + const index = unref(getValue).findIndex((item) => item.id === value.id);
  65 + ~index && _value.splice(index, 1, value);
  66 + } else {
  67 + _value.push(value);
  68 + }
  69 +
  70 + emit('update:value', _value);
  71 + };
  72 +</script>
  73 +
  74 +<template>
  75 + <section>
  76 + <div class="text-blue-500 cursor-pointer">
  77 + <section>
  78 + <div
  79 + class="flex bg-blue-50 mb-2 p-2 text-gray-500 justify-between items-center"
  80 + v-for="item in getValue"
  81 + :key="item.id"
  82 + >
  83 + <div>参数名称: {{ item.functionName }}</div>
  84 + <div class="flex">
  85 + <Button class="!p-0" type="link" @click="handleUpdate(item)">编辑</Button>
  86 + <Divider type="vertical" />
  87 + <Button class="!p-0" type="link" @click="handleDelete(item)">删除</Button>
  88 + </div>
  89 + </div>
  90 + </section>
  91 + <div>
  92 + <span class="mr-2">
  93 + <PlusOutlined />
  94 + </span>
  95 + <span @click="handleCreateParams">增加参数</span>
  96 + </div>
  97 + </div>
  98 + <StructFormModel @register="registerModal" @submit="handleSaveStruct" />
  99 + </section>
  100 +</template>
  101 +
  102 +<style lang="less" scoped></style>
  1 +<script lang="ts">
  2 + export default {
  3 + inheritAttrs: false,
  4 + };
  5 +</script>
  6 +<script lang="ts" setup>
  7 + import { BasicForm, useForm } from '/@/components/Form';
  8 + import { formSchemas } from './config';
  9 + import { BasicModal, useModalInner } from '/@/components/Modal';
  10 + import { OpenModalMode, OpenModalParams, StructRecord } from './type';
  11 + import { ref, unref } from 'vue';
  12 + import { transformFormValue } from './util';
  13 + import { cloneDeep } from 'lodash-es';
  14 +
  15 + const modalReceiveRecord = ref<OpenModalParams>({
  16 + mode: OpenModalMode.CREATE,
  17 + });
  18 +
  19 + const emit = defineEmits(['register', 'submit']);
  20 +
  21 + const [register, { validate, setFieldsValue }] = useForm({
  22 + labelWidth: 100,
  23 + schemas: formSchemas,
  24 + actionColOptions: {
  25 + span: 14,
  26 + },
  27 + showResetButton: false,
  28 + submitOnReset: false,
  29 + showActionButtonGroup: false,
  30 + });
  31 +
  32 + const [registerModal, { closeModal }] = useModalInner((record: OpenModalParams) => {
  33 + modalReceiveRecord.value = record;
  34 + const data = record.record || {};
  35 + const { functionJson = {} } = data! as StructRecord;
  36 + const { specs = {} } = functionJson as StructRecord['functionJson'];
  37 + if (record.record) {
  38 + const value = {
  39 + ...data,
  40 + ...functionJson,
  41 + ...specs,
  42 + valueRange: {
  43 + min: specs.min,
  44 + max: specs.max,
  45 + },
  46 + };
  47 +
  48 + setFieldsValue(value);
  49 + }
  50 + });
  51 +
  52 + const handleSubmit = async () => {
  53 + try {
  54 + const _value = await validate();
  55 + let value = transformFormValue(_value);
  56 + value = {
  57 + ...value,
  58 + ...(unref(modalReceiveRecord)?.record?.id
  59 + ? { id: unref(modalReceiveRecord)?.record?.id }
  60 + : {}),
  61 + };
  62 + emit('submit', unref(modalReceiveRecord).mode, cloneDeep(value));
  63 + closeModal();
  64 + } catch (error) {}
  65 + };
  66 +</script>
  67 +
  68 +<template>
  69 + <BasicModal
  70 + @register="registerModal"
  71 + :title="modalReceiveRecord.mode === OpenModalMode.CREATE ? '创建参数' : '编辑参数'"
  72 + :width="800"
  73 + @ok="handleSubmit"
  74 + destroy-on-close
  75 + >
  76 + <BasicForm @register="register" />
  77 + </BasicModal>
  78 +</template>
  79 +
  80 +<style lang="less" scoped></style>
  1 +import { h } from 'vue';
  2 +import { findDictItemByCode } from '/@/api/system/dict';
  3 +import { FormSchema } from '/@/components/Table';
  4 +import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
  5 +
  6 +export enum DateTypeEnum {
  7 + IS_NUMBER_INT = 'INT',
  8 + IS_NUMBER_DOUBLE = 'DOUBLE',
  9 + IS_STRING = 'TEXT',
  10 + IS_STRUCT = 'STRUCT',
  11 + IS_BOOL = 'BOOL',
  12 +}
  13 +
  14 +export const formSchemas: FormSchema[] = [
  15 + {
  16 + field: FormField.FUNCTION_NAME,
  17 + label: '功能名称',
  18 + required: true,
  19 + component: 'Input',
  20 + colProps: {
  21 + span: 18,
  22 + },
  23 + componentProps: {
  24 + maxLength: 255,
  25 + placeholder: '请输入功能名称',
  26 + },
  27 + },
  28 + {
  29 + field: FormField.IDENTIFIER,
  30 + label: '标识符',
  31 + required: true,
  32 + component: 'Input',
  33 + colProps: {
  34 + span: 18,
  35 + },
  36 + componentProps: {
  37 + maxLength: 255,
  38 + placeholder: '请输入标识符',
  39 + },
  40 + },
  41 + {
  42 + field: FormField.TYPE,
  43 + label: '数据类型',
  44 + required: true,
  45 + component: 'ApiSelect',
  46 + colProps: {
  47 + span: 9,
  48 + },
  49 + defaultValue: 'INT',
  50 + componentProps: {
  51 + placeholder: '请选择数据类型',
  52 + api: findDictItemByCode,
  53 + params: {
  54 + dictCode: 'data_type',
  55 + },
  56 + labelField: 'itemText',
  57 + valueField: 'itemValue',
  58 + getPopupContainer: () => document.body,
  59 + },
  60 + },
  61 + {
  62 + field: FormField.VALUE_RANGE,
  63 + label: '取值范围',
  64 + component: 'CustomMinMaxInput',
  65 + colProps: {
  66 + span: 18,
  67 + },
  68 + ifShow: ({ values }) =>
  69 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
  70 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  71 + },
  72 + {
  73 + field: FormField.STEP,
  74 + label: '步长',
  75 + component: 'Input',
  76 + colProps: {
  77 + span: 18,
  78 + },
  79 + componentProps: {
  80 + maxLength: 255,
  81 + placeholder: '请输入步长',
  82 + },
  83 + ifShow: ({ values }) =>
  84 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
  85 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  86 + },
  87 + {
  88 + field: FormField.UNIT_NAME,
  89 + label: '单位名称',
  90 + component: 'Input',
  91 + show: false,
  92 + },
  93 + {
  94 + field: FormField.UNIT,
  95 + label: '单位',
  96 + component: 'ApiSelect',
  97 + colProps: {
  98 + span: 9,
  99 + },
  100 + componentProps: ({ formActionType }) => {
  101 + const { setFieldsValue } = formActionType;
  102 + return {
  103 + placeholder: '请选择单位',
  104 + api: findDictItemByCode,
  105 + params: {
  106 + dictCode: 'attribute_unit',
  107 + },
  108 + labelField: 'itemText',
  109 + valueField: 'itemValue',
  110 + onChange(_, record: Record<'label' | 'value', string>) {
  111 + const { label } = record;
  112 + setFieldsValue({ [FormField.UNIT_NAME]: label });
  113 + },
  114 + getPopupContainer: () => document.body,
  115 + };
  116 + },
  117 + ifShow: ({ values }) =>
  118 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
  119 + values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  120 + renderComponentContent: () => {
  121 + return {
  122 + option: (params: Record<'label' | 'value', string>) => {
  123 + const { label, value } = params;
  124 + return h('span', `${label} / ${value}`);
  125 + },
  126 + };
  127 + },
  128 + },
  129 + {
  130 + field: FormField.BOOL_CLOSE,
  131 + component: 'Input',
  132 + required: true,
  133 + label: '0 -',
  134 + colProps: {
  135 + span: 18,
  136 + },
  137 + componentProps: {
  138 + placeholder: '如:关',
  139 + },
  140 + ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_BOOL,
  141 + },
  142 + {
  143 + field: FormField.BOOL_OPEN,
  144 + component: 'Input',
  145 + required: true,
  146 + label: '1 -',
  147 + colProps: {
  148 + span: 18,
  149 + },
  150 + componentProps: {
  151 + placeholder: '如:开',
  152 + },
  153 + ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_BOOL,
  154 + },
  155 + {
  156 + field: FormField.LENGTH,
  157 + component: 'Input',
  158 + required: true,
  159 + label: '数据长度',
  160 + defaultValue: '10240',
  161 + colProps: {
  162 + span: 8,
  163 + },
  164 + componentProps: {
  165 + placeholder: '请输入数据长度',
  166 + },
  167 + renderComponentContent: () => {
  168 + return {
  169 + suffix: () => '字节',
  170 + };
  171 + },
  172 + ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_STRING,
  173 + },
  174 + {
  175 + field: FormField.R_W_FLAG,
  176 + component: 'ApiRadioGroup',
  177 + label: '读写类型',
  178 + required: true,
  179 + colProps: {
  180 + span: 24,
  181 + },
  182 + defaultValue: 'READ_ONLY',
  183 + componentProps: {
  184 + placeholder: '请选择读写类型',
  185 + api: findDictItemByCode,
  186 + params: {
  187 + dictCode: 'read_write_type',
  188 + },
  189 + labelField: 'itemText',
  190 + valueField: 'itemValue',
  191 + },
  192 + },
  193 + {
  194 + field: FormField.SPECS_LIST,
  195 + label: 'JSON对象',
  196 + component: 'StructForm',
  197 + valueField: 'value',
  198 + changeEvent: 'update:value',
  199 + colProps: { span: 24 },
  200 + ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_STRUCT,
  201 + },
  202 + {
  203 + field: FormField.REFARK,
  204 + label: '备注',
  205 + component: 'InputTextArea',
  206 + componentProps: {
  207 + rows: 4,
  208 + maxLength: 100,
  209 + placeholder: '请输入描述',
  210 + },
  211 + },
  212 +];
  1 +import { DateTypeEnum } from './config';
  2 +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  3 +import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
  4 +
  5 +export enum OpenModalMode {
  6 + CREATE = 'create',
  7 + UPDATE = 'update',
  8 +}
  9 +
  10 +export interface OpenModalParams {
  11 + mode: OpenModalMode;
  12 + record?: StructRecord;
  13 +}
  14 +
  15 +export interface StructFormValue
  16 + extends Partial<Record<Exclude<FormField, FormField.VALUE_RANGE | FormField.STRUCT>, string>> {
  17 + [FormField.TYPE]: DateTypeEnum;
  18 + [FormField.VALUE_RANGE]?: {
  19 + [FormField.MIN]: string;
  20 + [FormField.MAX]: string;
  21 + };
  22 + [FormField.STRUCT]: StructRecord[];
  23 +}
  24 +
  25 +export interface StructRecord extends ModelOfMatterParams {
  26 + id: string;
  27 +}
  1 +import { DateTypeEnum } from './config';
  2 +import { StructFormValue } from './type';
  3 +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  4 +import { useMessage } from '/@/hooks/web/useMessage';
  5 +import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
  6 +
  7 +export const validateValueRangeAndStep = (min: number, step: number, max: number) => {
  8 + const { createMessage } = useMessage();
  9 + if (min > max) {
  10 + createMessage.error('最大值必须大于最小值,整数型不能有小数位,单精度有效位为7,双精度为16');
  11 + throw '最大值必须大于最小值,整数型不能有小数位,单精度有效位为7,双精度为16';
  12 + }
  13 +
  14 + if (step > max - min) {
  15 + createMessage.error('步长不能大于取值范围的差值');
  16 + throw '步长不能大于取值范围的差值';
  17 + }
  18 +};
  19 +
  20 +export const validateValueBool = (boolClose, boolOpen) => {
  21 + const { createMessage } = useMessage();
  22 +
  23 + if (boolClose == boolOpen) {
  24 + createMessage.error('布尔值不能相同');
  25 + throw '布尔值不能相同';
  26 + }
  27 +};
  28 +
  29 +export const validateValueStruct = (data: []) => {
  30 + const { createMessage } = useMessage();
  31 +
  32 + if (data.length === 0) {
  33 + createMessage.error('struct不能为空');
  34 + throw 'struct不能为空';
  35 + }
  36 +};
  37 +
  38 +export function transformFormValue(value: StructFormValue): Partial<ModelOfMatterParams> {
  39 + const {
  40 + type,
  41 + valueRange,
  42 + step,
  43 + length = '',
  44 + boolClose,
  45 + boolOpen,
  46 + unit,
  47 + unitName,
  48 + functionName,
  49 + identifier,
  50 + remark,
  51 + specsList,
  52 + } = value;
  53 + const { min, max } = valueRange! || {};
  54 + const basic = { functionName, identifier, remark };
  55 + let functionJson = {} as unknown as ModelOfMatterParams['functionJson'];
  56 +
  57 + switch (type) {
  58 + case DateTypeEnum.IS_NUMBER_INT:
  59 + validateValueRangeAndStep(Number(min), Number(step), Number(max));
  60 + functionJson = {
  61 + type,
  62 + specs: { max, min, step, unit, unitName },
  63 + };
  64 + break;
  65 +
  66 + case DateTypeEnum.IS_NUMBER_DOUBLE:
  67 + validateValueRangeAndStep(Number(min), Number(step), Number(max));
  68 + functionJson = {
  69 + type,
  70 + specs: { max, min, step, unit, unitName },
  71 + };
  72 + break;
  73 +
  74 + case DateTypeEnum.IS_BOOL:
  75 + validateValueBool(Number(boolClose), Number(boolOpen));
  76 + functionJson = {
  77 + type,
  78 + specs: {
  79 + boolOpen: boolOpen,
  80 + boolClose: boolClose,
  81 + },
  82 + };
  83 + break;
  84 +
  85 + case DateTypeEnum.IS_STRING:
  86 + functionJson = {
  87 + type,
  88 + specs: { length },
  89 + };
  90 + break;
  91 +
  92 + case DateTypeEnum.IS_STRUCT:
  93 + functionJson = {
  94 + type,
  95 + specsList: specsList! as unknown as ModelOfMatterParams[],
  96 + };
  97 + break;
  98 + }
  99 + return {
  100 + ...basic,
  101 + functionType: FunctionType.PROPERTIES,
  102 + functionJson,
  103 + };
  104 +}
@@ -112,9 +112,10 @@ export type ComponentType = @@ -112,9 +112,10 @@ export type ComponentType =
112 | 'Render' 112 | 'Render'
113 | 'Slider' 113 | 'Slider'
114 | 'JAddInput' 114 | 'JAddInput'
115 - | 'CustomeMinMaxInput' 115 + | 'CustomMinMaxInput'
116 | 'Rate' 116 | 'Rate'
117 | 'ColorPicker' 117 | 'ColorPicker'
118 | 'IconDrawer' 118 | 'IconDrawer'
119 | 'ApiUpload' 119 | 'ApiUpload'
120 - | 'ApiSearchSelect'; 120 + | 'ApiSearchSelect'
  121 + | 'StructForm';
1 <template> 1 <template>
2 <BasicDrawer v-bind="$attrs" title="产品详情" @register="register" width="60%"> 2 <BasicDrawer v-bind="$attrs" title="产品详情" @register="register" width="60%">
3 <Tabs :animated="true" v-model:activeKey="activeKey" @change="handlePanelChange"> 3 <Tabs :animated="true" v-model:activeKey="activeKey" @change="handlePanelChange">
4 - <TabPane forceRender key="product" tab="产品"> 4 + <TabPane key="product" tab="产品">
5 <div class="relative"> 5 <div class="relative">
6 <DeviceConfigurationStep :ifShowBtn="false" ref="DevConStRef" /> 6 <DeviceConfigurationStep :ifShowBtn="false" ref="DevConStRef" />
7 <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> 7 <div class="absolute w-full h-full top-0 cursor-not-allowed"></div>
8 </div> 8 </div>
9 </TabPane> 9 </TabPane>
10 - <TabPane forceRender key="transport" tab="传输配置"> 10 + <TabPane key="transport" tab="传输配置">
11 <div class="relative"> 11 <div class="relative">
12 <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" /> 12 <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" />
13 <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> 13 <div class="absolute w-full h-full top-0 cursor-not-allowed"></div>
14 </div> 14 </div>
15 </TabPane> 15 </TabPane>
16 - <TabPane forceRender key="modelOfMatter" tab="物模型管理">  
17 - <PhysicalModelManagementStep /> 16 + <TabPane key="modelOfMatter" tab="物模型管理">
  17 + <PhysicalModelManagementStep :record="record" />
18 </TabPane> 18 </TabPane>
19 </Tabs> 19 </Tabs>
20 </BasicDrawer> 20 </BasicDrawer>
@@ -27,14 +27,15 @@ @@ -27,14 +27,15 @@
27 import PhysicalModelManagementStep from './step/PhysicalModelManagementStep.vue'; 27 import PhysicalModelManagementStep from './step/PhysicalModelManagementStep.vue';
28 import { ref, unref } from 'vue'; 28 import { ref, unref } from 'vue';
29 import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; 29 import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi';
  30 + import { DeviceRecord } from '/@/api/device/model/deviceModel';
30 31
31 defineEmits(['register']); 32 defineEmits(['register']);
32 33
33 type ActiveKey = 'product' | 'transport' | 'modelOfMatter'; 34 type ActiveKey = 'product' | 'transport' | 'modelOfMatter';
34 35
35 - const activeKey = ref<ActiveKey>('product'); 36 + const activeKey = ref<ActiveKey>('modelOfMatter');
36 37
37 - const record = ref<Recordable>({}); 38 + const record = ref<DeviceRecord>({} as unknown as DeviceRecord);
38 39
39 const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>(); 40 const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>();
40 const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>(); 41 const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>();
@@ -47,7 +48,7 @@ @@ -47,7 +48,7 @@
47 unref(TransConStRef)?.setFormData(res); 48 unref(TransConStRef)?.setFormData(res);
48 }; 49 };
49 50
50 - const [register, {}] = useDrawerInner(async (data: Recordable) => { 51 + const [register, {}] = useDrawerInner(async (data: { record: DeviceRecord }) => {
51 activeKey.value = 'product'; 52 activeKey.value = 'product';
52 record.value = await deviceConfigGetDetail(data.record.id); 53 record.value = await deviceConfigGetDetail(data.record.id);
53 setDeviceConfFormData(unref(record)); 54 setDeviceConfFormData(unref(record));
@@ -5,6 +5,7 @@ import { MessageEnum } from '/@/enums/messageEnum'; @@ -5,6 +5,7 @@ import { MessageEnum } from '/@/enums/messageEnum';
5 import { numberRule } from '/@/utils/rules'; 5 import { numberRule } from '/@/utils/rules';
6 6
7 import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; 7 import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi';
  8 +import { FormField, FunctionType } from './step/cpns/physical/cpns/config';
8 9
9 export const steps = [ 10 export const steps = [
10 { 11 {
@@ -17,49 +18,36 @@ export const steps = [ @@ -17,49 +18,36 @@ export const steps = [
17 }, 18 },
18 ]; 19 ];
19 20
  21 +export const formatFunctionType: Record<FunctionType, string> = {
  22 + [FunctionType.PROPERTIES]: '属性',
  23 + [FunctionType.EVENTS]: '事件',
  24 + [FunctionType.SERVICE]: '事件',
  25 +};
  26 +
20 export const physicalColumn: BasicColumn[] = [ 27 export const physicalColumn: BasicColumn[] = [
21 { 28 {
22 title: '功能类型', 29 title: '功能类型',
23 - dataIndex: 'dType', 30 + dataIndex: FormField.FUNCTION_TYPE,
24 width: 90, 31 width: 90,
  32 + format: (text: FunctionType) => {
  33 + return formatFunctionType[text];
  34 + },
25 }, 35 },
26 { 36 {
27 title: '功能名称', 37 title: '功能名称',
28 - dataIndex: 'name', 38 + dataIndex: FormField.FUNCTION_NAME,
29 width: 90, 39 width: 90,
30 }, 40 },
31 { 41 {
32 title: '标识符', 42 title: '标识符',
33 - dataIndex: 'type', 43 + dataIndex: FormField.IDENTIFIER,
34 width: 90, 44 width: 90,
35 }, 45 },
36 { 46 {
37 title: '数据类型', 47 title: '数据类型',
38 - dataIndex: 'transportType', 48 + dataIndex: 'functionJson.type',
39 width: 100, 49 width: 100,
40 }, 50 },
41 - // {  
42 - // title: '单位',  
43 - // dataIndex: 'description1',  
44 - // width: 90,  
45 - // },  
46 - // {  
47 - // title: '读写类型',  
48 - // dataIndex: 'default',  
49 - // width: 60,  
50 - // customRender: ({ record }) => {  
51 - // const status = record.actionStatus;  
52 - // const enable = status === 'SUCCESS' ? '读写' : '只读';  
53 - // const color = enable === '读写' ? 'blue' : 'green';  
54 - // const text = enable === '读写' ? '读写' : '只读';  
55 - // return h(Tag, { color }, () => text);  
56 - // },  
57 - // },  
58 - // {  
59 - // title: '创建人',  
60 - // dataIndex: 'description',  
61 - // width: 80,  
62 - // },  
63 { 51 {
64 title: '创建时间', 52 title: '创建时间',
65 dataIndex: 'createTime', 53 dataIndex: 'createTime',
@@ -409,130 +397,3 @@ export const formSchema: FormSchema[] = [ @@ -409,130 +397,3 @@ export const formSchema: FormSchema[] = [
409 }, 397 },
410 }, 398 },
411 ]; 399 ];
412 -  
413 -export const mockData: any = async () => {  
414 - const res = await [  
415 - {  
416 - dType: 'events',  
417 - name: '亮度百分比',  
418 - type: 'Brightness',  
419 - transportType: 'int32(整数型)',  
420 - description1: '饱和度/aw',  
421 - default: '1',  
422 - actionStatus: 'SUCCESS',  
423 - description: 'cheche',  
424 - createTime: '2022-10-20 10:24:22',  
425 - },  
426 - {  
427 - dType: 'service',  
428 - name: '运行状态',  
429 - type: 'RunningState',  
430 - transportType: 'bool(布尔型)',  
431 - description1: '',  
432 - default: '1',  
433 - actionStatus: 'FA',  
434 - description: 'cheche',  
435 - createTime: '2022-10-20 10:24:22',  
436 - },  
437 - {  
438 - dType: 'attr',  
439 - name: '设备运行状态',  
440 - type: 'E_Status_UP',  
441 - transportType: 'text(字符串)',  
442 - description1: '',  
443 - default: '1',  
444 - actionStatus: 'D',  
445 - description: 'cheche',  
446 - createTime: '2022-10-20 10:24:22',  
447 - },  
448 - {  
449 - dType: 'attr',  
450 - name: '过流告警使能',  
451 - type: 'OverCurrentEnable',  
452 - transportType: 'struct(结构体)',  
453 - description1: '',  
454 - default: '1',  
455 - actionStatus: 'SUCCESS',  
456 - description: 'cheche',  
457 - createTime: '2022-10-20 10:24:22',  
458 - },  
459 - {  
460 - dType: 'events',  
461 - name: '变频器运行状态1',  
462 - type: 'Brightness',  
463 - transportType: 'int32(整数型)',  
464 - description1: '转每分钟/turn/m',  
465 - default: '1',  
466 - actionStatus: 'Fa',  
467 - description: 'cheche',  
468 - createTime: '2022-10-20 10:24:22',  
469 - },  
470 - {  
471 - dType: 'service',  
472 - name: '产品序列号',  
473 - type: 'SerialNo',  
474 - transportType: 'text(字符串)',  
475 - description1: '',  
476 - default: '1',  
477 - actionStatus: 'FA',  
478 - description: 'cheche',  
479 - createTime: '2022-10-20 10:24:22',  
480 - },  
481 - {  
482 - dType: 'service',  
483 - name: '音量百分比',  
484 - type: 'Volume',  
485 - transportType: 'int32(整数型)',  
486 - description1: '分贝/db',  
487 - default: '1',  
488 - actionStatus: 'SUCCESS',  
489 - description: 'cheche',  
490 - createTime: '2022-10-20 10:24:22',  
491 - },  
492 - {  
493 - dType: 'attr',  
494 - name: '易释放氰化物',  
495 - type: 'easy_release_cyanide',  
496 - transportType: 'double(双精度浮点型)',  
497 - description1: '毫克每升/mg/L',  
498 - default: '1',  
499 - actionStatus: 'SUCCESS',  
500 - description: 'cheche',  
501 - createTime: '2022-10-20 10:24:22',  
502 - },  
503 - {  
504 - dType: 'attr',  
505 - name: '湿度',  
506 - type: 'Humidity',  
507 - transportType: 'float(单精度浮点型)',  
508 - description1: '相对湿度/%RH',  
509 - default: '1',  
510 - actionStatus: 'SUCCESS',  
511 - description: 'cheche',  
512 - createTime: '2022-10-20 10:24:22',  
513 - },  
514 - {  
515 - dType: 'attr',  
516 - name: '设备固件版本',  
517 - type: 'FirmwareVersion',  
518 - transportType: 'text(字符串)',  
519 - description1: '',  
520 - default: '1',  
521 - actionStatus: 'SUCCESS',  
522 - description: 'cheche',  
523 - createTime: '2022-10-20 10:24:22',  
524 - },  
525 - {  
526 - dType: 'events',  
527 - name: '用电量',  
528 - type: 'PowerConsumption',  
529 - transportType: 'float(单精度浮点型)',  
530 - description1: '千瓦时/kW.h',  
531 - default: '1',  
532 - actionStatus: 'F',  
533 - description: 'cheche',  
534 - createTime: '2022-10-20 10:24:22',  
535 - },  
536 - ];  
537 - return res;  
538 -};  
@@ -99,7 +99,7 @@ @@ -99,7 +99,7 @@
99 </div> 99 </div>
100 </template> 100 </template>
101 <script lang="ts" setup> 101 <script lang="ts" setup>
102 - import { ref, nextTick, onUnmounted } from 'vue'; 102 + import { ref, nextTick, onUnmounted, onMounted } from 'vue';
103 import { BasicTable, TableImg, useTable, TableAction, BasicColumn } from '/@/components/Table'; 103 import { BasicTable, TableImg, useTable, TableAction, BasicColumn } from '/@/components/Table';
104 import { columns, searchFormSchema, defaultObj } from './device.profile.data'; 104 import { columns, searchFormSchema, defaultObj } from './device.profile.data';
105 import { useMessage } from '/@/hooks/web/useMessage'; 105 import { useMessage } from '/@/hooks/web/useMessage';
@@ -258,6 +258,7 @@ @@ -258,6 +258,7 @@
258 } 258 }
259 259
260 const [registerDrawer, { openDrawer }] = useDrawer(); 260 const [registerDrawer, { openDrawer }] = useDrawer();
  261 + onMounted(() => openDrawer(true));
261 //详情 262 //详情
262 function handleDetailView(record: Recordable) { 263 function handleDetailView(record: Recordable) {
263 openDrawer(true, { record }); 264 openDrawer(true, { record });
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <template #toolbar> 8 <template #toolbar>
9 <div class="flex-auto"> 9 <div class="flex-auto">
10 <div class="mb-2"> 10 <div class="mb-2">
11 - <a-alert type="info" show-icon> 11 + <Alert type="info" show-icon>
12 <template #message> 12 <template #message>
13 <span v-if="!isShowBtn"> 13 <span v-if="!isShowBtn">
14 当前展示的是已发布到线上的功能定义,如需修改,请点击 14 当前展示的是已发布到线上的功能定义,如需修改,请点击
@@ -22,15 +22,15 @@ @@ -22,15 +22,15 @@
22 </span> 22 </span>
23 <span v-if="isShowBtn"> 您正在编辑的是草稿,需点击发布后,物模型才会正式生效. </span> 23 <span v-if="isShowBtn"> 您正在编辑的是草稿,需点击发布后,物模型才会正式生效. </span>
24 </template> 24 </template>
25 - </a-alert> 25 + </Alert>
26 </div> 26 </div>
27 <div class="flex justify-between items-end"> 27 <div class="flex justify-between items-end">
28 <div class="flex gap-2"> 28 <div class="flex gap-2">
29 <Authority value=""> 29 <Authority value="">
30 - <a-button v-if="isShowBtn" type="primary" @click="handleCreateOrEdit(null)"> 30 + <Button v-if="isShowBtn" type="primary" @click="handleCreateOrEdit">
31 新增物模型 31 新增物模型
32 - </a-button>  
33 - <a-button type="primary" @click="handleOpenTsl"> 物模型TSL </a-button> 32 + </Button>
  33 + <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button>
34 </Authority> 34 </Authority>
35 </div> 35 </div>
36 <div class="flex gap-2"> 36 <div class="flex gap-2">
@@ -41,25 +41,25 @@ @@ -41,25 +41,25 @@
41 cancel-text="取消" 41 cancel-text="取消"
42 @confirm="handleEmit" 42 @confirm="handleEmit"
43 > 43 >
44 - <a-button v-if="isShowBtn" type="primary"> 发布上线 </a-button> 44 + <Button v-if="isShowBtn" type="primary"> 发布上线 </Button>
45 </Popconfirm> 45 </Popconfirm>
46 - <a-button v-if="isShowBtn" class="!bg-gray-200" type="text" @click="handleReturn"> 46 + <Button v-if="isShowBtn" class="!bg-gray-200" type="text" @click="handleReturn">
47 返回 47 返回
48 - </a-button> 48 + </Button>
49 <Popconfirm 49 <Popconfirm
50 title="您确定要批量删除数据" 50 title="您确定要批量删除数据"
51 ok-text="确定" 51 ok-text="确定"
52 cancel-text="取消" 52 cancel-text="取消"
53 @confirm="handleDeleteOrBatchDelete(null)" 53 @confirm="handleDeleteOrBatchDelete(null)"
54 > 54 >
55 - <a-button 55 + <Button
56 style="display: none" 56 style="display: none"
57 type="primary" 57 type="primary"
58 color="error" 58 color="error"
59 :disabled="hasBatchDelete" 59 :disabled="hasBatchDelete"
60 > 60 >
61 批量删除 61 批量删除
62 - </a-button> 62 + </Button>
63 </Popconfirm> 63 </Popconfirm>
64 </Authority> 64 </Authority>
65 </div> 65 </div>
@@ -97,8 +97,12 @@ @@ -97,8 +97,12 @@
97 /> 97 />
98 </template> 98 </template>
99 </BasicTable> 99 </BasicTable>
100 - <PhysicalModelModal @register="registerModal" @success="handleSuccess" />  
101 - <PhysicalModelTsl @register="registerModalTsl" /> 100 + <PhysicalModelModal
  101 + :record="$props.record"
  102 + @register="registerModal"
  103 + @success="handleSuccess"
  104 + />
  105 + <PhysicalModelTsl :record="$props.record" @register="registerModalTsl" />
102 </div> 106 </div>
103 </template> 107 </template>
104 <script lang="ts" setup> 108 <script lang="ts" setup>
@@ -107,29 +111,32 @@ @@ -107,29 +111,32 @@
107 import { useModal } from '/@/components/Modal'; 111 import { useModal } from '/@/components/Modal';
108 import { physicalColumn } from '../device.profile.data'; 112 import { physicalColumn } from '../device.profile.data';
109 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 113 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
110 - import { deleteReportManage } from '/@/api/report/reportManager';  
111 import { Authority } from '/@/components/Authority'; 114 import { Authority } from '/@/components/Authority';
112 - // import { mockData } from '/@/api/device/deviceConfigApi';  
113 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue'; 115 import PhysicalModelModal from './cpns/physical/PhysicalModelModal.vue';
114 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue'; 116 import PhysicalModelTsl from './cpns/physical/PhysicalModelTsl.vue';
115 - import { Popconfirm } from 'ant-design-vue'; 117 + import { Popconfirm, Button, Alert } from 'ant-design-vue';
116 import { useMessage } from '/@/hooks/web/useMessage'; 118 import { useMessage } from '/@/hooks/web/useMessage';
117 - import { mockData } from '../device.profile.data';  
118 - 119 + import { DeviceRecord } from '/@/api/device/model/deviceModel';
  120 + import { deleteModel, getModelList } from '/@/api/device/modelOfMatter';
  121 + import { OpenModelOfMatterModelParams, OpenModelMode } from './cpns/physical/types';
  122 + import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
119 defineEmits(['register']); 123 defineEmits(['register']);
  124 +
  125 + defineProps<{
  126 + record: DeviceRecord;
  127 + }>();
  128 +
120 const { createMessage } = useMessage(); 129 const { createMessage } = useMessage();
121 const isShowBtn = ref(false); 130 const isShowBtn = ref(false);
122 const [registerModal, { openModal }] = useModal(); 131 const [registerModal, { openModal }] = useModal();
123 const [registerModalTsl, { openModal: openModalTsl }] = useModal(); 132 const [registerModalTsl, { openModal: openModalTsl }] = useModal();
124 133
125 const [registerTable, { reload, setProps }] = useTable({ 134 const [registerTable, { reload, setProps }] = useTable({
126 - // api: deviceConfigGetQuery,  
127 - api: mockData, 135 + api: getModelList,
128 columns: physicalColumn, 136 columns: physicalColumn,
129 showIndexColumn: false, 137 showIndexColumn: false,
130 clickToRowSelect: false, 138 clickToRowSelect: false,
131 useSearchForm: false, 139 useSearchForm: false,
132 - // rowKey: 'id',  
133 showTableSetting: true, 140 showTableSetting: true,
134 bordered: true, 141 bordered: true,
135 actionColumn: { 142 actionColumn: {
@@ -140,16 +147,18 @@ @@ -140,16 +147,18 @@
140 fixed: 'right', 147 fixed: 'right',
141 }, 148 },
142 }); 149 });
  150 +
143 // 刷新 151 // 刷新
144 const handleSuccess = () => { 152 const handleSuccess = () => {
145 reload(); 153 reload();
146 }; 154 };
147 155
148 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete( 156 const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
149 - deleteReportManage, 157 + deleteModel,
150 handleSuccess, 158 handleSuccess,
151 setProps 159 setProps
152 ); 160 );
  161 +
153 selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => { 162 selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => {
154 // Demo:status为1的选择框禁用 163 // Demo:status为1的选择框禁用
155 if (record.status === 1) { 164 if (record.status === 1) {
@@ -158,38 +167,36 @@ @@ -158,38 +167,36 @@
158 return { disabled: false }; 167 return { disabled: false };
159 } 168 }
160 }; 169 };
161 - const handleViewDetail = (record: Recordable | null) => { 170 +
  171 + const handleViewDetail = (record: ModelOfMatterParams) => {
162 if (record) { 172 if (record) {
163 openModal(true, { 173 openModal(true, {
164 - isUpdate: true,  
165 record, 174 record,
166 - isView: true,  
167 - isText: 'view',  
168 - }); 175 + mode: OpenModelMode.VIEW,
  176 + } as OpenModelOfMatterModelParams);
169 } 177 }
170 }; 178 };
  179 +
171 // 新增或编辑 180 // 新增或编辑
172 - const handleCreateOrEdit = (record: Recordable | null) => { 181 + const handleCreateOrEdit = (record?: ModelOfMatterParams) => {
173 if (record) { 182 if (record) {
174 openModal(true, { 183 openModal(true, {
175 - isUpdate: false, 184 + mode: OpenModelMode.UPDATE,
176 record, 185 record,
177 - isView: false,  
178 - isText: 'edit',  
179 - }); 186 + } as OpenModelOfMatterModelParams);
180 } else { 187 } else {
181 openModal(true, { 188 openModal(true, {
182 - isUpdate: true,  
183 - isView: false,  
184 - isText: 'add',  
185 - }); 189 + mode: OpenModelMode.CREATE,
  190 + } as OpenModelOfMatterModelParams);
186 } 191 }
187 }; 192 };
  193 +
188 const handleOpenTsl = () => { 194 const handleOpenTsl = () => {
189 openModalTsl(true, { 195 openModalTsl(true, {
190 isUpdate: true, 196 isUpdate: true,
191 }); 197 });
192 }; 198 };
  199 +
193 const handleEditPhysicalModel = () => (isShowBtn.value = true); 200 const handleEditPhysicalModel = () => (isShowBtn.value = true);
194 201
195 const handleReturn = () => (isShowBtn.value = false); 202 const handleReturn = () => (isShowBtn.value = false);
@@ -8,160 +8,138 @@ @@ -8,160 +8,138 @@
8 @ok="handleSubmit" 8 @ok="handleSubmit"
9 @cancel="handleCancel" 9 @cancel="handleCancel"
10 > 10 >
11 - <div v-if="isViewDetail">  
12 - <Attribute v-show="activeKey === '1'" ref="AttrRef" />  
13 - <Service v-show="activeKey === '2'" ref="ServiceRef" />  
14 - <Events v-show="activeKey === '3'" ref="EventsRef" />  
15 - </div>  
16 - <div v-if="!isViewDetail">  
17 - <div> 11 + <div>
  12 + <div v-if="openModalMode === OpenModelMode.CREATE">
18 <Typography> 13 <Typography>
19 <TypographyParagraph> 14 <TypographyParagraph>
20 - <blockquote style="background: #f2f2f2">{{ blockContent }}</blockquote> 15 + <blockquote class="bg-gray-100">{{ blockContent }}</blockquote>
21 </TypographyParagraph> 16 </TypographyParagraph>
22 </Typography> 17 </Typography>
23 </div> 18 </div>
24 - <Tabs type="card" v-model:activeKey="activeKey" :size="size">  
25 - <TabPane :disabled="attrDisable" forceRender key="1" tab="属性">  
26 - <Attribute v-show="activeKey === '1'" ref="AttrRef" />  
27 - </TabPane>  
28 - <TabPane :disabled="serveiceDisable" forceRender key="2" tab="服务">  
29 - <Service v-show="activeKey === '2'" ref="ServiceRef" />  
30 - </TabPane>  
31 - <TabPane  
32 - :disabled="eventDisable"  
33 - forceRender  
34 - key="3"  
35 - v-show="activeKey === '3'"  
36 - tab="事件"  
37 - >  
38 - <Events v-show="activeKey === '3'" ref="EventsRef" />  
39 - </TabPane> 19 + <Tabs
  20 + v-if="openModalMode === OpenModelMode.CREATE"
  21 + type="card"
  22 + v-model:activeKey="activeKey"
  23 + :size="size"
  24 + >
  25 + <TabPane :key="FunctionType.PROPERTIES" tab="属性" />
  26 + <TabPane :key="FunctionType.SERVICE" tab="服务" />
  27 + <TabPane :key="FunctionType.EVENTS" tab="事件" />
40 </Tabs> 28 </Tabs>
  29 + <Attribute v-show="activeKey === FunctionType.PROPERTIES" ref="AttrRef" />
  30 + <Service v-show="activeKey === FunctionType.SERVICE" ref="ServiceRef" />
  31 + <Events v-show="activeKey === FunctionType.EVENTS" ref="EventsRef" />
41 </div> 32 </div>
42 </BasicModal> 33 </BasicModal>
43 </div> 34 </div>
44 </template> 35 </template>
45 <script lang="ts" setup> 36 <script lang="ts" setup>
46 - import { ref, unref, reactive, nextTick } from 'vue'; 37 + import { ref, unref } from 'vue';
47 import { BasicModal, useModalInner } from '/@/components/Modal'; 38 import { BasicModal, useModalInner } from '/@/components/Modal';
48 import { Tabs, TabPane, Typography, TypographyParagraph } from 'ant-design-vue'; 39 import { Tabs, TabPane, Typography, TypographyParagraph } from 'ant-design-vue';
49 import Attribute from './cpns/Attribute.vue'; 40 import Attribute from './cpns/Attribute.vue';
50 import Service from './cpns/Service.vue'; 41 import Service from './cpns/Service.vue';
51 import Events from './cpns/Events.vue'; 42 import Events from './cpns/Events.vue';
52 - import { mockData } from '../physical/cpns/components/mock'; 43 + import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  44 + import { createModel, updateModel } from '/@/api/device/modelOfMatter';
  45 + import { DeviceRecord } from '/@/api/device/model/deviceModel';
  46 + import { useMessage } from '/@/hooks/web/useMessage';
  47 + import { OpenModelMode, OpenModelOfMatterModelParams } from './types/index';
  48 + import { FunctionType } from './cpns/config';
  49 + import { StructRecord } from '/@/components/Form/src/externalCompns/components/StructForm/type';
  50 +
  51 + const emit = defineEmits(['register', 'success']);
  52 +
  53 + const props = defineProps<{
  54 + record: DeviceRecord;
  55 + }>();
53 56
54 - defineEmits(['register']);  
55 - const attrDisable = ref(false);  
56 - const serveiceDisable = ref(false);  
57 - const eventDisable = ref(false);  
58 const blockContent = `属性一般是设备的运行状态,如当前温度等;服务是设备可被调用的方法,支持定义参数,如执行某项任务;事件则是设备上报的 57 const blockContent = `属性一般是设备的运行状态,如当前温度等;服务是设备可被调用的方法,支持定义参数,如执行某项任务;事件则是设备上报的
59 通知,如告警,需要被及时处理。`; 58 通知,如告警,需要被及时处理。`;
60 - const activeKey = ref('1'); 59 + const activeKey = ref<FunctionType>(FunctionType.PROPERTIES);
61 const size = ref('small'); 60 const size = ref('small');
62 const AttrRef = ref<InstanceType<typeof Attribute>>(); 61 const AttrRef = ref<InstanceType<typeof Attribute>>();
63 const ServiceRef = ref<InstanceType<typeof Service>>(); 62 const ServiceRef = ref<InstanceType<typeof Service>>();
64 const EventsRef = ref<InstanceType<typeof Events>>(); 63 const EventsRef = ref<InstanceType<typeof Events>>();
65 - const isUpdate = ref(false);  
66 - const isViewDetail = ref('');  
67 - const isText = ref('');  
68 - const dType = ref('');  
69 - const allData: any = reactive({  
70 - properties: [],  
71 - events: [],  
72 - services: [],  
73 - productKey: '',  
74 - _ppk: {},  
75 - }); 64 + const openModalMode = ref<OpenModelMode>(OpenModelMode.CREATE);
  65 +
  66 + const functionType = ref<FunctionType>();
  67 + const { createMessage } = useMessage();
  68 +
  69 + const setAttrFormData = (data: StructRecord) => AttrRef.value?.setFormData(data);
  70 + const setServiceFormData = (data) => ServiceRef.value?.setFormData(data);
  71 + const setEventsFormData = (data) => EventsRef.value?.setFormData(data);
76 72
77 - const setAttrFormData = (data: {}) => AttrRef.value?.setFormData(data);  
78 - const setServiceFormData = (data: {}) => ServiceRef.value?.setFormData(data);  
79 - const setEventsFormData = (data: {}) => EventsRef.value?.setFormData(data);  
80 const enums = { 73 const enums = {
81 - attr: setAttrFormData,  
82 - service: setServiceFormData,  
83 - events: setEventsFormData, 74 + [FunctionType.PROPERTIES]: setAttrFormData,
  75 + [FunctionType.SERVICE]: setServiceFormData,
  76 + [FunctionType.EVENTS]: setEventsFormData,
84 }; 77 };
85 - function action(val, data) {  
86 - let F = enums[val];  
87 - F(data); 78 +
  79 + function setFormData(type: FunctionType, value: StructRecord) {
  80 + const setFn = enums[type];
  81 + setFn(value);
88 } 82 }
89 - const dynamicData = (t, a, s, e) => {  
90 - switch (t) {  
91 - case 'attr':  
92 - activeKey.value = '1';  
93 - action(t, a);  
94 - attrDisable.value = false;  
95 - serveiceDisable.value = true;  
96 - eventDisable.value = true;  
97 - break;  
98 - case 'service':  
99 - activeKey.value = '2';  
100 - action(t, s);  
101 - attrDisable.value = true;  
102 - serveiceDisable.value = false;  
103 - eventDisable.value = true;  
104 - break;  
105 - case 'events':  
106 - activeKey.value = '3';  
107 - action(t, e);  
108 - attrDisable.value = true;  
109 - serveiceDisable.value = true;  
110 - eventDisable.value = false;  
111 - break;  
112 - }  
113 - };  
114 - const [register, { closeModal, setModalProps }] = useModalInner(async (data) => {  
115 - setModalProps({ loading: true });  
116 - handleCancel(false);  
117 - isUpdate.value = data.isUpdate;  
118 - isViewDetail.value = data.isView;  
119 - isText.value = data.isText;  
120 - dType.value = data.record?.dType;  
121 - if (!unref(isViewDetail)) {  
122 - const title = !unref(isUpdate) ? '编辑物模型' : '新增物模型';  
123 - if (!unref(isUpdate)) {  
124 - nextTick(() => {  
125 - dynamicData(dType.value, mockData.properties, mockData.services, mockData.events);  
126 - }); 83 +
  84 + const [register, { closeModal, setModalProps }] = useModalInner(
  85 + async (data: OpenModelOfMatterModelParams) => {
  86 + const { mode, record } = data;
  87 + openModalMode.value = mode;
  88 + if (record) {
  89 + functionType.value = data.record.functionType;
  90 + activeKey.value = data.record.functionType;
  91 + setFormData(record.functionType, record as unknown as StructRecord);
  92 + }
  93 + if (unref(openModalMode) === OpenModelMode.VIEW) {
  94 + setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看物模型' });
  95 + // setFormData(functionType.value, record);
  96 + } else {
  97 + const title = unref(openModalMode) === OpenModelMode.UPDATE ? '编辑物模型' : '新增物模型';
  98 + if (OpenModelMode.UPDATE) {
  99 + // setFormData(functionType.value, record);
  100 + }
  101 + setModalProps({ title, showOkBtn: true, showCancelBtn: true });
127 } 102 }
128 - setModalProps({ title, showOkBtn: true, showCancelBtn: true });  
129 - } else {  
130 - setModalProps({ showOkBtn: false, showCancelBtn: false, title: '查看物模型' });  
131 - nextTick(() => {  
132 - dynamicData(dType.value, mockData.properties, mockData.services, mockData.events);  
133 - });  
134 } 103 }
135 - setModalProps({ loading: false });  
136 - }); 104 + );
  105 +
137 const handleCancel = (flag) => { 106 const handleCancel = (flag) => {
138 AttrRef.value?.resetFormData(); 107 AttrRef.value?.resetFormData();
139 ServiceRef.value?.resetFormData(); 108 ServiceRef.value?.resetFormData();
140 EventsRef.value?.resetFormData(); 109 EventsRef.value?.resetFormData();
141 - activeKey.value = '1';  
142 - allData.properties = [];  
143 - allData.events = [];  
144 - allData.services = [];  
145 - attrDisable.value = false;  
146 - serveiceDisable.value = false;  
147 - eventDisable.value = false; 110 + activeKey.value = FunctionType.PROPERTIES;
148 if (flag) { 111 if (flag) {
149 closeModal(); 112 closeModal();
150 } 113 }
151 }; 114 };
  115 +
152 const handleSubmit = async () => { 116 const handleSubmit = async () => {
153 - if (activeKey.value == '1') {  
154 - const valueAttr = await AttrRef.value?.getFormData();  
155 - allData.properties.push(valueAttr);  
156 - } else if (activeKey.value == '2') {  
157 - const valueService = await ServiceRef.value?.getFormData();  
158 - allData.services.push(valueService);  
159 - } else {  
160 - const valueEvents = await EventsRef.value?.getFormData();  
161 - allData.events.push(valueEvents); 117 + try {
  118 + setModalProps({ loading: false, okButtonProps: { loading: true } });
  119 +
  120 + let params: Partial<ModelOfMatterParams>;
  121 + if (activeKey.value == FunctionType.PROPERTIES) {
  122 + params = (await AttrRef.value?.getFormData()) || {};
  123 + } else if (activeKey.value == FunctionType.SERVICE) {
  124 + params = await ServiceRef.value?.getFormData();
  125 + } else {
  126 + params = await EventsRef.value?.getFormData();
  127 + }
  128 + params.deviceProfileId = props.record.id;
  129 + if (unref(openModalMode) === OpenModelMode.CREATE) {
  130 + await createModel(params);
  131 + createMessage.success('创建成功');
  132 + } else {
  133 + params.id = props.record.id;
  134 + await updateModel(params);
  135 + createMessage.success('修改成功');
  136 + }
  137 + closeModal();
  138 + emit('success');
  139 + } catch (error) {
  140 + } finally {
  141 + setModalProps({ loading: false, okButtonProps: { loading: false } });
162 } 142 }
163 - console.log('搜集值', allData);  
164 - closeModal();  
165 }; 143 };
166 </script> 144 </script>
167 145
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicForm @register="register">  
4 - <template #outputParamSlot>  
5 - <div>  
6 - <template v-for="(item, index) in outputParamData" :key="item">  
7 - <span style="display: none">{{ item + index }}</span>  
8 - <InputParamItem  
9 - :title="item.name"  
10 - :item="item"  
11 - class="mt-4"  
12 - :index="item.id"  
13 - :ref="dynamicBindRef.outputParamItemRef"  
14 - @delete="deleteOutParItem"  
15 - @edit="editOutParItem"  
16 - />  
17 - </template>  
18 - <div style="display: flex" :class="{ 'mt-2': outputParamData.length > 0 }">  
19 - <span class="add-style">+</span>  
20 - <span class="add-style" @click="handleAddOutParam">增加参数</span>  
21 - </div>  
22 - </div>  
23 - </template>  
24 - </BasicForm>  
25 - <AddParamsModal @register="registerModal" @data="getData" /> 3 + <BasicForm @register="register" />
26 </div> 4 </div>
27 </template> 5 </template>
28 <script lang="ts" setup> 6 <script lang="ts" setup>
29 - import { ref, unref } from 'vue';  
30 import { BasicForm, useForm } from '/@/components/Form'; 7 import { BasicForm, useForm } from '/@/components/Form';
31 - import { attrSchemas } from './config';  
32 - import { useModal } from '/@/components/Modal';  
33 - import InputParamItem from './components/InputParamItem.vue';  
34 - import AddParamsModal from './components/AddParamsModal.vue';  
35 - import { validateValueStruct } from '../hook/useValidateParital';  
36 - import { useChangeTypeGetTypeForm } from '../hook/useTypeGetForm';  
37 - import { buildUUID } from '/@/utils/uuid'; 8 + import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  9 + import { formSchemas } from '/@/components/Form/src/externalCompns/components/StructForm/config';
  10 + import { transformFormValue } from '/@/components/Form/src/externalCompns/components/StructForm/util';
  11 + import {
  12 + StructFormValue,
  13 + StructRecord,
  14 + } from '/@/components/Form/src/externalCompns/components/StructForm/type';
38 15
39 - const outputParamData: any = ref([]);  
40 - const dynamicBindRef = {  
41 - outputParamItemRef: ref([]),  
42 - };  
43 -  
44 - const [registerModal, { openModal }] = useModal();  
45 -  
46 - const [register, { validate, setFieldsValue, resetFields }] = useForm({ 16 + const [register, { validate, resetFields, setFieldsValue }] = useForm({
47 labelWidth: 100, 17 labelWidth: 100,
48 - schemas: attrSchemas, 18 + schemas: formSchemas,
49 actionColOptions: { 19 actionColOptions: {
50 span: 14, 20 span: 14,
51 }, 21 },
@@ -54,112 +24,38 @@ @@ -54,112 +24,38 @@
54 showActionButtonGroup: false, 24 showActionButtonGroup: false,
55 }); 25 });
56 26
57 - const getData = (d, f) => {  
58 - if (f == 'output') {  
59 - if (d.id !== null) {  
60 - const findIndex = unref(outputParamData).findIndex((f) => f.id == d.id);  
61 - if (findIndex !== -1) unref(outputParamData).splice(findIndex, 1, d);  
62 - } else {  
63 - unref(outputParamData).push({ ...d, id: buildUUID() });  
64 - }  
65 - }  
66 - };  
67 -  
68 - const handleAddOutParam = () => {  
69 - openModal(true, {  
70 - isUpdate: true,  
71 - flag: 'output',  
72 - excludeStruct: true,  
73 - });  
74 - };  
75 -  
76 - const deleteOutParItem = (index) => {  
77 - unref(outputParamData).splice(index, 1);  
78 - };  
79 -  
80 - const editOutParItem = (item) => {  
81 - openModal(true, {  
82 - isUpdate: false,  
83 - record: item,  
84 - flag: 'output',  
85 - excludeStruct: true,  
86 - });  
87 - };  
88 -  
89 - const setTypeData = (T, D) => {  
90 - if (T === 'INT' || T === 'DOUBLE' || T === 'TEXT') {  
91 - return {  
92 - ...D?.dataSpecs,  
93 - valueRange: D?.dataSpecs,  
94 - };  
95 - } else if (T === 'BOOL') {  
96 - return {  
97 - boolClose: D?.dataSpecsList[0]?.name,  
98 - boolOpen: D?.dataSpecsList[1]?.name,  
99 - };  
100 - }  
101 - };  
102 -  
103 - //回显数据  
104 - const setFormData = (v) => {  
105 - setFieldsValue({ ...v[0] });  
106 - setFieldsValue(setTypeData(v[0].dataType, v[0]));  
107 - const { dataSpecsList } = v[0];  
108 - if (dataSpecsList !== undefined) {  
109 - outputParamData.value = [...new Array(dataSpecsList.length).keys()];  
110 - outputParamData.value = dataSpecsList;  
111 - }  
112 - }; 27 + async function getFormData(): Promise<Partial<ModelOfMatterParams>> {
  28 + const _values = (await validate()) as StructFormValue;
  29 + if (!_values) return {};
  30 + let value = transformFormValue(_values);
  31 + return value;
  32 + }
113 33
114 - //获取结构体数据  
115 - const getStructList = () => {  
116 - const val = unref(dynamicBindRef.outputParamItemRef)?.map((item: any) => item.getFormData());  
117 - return val; 34 + const resetFormData = () => {
  35 + resetFields();
118 }; 36 };
119 37
120 - const getBoolOrStructData = (T, S, B) => {  
121 - if (T === 'STRUCT') {  
122 - return S;  
123 - } else {  
124 - return B;  
125 - }  
126 - }; 38 + const setFormData = (record: StructRecord) => {
  39 + const { functionJson } = record as StructRecord;
  40 + const { specs = {} } = functionJson || ({} as StructRecord['functionJson']);
127 41
128 - async function getFormData() {  
129 - const values = await validate();  
130 - if (!values) return;  
131 - const dataSpecsList = getStructList();  
132 - if (values.dataType === 'STRUCT') {  
133 - validateValueStruct(dataSpecsList as any);  
134 - }  
135 - const dataSpecs = useChangeTypeGetTypeForm(values.dataType, values);  
136 - const dataSpecsListBool = useChangeTypeGetTypeForm(values.dataType, values);  
137 - const { valueRange, step, unit, outputParam, ...value } = values;  
138 - const none = {  
139 - ...outputParam,  
140 - ...step,  
141 - ...unit,  
142 - ...valueRange,  
143 - };  
144 - console.log(none);  
145 - return {  
146 - ...value,  
147 - ...{ dataSpecs },  
148 - ...{  
149 - dataSpecsList: getBoolOrStructData(values.dataType, dataSpecsList, dataSpecsListBool), 42 + const value = {
  43 + ...record,
  44 + ...functionJson,
  45 + ...specs,
  46 + valueRange: {
  47 + min: specs.min,
  48 + max: specs.max,
150 }, 49 },
151 }; 50 };
152 - }  
153 51
154 - const resetFormData = () => {  
155 - resetFields();  
156 - outputParamData.value = []; 52 + setFieldsValue(value);
157 }; 53 };
158 54
159 defineExpose({ 55 defineExpose({
160 - setFormData,  
161 resetFormData, 56 resetFormData,
162 getFormData, 57 getFormData,
  58 + setFormData,
163 }); 59 });
164 </script> 60 </script>
165 <style lang="less" scoped> 61 <style lang="less" scoped>
@@ -3,20 +3,20 @@ @@ -3,20 +3,20 @@
3 <BasicForm @register="registerForm"> 3 <BasicForm @register="registerForm">
4 <template #structSlot> 4 <template #structSlot>
5 <div> 5 <div>
6 - <template v-for="(item, index) in outputParamData" :key="item">  
7 - <span style="display: none">{{ item }}</span> 6 + <template v-for="item in outputParamData" :key="item.id">
  7 + <span class="hidden">{{ item }}</span>
8 <InputParamItem 8 <InputParamItem
9 - :title="item.name"  
10 :item="item" 9 :item="item"
11 class="mt-4" 10 class="mt-4"
12 - :index="index"  
13 :ref="dynamicBindRef.outputParamItemRef" 11 :ref="dynamicBindRef.outputParamItemRef"
14 @delete="deleteOutParItem" 12 @delete="deleteOutParItem"
15 @edit="editOutParItem" 13 @edit="editOutParItem"
16 /> 14 />
17 </template> 15 </template>
18 - <div style="display: flex" :class="{ 'mt-2': outputParamData.length > 0 }">  
19 - <span class="add-style">+</span> 16 + <div class="flex" :class="{ 'mt-2': outputParamData.length > 0 }">
  17 + <span class="add-style">
  18 + <PlusOutlined />
  19 + </span>
20 <span class="add-style" @click="handleAddOutParam">增加参数</span> 20 <span class="add-style" @click="handleAddOutParam">增加参数</span>
21 </div> 21 </div>
22 </div> 22 </div>
@@ -28,21 +28,28 @@ @@ -28,21 +28,28 @@
28 <script lang="ts" setup> 28 <script lang="ts" setup>
29 import { ref, unref } from 'vue'; 29 import { ref, unref } from 'vue';
30 import { BasicForm, useForm } from '/@/components/Form'; 30 import { BasicForm, useForm } from '/@/components/Form';
31 - import { addParamsSchemas } from '../config'; 31 + import { addParamsSchemas, FormField } from '../config';
32 import { useModal } from '/@/components/Modal'; 32 import { useModal } from '/@/components/Modal';
33 import InputParamItem from './InputParamItem.vue'; 33 import InputParamItem from './InputParamItem.vue';
34 import AddParamsModal from './AddParamsModal.vue'; 34 import AddParamsModal from './AddParamsModal.vue';
35 import { buildUUID } from '/@/utils/uuid'; 35 import { buildUUID } from '/@/utils/uuid';
36 - import { useChangeTypeGetTypeForm, useUpdateFormExcludeStruct } from '../../hook/useTypeGetForm'; 36 + import { PlusOutlined } from '@ant-design/icons-vue';
  37 + import { FunctionJson, ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  38 + import { transformFormValue } from '/@/components/Form/src/externalCompns/components/StructForm/util';
  39 + import { StructFormValue } from '/@/components/Form/src/externalCompns/components/StructForm/type';
  40 + type OutputParam = FunctionJson & { id: string };
37 41
38 defineEmits(['register']); 42 defineEmits(['register']);
39 - const outputParamData: any = ref([]); 43 +
  44 + const outputParamData = ref<OutputParam[]>([]);
  45 +
40 const dynamicBindRef = { 46 const dynamicBindRef = {
41 outputParamItemRef: ref([]), 47 outputParamItemRef: ref([]),
42 }; 48 };
  49 +
43 const [registerModal, { openModal }] = useModal(); 50 const [registerModal, { openModal }] = useModal();
44 51
45 - const [registerForm, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({ 52 + const [registerForm, { validate, resetFields, updateSchema }] = useForm({
46 labelWidth: 100, 53 labelWidth: 100,
47 schemas: addParamsSchemas, 54 schemas: addParamsSchemas,
48 actionColOptions: { 55 actionColOptions: {
@@ -53,15 +60,8 @@ @@ -53,15 +60,8 @@
53 showActionButtonGroup: false, 60 showActionButtonGroup: false,
54 }); 61 });
55 62
56 - const getData = (d, f) => {  
57 - if (f == 'output') {  
58 - if (d.id !== null) {  
59 - const findIndex = unref(outputParamData).findIndex((f) => f.id == d.id);  
60 - if (findIndex !== -1) unref(outputParamData).splice(findIndex, 1, d);  
61 - } else {  
62 - unref(outputParamData).push({ ...d, id: buildUUID() });  
63 - }  
64 - } 63 + const getData = (value: FunctionJson) => {
  64 + unref(outputParamData).push({ ...value, id: buildUUID() });
65 }; 65 };
66 66
67 const handleAddOutParam = () => { 67 const handleAddOutParam = () => {
@@ -72,11 +72,12 @@ @@ -72,11 +72,12 @@
72 }); 72 });
73 }; 73 };
74 74
75 - const deleteOutParItem = (index) => {  
76 - unref(outputParamData).splice(index, 1); 75 + const deleteOutParItem = (value: OutputParam) => {
  76 + const index = unref(outputParamData).findIndex((item) => item.id === value.id);
  77 + ~index && unref(outputParamData).splice(index, 1);
77 }; 78 };
78 79
79 - const editOutParItem = (item) => { 80 + const editOutParItem = (item: FunctionJson) => {
80 openModal(true, { 81 openModal(true, {
81 isUpdate: false, 82 isUpdate: false,
82 record: item, 83 record: item,
@@ -85,98 +86,26 @@ @@ -85,98 +86,26 @@
85 }); 86 });
86 }; 87 };
87 88
88 - const updateFormExcludeStruct = (flag) => useUpdateFormExcludeStruct(flag, updateSchema);  
89 -  
90 - const getOutputStructList = () =>  
91 - unref(dynamicBindRef.outputParamItemRef)?.map((item: any) => item.getFormData());  
92 -  
93 - const getBoolOrStruct = (T, S, B) => {  
94 - if (T === 'STRUCT') {  
95 - return S;  
96 - } else if (T === 'INT' || T === 'DOUBLE' || T === 'TEXT') {  
97 - return null;  
98 - } else {  
99 - return B;  
100 - }  
101 - };  
102 -  
103 - const getIntOrText = (T, D) => {  
104 - if (T === 'STRUCT') {  
105 - return null;  
106 - } else if (T === 'INT' || T === 'DOUBLE' || T === 'TEXT') {  
107 - return D;  
108 - }  
109 - };  
110 -  
111 - const getFormData = async () => {  
112 - const values = await validate();  
113 - if (!values) return;  
114 - const outputParams = getOutputStructList();  
115 - outputParams.forEach((f) => {  
116 - f.dataType = 'STRUCT';  
117 - f.childDataType = values.dataType;  
118 - f.childName = values.name; 89 + const updateFormExcludeStruct = () => {
  90 + const options = useUpdateFormExcludeStruct();
  91 + updateSchema({
  92 + field: FormField.TYPE,
  93 + componentProps: { options },
119 }); 94 });
120 - const dataSpecs = useChangeTypeGetTypeForm(values.dataType, values);  
121 - const dataSpecsList = useChangeTypeGetTypeForm(values.dataType, values);  
122 - const { boolClose, boolOpen, step, unit, valueRange, ...value } = values;  
123 - const none = {  
124 - ...boolClose,  
125 - ...boolOpen,  
126 - ...step,  
127 - ...unit,  
128 - ...valueRange,  
129 - };  
130 - console.log(none);  
131 - return {  
132 - ...value,  
133 - ...{  
134 - dataSpecs: getIntOrText(values.dataType, dataSpecs),  
135 - },  
136 - // ...{  
137 - // childSpecsDTO: getIntOrText(values.dataType, dataSpecs),  
138 - // },  
139 - ...{  
140 - dataSpecsList: getBoolOrStruct(values.dataType, outputParams, dataSpecsList),  
141 - },  
142 - // ...{ childEnumSpecsDTO: getBoolOrStruct(values.dataType, outputParams, dataSpecsList) },  
143 - // ...{  
144 - // childDataType: values.dataType,  
145 - // childName: values.name,  
146 - // },  
147 - };  
148 }; 95 };
149 96
150 - const setFormData = (v) => {  
151 - setFieldsValue(v);  
152 - setFieldsValue({  
153 - ...v.dataSpecs,  
154 - valueRange: v.dataSpecs,  
155 - }); 97 + const getFormData = async (): Promise<Partial<ModelOfMatterParams>> => {
156 try { 98 try {
157 - setFieldsValue({  
158 - boolClose: v.dataType == 'BOOL' ? v.dataSpecsList[0].name : '',  
159 - boolOpen: v.dataType == 'BOOL' ? v.dataSpecsList[1].name : '',  
160 - });  
161 - } catch (e) {  
162 - console.log(e);  
163 - }  
164 - const { dataSpecsList, dataType, childDataType } = v;  
165 - if (childDataType == 'BOOL') {  
166 - setFieldsValue({  
167 - dataType: childDataType,  
168 - boolClose: dataSpecsList[0].name,  
169 - boolOpen: dataSpecsList[1].name,  
170 - });  
171 - }  
172 - try {  
173 - if (dataType == 'BOOL' || dataType == 'STRUCT') {  
174 - outputParamData.value = [...new Array(dataSpecsList.length).keys()];  
175 - outputParamData.value = dataSpecsList;  
176 - }  
177 - } catch (e) {  
178 - console.log(e);  
179 - } 99 + const values = (await validate()) as StructFormValue;
  100 + if (!values) return {} as unknown as ModelOfMatterParams;
  101 + const functionJson = transformFormValue(values);
  102 + return functionJson;
  103 + } catch (error) {}
  104 + return {} as unknown as ModelOfMatterParams;
  105 + };
  106 +
  107 + const setFormData = (value: FunctionJson) => {
  108 + setFormData(value);
180 }; 109 };
181 110
182 const resetFormData = () => { 111 const resetFormData = () => {
@@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
17 import { ref, computed, reactive } from 'vue'; 17 import { ref, computed, reactive } from 'vue';
18 import { BasicModal, useModalInner } from '/@/components/Modal'; 18 import { BasicModal, useModalInner } from '/@/components/Modal';
19 import AddParamForm from './AddParamForm.vue'; 19 import AddParamForm from './AddParamForm.vue';
20 - import { validateValueStruct } from '../../hook/useValidateParital';  
21 20
22 const emits = defineEmits(['register', 'data']); 21 const emits = defineEmits(['register', 'data']);
23 const setEditData: any = reactive({ 22 const setEditData: any = reactive({
@@ -29,9 +28,9 @@ @@ -29,9 +28,9 @@
29 const excludeStruct = ref(false); 28 const excludeStruct = ref(false);
30 const getTitle = computed(() => (!isUpdate.value ? '编辑参数' : '新增参数')); 29 const getTitle = computed(() => (!isUpdate.value ? '编辑参数' : '新增参数'));
31 30
32 - const [register, { closeModal, setModalProps }] = useModalInner(async (data) => { 31 + const [register, { setModalProps }] = useModalInner(async (data) => {
33 setModalProps({ loading: true }); 32 setModalProps({ loading: true });
34 - handleCancel(false); 33 +
35 isUpdate.value = data.isUpdate; 34 isUpdate.value = data.isUpdate;
36 isFlag.value = data.flag; 35 isFlag.value = data.flag;
37 excludeStruct.value = data.excludeStruct; 36 excludeStruct.value = data.excludeStruct;
@@ -45,29 +44,15 @@ @@ -45,29 +44,15 @@
45 } 44 }
46 }); 45 });
47 46
48 - const handleCancel = (flag) => { 47 + const handleCancel = () => {
49 AddParamFormRef.value?.resetFormData(); 48 AddParamFormRef.value?.resetFormData();
50 - if (flag) {  
51 - closeModal();  
52 - }  
53 }; 49 };
54 50
55 const handleSubmit = async () => { 51 const handleSubmit = async () => {
56 const value = await AddParamFormRef.value?.getFormData(); 52 const value = await AddParamFormRef.value?.getFormData();
57 if (!value) return; 53 if (!value) return;
58 - if (value.dataType === 'STRUCT') {  
59 - validateValueStruct(value.dataSpecsList as any);  
60 - }  
61 - emits(  
62 - 'data',  
63 - {  
64 - ...value,  
65 - ...{ id: !isUpdate.value ? setEditData.getEditData.id : null },  
66 - ...{ index: !isUpdate.value ? setEditData.getEditData.index : null },  
67 - },  
68 - isFlag.value  
69 - );  
70 - handleCancel(true); 54 + emits('data', value);
  55 + handleCancel();
71 }; 56 };
72 </script> 57 </script>
73 <style lang="less" scope></style> 58 <style lang="less" scope></style>
1 <template> 1 <template>
2 <div> 2 <div>
3 - <a-card :title="`参数名称:${title}`" style="width: 540px; margin-top: -5px"> 3 + <a-card :title="`参数名称:${item.id}`" style="width: 540px; margin-top: -5px">
4 <template #extra> 4 <template #extra>
5 <div style="display: flex; align-items: center"> 5 <div style="display: flex; align-items: center">
6 - <span style="color: #0170cc; cursor: pointer" @click="handleEdit(item, index)">编辑</span> 6 + <span style="color: #0170cc; cursor: pointer" @click="handleEdit">编辑</span>
7 <a-divider type="vertical" style="height: 12px; background-color: #d8d8d8" /> 7 <a-divider type="vertical" style="height: 12px; background-color: #d8d8d8" />
8 - <span style="color: #0170cc; cursor: pointer" class="ml-1" @click="handleDelete(index)" 8 + <span style="color: #0170cc; cursor: pointer" class="ml-1" @click="handleDelete"
9 >删除</span 9 >删除</span
10 > 10 >
11 </div> 11 </div>
@@ -14,33 +14,26 @@ @@ -14,33 +14,26 @@
14 </div> 14 </div>
15 </template> 15 </template>
16 <script lang="ts" setup> 16 <script lang="ts" setup>
  17 + import { FunctionJson } from '/@/api/device/model/modelOfMatterModel';
  18 +
17 const emit = defineEmits(['delete', 'edit']); 19 const emit = defineEmits(['delete', 'edit']);
  20 +
  21 + type ItemRecrod = FunctionJson & { id: string };
  22 +
18 const props = defineProps({ 23 const props = defineProps({
19 - index: {  
20 - type: Number,  
21 - required: true,  
22 - },  
23 - title: {  
24 - type: String,  
25 - default: '',  
26 - },  
27 item: { 24 item: {
28 - type: Object, 25 + type: Object as PropType<ItemRecrod>,
29 required: true, 26 required: true,
30 default: () => {}, 27 default: () => {},
31 }, 28 },
32 }); 29 });
33 30
34 - const handleDelete = (index) => {  
35 - emit('delete', index); 31 + const handleDelete = () => {
  32 + emit('delete', props.item);
36 }; 33 };
37 34
38 - const handleEdit = (item, index) => {  
39 - const value = {  
40 - ...item,  
41 - ...{ index },  
42 - };  
43 - emit('edit', value); 35 + const handleEdit = () => {
  36 + emit('edit', props.item);
44 }; 37 };
45 38
46 const getFormData = () => { 39 const getFormData = () => {
1 import { FormSchema } from '/@/components/Table'; 1 import { FormSchema } from '/@/components/Table';
2 import { findDictItemByCode } from '/@/api/system/dict'; 2 import { findDictItemByCode } from '/@/api/system/dict';
3 3
  4 +export enum FormField {
  5 + FUNCTION_NAME = 'functionName',
  6 + FUNCTION_TYPE = 'functionType',
  7 + FUNCTION_JSON = 'functionJson',
  8 + IDENTIFIER = 'identifier',
  9 + TYPE = 'type',
  10 + REFARK = 'remark',
  11 + MIN = 'min',
  12 + MAX = 'max',
  13 + UNIT = 'unit',
  14 + UNIT_NAME = 'unitName',
  15 + STEP = 'step',
  16 + VALUE_RANGE = 'valueRange',
  17 + BOOL_CLOSE = 'boolClose',
  18 + BOOL_OPEN = 'boolOpen',
  19 + LENGTH = 'length',
  20 + R_W_FLAG = 'rwFlag',
  21 + SPECS_LIST = 'specsList',
  22 + CALL_TYPE = 'callType',
  23 + INPUT_PARAM = 'inputParam',
  24 + EVENT_TYPE = 'eventType',
  25 +
  26 + STRUCT = 'struct',
  27 +}
  28 +
  29 +export enum FunctionType {
  30 + PROPERTIES = 'properties',
  31 + EVENTS = 'events',
  32 + SERVICE = 'services',
  33 +}
  34 +
  35 +/**
  36 + * 新增参数 动态显示表单
  37 + */
  38 +export enum DateTypeEnum {
  39 + IS_NUMBER_INT = 'INT',
  40 + IS_NUMBER_DOUBLE = 'DOUBLE',
  41 + IS_STRING = 'TEXT',
  42 + IS_STRUCT = 'STRUCT',
  43 + IS_BOOL = 'BOOL',
  44 +}
  45 +
  46 +const isNumber = (type: string) => {
  47 + return type === DateTypeEnum.IS_NUMBER_INT || type === DateTypeEnum.IS_NUMBER_DOUBLE;
  48 +};
  49 +
  50 +const isString = (type: string) => {
  51 + return type === DateTypeEnum.IS_STRING;
  52 +};
  53 +const isStruct = (type: string) => {
  54 + return type === DateTypeEnum.IS_STRUCT;
  55 +};
  56 +
  57 +const isBool = (type: string) => {
  58 + return type === DateTypeEnum.IS_BOOL;
  59 +};
  60 +
4 export const defaultTslContent = { 61 export const defaultTslContent = {
5 schema: 'https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json', 62 schema: 'https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json',
6 profile: { 63 profile: {
@@ -24,180 +81,9 @@ export const defaultTslContent = { @@ -24,180 +81,9 @@ export const defaultTslContent = {
24 ], 81 ],
25 }; 82 };
26 83
27 -export const attrSchemas: FormSchema[] = [  
28 - {  
29 - field: 'name',  
30 - label: '功能名称',  
31 - required: true,  
32 - component: 'Input',  
33 - colProps: {  
34 - span: 18,  
35 - },  
36 - componentProps: {  
37 - maxLength: 255,  
38 - placeholder: '请输入功能名称',  
39 - },  
40 - },  
41 - {  
42 - field: 'identifier',  
43 - label: '标识符',  
44 - required: true,  
45 - component: 'Input',  
46 - colProps: {  
47 - span: 18,  
48 - },  
49 - componentProps: {  
50 - maxLength: 255,  
51 - placeholder: '请输入标识符',  
52 - },  
53 - },  
54 - {  
55 - field: 'dataType',  
56 - label: '数据类型',  
57 - required: true,  
58 - component: 'ApiSelect',  
59 - colProps: {  
60 - span: 9,  
61 - },  
62 - defaultValue: 'INT',  
63 - componentProps: {  
64 - placeholder: '请选择数据类型',  
65 - api: findDictItemByCode,  
66 - params: {  
67 - dictCode: 'data_type',  
68 - },  
69 - labelField: 'itemText',  
70 - valueField: 'itemValue',  
71 - },  
72 - },  
73 - {  
74 - field: 'valueRange',  
75 - label: '取值范围',  
76 - component: 'CustomeMinMaxInput',  
77 - colProps: {  
78 - span: 18,  
79 - },  
80 - ifShow: ({ values }) => isNumber(values.dataType),  
81 - },  
82 - {  
83 - field: 'step',  
84 - label: '步长',  
85 - component: 'Input',  
86 - colProps: {  
87 - span: 18,  
88 - },  
89 - componentProps: {  
90 - maxLength: 255,  
91 - placeholder: '请输入步长',  
92 - },  
93 - ifShow: ({ values }) => isNumber(values.dataType),  
94 - },  
95 - {  
96 - field: 'unit',  
97 - label: '单位',  
98 - component: 'ApiSelect',  
99 - colProps: {  
100 - span: 9,  
101 - },  
102 - componentProps: {  
103 - placeholder: '请选择单位',  
104 - api: findDictItemByCode,  
105 - params: {  
106 - dictCode: 'attribute_unit',  
107 - },  
108 - labelField: 'itemText',  
109 - valueField: 'itemValue',  
110 - },  
111 - ifShow: ({ values }) => isNumber(values.dataType),  
112 - },  
113 - {  
114 - field: 'boolClose',  
115 - component: 'Input',  
116 - required: true,  
117 - label: '0 -',  
118 - colProps: {  
119 - span: 18,  
120 - },  
121 - componentProps: {  
122 - placeholder: '如:关',  
123 - },  
124 - ifShow: ({ values }) => isBool(values.dataType),  
125 - },  
126 - {  
127 - field: 'boolOpen',  
128 - component: 'Input',  
129 - required: true,  
130 - label: '1 -',  
131 - colProps: {  
132 - span: 18,  
133 - },  
134 - componentProps: {  
135 - placeholder: '如:开',  
136 - },  
137 - ifShow: ({ values }) => isBool(values.dataType),  
138 - },  
139 - {  
140 - field: 'length',  
141 - component: 'Input',  
142 - required: true,  
143 - label: '数据长度',  
144 - defaultValue: '10240',  
145 - colProps: {  
146 - span: 8,  
147 - },  
148 - componentProps: {  
149 - placeholder: '请输入数据长度',  
150 - },  
151 - renderComponentContent: () => {  
152 - return {  
153 - suffix: () => '字节',  
154 - };  
155 - },  
156 - ifShow: ({ values }) => isString(values.dataType),  
157 - },  
158 - {  
159 - field: 'rwFlag',  
160 - component: 'ApiRadioGroup',  
161 - label: '读写类型',  
162 - required: true,  
163 - colProps: {  
164 - span: 24,  
165 - },  
166 - defaultValue: 'READ_ONLY',  
167 - componentProps: {  
168 - placeholder: '请选择读写类型',  
169 - api: findDictItemByCode,  
170 - params: {  
171 - dictCode: 'read_write_type',  
172 - },  
173 - labelField: 'itemText',  
174 - valueField: 'itemValue',  
175 - },  
176 - },  
177 - {  
178 - field: 'outputParam',  
179 - label: 'JSON 对象',  
180 - component: 'Input',  
181 - // required: true,  
182 - slot: 'outputParamSlot',  
183 - colProps: { span: 24 },  
184 - ifShow: ({ values }) => isStruct(values.dataType),  
185 - },  
186 - {  
187 - label: '描述',  
188 - field: 'description',  
189 - component: 'InputTextArea',  
190 - componentProps: {  
191 - rows: 6,  
192 - maxLength: 100,  
193 - placeholder: '请输入描述',  
194 - },  
195 - },  
196 -];  
197 -  
198 export const serviceSchemas: FormSchema[] = [ 84 export const serviceSchemas: FormSchema[] = [
199 { 85 {
200 - field: 'serviceName', 86 + field: FormField.FUNCTION_NAME,
201 label: '功能名称', 87 label: '功能名称',
202 required: true, 88 required: true,
203 component: 'Input', 89 component: 'Input',
@@ -210,7 +96,7 @@ export const serviceSchemas: FormSchema[] = [ @@ -210,7 +96,7 @@ export const serviceSchemas: FormSchema[] = [
210 }, 96 },
211 }, 97 },
212 { 98 {
213 - field: 'identifier', 99 + field: FormField.IDENTIFIER,
214 label: '标识符', 100 label: '标识符',
215 required: true, 101 required: true,
216 component: 'Input', 102 component: 'Input',
@@ -223,7 +109,7 @@ export const serviceSchemas: FormSchema[] = [ @@ -223,7 +109,7 @@ export const serviceSchemas: FormSchema[] = [
223 }, 109 },
224 }, 110 },
225 { 111 {
226 - field: 'callType', 112 + field: FormField.CALL_TYPE,
227 component: 'ApiRadioGroup', 113 component: 'ApiRadioGroup',
228 label: '调用方式', 114 label: '调用方式',
229 required: true, 115 required: true,
@@ -242,22 +128,22 @@ export const serviceSchemas: FormSchema[] = [ @@ -242,22 +128,22 @@ export const serviceSchemas: FormSchema[] = [
242 }, 128 },
243 }, 129 },
244 { 130 {
245 - field: 'inputParam', 131 + field: FormField.INPUT_PARAM,
246 label: '输入参数', 132 label: '输入参数',
247 component: 'Input', 133 component: 'Input',
248 slot: 'inputParamSlot', 134 slot: 'inputParamSlot',
249 colProps: { span: 24 }, 135 colProps: { span: 24 },
250 }, 136 },
251 { 137 {
252 - field: 'outputParam', 138 + field: FormField.SPECS_LIST,
253 label: '输出参数', 139 label: '输出参数',
254 component: 'Input', 140 component: 'Input',
255 slot: 'outputParamSlot', 141 slot: 'outputParamSlot',
256 colProps: { span: 24 }, 142 colProps: { span: 24 },
257 }, 143 },
258 { 144 {
259 - label: '描述',  
260 - field: 'description', 145 + field: FormField.REFARK,
  146 + label: '备注',
261 component: 'InputTextArea', 147 component: 'InputTextArea',
262 componentProps: { 148 componentProps: {
263 rows: 6, 149 rows: 6,
@@ -269,7 +155,7 @@ export const serviceSchemas: FormSchema[] = [ @@ -269,7 +155,7 @@ export const serviceSchemas: FormSchema[] = [
269 155
270 export const eventSchemas: FormSchema[] = [ 156 export const eventSchemas: FormSchema[] = [
271 { 157 {
272 - field: 'eventName', 158 + field: FormField.FUNCTION_NAME,
273 label: '功能名称', 159 label: '功能名称',
274 required: true, 160 required: true,
275 component: 'Input', 161 component: 'Input',
@@ -282,7 +168,7 @@ export const eventSchemas: FormSchema[] = [ @@ -282,7 +168,7 @@ export const eventSchemas: FormSchema[] = [
282 }, 168 },
283 }, 169 },
284 { 170 {
285 - field: 'identifier', 171 + field: FormField.IDENTIFIER,
286 label: '标识符', 172 label: '标识符',
287 required: true, 173 required: true,
288 component: 'Input', 174 component: 'Input',
@@ -295,7 +181,7 @@ export const eventSchemas: FormSchema[] = [ @@ -295,7 +181,7 @@ export const eventSchemas: FormSchema[] = [
295 }, 181 },
296 }, 182 },
297 { 183 {
298 - field: 'eventType', 184 + field: FormField.EVENT_TYPE,
299 component: 'ApiRadioGroup', 185 component: 'ApiRadioGroup',
300 label: '事件类型', 186 label: '事件类型',
301 required: true, 187 required: true,
@@ -314,15 +200,15 @@ export const eventSchemas: FormSchema[] = [ @@ -314,15 +200,15 @@ export const eventSchemas: FormSchema[] = [
314 }, 200 },
315 }, 201 },
316 { 202 {
317 - field: 'outputParam', 203 + field: FormField.SPECS_LIST,
318 label: '输出参数', 204 label: '输出参数',
319 component: 'Input', 205 component: 'Input',
320 slot: 'outputParamSlot', 206 slot: 'outputParamSlot',
321 colProps: { span: 24 }, 207 colProps: { span: 24 },
322 }, 208 },
323 { 209 {
324 - label: '描述',  
325 - field: 'description', 210 + field: FormField.REFARK,
  211 + label: '备注',
326 component: 'InputTextArea', 212 component: 'InputTextArea',
327 componentProps: { 213 componentProps: {
328 rows: 6, 214 rows: 6,
@@ -332,34 +218,9 @@ export const eventSchemas: FormSchema[] = [ @@ -332,34 +218,9 @@ export const eventSchemas: FormSchema[] = [
332 }, 218 },
333 ]; 219 ];
334 220
335 -/**  
336 - * 新增参数 动态显示表单  
337 - */  
338 -enum DateTypeEnum {  
339 - IS_NUMBER_INT = 'INT',  
340 - IS_NUMBER_DOUBLE = 'DOUBLE',  
341 - IS_STRING = 'TEXT',  
342 - IS_STRUCT = 'STRUCT',  
343 - IS_BOOL = 'BOOL',  
344 -}  
345 -const isNumber = (type: string) => {  
346 - return type === DateTypeEnum.IS_NUMBER_INT || type === DateTypeEnum.IS_NUMBER_DOUBLE;  
347 -};  
348 -  
349 -const isString = (type: string) => {  
350 - return type === DateTypeEnum.IS_STRING;  
351 -};  
352 -const isStruct = (type: string) => {  
353 - return type === DateTypeEnum.IS_STRUCT;  
354 -};  
355 -  
356 -const isBool = (type: string) => {  
357 - return type === DateTypeEnum.IS_BOOL;  
358 -};  
359 -  
360 export const addParamsSchemas: FormSchema[] = [ 221 export const addParamsSchemas: FormSchema[] = [
361 { 222 {
362 - field: 'name', 223 + field: FormField.FUNCTION_NAME,
363 label: '参数名称', 224 label: '参数名称',
364 required: true, 225 required: true,
365 component: 'Input', 226 component: 'Input',
@@ -372,7 +233,7 @@ export const addParamsSchemas: FormSchema[] = [ @@ -372,7 +233,7 @@ export const addParamsSchemas: FormSchema[] = [
372 }, 233 },
373 }, 234 },
374 { 235 {
375 - field: 'identifier', 236 + field: FormField.IDENTIFIER,
376 label: '标识符', 237 label: '标识符',
377 required: true, 238 required: true,
378 component: 'Input', 239 component: 'Input',
@@ -385,7 +246,7 @@ export const addParamsSchemas: FormSchema[] = [ @@ -385,7 +246,7 @@ export const addParamsSchemas: FormSchema[] = [
385 }, 246 },
386 }, 247 },
387 { 248 {
388 - field: 'dataType', 249 + field: FormField.TYPE,
389 label: '数据类型', 250 label: '数据类型',
390 required: true, 251 required: true,
391 component: 'ApiSelect', 252 component: 'ApiSelect',
@@ -404,17 +265,16 @@ export const addParamsSchemas: FormSchema[] = [ @@ -404,17 +265,16 @@ export const addParamsSchemas: FormSchema[] = [
404 }, 265 },
405 }, 266 },
406 { 267 {
407 - field: 'structSlot', 268 + field: FormField.STRUCT,
408 label: 'JSON 对象', 269 label: 'JSON 对象',
409 component: 'Input', 270 component: 'Input',
410 - slot: 'structSlot',  
411 colProps: { 271 colProps: {
412 span: 23, 272 span: 23,
413 }, 273 },
414 - ifShow: ({ values }) => isStruct(values.dataType), 274 + ifShow: ({ values }) => isStruct(values[FormField.TYPE]),
415 }, 275 },
416 { 276 {
417 - field: 'boolClose', 277 + field: FormField.BOOL_CLOSE,
418 component: 'Input', 278 component: 'Input',
419 required: true, 279 required: true,
420 label: '0 -', 280 label: '0 -',
@@ -424,10 +284,10 @@ export const addParamsSchemas: FormSchema[] = [ @@ -424,10 +284,10 @@ export const addParamsSchemas: FormSchema[] = [
424 componentProps: { 284 componentProps: {
425 placeholder: '如:关', 285 placeholder: '如:关',
426 }, 286 },
427 - ifShow: ({ values }) => isBool(values.dataType), 287 + ifShow: ({ values }) => isBool(values[FormField.TYPE]),
428 }, 288 },
429 { 289 {
430 - field: 'boolOpen', 290 + field: FormField.BOOL_OPEN,
431 component: 'Input', 291 component: 'Input',
432 required: true, 292 required: true,
433 label: '1 -', 293 label: '1 -',
@@ -437,10 +297,10 @@ export const addParamsSchemas: FormSchema[] = [ @@ -437,10 +297,10 @@ export const addParamsSchemas: FormSchema[] = [
437 componentProps: { 297 componentProps: {
438 placeholder: '如:开', 298 placeholder: '如:开',
439 }, 299 },
440 - ifShow: ({ values }) => isBool(values.dataType), 300 + ifShow: ({ values }) => isBool(values[FormField.TYPE]),
441 }, 301 },
442 { 302 {
443 - field: 'length', 303 + field: FormField.LENGTH,
444 component: 'Input', 304 component: 'Input',
445 required: true, 305 required: true,
446 label: '数据长度', 306 label: '数据长度',
@@ -456,19 +316,19 @@ export const addParamsSchemas: FormSchema[] = [ @@ -456,19 +316,19 @@ export const addParamsSchemas: FormSchema[] = [
456 suffix: () => '字节', 316 suffix: () => '字节',
457 }; 317 };
458 }, 318 },
459 - ifShow: ({ values }) => isString(values.dataType), 319 + ifShow: ({ values }) => isString(values[FormField.TYPE]),
460 }, 320 },
461 { 321 {
462 - field: 'valueRange', 322 + field: FormField.VALUE_RANGE,
463 label: '取值范围', 323 label: '取值范围',
464 - component: 'CustomeMinMaxInput', 324 + component: 'CustomMinMaxInput',
465 colProps: { 325 colProps: {
466 span: 23, 326 span: 23,
467 }, 327 },
468 - ifShow: ({ values }) => isNumber(values.dataType), 328 + ifShow: ({ values }) => isNumber(values[FormField.TYPE]),
469 }, 329 },
470 { 330 {
471 - field: 'step', 331 + field: FormField.STEP,
472 label: '步长', 332 label: '步长',
473 component: 'Input', 333 component: 'Input',
474 colProps: { 334 colProps: {
@@ -478,10 +338,10 @@ export const addParamsSchemas: FormSchema[] = [ @@ -478,10 +338,10 @@ export const addParamsSchemas: FormSchema[] = [
478 maxLength: 255, 338 maxLength: 255,
479 placeholder: '请输入步长', 339 placeholder: '请输入步长',
480 }, 340 },
481 - ifShow: ({ values }) => isNumber(values.dataType), 341 + ifShow: ({ values }) => isNumber(values[FormField.TYPE]),
482 }, 342 },
483 { 343 {
484 - field: 'unit', 344 + field: FormField.UNIT,
485 label: '单位', 345 label: '单位',
486 component: 'ApiSelect', 346 component: 'ApiSelect',
487 colProps: { 347 colProps: {
@@ -496,6 +356,6 @@ export const addParamsSchemas: FormSchema[] = [ @@ -496,6 +356,6 @@ export const addParamsSchemas: FormSchema[] = [
496 labelField: 'itemText', 356 labelField: 'itemText',
497 valueField: 'itemValue', 357 valueField: 'itemValue',
498 }, 358 },
499 - ifShow: ({ values }) => isNumber(values.dataType), 359 + ifShow: ({ values }) => isNumber(values[FormField.TYPE]),
500 }, 360 },
501 ]; 361 ];
1 -import { validateValueBool, validateValueRangeAndStep } from './useValidateParital';  
2 -import { findDictItemByCode } from '/@/api/system/dict';  
3 -  
4 -///根据不同数据类型得到不同表单数据  
5 -type TForm = {  
6 - dataType: string;  
7 - max?: string;  
8 - min?: string;  
9 - step?: string;  
10 - unit?: string;  
11 - boolClose?: string;  
12 - boolOpen?: string;  
13 - length?: string;  
14 - valueRange?: {  
15 - min: string;  
16 - max: string;  
17 - };  
18 -};  
19 -export const useChangeTypeGetTypeForm = (type, options: TForm) => {  
20 - switch (type) {  
21 - //INT和DOUBLE收集表单一样  
22 - case 'INT':  
23 - validateValueRangeAndStep(  
24 - Number(options?.valueRange?.min),  
25 - Number(options?.step),  
26 - Number(options?.valueRange?.max)  
27 - );  
28 - return {  
29 - dataType: options?.dataType,  
30 - max: options?.valueRange?.max,  
31 - min: options?.valueRange?.min,  
32 - step: options?.step,  
33 - unit: options?.unit,  
34 - };  
35 - case 'DOUBLE':  
36 - validateValueRangeAndStep(  
37 - Number(options?.valueRange?.min),  
38 - Number(options?.step),  
39 - Number(options?.valueRange?.max)  
40 - );  
41 - return {  
42 - dataType: options?.dataType,  
43 - max: options?.valueRange?.max,  
44 - min: options?.valueRange?.min,  
45 - step: options?.step,  
46 - unit: options?.unit,  
47 - };  
48 - case 'BOOL':  
49 - validateValueBool(Number(options?.boolClose), Number(options?.boolOpen));  
50 - return [  
51 - {  
52 - dataType: options?.dataType,  
53 - name: options?.boolClose,  
54 - value: '0',  
55 - },  
56 - {  
57 - dataType: options?.dataType,  
58 - name: options?.boolOpen,  
59 - value: '1',  
60 - },  
61 - ];  
62 - case 'TEXT':  
63 - return {  
64 - dataType: options?.dataType,  
65 - length: options?.length,  
66 - };  
67 - }  
68 -};  
69 -  
70 -//是否排除结构体  
71 -export const useUpdateFormExcludeStruct = async (F, U) => {  
72 - const res: any = await findDictItemByCode({ dictCode: 'data_type' });  
73 - const optionTrue = res  
74 - .map((m) => {  
75 - if (F) {  
76 - if (m.itemValue !== 'STRUCT') {  
77 - return {  
78 - value: m.itemValue,  
79 - label: m.itemText,  
80 - };  
81 - }  
82 - } else {  
83 - return {  
84 - value: m.itemValue,  
85 - label: m.itemText,  
86 - };  
87 - }  
88 - })  
89 - .filter(Boolean);  
90 - U({  
91 - field: 'dataType',  
92 - componentProps: {  
93 - options: optionTrue,  
94 - },  
95 - });  
96 -};  
1 -/**  
2 - * 校验部分字段  
3 - */  
4 -import { useMessage } from '/@/hooks/web/useMessage';  
5 -const { createMessage } = useMessage();  
6 -  
7 -export const validateValueRangeAndStep = (min, step, max) => {  
8 - if (min > max) {  
9 - createMessage.error('最大值必须大于最小值,整数型不能有小数位,单精度有效位为7,双精度为16');  
10 - throw '最大值必须大于最小值,整数型不能有小数位,单精度有效位为7,双精度为16';  
11 - }  
12 - if (step > max - min) {  
13 - createMessage.error('步长不能大于取值范围的差值');  
14 - throw '步长不能大于取值范围的差值';  
15 - }  
16 -};  
17 -  
18 -export const validateValueBool = (boolClose, boolOpen) => {  
19 - if (boolClose == boolOpen) {  
20 - createMessage.error('布尔值不能相同');  
21 - throw '布尔值不能相同';  
22 - }  
23 -};  
24 -  
25 -export const validateValueStruct = (data: []) => {  
26 - if (data.length === 0) {  
27 - createMessage.error('struct不能为空');  
28 - throw 'struct不能为空';  
29 - }  
30 -};  
  1 +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel';
  2 +
  3 +export enum OpenModelMode {
  4 + UPDATE = 'update',
  5 + CREATE = 'create',
  6 + VIEW = 'view',
  7 +}
  8 +
  9 +export interface OpenModelOfMatterModelParams {
  10 + mode: OpenModelMode;
  11 + record: ModelOfMatterParams;
  12 +}