Commit c676c5e3e658c66e83668786b0eef468d5124bdc
Merge remote-tracking branch 'origin/ww'
# Conflicts: # src/views/device/list/cpns/tabs/commandRecord/index.vue
Showing
13 changed files
with
695 additions
and
211 deletions
... | ... | @@ -2,7 +2,8 @@ |
2 | 2 | <div class="flex"> |
3 | 3 | <InputNumber |
4 | 4 | placeholder="最小值" |
5 | - :value="getValue.min" | |
5 | + :disabled="$props.disabled" | |
6 | + :value="getValue.min!" | |
6 | 7 | style="width: 38%" |
7 | 8 | @change="(value) => emitChange(value, 'min')" |
8 | 9 | /> |
... | ... | @@ -11,7 +12,8 @@ |
11 | 12 | <span style="width: 8px"></span> |
12 | 13 | <InputNumber |
13 | 14 | placeholder="最大值" |
14 | - :value="getValue.max" | |
15 | + :disabled="$props.disabled" | |
16 | + :value="getValue.max!" | |
15 | 17 | style="width: 38%" |
16 | 18 | @change="(value) => emitChange(value, 'max')" |
17 | 19 | /> |
... | ... | @@ -33,6 +35,7 @@ |
33 | 35 | min: Nullable<number>; |
34 | 36 | max: Nullable<number>; |
35 | 37 | }; |
38 | + disabled: boolean; | |
36 | 39 | }>(), |
37 | 40 | { |
38 | 41 | value: () => ({ min: null, max: null }), | ... | ... |
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | const props = withDefaults( |
20 | 20 | defineProps<{ |
21 | 21 | value: ModelOfMatterParams[]; |
22 | + disabled: boolean; | |
22 | 23 | }>(), |
23 | 24 | { |
24 | 25 | value: () => [], |
... | ... | @@ -82,20 +83,33 @@ |
82 | 83 | > |
83 | 84 | <div>参数名称: {{ item.functionName }}</div> |
84 | 85 | <div class="flex"> |
85 | - <Button class="!p-0" type="link" @click="handleUpdate(item)">编辑</Button> | |
86 | + <Button class="!p-0" type="link" @click="handleUpdate(item)"> | |
87 | + <span>{{ $props.disabled ? '查看' : '编辑' }}</span> | |
88 | + </Button> | |
86 | 89 | <Divider type="vertical" /> |
87 | - <Button class="!p-0" type="link" @click="handleDelete(item)">删除</Button> | |
90 | + <Button | |
91 | + :disabled="$props.disabled" | |
92 | + class="!p-0" | |
93 | + type="link" | |
94 | + @click="handleDelete(item)" | |
95 | + > | |
96 | + <span>删除</span> | |
97 | + </Button> | |
88 | 98 | </div> |
89 | 99 | </div> |
90 | 100 | </section> |
91 | - <div> | |
101 | + <div :class="$props.disabled && 'text-gray-400'"> | |
92 | 102 | <span class="mr-2"> |
93 | 103 | <PlusOutlined /> |
94 | 104 | </span> |
95 | - <span @click="handleCreateParams">增加参数</span> | |
105 | + <span @click="!$props.disabled && handleCreateParams()">增加参数</span> | |
96 | 106 | </div> |
97 | 107 | </div> |
98 | - <StructFormModel @register="registerModal" @submit="handleSaveStruct" /> | |
108 | + <StructFormModel | |
109 | + :disabled="$props.disabled" | |
110 | + @register="registerModal" | |
111 | + @submit="handleSaveStruct" | |
112 | + /> | |
99 | 113 | </section> |
100 | 114 | </template> |
101 | 115 | ... | ... |
... | ... | @@ -18,14 +18,17 @@ |
18 | 18 | mode: OpenModalMode.CREATE, |
19 | 19 | }); |
20 | 20 | |
21 | + const props = defineProps<{ disabled: boolean }>(); | |
22 | + | |
21 | 23 | const emit = defineEmits(['register', 'submit']); |
22 | 24 | |
23 | - const [register, { validate, setFieldsValue }] = useForm({ | |
25 | + const [register, { validate, setFieldsValue, setProps }] = useForm({ | |
24 | 26 | labelWidth: 100, |
25 | 27 | schemas: formSchemas, |
26 | 28 | actionColOptions: { |
27 | 29 | span: 14, |
28 | 30 | }, |
31 | + disabled: props.disabled, | |
29 | 32 | showResetButton: false, |
30 | 33 | submitOnReset: false, |
31 | 34 | showActionButtonGroup: false, |
... | ... | @@ -46,6 +49,7 @@ |
46 | 49 | |
47 | 50 | setFieldsValue(value); |
48 | 51 | } |
52 | + setProps({ disabled: props.disabled }); | |
49 | 53 | }); |
50 | 54 | |
51 | 55 | const handleSubmit = async () => { |
... | ... | @@ -71,6 +75,7 @@ |
71 | 75 | :width="800" |
72 | 76 | @ok="handleSubmit" |
73 | 77 | destroy-on-close |
78 | + :show-ok-btn="!$props.disabled" | |
74 | 79 | > |
75 | 80 | <BasicForm @register="register" /> |
76 | 81 | </BasicModal> | ... | ... |
... | ... | @@ -11,7 +11,7 @@ export enum DataTypeEnum { |
11 | 11 | IS_BOOL = 'BOOL', |
12 | 12 | } |
13 | 13 | |
14 | -const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callback) => { | |
14 | +export const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callback) => { | |
15 | 15 | value = value || {}; |
16 | 16 | const { min, max } = value; |
17 | 17 | if (min >= max) { |
... | ... | @@ -20,7 +20,7 @@ const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callba |
20 | 20 | return Promise.resolve(); |
21 | 21 | }; |
22 | 22 | |
23 | -const validateJSON = (_rule, value: ModelOfMatterParams[], _callback) => { | |
23 | +export const validateJSON = (_rule, value: ModelOfMatterParams[], _callback) => { | |
24 | 24 | if (value.length) { |
25 | 25 | return Promise.resolve(); |
26 | 26 | } |
... | ... | @@ -65,7 +65,15 @@ export const formSchemas: FormSchema[] = [ |
65 | 65 | defaultValue: 'INT', |
66 | 66 | componentProps: { |
67 | 67 | placeholder: '请选择数据类型', |
68 | - api: findDictItemByCode, | |
68 | + api: async (params: Recordable) => { | |
69 | + try { | |
70 | + const record = await findDictItemByCode(params); | |
71 | + return record.filter((item) => item.itemValue !== 'STRUCT'); | |
72 | + } catch (error) { | |
73 | + console.log(error); | |
74 | + return []; | |
75 | + } | |
76 | + }, | |
69 | 77 | params: { |
70 | 78 | dictCode: 'data_type', |
71 | 79 | }, | ... | ... |
1 | -<template> | |
2 | - <BasicDrawer | |
3 | - v-bind="$attrs" | |
4 | - isDetail | |
5 | - @register="register" | |
6 | - destroyOnClose | |
7 | - @close="closeDrawer" | |
8 | - :title="deviceDetail.alias || deviceDetail.name" | |
9 | - width="80%" | |
10 | - > | |
11 | - <Tabs v-model:activeKey="activeKey" :size="size"> | |
12 | - <TabPane key="1" tab="详情"> | |
13 | - <Detail | |
14 | - ref="deviceDetailRef" | |
15 | - :deviceDetail="deviceDetail" | |
16 | - @open-gateway-device="handleOpenGatewayDevice" | |
17 | - /> | |
18 | - </TabPane> | |
19 | - <TabPane key="modelOfMatter" tab="物模型数据"> | |
20 | - <ModelOfMatter :deviceDetail="deviceDetail" /> | |
21 | - </TabPane> | |
22 | - <!-- <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"> | |
23 | - <RealTimeData :deviceDetail="deviceDetail" /> | |
24 | - </TabPane> | |
25 | - <TabPane key="7" tab="历史数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"> | |
26 | - <HistoryData :deviceDetail="deviceDetail" /> | |
27 | - </TabPane> --> | |
28 | - <TabPane key="5" tab="命令下发" v-if="deviceDetail?.deviceType !== 'SENSOR'"> | |
29 | - <CommandIssuance :deviceDetail="deviceDetail" /> | |
30 | - </TabPane> | |
31 | - <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane> | |
32 | - <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"> | |
33 | - <ChildDevice | |
34 | - :fromId="deviceDetail?.tbDeviceId" | |
35 | - @openTbDeviceDetail="handleOpenTbDeviceDetail" | |
36 | - /> | |
37 | - </TabPane> | |
38 | - <TabPane key="7" tab="命令下发记录"> | |
39 | - <CommandRecord :fromId="deviceDetail?.tbDeviceId" /> | |
40 | - </TabPane> | |
41 | - <!-- 网关设备并且场家是TBox --> | |
42 | - <TabPane | |
43 | - key="6" | |
44 | - tab="TBox" | |
45 | - v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'" | |
46 | - > | |
47 | - <TBoxDetail :deviceDetail="deviceDetail" /> | |
48 | - </TabPane> | |
49 | - <!-- 网关设备并且是TBox --> | |
50 | - </Tabs> | |
51 | - </BasicDrawer> | |
52 | -</template> | |
53 | -<script lang="ts"> | |
54 | - import { defineComponent, ref } from 'vue'; | |
55 | - import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
56 | - | |
57 | - import { Tabs } from 'ant-design-vue'; | |
58 | - import Detail from '../tabs/Detail.vue'; | |
59 | - // import RealTimeData from '../tabs/RealTimeData.vue'; | |
60 | - import Alarm from '../tabs/Alarm.vue'; | |
61 | - import ChildDevice from '../tabs/ChildDevice.vue'; | |
62 | - import TBoxDetail from '../tabs/TBoxDetail.vue'; | |
63 | - import CommandIssuance from '../tabs/CommandIssuance.vue'; | |
64 | - import { CommandRecord } from '../tabs/commandRecord/index'; | |
65 | - import { getDeviceDetail } from '/@/api/device/deviceManager'; | |
66 | - // import HistoryData from '../tabs/HistoryData.vue'; | |
67 | - import ModelOfMatter from '../tabs/ModelOfMatter.vue'; | |
68 | - export default defineComponent({ | |
69 | - name: 'DeviceModal', | |
70 | - components: { | |
71 | - BasicDrawer, | |
72 | - Tabs, | |
73 | - TabPane: Tabs.TabPane, | |
74 | - Detail, | |
75 | - // RealTimeData, | |
76 | - Alarm, | |
77 | - ChildDevice, | |
78 | - CommandIssuance, | |
79 | - TBoxDetail, | |
80 | - // HistoryData, | |
81 | - ModelOfMatter, | |
82 | - CommandRecord, | |
83 | - }, | |
84 | - emits: ['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail'], | |
85 | - setup(_props, { emit }) { | |
86 | - const activeKey = ref('1'); | |
87 | - const size = ref('small'); | |
88 | - const deviceDetailRef = ref(); | |
89 | - const deviceDetail = ref<any>({}); | |
90 | - const tbDeviceId = ref(''); | |
91 | - // 详情回显 | |
92 | - const [register] = useDrawerInner(async (data) => { | |
93 | - const { id } = data; | |
94 | - // 设备详情 | |
95 | - const res = await getDeviceDetail(id); | |
96 | - deviceDetail.value = res; | |
97 | - const { latitude, longitude, address } = res.deviceInfo; | |
98 | - if (latitude) { | |
99 | - deviceDetailRef.value.initMap(longitude, latitude, address); | |
100 | - } | |
101 | - }); | |
102 | - const closeDrawer = () => { | |
103 | - activeKey.value = '1'; | |
104 | - }; | |
105 | - | |
106 | - const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => { | |
107 | - emit('openTbDeviceDetail', data); | |
108 | - }; | |
109 | - | |
110 | - const handleOpenGatewayDevice = (data: { gatewayId: string; tbDeviceId: string }) => { | |
111 | - emit('openGatewayDeviceDetail', { id: data.gatewayId }); | |
112 | - }; | |
113 | - | |
114 | - return { | |
115 | - size, | |
116 | - activeKey, | |
117 | - register, | |
118 | - closeDrawer, | |
119 | - deviceDetail, | |
120 | - deviceDetailRef, | |
121 | - tbDeviceId, | |
122 | - handleOpenTbDeviceDetail, | |
123 | - handleOpenGatewayDevice, | |
124 | - }; | |
125 | - }, | |
126 | - }); | |
127 | -</script> | |
1 | +<template> | |
2 | + <BasicDrawer | |
3 | + v-bind="$attrs" | |
4 | + isDetail | |
5 | + @register="register" | |
6 | + destroyOnClose | |
7 | + @close="closeDrawer" | |
8 | + :title="deviceDetail.alias || deviceDetail.name" | |
9 | + width="80%" | |
10 | + > | |
11 | + <Tabs v-model:activeKey="activeKey" :size="size"> | |
12 | + <TabPane key="1" tab="详情"> | |
13 | + <Detail | |
14 | + ref="deviceDetailRef" | |
15 | + :deviceDetail="deviceDetail" | |
16 | + @open-gateway-device="handleOpenGatewayDevice" | |
17 | + /> | |
18 | + </TabPane> | |
19 | + <TabPane key="modelOfMatter" tab="物模型数据"> | |
20 | + <ModelOfMatter :deviceDetail="deviceDetail" /> | |
21 | + </TabPane> | |
22 | + <!-- <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"> | |
23 | + <RealTimeData :deviceDetail="deviceDetail" /> | |
24 | + </TabPane> | |
25 | + <TabPane key="7" tab="历史数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"> | |
26 | + <HistoryData :deviceDetail="deviceDetail" /> | |
27 | + </TabPane> --> | |
28 | + <TabPane key="5" tab="命令下发" v-if="deviceDetail?.deviceType !== 'SENSOR'"> | |
29 | + <CommandIssuance :deviceDetail="deviceDetail" /> | |
30 | + </TabPane> | |
31 | + <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane> | |
32 | + <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"> | |
33 | + <ChildDevice | |
34 | + :fromId="deviceDetail?.tbDeviceId" | |
35 | + @openTbDeviceDetail="handleOpenTbDeviceDetail" | |
36 | + /> | |
37 | + </TabPane> | |
38 | + <TabPane key="7" tab="命令下发记录"> | |
39 | + <CommandRecord :fromId="deviceDetail?.tbDeviceId" /> | |
40 | + </TabPane> | |
41 | + <!-- 网关设备并且场家是TBox --> | |
42 | + <TabPane | |
43 | + key="6" | |
44 | + tab="TBox" | |
45 | + v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'" | |
46 | + > | |
47 | + <TBoxDetail :deviceDetail="deviceDetail" /> | |
48 | + </TabPane> | |
49 | + <!-- 网关设备并且是TBox --> | |
50 | + | |
51 | + <TabPane key="eventManage" tab="事件管理"> | |
52 | + <EventManage /> | |
53 | + </TabPane> | |
54 | + </Tabs> | |
55 | + </BasicDrawer> | |
56 | +</template> | |
57 | +<script lang="ts"> | |
58 | + import { defineComponent, ref } from 'vue'; | |
59 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
60 | + | |
61 | + import { Tabs } from 'ant-design-vue'; | |
62 | + import Detail from '../tabs/Detail.vue'; | |
63 | + // import RealTimeData from '../tabs/RealTimeData.vue'; | |
64 | + import Alarm from '../tabs/Alarm.vue'; | |
65 | + import ChildDevice from '../tabs/ChildDevice.vue'; | |
66 | + import TBoxDetail from '../tabs/TBoxDetail.vue'; | |
67 | + import CommandIssuance from '../tabs/CommandIssuance.vue'; | |
68 | + import { CommandRecord } from '../tabs/commandRecord/index'; | |
69 | + import { getDeviceDetail } from '/@/api/device/deviceManager'; | |
70 | + // import HistoryData from '../tabs/HistoryData.vue'; | |
71 | + import ModelOfMatter from '../tabs/ModelOfMatter.vue'; | |
72 | + import EventManage from '../tabs/EventManage/index.vue'; | |
73 | + | |
74 | + export default defineComponent({ | |
75 | + name: 'DeviceModal', | |
76 | + components: { | |
77 | + BasicDrawer, | |
78 | + Tabs, | |
79 | + TabPane: Tabs.TabPane, | |
80 | + Detail, | |
81 | + // RealTimeData, | |
82 | + Alarm, | |
83 | + ChildDevice, | |
84 | + CommandIssuance, | |
85 | + TBoxDetail, | |
86 | + // HistoryData, | |
87 | + ModelOfMatter, | |
88 | + CommandRecord, | |
89 | + EventManage, | |
90 | + }, | |
91 | + emits: ['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail'], | |
92 | + setup(_props, { emit }) { | |
93 | + const activeKey = ref('1'); | |
94 | + const size = ref('small'); | |
95 | + const deviceDetailRef = ref(); | |
96 | + const deviceDetail = ref<any>({}); | |
97 | + const tbDeviceId = ref(''); | |
98 | + // 详情回显 | |
99 | + const [register] = useDrawerInner(async (data) => { | |
100 | + const { id } = data; | |
101 | + // 设备详情 | |
102 | + const res = await getDeviceDetail(id); | |
103 | + deviceDetail.value = res; | |
104 | + const { latitude, longitude, address } = res.deviceInfo; | |
105 | + if (latitude) { | |
106 | + deviceDetailRef.value.initMap(longitude, latitude, address); | |
107 | + } | |
108 | + }); | |
109 | + const closeDrawer = () => { | |
110 | + activeKey.value = '1'; | |
111 | + }; | |
112 | + | |
113 | + const handleOpenTbDeviceDetail = (data: { id: string; tbDeviceId: string }) => { | |
114 | + emit('openTbDeviceDetail', data); | |
115 | + }; | |
116 | + | |
117 | + const handleOpenGatewayDevice = (data: { gatewayId: string; tbDeviceId: string }) => { | |
118 | + emit('openGatewayDeviceDetail', { id: data.gatewayId }); | |
119 | + }; | |
120 | + | |
121 | + return { | |
122 | + size, | |
123 | + activeKey, | |
124 | + register, | |
125 | + closeDrawer, | |
126 | + deviceDetail, | |
127 | + deviceDetailRef, | |
128 | + tbDeviceId, | |
129 | + handleOpenTbDeviceDetail, | |
130 | + handleOpenGatewayDevice, | |
131 | + }; | |
132 | + }, | |
133 | + }); | |
134 | +</script> | ... | ... |
1 | +import { findDictItemByCode } from '/@/api/system/dict'; | |
2 | +import { BasicColumn, FormSchema } from '/@/components/Table'; | |
3 | + | |
4 | +export const columnSchema: BasicColumn[] = [ | |
5 | + { | |
6 | + title: '时间', | |
7 | + dataIndex: 'time', | |
8 | + }, | |
9 | + { | |
10 | + title: '标识符', | |
11 | + dataIndex: 'identifier', | |
12 | + helpMessage: ['标识符格式为模块标识符: 功能定义标识符'], | |
13 | + }, | |
14 | + { | |
15 | + title: '事件名称', | |
16 | + dataIndex: 'eventName', | |
17 | + }, | |
18 | + { | |
19 | + title: '事件类型', | |
20 | + dataIndex: 'eventType', | |
21 | + }, | |
22 | + { | |
23 | + title: '输出参数', | |
24 | + dataIndex: 'outputParams', | |
25 | + slots: { customRender: 'outputParams' }, | |
26 | + }, | |
27 | +]; | |
28 | + | |
29 | +export const formSchemas: FormSchema[] = [ | |
30 | + { | |
31 | + field: 'identifier', | |
32 | + label: '标识符', | |
33 | + component: 'Input', | |
34 | + }, | |
35 | + { | |
36 | + field: 'alarmType', | |
37 | + label: '告警类型', | |
38 | + component: 'ApiSelect', | |
39 | + defaultValue: 'INFO', | |
40 | + componentProps: { | |
41 | + placeholder: '请选择事件类型', | |
42 | + api: findDictItemByCode, | |
43 | + params: { | |
44 | + dictCode: 'event_type', | |
45 | + }, | |
46 | + labelField: 'itemText', | |
47 | + valueField: 'itemValue', | |
48 | + }, | |
49 | + }, | |
50 | + { | |
51 | + field: 'dateRange', | |
52 | + label: '时间范围', | |
53 | + component: 'RangePicker', | |
54 | + colProps: { span: 10 }, | |
55 | + }, | |
56 | +]; | ... | ... |
1 | +<script lang="ts" setup> | |
2 | + import { BasicTable, useTable } from '/@/components/Table'; | |
3 | + import { formSchemas, columnSchema } from './config'; | |
4 | + import { BasicModal, useModal } from '/@/components/Modal'; | |
5 | + import { Textarea } from 'ant-design-vue'; | |
6 | + import { ref } from 'vue'; | |
7 | + import { formatToDateTime } from '/@/utils/dateUtil'; | |
8 | + import { EyeOutlined } from '@ant-design/icons-vue'; | |
9 | + | |
10 | + const outputData = ref<string>(); | |
11 | + | |
12 | + const [register] = useTable({ | |
13 | + columns: columnSchema, | |
14 | + size: 'small', | |
15 | + showIndexColumn: false, | |
16 | + useSearchForm: true, | |
17 | + showTableSetting: true, | |
18 | + bordered: true, | |
19 | + dataSource: [ | |
20 | + { | |
21 | + time: formatToDateTime(new Date()), | |
22 | + identifier: '标识符', | |
23 | + eventName: '事件名', | |
24 | + eventType: '告警', | |
25 | + outputParams: { test: 1 }, | |
26 | + }, | |
27 | + ], | |
28 | + formConfig: { | |
29 | + layout: 'inline', | |
30 | + baseColProps: { span: 6 }, | |
31 | + labelWidth: 80, | |
32 | + schemas: formSchemas, | |
33 | + }, | |
34 | + handleSearchInfoFn: (params: Recordable) => { | |
35 | + // console.log(params); | |
36 | + return params; | |
37 | + }, | |
38 | + }); | |
39 | + | |
40 | + const [registerModal, { openModal }] = useModal(); | |
41 | + | |
42 | + const handleViewDetail = () => { | |
43 | + outputData.value = JSON.stringify( | |
44 | + { | |
45 | + test: '123', | |
46 | + }, | |
47 | + null, | |
48 | + 2 | |
49 | + ); | |
50 | + openModal(true); | |
51 | + }; | |
52 | +</script> | |
53 | + | |
54 | +<template> | |
55 | + <BasicTable class="event-manage-table" @register="register"> | |
56 | + <template #outputParams> | |
57 | + <span class="cursor-pointer text-blue-500" @click="handleViewDetail"> | |
58 | + <EyeOutlined class="svg:text-blue-500" /> | |
59 | + <span class="ml-2">详情</span> | |
60 | + </span> | |
61 | + </template> | |
62 | + </BasicTable> | |
63 | + <BasicModal title="输出参数" @register="registerModal"> | |
64 | + <Textarea v-model:value="outputData" :autosize="true" /> | |
65 | + </BasicModal> | |
66 | +</template> | |
67 | + | |
68 | +<style lang="less" scoped> | |
69 | + .event-manage-table { | |
70 | + background-color: #f0f2f5; | |
71 | + } | |
72 | +</style> | ... | ... |
1 | -<template> | |
2 | - <div style="background-color: #f0f2f5"> | |
3 | - <BasicTable @register="registerTable"> | |
4 | - <template #recordContent="{ record }"> | |
5 | - <a-button type="link" class="ml-2" @click="handleRecordContent(record)"> 查看 </a-button> | |
6 | - </template> | |
7 | - <template #responseContent="{ record }"> | |
8 | - <div v-if="!record.request?.oneway"> | |
9 | - <a-button v-if="record?.response === null" type="text" class="ml-2"> 无 </a-button> | |
10 | - <a-button v-else type="link" class="ml-2" @click="handleRecordResponseContent(record)"> | |
11 | - 查看 | |
12 | - </a-button> | |
13 | - </div> | |
14 | - </template> | |
15 | - </BasicTable> | |
16 | - </div> | |
17 | -</template> | |
18 | -<script lang="ts" setup> | |
19 | - import { h } from 'vue'; | |
20 | - import { configColumns } from './config'; | |
21 | - import { deviceCommandRecordGetQuery } from '/@/api/device/deviceConfigApi'; | |
22 | - import { BasicTable, useTable } from '/@/components/Table'; | |
23 | - import { Modal } from 'ant-design-vue'; | |
24 | - import { JsonPreview } from '/@/components/CodeEditor'; | |
25 | - | |
26 | - const props = defineProps({ | |
27 | - fromId: { | |
28 | - type: String, | |
29 | - default: '', | |
30 | - }, | |
31 | - }); | |
32 | - const [registerTable] = useTable({ | |
33 | - api: deviceCommandRecordGetQuery, | |
34 | - columns: configColumns, | |
35 | - beforeFetch: (params) => { | |
36 | - return { | |
37 | - ...params, | |
38 | - tbDeviceId: props.fromId, | |
39 | - }; | |
40 | - }, | |
41 | - showTableSetting: true, | |
42 | - bordered: true, | |
43 | - showIndexColumn: false, | |
44 | - }); | |
45 | - const commonModalInfo = (title, value) => { | |
46 | - Modal.info({ | |
47 | - title, | |
48 | - width: 600, | |
49 | - content: h(JsonPreview, { data: value }), | |
50 | - }); | |
51 | - }; | |
52 | - const handleRecordContent = (record) => { | |
53 | - if (!record?.request?.body?.params) return; | |
54 | - //如果是正常格式则返回params,否则输入什么内容则显示什么内容 | |
55 | - const jsonParams = JSON.parse(record?.request?.body?.params); | |
56 | - commonModalInfo('命令下发内容', jsonParams?.params ? jsonParams?.params : jsonParams); | |
57 | - }; | |
58 | - const handleRecordResponseContent = (record) => { | |
59 | - const jsonParams = record?.response; | |
60 | - commonModalInfo('响应结果', jsonParams); | |
61 | - }; | |
62 | -</script> | |
1 | +<template> | |
2 | + <BasicTable class="command-record-table" @register="registerTable"> | |
3 | + <template #recordContent="{ record }"> | |
4 | + <a-button type="link" class="ml-2" @click="handleRecordContent(record)"> 查看 </a-button> | |
5 | + </template> | |
6 | + <template #responseContent="{ record }"> | |
7 | + <div v-if="!record.request?.oneway"> | |
8 | + <a-button v-if="record?.response === null" type="text" class="ml-2"> 无 </a-button> | |
9 | + <a-button v-else type="link" class="ml-2" @click="handleRecordResponseContent(record)"> | |
10 | + 查看 | |
11 | + </a-button> | |
12 | + </div> | |
13 | + </template> | |
14 | + </BasicTable> | |
15 | +</template> | |
16 | +<script lang="ts" setup> | |
17 | + import { h } from 'vue'; | |
18 | + import { configColumns } from './config'; | |
19 | + import { deviceCommandRecordGetQuery } from '/@/api/device/deviceConfigApi'; | |
20 | + import { BasicTable, useTable } from '/@/components/Table'; | |
21 | + import { Modal } from 'ant-design-vue'; | |
22 | + import { JsonPreview } from '/@/components/CodeEditor'; | |
23 | + | |
24 | + const props = defineProps({ | |
25 | + fromId: { | |
26 | + type: String, | |
27 | + default: '', | |
28 | + }, | |
29 | + }); | |
30 | + const [registerTable] = useTable({ | |
31 | + api: deviceCommandRecordGetQuery, | |
32 | + columns: configColumns, | |
33 | + beforeFetch: (params) => { | |
34 | + return { | |
35 | + ...params, | |
36 | + tbDeviceId: props.fromId, | |
37 | + }; | |
38 | + }, | |
39 | + showTableSetting: true, | |
40 | + bordered: true, | |
41 | + showIndexColumn: false, | |
42 | + }); | |
43 | + const commonModalInfo = (title, value) => { | |
44 | + Modal.info({ | |
45 | + title, | |
46 | + width: 600, | |
47 | + content: h(JsonPreview, { data: value }), | |
48 | + }); | |
49 | + }; | |
50 | + const handleRecordContent = (record) => { | |
51 | + if (!record?.request?.body?.params) return; | |
52 | + //如果是正常格式则返回params,否则输入什么内容则显示什么内容 | |
53 | + const jsonParams = JSON.parse(record?.request?.body?.params); | |
54 | + commonModalInfo('命令下发内容', jsonParams?.params ? jsonParams?.params : jsonParams); | |
55 | + }; | |
56 | + const handleRecordResponseContent = (record) => { | |
57 | + const jsonParams = record?.response; | |
58 | + commonModalInfo('响应结果', jsonParams); | |
59 | + }; | |
60 | +</script> | |
61 | + | |
62 | +<style lang="less" scoped> | |
63 | + .command-record-table { | |
64 | + background-color: #f0f2f5; | |
65 | + padding: 16px; | |
66 | + } | |
67 | +</style> | ... | ... |
... | ... | @@ -27,17 +27,26 @@ |
27 | 27 | <TabPane :key="FunctionType.SERVICE" :disabled="isTCPGatewaySubDevice" tab="服务" /> |
28 | 28 | <TabPane :key="FunctionType.EVENTS" tab="事件" :disabled="isTCPGatewaySubDevice" /> |
29 | 29 | </Tabs> |
30 | - <Attribute v-if="activeKey === FunctionType.PROPERTIES" ref="AttrRef" /> | |
30 | + <Attribute | |
31 | + v-if="activeKey === FunctionType.PROPERTIES" | |
32 | + :openModalMode="openModalMode" | |
33 | + ref="AttrRef" | |
34 | + /> | |
31 | 35 | <Service |
32 | 36 | v-if="activeKey === FunctionType.SERVICE" |
33 | 37 | :record="$props.record" |
38 | + :openModalMode="openModalMode" | |
34 | 39 | ref="ServiceRef" |
35 | 40 | /> |
36 | - <Events v-if="activeKey === FunctionType.EVENTS" ref="EventsRef" /> | |
37 | - <div | |
41 | + <Events | |
42 | + v-if="activeKey === FunctionType.EVENTS" | |
43 | + :openModalMode="openModalMode" | |
44 | + ref="EventsRef" | |
45 | + /> | |
46 | + <!-- <div | |
38 | 47 | v-if="openModalMode === OpenModelMode.VIEW" |
39 | 48 | class="absolute w-full h-full top-0 cursor-not-allowed z-50" |
40 | - ></div> | |
49 | + ></div> --> | |
41 | 50 | </div> |
42 | 51 | </BasicModal> |
43 | 52 | </div> |
... | ... | @@ -116,6 +125,9 @@ |
116 | 125 | const title = unref(openModalMode) === OpenModelMode.UPDATE ? '编辑物模型' : '新增物模型'; |
117 | 126 | setModalProps({ title, showOkBtn: true, showCancelBtn: true }); |
118 | 127 | } |
128 | + AttrRef.value?.setDisable(unref(openModalMode) === OpenModelMode.VIEW); | |
129 | + EventsRef.value?.setDisable(unref(openModalMode) === OpenModelMode.VIEW); | |
130 | + ServiceRef.value?.setDisable(unref(openModalMode) === OpenModelMode.VIEW); | |
119 | 131 | } |
120 | 132 | ); |
121 | 133 | |
... | ... | @@ -153,7 +165,7 @@ |
153 | 165 | closeModal(); |
154 | 166 | emit('success'); |
155 | 167 | } catch (error) { |
156 | - throw Error(error); | |
168 | + throw Error(error as string); | |
157 | 169 | } finally { |
158 | 170 | setModalProps({ loading: false, okButtonProps: { loading: false } }); |
159 | 171 | } | ... | ... |
... | ... | @@ -4,18 +4,20 @@ |
4 | 4 | <script lang="ts" setup> |
5 | 5 | import { BasicForm, useForm } from '/@/components/Form'; |
6 | 6 | import { DataType, ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; |
7 | - import { formSchemas } from '/@/components/Form/src/externalCompns/components/StructForm/config'; | |
8 | 7 | import { StructFormValue } from '/@/components/Form/src/externalCompns/components/StructForm/type'; |
9 | 8 | import { |
10 | 9 | transfromToStructJSON, |
11 | 10 | excludeIdInStructJSON, |
12 | 11 | } from '/@/components/Form/src/externalCompns/components/StructForm/util'; |
13 | - import { FunctionType } from './config'; | |
12 | + import { FunctionType, attributeSchema } from './config'; | |
14 | 13 | import { isArray } from 'lodash'; |
14 | + import { OpenModelMode } from '../types'; | |
15 | 15 | |
16 | - const [register, { validate, resetFields, setFieldsValue }] = useForm({ | |
16 | + defineProps<{ openModalMode: OpenModelMode }>(); | |
17 | + | |
18 | + const [register, { validate, resetFields, setFieldsValue, setProps }] = useForm({ | |
17 | 19 | labelWidth: 100, |
18 | - schemas: formSchemas, | |
20 | + schemas: attributeSchema, | |
19 | 21 | actionColOptions: { |
20 | 22 | span: 14, |
21 | 23 | }, |
... | ... | @@ -24,6 +26,10 @@ |
24 | 26 | showActionButtonGroup: false, |
25 | 27 | }); |
26 | 28 | |
29 | + const setDisable = (flag: boolean) => { | |
30 | + setProps({ disabled: flag }); | |
31 | + }; | |
32 | + | |
27 | 33 | async function getFormData(): Promise<Partial<ModelOfMatterParams>> { |
28 | 34 | const _values = (await validate()) as StructFormValue; |
29 | 35 | if (!_values) return {}; |
... | ... | @@ -68,6 +74,7 @@ |
68 | 74 | resetFormData, |
69 | 75 | getFormData, |
70 | 76 | setFormData, |
77 | + setDisable, | |
71 | 78 | }); |
72 | 79 | </script> |
73 | 80 | <style lang="less" scoped></style> | ... | ... |
... | ... | @@ -7,8 +7,11 @@ |
7 | 7 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
8 | 8 | import { StructFormValue } from '/@/components/Form/src/externalCompns/components/StructForm/type'; |
9 | 9 | import { excludeIdInStructJSON } from '/@/components/Form/src/externalCompns/components/StructForm/util'; |
10 | + import { OpenModelMode } from '../types'; | |
10 | 11 | |
11 | - const [register, { validate, resetFields, setFieldsValue }] = useForm({ | |
12 | + defineProps<{ openModalMode: OpenModelMode }>(); | |
13 | + | |
14 | + const [register, { validate, resetFields, setFieldsValue, setProps }] = useForm({ | |
12 | 15 | labelWidth: 100, |
13 | 16 | schemas: eventSchemas, |
14 | 17 | actionColOptions: { |
... | ... | @@ -19,6 +22,10 @@ |
19 | 22 | showActionButtonGroup: false, |
20 | 23 | }); |
21 | 24 | |
25 | + const setDisable = (flag: boolean) => { | |
26 | + setProps({ disabled: flag }); | |
27 | + }; | |
28 | + | |
22 | 29 | //回显数据 |
23 | 30 | const setFormData = (record: ModelOfMatterParams) => { |
24 | 31 | const { functionJson = {}, functionName, identifier, remark, eventType } = record; |
... | ... | @@ -69,6 +76,7 @@ |
69 | 76 | setFormData, |
70 | 77 | resetFormData, |
71 | 78 | getFormData, |
79 | + setDisable, | |
72 | 80 | }); |
73 | 81 | </script> |
74 | 82 | <style lang="less" scoped></style> | ... | ... |
... | ... | @@ -9,22 +9,29 @@ |
9 | 9 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
10 | 10 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
11 | 11 | import { excludeIdInStructJSON } from '/@/components/Form/src/externalCompns/components/StructForm/util'; |
12 | + import { OpenModelMode } from '../types'; | |
12 | 13 | |
13 | 14 | const props = defineProps<{ |
14 | 15 | record: DeviceRecord; |
16 | + openModalMode: OpenModelMode; | |
15 | 17 | }>(); |
16 | 18 | |
17 | - const [register, { validate, resetFields, setFieldsValue }] = useForm({ | |
19 | + const [register, { validate, resetFields, setFieldsValue, setProps }] = useForm({ | |
18 | 20 | labelWidth: 100, |
19 | 21 | schemas: serviceSchemas(props.record.transportType === 'TCP'), |
20 | 22 | actionColOptions: { |
21 | 23 | span: 14, |
22 | 24 | }, |
25 | + disabled: props.openModalMode === OpenModelMode.VIEW, | |
23 | 26 | showResetButton: false, |
24 | 27 | submitOnReset: false, |
25 | 28 | showActionButtonGroup: false, |
26 | 29 | }); |
27 | 30 | |
31 | + const setDisable = (flag: boolean) => { | |
32 | + setProps({ disabled: flag }); | |
33 | + }; | |
34 | + | |
28 | 35 | //回显数据 |
29 | 36 | const setFormData = (record: ModelOfMatterParams) => { |
30 | 37 | const { functionJson = {}, functionName, identifier, remark, callType } = record; |
... | ... | @@ -98,6 +105,7 @@ |
98 | 105 | setFormData, |
99 | 106 | resetFormData, |
100 | 107 | getFormData, |
108 | + setDisable, | |
101 | 109 | }); |
102 | 110 | </script> |
103 | 111 | <style lang="less" scoped></style> | ... | ... |
1 | 1 | import { FormSchema } from '/@/components/Table'; |
2 | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | +import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | |
4 | + | |
5 | +export const validateValueRange = (_rule, value: Record<'min' | 'max', number>, _callback) => { | |
6 | + value = value || {}; | |
7 | + const { min, max } = value; | |
8 | + if (min >= max) { | |
9 | + return Promise.reject('最大值小于最小值'); | |
10 | + } | |
11 | + return Promise.resolve(); | |
12 | +}; | |
13 | + | |
14 | +export const validateJSON = (_rule, value: ModelOfMatterParams[], _callback) => { | |
15 | + if (value.length) { | |
16 | + return Promise.resolve(); | |
17 | + } | |
18 | + return Promise.reject('JSON对象不能为空'); | |
19 | +}; | |
3 | 20 | |
4 | 21 | export enum FormField { |
5 | 22 | FUNCTION_NAME = 'functionName', |
... | ... | @@ -358,3 +375,265 @@ export const addParamsSchemas: FormSchema[] = [ |
358 | 375 | ifShow: ({ values }) => isNumber(values[FormField.TYPE]), |
359 | 376 | }, |
360 | 377 | ]; |
378 | + | |
379 | +export const attributeSchema: FormSchema[] = [ | |
380 | + { | |
381 | + field: FormField.FUNCTION_NAME, | |
382 | + label: '功能名称', | |
383 | + required: true, | |
384 | + component: 'Input', | |
385 | + colProps: { | |
386 | + span: 18, | |
387 | + }, | |
388 | + componentProps: { | |
389 | + maxLength: 255, | |
390 | + placeholder: '请输入功能名称', | |
391 | + }, | |
392 | + }, | |
393 | + { | |
394 | + field: FormField.IDENTIFIER, | |
395 | + label: '标识符', | |
396 | + required: true, | |
397 | + component: 'Input', | |
398 | + colProps: { | |
399 | + span: 18, | |
400 | + }, | |
401 | + componentProps: { | |
402 | + maxLength: 255, | |
403 | + placeholder: '请输入标识符', | |
404 | + }, | |
405 | + }, | |
406 | + { | |
407 | + field: FormField.TYPE, | |
408 | + label: '数据类型', | |
409 | + required: true, | |
410 | + component: 'ApiSelect', | |
411 | + colProps: { | |
412 | + span: 9, | |
413 | + }, | |
414 | + defaultValue: 'INT', | |
415 | + componentProps: { | |
416 | + placeholder: '请选择数据类型', | |
417 | + api: findDictItemByCode, | |
418 | + params: { | |
419 | + dictCode: 'data_type', | |
420 | + }, | |
421 | + labelField: 'itemText', | |
422 | + valueField: 'itemValue', | |
423 | + getPopupContainer: () => document.body, | |
424 | + }, | |
425 | + }, | |
426 | + { | |
427 | + field: FormField.VALUE_RANGE, | |
428 | + label: '取值范围', | |
429 | + component: 'CustomMinMaxInput', | |
430 | + valueField: 'value', | |
431 | + changeEvent: 'update:value', | |
432 | + colProps: { | |
433 | + span: 18, | |
434 | + }, | |
435 | + ifShow: ({ values }) => | |
436 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | |
437 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | |
438 | + rules: [{ validator: validateValueRange }], | |
439 | + }, | |
440 | + { | |
441 | + field: FormField.STEP, | |
442 | + label: '步长', | |
443 | + component: 'InputNumber', | |
444 | + colProps: { | |
445 | + span: 18, | |
446 | + }, | |
447 | + componentProps: { | |
448 | + maxLength: 255, | |
449 | + placeholder: '请输入步长', | |
450 | + min: 1, | |
451 | + formatter: (value: number | string) => { | |
452 | + return value ? Math.floor(Number(value)) : value; | |
453 | + }, | |
454 | + }, | |
455 | + ifShow: ({ values }) => | |
456 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | |
457 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | |
458 | + dynamicRules: ({ model }) => { | |
459 | + const valueRange = model[FormField.VALUE_RANGE] || {}; | |
460 | + const { min = 0, max = 0 } = valueRange; | |
461 | + const step = model[FormField.STEP]; | |
462 | + return [ | |
463 | + { | |
464 | + validator: () => { | |
465 | + if (step > max - min) { | |
466 | + return Promise.reject('步长不能大于取值范围的差值'); | |
467 | + } | |
468 | + return Promise.resolve(); | |
469 | + }, | |
470 | + }, | |
471 | + ]; | |
472 | + }, | |
473 | + }, | |
474 | + { | |
475 | + field: FormField.UNIT_NAME, | |
476 | + label: '单位名称', | |
477 | + component: 'Input', | |
478 | + show: false, | |
479 | + }, | |
480 | + { | |
481 | + field: FormField.UNIT, | |
482 | + label: '单位', | |
483 | + component: 'ApiSelect', | |
484 | + colProps: { | |
485 | + span: 9, | |
486 | + }, | |
487 | + componentProps: ({ formActionType }) => { | |
488 | + const { setFieldsValue } = formActionType; | |
489 | + return { | |
490 | + placeholder: '请选择单位', | |
491 | + api: async (params) => { | |
492 | + const list = await findDictItemByCode(params); | |
493 | + list.map((item) => (item.itemText = `${item.itemText} / ${item.itemValue}`)); | |
494 | + return list; | |
495 | + }, | |
496 | + params: { | |
497 | + dictCode: 'attribute_unit', | |
498 | + }, | |
499 | + labelInValue: true, | |
500 | + labelField: 'itemText', | |
501 | + valueField: 'itemValue', | |
502 | + onChange(_, record: Record<'label' | 'value', string>) { | |
503 | + if (record) { | |
504 | + const { label } = record; | |
505 | + setFieldsValue({ [FormField.UNIT_NAME]: label }); | |
506 | + } | |
507 | + }, | |
508 | + getPopupContainer: () => document.body, | |
509 | + showSearch: true, | |
510 | + filterOption: (inputValue: string, option: Record<'label' | 'value', string>) => { | |
511 | + let { label, value } = option; | |
512 | + label = label.toLowerCase(); | |
513 | + value = value.toLowerCase(); | |
514 | + inputValue = inputValue.toLowerCase(); | |
515 | + return label.includes(inputValue) || value.includes(inputValue); | |
516 | + }, | |
517 | + }; | |
518 | + }, | |
519 | + ifShow: ({ values }) => | |
520 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT || | |
521 | + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE, | |
522 | + }, | |
523 | + { | |
524 | + field: FormField.BOOL_CLOSE, | |
525 | + component: 'Input', | |
526 | + required: true, | |
527 | + label: '0 -', | |
528 | + colProps: { | |
529 | + span: 18, | |
530 | + }, | |
531 | + componentProps: { | |
532 | + placeholder: '如:关', | |
533 | + }, | |
534 | + defaultValue: '关', | |
535 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL, | |
536 | + dynamicRules: ({ model }) => { | |
537 | + const close = model[FormField.BOOL_CLOSE]; | |
538 | + const open = model[FormField.BOOL_OPEN]; | |
539 | + return [ | |
540 | + { | |
541 | + required: true, | |
542 | + }, | |
543 | + { | |
544 | + validator() { | |
545 | + if (open === close) return Promise.reject('布尔值不能相同'); | |
546 | + return Promise.resolve(); | |
547 | + }, | |
548 | + }, | |
549 | + ]; | |
550 | + }, | |
551 | + }, | |
552 | + { | |
553 | + field: FormField.BOOL_OPEN, | |
554 | + component: 'Input', | |
555 | + required: true, | |
556 | + label: '1 -', | |
557 | + colProps: { | |
558 | + span: 18, | |
559 | + }, | |
560 | + componentProps: { | |
561 | + placeholder: '如:开', | |
562 | + }, | |
563 | + defaultValue: '开', | |
564 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL, | |
565 | + dynamicRules: ({ model }) => { | |
566 | + const close = model[FormField.BOOL_CLOSE]; | |
567 | + const open = model[FormField.BOOL_OPEN]; | |
568 | + return [ | |
569 | + { | |
570 | + required: true, | |
571 | + }, | |
572 | + { | |
573 | + validator() { | |
574 | + if (open === close) return Promise.reject('布尔值不能相同'); | |
575 | + return Promise.resolve(); | |
576 | + }, | |
577 | + }, | |
578 | + ]; | |
579 | + }, | |
580 | + }, | |
581 | + { | |
582 | + field: FormField.LENGTH, | |
583 | + component: 'Input', | |
584 | + required: true, | |
585 | + label: '数据长度', | |
586 | + defaultValue: '10240', | |
587 | + colProps: { | |
588 | + span: 8, | |
589 | + }, | |
590 | + componentProps: { | |
591 | + placeholder: '请输入数据长度', | |
592 | + }, | |
593 | + renderComponentContent: () => { | |
594 | + return { | |
595 | + suffix: () => '字节', | |
596 | + }; | |
597 | + }, | |
598 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRING, | |
599 | + }, | |
600 | + { | |
601 | + field: FormField.ACCESS_MODE, | |
602 | + component: 'ApiRadioGroup', | |
603 | + label: '读写类型', | |
604 | + required: true, | |
605 | + colProps: { | |
606 | + span: 24, | |
607 | + }, | |
608 | + defaultValue: 'r', | |
609 | + componentProps: { | |
610 | + placeholder: '请选择读写类型', | |
611 | + api: findDictItemByCode, | |
612 | + params: { | |
613 | + dictCode: 'read_write_type', | |
614 | + }, | |
615 | + labelField: 'itemText', | |
616 | + valueField: 'itemValue', | |
617 | + }, | |
618 | + }, | |
619 | + { | |
620 | + field: FormField.SPECS_LIST, | |
621 | + label: 'JSON对象', | |
622 | + component: 'StructForm', | |
623 | + valueField: 'value', | |
624 | + changeEvent: 'update:value', | |
625 | + colProps: { span: 24 }, | |
626 | + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRUCT, | |
627 | + rules: [{ required: true, validator: validateJSON }], | |
628 | + }, | |
629 | + { | |
630 | + field: FormField.REFARK, | |
631 | + label: '备注', | |
632 | + component: 'InputTextArea', | |
633 | + componentProps: { | |
634 | + rows: 4, | |
635 | + maxLength: 100, | |
636 | + placeholder: '请输入描述', | |
637 | + }, | |
638 | + }, | |
639 | +]; | ... | ... |