Showing
11 changed files
with
813 additions
and
23 deletions
| @@ -124,6 +124,10 @@ | @@ -124,6 +124,10 @@ | ||
| 124 | 124 | ||
| 125 | const handleCopy = async (record: DataSourceType) => { | 125 | const handleCopy = async (record: DataSourceType) => { |
| 126 | const { key } = props.componentConfig || {}; | 126 | const { key } = props.componentConfig || {}; |
| 127 | + if (key === 'ComponentStructural' && props.dataSource.length >= 1) { | ||
| 128 | + createMessage.warning('结构体组件绑定的数据源不能超过1条'); | ||
| 129 | + return; | ||
| 130 | + } | ||
| 127 | if (key == 'HumidityComponent2' && props.dataSource.length >= 6) { | 131 | if (key == 'HumidityComponent2' && props.dataSource.length >= 6) { |
| 128 | createMessage.warning('绑定的数据源不能超过6条~'); | 132 | createMessage.warning('绑定的数据源不能超过6条~'); |
| 129 | return; | 133 | return; |
| @@ -145,8 +149,13 @@ | @@ -145,8 +149,13 @@ | ||
| 145 | ]); | 149 | ]); |
| 146 | }; | 150 | }; |
| 147 | 151 | ||
| 148 | - const handleSetting = (record: DataSourceType) => { | ||
| 149 | - openModal(true, { mode: DataActionModeEnum.UPDATE, record: record } as ModalParamsType); | 152 | + const handleSetting = (record: DataSourceType, index: number) => { |
| 153 | + const values = getFormValues(); | ||
| 154 | + | ||
| 155 | + openModal(true, { | ||
| 156 | + mode: DataActionModeEnum.UPDATE, | ||
| 157 | + record: { ...record, ...values[index] }, | ||
| 158 | + } as ModalParamsType); | ||
| 150 | }; | 159 | }; |
| 151 | 160 | ||
| 152 | const handleDelete = (record: DataSourceType) => { | 161 | const handleDelete = (record: DataSourceType) => { |
| @@ -208,7 +217,7 @@ | @@ -208,7 +217,7 @@ | ||
| 208 | </Tooltip> | 217 | </Tooltip> |
| 209 | <Tooltip title="设置" v-if="hasSettingDesignIcon"> | 218 | <Tooltip title="设置" v-if="hasSettingDesignIcon"> |
| 210 | <SettingOutlined | 219 | <SettingOutlined |
| 211 | - @click="handleSetting(item)" | 220 | + @click="handleSetting(item, index)" |
| 212 | class="cursor-pointer text-lg !leading-32px" | 221 | class="cursor-pointer text-lg !leading-32px" |
| 213 | /> | 222 | /> |
| 214 | </Tooltip> | 223 | </Tooltip> |
| @@ -5,8 +5,12 @@ | @@ -5,8 +5,12 @@ | ||
| 5 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 5 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| 6 | import { ConfigType, CreateComponentType } from '../../../packages/index.type'; | 6 | import { ConfigType, CreateComponentType } from '../../../packages/index.type'; |
| 7 | import { ref } from 'vue'; | 7 | import { ref } from 'vue'; |
| 8 | - import { unref } from 'vue'; | 8 | + import { unref, nextTick } from 'vue'; |
| 9 | import { ModalParamsType } from '/#/utils'; | 9 | import { ModalParamsType } from '/#/utils'; |
| 10 | + import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
| 11 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
| 12 | + import { createImgPreview } from '/@/components/Preview'; | ||
| 13 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
| 10 | 14 | ||
| 11 | const props = defineProps<{ | 15 | const props = defineProps<{ |
| 12 | selectWidgetKeys: SelectedWidgetKeys; | 16 | selectWidgetKeys: SelectedWidgetKeys; |
| @@ -30,9 +34,94 @@ | @@ -30,9 +34,94 @@ | ||
| 30 | const currentEditRecord = ref<DataSourceType>({} as DataSourceType); | 34 | const currentEditRecord = ref<DataSourceType>({} as DataSourceType); |
| 31 | 35 | ||
| 32 | const [register, { closeModal }] = useModalInner((data: ModalParamsType<DataSourceType>) => { | 36 | const [register, { closeModal }] = useModalInner((data: ModalParamsType<DataSourceType>) => { |
| 33 | - const { record } = data; | 37 | + const { record }: any = data; |
| 34 | currentEditRecord.value = record; | 38 | currentEditRecord.value = record; |
| 35 | - setFormValues(record.componentInfo || {}); | 39 | + if (record.structural?.length) { |
| 40 | + record.structural.forEach((item, index) => { | ||
| 41 | + nextTick(() => { | ||
| 42 | + unref(settingFormEl)?.appendSchemaByField?.({ | ||
| 43 | + field: item + 'StructuralIcon', | ||
| 44 | + label: record.structuralLabel[index] + '图标', | ||
| 45 | + // labelWidth: '300', | ||
| 46 | + component: 'IconDrawer', | ||
| 47 | + changeEvent: 'update:value', | ||
| 48 | + defaultValue: 'shuiwen', | ||
| 49 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom', | ||
| 50 | + componentProps({ formModel }) { | ||
| 51 | + const color = formModel[item + 'StructuralIconColor']; | ||
| 52 | + return { | ||
| 53 | + color, | ||
| 54 | + }; | ||
| 55 | + }, | ||
| 56 | + }); | ||
| 57 | + unref(settingFormEl)?.appendSchemaByField?.({ | ||
| 58 | + field: item + 'StructuralIconColor', | ||
| 59 | + label: record.structuralLabel[index] + '图标颜色', | ||
| 60 | + component: 'ColorPicker', | ||
| 61 | + changeEvent: 'update:value', | ||
| 62 | + defaultValue: '#367bff', | ||
| 63 | + ifShow: ({ model }) => { | ||
| 64 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
| 65 | + }, | ||
| 66 | + }); | ||
| 67 | + unref(settingFormEl)?.appendSchemaByField?.({ | ||
| 68 | + field: item + 'StructuralCustomIcon', | ||
| 69 | + label: record.structuralLabel[index] + '图标', | ||
| 70 | + component: 'ApiUpload', | ||
| 71 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
| 72 | + changeEvent: 'update:fileList', | ||
| 73 | + valueField: 'fileList', | ||
| 74 | + required: true, | ||
| 75 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
| 76 | + componentProps: ({ formModel, formActionType }) => { | ||
| 77 | + const { setFieldsValue } = formActionType; | ||
| 78 | + return { | ||
| 79 | + maxSize: 50 * 1024, | ||
| 80 | + listType: 'picture-card', | ||
| 81 | + maxFileLimit: 1, | ||
| 82 | + accept: '.svg', | ||
| 83 | + api: async (file: File) => { | ||
| 84 | + try { | ||
| 85 | + const formData = new FormData(); | ||
| 86 | + const { name } = file; | ||
| 87 | + formData.set('file', file); | ||
| 88 | + const { fileStaticUri, fileName } = await upload(formData); | ||
| 89 | + return { | ||
| 90 | + uid: fileStaticUri, | ||
| 91 | + name: name || fileName, | ||
| 92 | + url: fileStaticUri, | ||
| 93 | + } as FileItem; | ||
| 94 | + } catch (error) { | ||
| 95 | + return {}; | ||
| 96 | + } | ||
| 97 | + }, | ||
| 98 | + onDownload() {}, | ||
| 99 | + onPreview: (fileList: FileItem) => { | ||
| 100 | + createImgPreview({ imageList: [fileList.url!] }); | ||
| 101 | + }, | ||
| 102 | + | ||
| 103 | + onDelete(url: string) { | ||
| 104 | + // 去重 取要删除的自定义图标 | ||
| 105 | + setFieldsValue({ | ||
| 106 | + structuralDeleteUrl: [ | ||
| 107 | + ...new Set([ | ||
| 108 | + ...formModel.structuralDeleteUrl | ||
| 109 | + .split(',') | ||
| 110 | + ?.filter((item) => Boolean(item)), | ||
| 111 | + url!, | ||
| 112 | + ]), | ||
| 113 | + ].join(','), | ||
| 114 | + }); | ||
| 115 | + }, | ||
| 116 | + }; | ||
| 117 | + }, | ||
| 118 | + }); | ||
| 119 | + }); | ||
| 120 | + }); | ||
| 121 | + } | ||
| 122 | + nextTick(() => { | ||
| 123 | + setFormValues(record.componentInfo || {}); | ||
| 124 | + }); | ||
| 36 | }); | 125 | }); |
| 37 | 126 | ||
| 38 | const getFormValues = () => { | 127 | const getFormValues = () => { |
| @@ -43,9 +132,25 @@ | @@ -43,9 +132,25 @@ | ||
| 43 | unref(settingFormEl)?.setFormValues(data || {}); | 132 | unref(settingFormEl)?.setFormValues(data || {}); |
| 44 | }; | 133 | }; |
| 45 | 134 | ||
| 46 | - const handleOk = () => { | 135 | + const handleOk = async () => { |
| 47 | const { uuid } = unref(currentEditRecord); | 136 | const { uuid } = unref(currentEditRecord); |
| 137 | + await unref(settingFormEl)?.validate?.(); | ||
| 48 | emit('ok', { uuid, componentInfo: getFormValues() } as DataSourceType); | 138 | emit('ok', { uuid, componentInfo: getFormValues() } as DataSourceType); |
| 139 | + handleCancel(); | ||
| 140 | + }; | ||
| 141 | + | ||
| 142 | + const handleCancel = () => { | ||
| 143 | + const { structural } = unref(currentEditRecord) || {}; | ||
| 144 | + if (structural?.length) { | ||
| 145 | + structural.forEach((item) => { | ||
| 146 | + unref(settingFormEl)?.removeSchemaByFiled?.([ | ||
| 147 | + item + 'StructuralIcon', | ||
| 148 | + item + 'StructuralIconColor', | ||
| 149 | + item + 'StructuralCustomIcon', | ||
| 150 | + // item + 'StructuralDeleteUrl', | ||
| 151 | + ]); | ||
| 152 | + }); | ||
| 153 | + } | ||
| 49 | closeModal(); | 154 | closeModal(); |
| 50 | }; | 155 | }; |
| 51 | 156 | ||
| @@ -56,7 +161,13 @@ | @@ -56,7 +161,13 @@ | ||
| 56 | </script> | 161 | </script> |
| 57 | 162 | ||
| 58 | <template> | 163 | <template> |
| 59 | - <BasicModal @register="register" title="组件设置" @ok="handleOk" :width="700"> | 164 | + <BasicModal |
| 165 | + @register="register" | ||
| 166 | + title="组件设置" | ||
| 167 | + @ok="handleOk" | ||
| 168 | + :width="700" | ||
| 169 | + @cancel="handleCancel" | ||
| 170 | + > | ||
| 60 | <!-- --> | 171 | <!-- --> |
| 61 | <component ref="settingFormEl" :is="getSettingComponent" /> | 172 | <component ref="settingFormEl" :is="getSettingComponent" /> |
| 62 | </BasicModal> | 173 | </BasicModal> |
| 1 | import { ValidateErrorEntity } from 'ant-design-vue/es/form/interface'; | 1 | import { ValidateErrorEntity } from 'ant-design-vue/es/form/interface'; |
| 2 | import { DataSource } from '../palette/types'; | 2 | import { DataSource } from '../palette/types'; |
| 3 | +import { FormSchema } from '/@/components/Form'; | ||
| 3 | 4 | ||
| 4 | export interface SelectedWidgetKeys { | 5 | export interface SelectedWidgetKeys { |
| 5 | categoryKey: string; | 6 | categoryKey: string; |
| @@ -21,5 +22,11 @@ export interface PublicFormInstaceType { | @@ -21,5 +22,11 @@ export interface PublicFormInstaceType { | ||
| 21 | getFormValues: () => Recordable; | 22 | getFormValues: () => Recordable; |
| 22 | setFormValues: (data: Recordable) => void; | 23 | setFormValues: (data: Recordable) => void; |
| 23 | resetFormValues: () => Promise<void>; | 24 | resetFormValues: () => Promise<void>; |
| 25 | + appendSchemaByField?: ( | ||
| 26 | + schema: FormSchema, | ||
| 27 | + prefixField?: string | undefined, | ||
| 28 | + first?: boolean | undefined | ||
| 29 | + ) => Promise<void>; | ||
| 30 | + removeSchemaByFiled?: (field: string | string[]) => Promise<void>; | ||
| 24 | validate?: () => Promise<{ flag: boolean; errors: ValidateErrorEntity }>; | 31 | validate?: () => Promise<{ flag: boolean; errors: ValidateErrorEntity }>; |
| 25 | } | 32 | } |
| @@ -122,6 +122,11 @@ | @@ -122,6 +122,11 @@ | ||
| 122 | 122 | ||
| 123 | const handleNewRecord = () => { | 123 | const handleNewRecord = () => { |
| 124 | const { componentKey } = unref(selectWidgetKeys); | 124 | const { componentKey } = unref(selectWidgetKeys); |
| 125 | + | ||
| 126 | + if (componentKey === 'ComponentStructural' && unref(dataSource).length >= 1) { | ||
| 127 | + createMessage.warning('结构体组件绑定的数据源不能超过1条'); | ||
| 128 | + return; | ||
| 129 | + } | ||
| 125 | if (componentKey === 'HumidityComponent2' && unref(dataSource).length >= 6) { | 130 | if (componentKey === 'HumidityComponent2' && unref(dataSource).length >= 6) { |
| 126 | createMessage.warning('绑定的数据源不能超过6条'); | 131 | createMessage.warning('绑定的数据源不能超过6条'); |
| 127 | return; | 132 | return; |
| @@ -258,22 +263,48 @@ | @@ -258,22 +263,48 @@ | ||
| 258 | } | 263 | } |
| 259 | const value = getFormValues(); | 264 | const value = getFormValues(); |
| 260 | const { record } = value || {}; | 265 | const { record } = value || {}; |
| 266 | + const { componentKey } = unref(selectWidgetKeys); | ||
| 261 | try { | 267 | try { |
| 262 | const currentRecordIconUrl = ref<any>([]); | 268 | const currentRecordIconUrl = ref<any>([]); |
| 263 | - // 判断当前自定义组件表单以前的自定义图片呢url | ||
| 264 | - currentRecord.value?.dataSource.forEach((item) => { | ||
| 265 | - if (item.componentInfo?.customIcon) { | ||
| 266 | - item.componentInfo?.customIcon?.forEach((icon: FileItem) => { | ||
| 267 | - currentRecordIconUrl.value.push(icon.url); | ||
| 268 | - }); | ||
| 269 | - } | ||
| 270 | - }); | 269 | + // 判断当前自定义组件表单以前自定义图片的url |
| 270 | + if (unref(currentRecord)?.dataSource) { | ||
| 271 | + currentRecord.value?.dataSource?.forEach((item) => { | ||
| 272 | + if (item.componentInfo?.customIcon || componentKey !== 'ComponentStructural') { | ||
| 273 | + item.componentInfo?.customIcon?.forEach((icon: FileItem) => { | ||
| 274 | + currentRecordIconUrl.value.push(icon.url); | ||
| 275 | + }); | ||
| 276 | + } | ||
| 277 | + // if (componentKey === 'ComponentStructural' && item?.StructuralDeleteUrl) { | ||
| 278 | + // currentRecordIconUrl.value.push(...item?.StructuralDeleteUrl?.split(',')); | ||
| 279 | + | ||
| 280 | + // } | ||
| 281 | + for (const item1 in item.componentInfo) { | ||
| 282 | + if (item1.includes('StructuralCustomIcon')) { | ||
| 283 | + currentRecordIconUrl.value.push(item.componentInfo[item1]?.[0].url); | ||
| 284 | + } | ||
| 285 | + } | ||
| 286 | + }); | ||
| 287 | + } | ||
| 271 | // 取当前修改过后的自定义图片url | 288 | // 取当前修改过后的自定义图片url |
| 272 | - const dataSourceUrl = record.dataSource?.map( | ||
| 273 | - (item) => item.componentInfo.customIcon?.[0].url | ||
| 274 | - ); | ||
| 275 | 289 | ||
| 276 | - // 当前自定义组件取出要进行删除的图标url | 290 | + const dataSourceUrl = |
| 291 | + componentKey !== 'ComponentStructural' | ||
| 292 | + ? record.dataSource?.map((item) => item.componentInfo.customIcon?.[0].url) | ||
| 293 | + : []; | ||
| 294 | + | ||
| 295 | + if (componentKey === 'ComponentStructural') { | ||
| 296 | + record.dataSource?.forEach((item) => { | ||
| 297 | + for (const item1 in item.componentInfo) { | ||
| 298 | + if (item1.includes('StructuralCustomIcon')) { | ||
| 299 | + dataSourceUrl?.push(item.componentInfo[item1]?.[0].url); | ||
| 300 | + } | ||
| 301 | + } | ||
| 302 | + }); | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + // StructuralCustomIcon | ||
| 306 | + | ||
| 307 | + // 当前自定义组件取出要进行删除的图标url ->判断当前组件的自定义图标url是跟以前不一样 取出不一样的以前自定义组件的url进行删除 | ||
| 277 | const dataSourceDeleteUrl = unref(currentRecordIconUrl).filter( | 308 | const dataSourceDeleteUrl = unref(currentRecordIconUrl).filter( |
| 278 | (item) => !dataSourceUrl?.includes(item) | 309 | (item) => !dataSourceUrl?.includes(item) |
| 279 | ); | 310 | ); |
| @@ -283,11 +314,18 @@ | @@ -283,11 +314,18 @@ | ||
| 283 | const customIconUrls = ref<any>([]); | 314 | const customIconUrls = ref<any>([]); |
| 284 | oldDataSource?.forEach((item: any) => { | 315 | oldDataSource?.forEach((item: any) => { |
| 285 | item.dataSource?.forEach((dataSource) => { | 316 | item.dataSource?.forEach((dataSource) => { |
| 286 | - if (dataSource.componentInfo?.customIcon) { | ||
| 287 | - dataSource.componentInfo?.customIcon?.forEach((icon: FileItem) => { | 317 | + if (dataSource.componentInfo?.customIcon || componentKey !== 'ComponentStructural') { |
| 318 | + dataSource?.componentInfo?.customIcon?.forEach((icon: FileItem) => { | ||
| 288 | customIconUrls.value.push(icon.url); | 319 | customIconUrls.value.push(icon.url); |
| 289 | }); | 320 | }); |
| 290 | } | 321 | } |
| 322 | + if (componentKey === 'ComponentStructural') { | ||
| 323 | + for (const structural in dataSource?.componentInfo) { | ||
| 324 | + if (structural?.includes('StructuralCustomIcon')) { | ||
| 325 | + customIconUrls.value.push(dataSource?.componentInfo[structural]?.[0].url); | ||
| 326 | + } | ||
| 327 | + } | ||
| 328 | + } | ||
| 291 | }); | 329 | }); |
| 292 | }); | 330 | }); |
| 293 | // const dataSourceDeleteUrl = record.dataSource?.map((item) => item.componentInfo.deleteUrl); | 331 | // const dataSourceDeleteUrl = record.dataSource?.map((item) => item.componentInfo.deleteUrl); |
| 1 | +import cloneDeep from 'lodash-es/cloneDeep'; | ||
| 2 | +import { ComponentStructuralConfig } from '.'; | ||
| 3 | +import { | ||
| 4 | + ConfigType, | ||
| 5 | + CreateComponentType, | ||
| 6 | + PublicComponentOptions, | ||
| 7 | + PublicPresetOptions, | ||
| 8 | +} from '/@/views/visual/packages/index.type'; | ||
| 9 | +import { PublicConfigClass, componentInitConfig } from '/@/views/visual/packages/publicConfig'; | ||
| 10 | +import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
| 11 | + | ||
| 12 | +export const option: PublicPresetOptions = { | ||
| 13 | + [ComponentConfigFieldEnum.UNIT]: '℃', | ||
| 14 | + [ComponentConfigFieldEnum.ICON]: 'shuiwen', | ||
| 15 | + [ComponentConfigFieldEnum.ICON_COLOR]: '#367bff', | ||
| 16 | + [ComponentConfigFieldEnum.FONT_COLOR]: '#000', | ||
| 17 | + [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | ||
| 18 | + [ComponentConfigFieldEnum.VALUE_SIZE]: 20, | ||
| 19 | + [ComponentConfigFieldEnum.FONT_SIZE]: 14, | ||
| 20 | +}; | ||
| 21 | + | ||
| 22 | +export default class Config extends PublicConfigClass implements CreateComponentType { | ||
| 23 | + public key: string = ComponentStructuralConfig.key; | ||
| 24 | + | ||
| 25 | + public attr = { ...componentInitConfig }; | ||
| 26 | + | ||
| 27 | + public componentConfig: ConfigType = cloneDeep(ComponentStructuralConfig); | ||
| 28 | + | ||
| 29 | + public persetOption = cloneDeep(option); | ||
| 30 | + | ||
| 31 | + public option: PublicComponentOptions; | ||
| 32 | + | ||
| 33 | + constructor(option: PublicComponentOptions) { | ||
| 34 | + super(); | ||
| 35 | + this.option = { ...option }; | ||
| 36 | + } | ||
| 37 | +} |
| 1 | +<script lang="ts" setup> | ||
| 2 | + import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
| 3 | + import { useForm, BasicForm } from '/@/components/Form'; | ||
| 4 | + import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
| 5 | + import { option } from './config'; | ||
| 6 | + | ||
| 7 | + const [ | ||
| 8 | + register, | ||
| 9 | + { | ||
| 10 | + getFieldsValue, | ||
| 11 | + setFieldsValue, | ||
| 12 | + resetFields, | ||
| 13 | + appendSchemaByField, | ||
| 14 | + removeSchemaByFiled, | ||
| 15 | + validate, | ||
| 16 | + }, | ||
| 17 | + ] = useForm({ | ||
| 18 | + schemas: [ | ||
| 19 | + { | ||
| 20 | + field: ComponentConfigFieldEnum.FONT_COLOR, | ||
| 21 | + label: '数值字体颜色', | ||
| 22 | + component: 'ColorPicker', | ||
| 23 | + changeEvent: 'update:value', | ||
| 24 | + valueField: 'value', | ||
| 25 | + defaultValue: option.fontColor, | ||
| 26 | + }, | ||
| 27 | + // { | ||
| 28 | + // field: ComponentConfigFieldEnum.UNIT, | ||
| 29 | + // label: '数值单位', | ||
| 30 | + // component: 'Input', | ||
| 31 | + // defaultValue: option.unit, | ||
| 32 | + // componentProps: { | ||
| 33 | + // placeholder: '请输入数值单位', | ||
| 34 | + // }, | ||
| 35 | + // }, | ||
| 36 | + | ||
| 37 | + { | ||
| 38 | + field: ComponentConfigFieldEnum.VALUE_SIZE, | ||
| 39 | + label: '数值字体大小', | ||
| 40 | + component: 'InputNumber', | ||
| 41 | + defaultValue: 20, | ||
| 42 | + componentProps: { | ||
| 43 | + min: 0, | ||
| 44 | + max: 100, | ||
| 45 | + formatter: (e) => { | ||
| 46 | + const value = e?.toString().replace(/^0/g, ''); | ||
| 47 | + if (value) { | ||
| 48 | + return value.replace(/^0/g, ''); | ||
| 49 | + } else { | ||
| 50 | + return 0; | ||
| 51 | + } | ||
| 52 | + }, | ||
| 53 | + }, | ||
| 54 | + }, | ||
| 55 | + { | ||
| 56 | + field: ComponentConfigFieldEnum.FONT_SIZE, | ||
| 57 | + label: '文本字体大小', | ||
| 58 | + component: 'InputNumber', | ||
| 59 | + defaultValue: 14, | ||
| 60 | + componentProps: { | ||
| 61 | + min: 0, | ||
| 62 | + max: 100, | ||
| 63 | + formatter: (e) => { | ||
| 64 | + const value = e?.toString().replace(/^0/g, ''); | ||
| 65 | + if (value) { | ||
| 66 | + return value.replace(/^0/g, ''); | ||
| 67 | + } else { | ||
| 68 | + return 0; | ||
| 69 | + } | ||
| 70 | + }, | ||
| 71 | + }, | ||
| 72 | + }, | ||
| 73 | + { | ||
| 74 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
| 75 | + label: '显示设备名称', | ||
| 76 | + component: 'Checkbox', | ||
| 77 | + defaultValue: option.showDeviceName, | ||
| 78 | + }, | ||
| 79 | + { | ||
| 80 | + field: ComponentConfigFieldEnum.SHOW_TIME, | ||
| 81 | + label: '显示时间', | ||
| 82 | + component: 'Checkbox', | ||
| 83 | + defaultValue: option.showDeviceName, | ||
| 84 | + }, | ||
| 85 | + { | ||
| 86 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
| 87 | + label: '图标类型', | ||
| 88 | + component: 'RadioGroup', | ||
| 89 | + defaultValue: 'default', | ||
| 90 | + componentProps: ({ formModel }) => { | ||
| 91 | + return { | ||
| 92 | + options: [ | ||
| 93 | + { label: '系统默认', value: 'default' }, | ||
| 94 | + { label: '自定义', value: 'custom' }, | ||
| 95 | + ], | ||
| 96 | + onChange() { | ||
| 97 | + for (const item in formModel) { | ||
| 98 | + if (item.includes('CustomIcon')) { | ||
| 99 | + formModel[item] = []; | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
| 103 | + }, | ||
| 104 | + }; | ||
| 105 | + }, | ||
| 106 | + }, | ||
| 107 | + { | ||
| 108 | + field: 'structuralDeleteUrl', | ||
| 109 | + label: '删除图标存储地址', | ||
| 110 | + component: 'Input', | ||
| 111 | + defaultValue: '123', | ||
| 112 | + show: false, | ||
| 113 | + }, | ||
| 114 | + ], | ||
| 115 | + showActionButtonGroup: false, | ||
| 116 | + labelWidth: 120, | ||
| 117 | + baseColProps: { | ||
| 118 | + span: 12, | ||
| 119 | + }, | ||
| 120 | + }); | ||
| 121 | + | ||
| 122 | + const getFormValues = () => { | ||
| 123 | + return getFieldsValue(); | ||
| 124 | + }; | ||
| 125 | + | ||
| 126 | + const setFormValues = (data: Recordable) => { | ||
| 127 | + return setFieldsValue(data); | ||
| 128 | + }; | ||
| 129 | + | ||
| 130 | + defineExpose({ | ||
| 131 | + getFormValues, | ||
| 132 | + setFormValues, | ||
| 133 | + resetFormValues: resetFields, | ||
| 134 | + appendSchemaByField, | ||
| 135 | + removeSchemaByFiled, | ||
| 136 | + validate, | ||
| 137 | + } as PublicFormInstaceType); | ||
| 138 | +</script> | ||
| 139 | + | ||
| 140 | +<template> | ||
| 141 | + <BasicForm @register="register" /> | ||
| 142 | +</template> | ||
| 143 | + | ||
| 144 | +<style lang="less" scoped> | ||
| 145 | + :deep(.ant-form-item-label) { | ||
| 146 | + label { | ||
| 147 | + span { | ||
| 148 | + max-width: 120px !important; | ||
| 149 | + text-overflow: ellipsis !important; | ||
| 150 | + overflow: hidden; | ||
| 151 | + vertical-align: middle; | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + :deep(.ant-form-item-label) { | ||
| 156 | + span { | ||
| 157 | + max-width: 120px !important; | ||
| 158 | + text-overflow: ellipsis !important; | ||
| 159 | + overflow: hidden; | ||
| 160 | + vertical-align: middle; | ||
| 161 | + } | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | +</style> |
| 1 | +<script lang="ts" setup> | ||
| 2 | + import { commonDataSourceSchemas } from '../../../config/common.config'; | ||
| 3 | + import { BasicForm, useForm } from '/@/components/Form'; | ||
| 4 | + import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
| 5 | + | ||
| 6 | + // const props = defineProps<{ | ||
| 7 | + // values: PublicComponentDataSourceProps; | ||
| 8 | + // }>(); | ||
| 9 | + | ||
| 10 | + const [register, { getFieldsValue, setFieldsValue, validate, resetFields, appendSchemaByField }] = | ||
| 11 | + useForm({ | ||
| 12 | + labelWidth: 0, | ||
| 13 | + showActionButtonGroup: false, | ||
| 14 | + layout: 'horizontal', | ||
| 15 | + labelCol: { span: 0 }, | ||
| 16 | + schemas: commonDataSourceSchemas(), | ||
| 17 | + }); | ||
| 18 | + | ||
| 19 | + const getFormValues = () => { | ||
| 20 | + return getFieldsValue(); | ||
| 21 | + }; | ||
| 22 | + | ||
| 23 | + const setFormValues = (record: Recordable) => { | ||
| 24 | + return setFieldsValue(record); | ||
| 25 | + }; | ||
| 26 | + | ||
| 27 | + defineExpose({ | ||
| 28 | + getFormValues, | ||
| 29 | + setFormValues, | ||
| 30 | + validate, | ||
| 31 | + resetFormValues: resetFields, | ||
| 32 | + appendSchemaByField, | ||
| 33 | + } as PublicFormInstaceType); | ||
| 34 | +</script> | ||
| 35 | + | ||
| 36 | +<template> | ||
| 37 | + <BasicForm @register="register" /> | ||
| 38 | +</template> |
| 1 | +import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; | ||
| 2 | +import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; | ||
| 3 | + | ||
| 4 | +const componentKeys = useComponentKeys('ComponentStructural'); | ||
| 5 | +export const ComponentStructuralConfig: ConfigType = { | ||
| 6 | + ...componentKeys, | ||
| 7 | + title: '结构体组件', | ||
| 8 | + package: PackagesCategoryEnum.TEXT, | ||
| 9 | +}; |
| 1 | +<script lang="ts" setup> | ||
| 2 | + import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | ||
| 3 | + import { option } from './config'; | ||
| 4 | + import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | ||
| 5 | + import { ref, unref } from 'vue'; | ||
| 6 | + import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime'; | ||
| 7 | + import { SvgIcon } from '/@/components/Icon'; | ||
| 8 | + import { computed } from 'vue'; | ||
| 9 | + import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | ||
| 10 | + import { useDataFetch } from '../../../hook/socket/useSocket'; | ||
| 11 | + import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | ||
| 12 | + import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform'; | ||
| 13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
| 14 | + import { isObject } from '/@/utils/is'; | ||
| 15 | + | ||
| 16 | + const props = defineProps<{ | ||
| 17 | + config: ComponentPropsConfigType<typeof option>; | ||
| 18 | + }>(); | ||
| 19 | + | ||
| 20 | + const currentValue = ref<string | number>(123); | ||
| 21 | + | ||
| 22 | + const structuralData = ref< | ||
| 23 | + { | ||
| 24 | + label: string; | ||
| 25 | + value: string | number; | ||
| 26 | + icon: any; | ||
| 27 | + iconColor: string; | ||
| 28 | + }[] | ||
| 29 | + >([{ label: '温度', value: 20, icon: 'shuiwen', iconColor: '#367bff' }]); | ||
| 30 | + | ||
| 31 | + const time = ref<Nullable<number>>(null); | ||
| 32 | + | ||
| 33 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
| 34 | + | ||
| 35 | + const getThingModelTsl = computed(() => { | ||
| 36 | + const { option } = props.config; | ||
| 37 | + | ||
| 38 | + const { deviceProfileId, attribute } = option; | ||
| 39 | + return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + const getDesign = computed(() => { | ||
| 43 | + const { persetOption = {}, option } = props.config; | ||
| 44 | + const { | ||
| 45 | + iconColor: persetIconColor, | ||
| 46 | + unit: perseUnit, | ||
| 47 | + icon: persetIcon, | ||
| 48 | + fontColor: persetFontColor, | ||
| 49 | + valueSize: persetValueSize, | ||
| 50 | + fontSize: persetFontSize, | ||
| 51 | + showTime: persetShowTime, | ||
| 52 | + } = persetOption; | ||
| 53 | + | ||
| 54 | + const { componentInfo, attributeRename, structural, structuralLabel } = option; | ||
| 55 | + const { functionName } = unref(getThingModelTsl) || {}; | ||
| 56 | + | ||
| 57 | + const { | ||
| 58 | + icon, | ||
| 59 | + iconColor, | ||
| 60 | + fontColor, | ||
| 61 | + showTime, | ||
| 62 | + unit, | ||
| 63 | + valueSize, | ||
| 64 | + fontSize, | ||
| 65 | + customIcon, | ||
| 66 | + defaultCustom, | ||
| 67 | + } = componentInfo || {}; | ||
| 68 | + return { | ||
| 69 | + iconColor: iconColor || persetIconColor, | ||
| 70 | + unit: unit ?? perseUnit, | ||
| 71 | + icon: icon || persetIcon, | ||
| 72 | + fontColor: fontColor || persetFontColor, | ||
| 73 | + attribute: attributeRename || functionName, | ||
| 74 | + valueSize: valueSize || persetValueSize || 20, | ||
| 75 | + fontSize: fontSize || persetFontSize || 14, | ||
| 76 | + showTime: showTime || persetShowTime, | ||
| 77 | + defaultCustom: defaultCustom || 'default', | ||
| 78 | + customIcon: customIcon || [], | ||
| 79 | + structural: structural || [], | ||
| 80 | + structuralLabel: structuralLabel || [], | ||
| 81 | + componentInfo, | ||
| 82 | + }; | ||
| 83 | + }); | ||
| 84 | + | ||
| 85 | + const updateFn: DataFetchUpdateFn = (message, attribute) => { | ||
| 86 | + const { data = {} } = message; | ||
| 87 | + const [latest] = data[attribute] || []; | ||
| 88 | + if (!latest.length) return; | ||
| 89 | + const [timespan, value] = latest; | ||
| 90 | + | ||
| 91 | + const { structuralLabel, structural, componentInfo } = unref(getDesign) || {}; | ||
| 92 | + const { defaultCustom } = componentInfo || {}; | ||
| 93 | + | ||
| 94 | + time.value = timespan; | ||
| 95 | + if (structural?.length && structuralLabel?.length) { | ||
| 96 | + const values = JSON.parse(value); | ||
| 97 | + const newValues = isObject(values) | ||
| 98 | + ? defaultCustom === 'custom' | ||
| 99 | + ? structural.map((item, index) => { | ||
| 100 | + const option = { | ||
| 101 | + label: structuralLabel[index], | ||
| 102 | + value: values[item], | ||
| 103 | + icon: componentInfo[item + 'StructuralCustomIcon'], | ||
| 104 | + // iconColor: componentInfo[item + 'CustomIconColor'], | ||
| 105 | + }; | ||
| 106 | + return option; | ||
| 107 | + }) | ||
| 108 | + : structural.map((item, index) => { | ||
| 109 | + const option = { | ||
| 110 | + label: structuralLabel[index], | ||
| 111 | + value: values[item], | ||
| 112 | + icon: componentInfo[item + 'StructuralIcon'], | ||
| 113 | + iconColor: componentInfo[item + 'StructuralIconColor'], | ||
| 114 | + }; | ||
| 115 | + return option; | ||
| 116 | + }) | ||
| 117 | + : []; | ||
| 118 | + structuralData.value = newValues; | ||
| 119 | + return; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + currentValue.value = useThingsModelValueTransform( | ||
| 123 | + value, | ||
| 124 | + unref(getThingModelTsl)?.specs?.dataType | ||
| 125 | + ); | ||
| 126 | + }; | ||
| 127 | + | ||
| 128 | + useDataFetch(props, updateFn); | ||
| 129 | + | ||
| 130 | + const { getScale, getRatio } = useComponentScale(props); | ||
| 131 | +</script> | ||
| 132 | + | ||
| 133 | +<template> | ||
| 134 | + <main | ||
| 135 | + :style="getScale" | ||
| 136 | + class="w-full h-full flex flex-col justify-center items-center" | ||
| 137 | + :class="!getDesign.showTime && 'p-5'" | ||
| 138 | + > | ||
| 139 | + <DeviceName :config="config" /> | ||
| 140 | + <!-- <div class="flex-1 flex justify-center items-center flex-col w-full"> | ||
| 141 | + <SvgIcon | ||
| 142 | + v-if="getDesign.defaultCustom !== 'custom'" | ||
| 143 | + :name="getDesign.icon!" | ||
| 144 | + prefix="iconfont" | ||
| 145 | + :size="getRatio ? getRatio * 70 : 70" | ||
| 146 | + :style="{ color: getDesign.iconColor }" | ||
| 147 | + /> | ||
| 148 | + <img | ||
| 149 | + v-else | ||
| 150 | + :src="getDesign.customIcon[0]?.url" | ||
| 151 | + :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }" | ||
| 152 | + :alt="getDesign.customIcon[0]?.name" | ||
| 153 | + /> | ||
| 154 | + <h1 | ||
| 155 | + class="font-bold m-2 truncate w-full text-center" | ||
| 156 | + :style="{ | ||
| 157 | + color: getDesign.fontColor, | ||
| 158 | + fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | ||
| 159 | + }" | ||
| 160 | + > | ||
| 161 | + <span> {{ currentValue || 0 }}</span> | ||
| 162 | + <span>{{ getDesign.unit }} </span> | ||
| 163 | + </h1> | ||
| 164 | + <div | ||
| 165 | + class="text-gray-500 truncate" | ||
| 166 | + :style="{ | ||
| 167 | + fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px', | ||
| 168 | + }" | ||
| 169 | + >{{ getDesign.attribute || '温度' }}</div | ||
| 170 | + > | ||
| 171 | + </div> --> | ||
| 172 | + <div class="flex flex-1 justify-center items-center w-full flex-wrap"> | ||
| 173 | + <div | ||
| 174 | + v-for="item in structuralData" | ||
| 175 | + :key="item.label" | ||
| 176 | + class="flex-1 flex justify-center items-center flex-col w-full" | ||
| 177 | + > | ||
| 178 | + <SvgIcon | ||
| 179 | + v-if="getDesign.defaultCustom !== 'custom'" | ||
| 180 | + :name="item.icon || 'shuiwen'" | ||
| 181 | + prefix="iconfont" | ||
| 182 | + :size="getRatio ? (getRatio * 70) / structuralData?.length || 1 : 70" | ||
| 183 | + :style="{ color: item.iconColor || '#367bff' }" | ||
| 184 | + /> | ||
| 185 | + <img | ||
| 186 | + v-else | ||
| 187 | + :src="item.icon?.[0]?.url!" | ||
| 188 | + :style="{ | ||
| 189 | + width: getRatio ? (getRatio * 70) / structuralData?.length + 'px' : '70px', | ||
| 190 | + height: getRatio ? (getRatio * 70) / structuralData?.length + 'px' : '70px', | ||
| 191 | + }" | ||
| 192 | + :alt="item.icon?.[0]?.name!" | ||
| 193 | + /> | ||
| 194 | + <h1 | ||
| 195 | + class="font-bold m-2 truncate w-full text-center" | ||
| 196 | + :style="{ | ||
| 197 | + color: getDesign.fontColor, | ||
| 198 | + fontSize: | ||
| 199 | + (getRatio | ||
| 200 | + ? (getRatio * getDesign.valueSize) / structuralData?.length || 1 | ||
| 201 | + : getDesign.valueSize) + 'px', | ||
| 202 | + }" | ||
| 203 | + > | ||
| 204 | + <span> {{ item.value || 0 }}</span> | ||
| 205 | + <span>{{ getDesign.unit }} </span> | ||
| 206 | + </h1> | ||
| 207 | + <div | ||
| 208 | + class="text-gray-500 truncate text-center" | ||
| 209 | + :style="{ | ||
| 210 | + fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px', | ||
| 211 | + width: getRatio ? getRatio * 90 + 'px' : '90px', | ||
| 212 | + }" | ||
| 213 | + >{{ getDesign.attribute + '-' + item.label || '温度' }}</div | ||
| 214 | + > | ||
| 215 | + </div> | ||
| 216 | + </div> | ||
| 217 | + <UpdateTime v-show="getDesign.showTime" :time="time" /> | ||
| 218 | + </main> | ||
| 219 | +</template> |
| @@ -2,6 +2,7 @@ import { TextComponent1Config } from './TextComponent1'; | @@ -2,6 +2,7 @@ import { TextComponent1Config } from './TextComponent1'; | ||
| 2 | import { TextComponent2Config } from './TextComponent2'; | 2 | import { TextComponent2Config } from './TextComponent2'; |
| 3 | import { TextComponent3Config } from './TextComponent3'; | 3 | import { TextComponent3Config } from './TextComponent3'; |
| 4 | import { TextComponent4Config } from './TextComponent4'; | 4 | import { TextComponent4Config } from './TextComponent4'; |
| 5 | +import { ComponentStructuralConfig } from './ComponentStructural'; | ||
| 5 | import { ValueList1Config } from './ValueList1'; | 6 | import { ValueList1Config } from './ValueList1'; |
| 6 | import { ValueList2Config } from './ValueList2'; | 7 | import { ValueList2Config } from './ValueList2'; |
| 7 | 8 | ||
| @@ -9,6 +10,7 @@ export const TextList = [ | @@ -9,6 +10,7 @@ export const TextList = [ | ||
| 9 | TextComponent1Config, | 10 | TextComponent1Config, |
| 10 | TextComponent2Config, | 11 | TextComponent2Config, |
| 11 | TextComponent3Config, | 12 | TextComponent3Config, |
| 13 | + ComponentStructuralConfig, | ||
| 12 | TextComponent4Config, | 14 | TextComponent4Config, |
| 13 | ValueList1Config, | 15 | ValueList1Config, |
| 14 | ValueList2Config, | 16 | ValueList2Config, |
| @@ -43,6 +43,7 @@ export enum DataSourceField { | @@ -43,6 +43,7 @@ export enum DataSourceField { | ||
| 43 | ATTRIBUTE_RENAME = 'attributeRename', | 43 | ATTRIBUTE_RENAME = 'attributeRename', |
| 44 | DEVICE_NAME = 'deviceName', | 44 | DEVICE_NAME = 'deviceName', |
| 45 | DEVICE_RENAME = 'deviceRename', | 45 | DEVICE_RENAME = 'deviceRename', |
| 46 | + STRUCTURAL_MORPHOLOGY = 'structural morphology', | ||
| 46 | 47 | ||
| 47 | // COMMAND = 'command', | 48 | // COMMAND = 'command', |
| 48 | 49 | ||
| @@ -290,8 +291,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -290,8 +291,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
| 290 | colProps: { span: 8 }, | 291 | colProps: { span: 8 }, |
| 291 | rules: [{ required: true, message: '请选择属性' }], | 292 | rules: [{ required: true, message: '请选择属性' }], |
| 292 | ifShow: () => category !== CategoryEnum.MAP, | 293 | ifShow: () => category !== CategoryEnum.MAP, |
| 293 | - componentProps({ formModel }) { | 294 | + componentProps({ formModel, formActionType }) { |
| 294 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | 295 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; |
| 296 | + const { setFieldsValue } = formActionType; | ||
| 295 | return { | 297 | return { |
| 296 | api: async () => { | 298 | api: async () => { |
| 297 | try { | 299 | try { |
| @@ -334,12 +336,166 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -334,12 +336,166 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
| 334 | } catch (error) {} | 336 | } catch (error) {} |
| 335 | return []; | 337 | return []; |
| 336 | }, | 338 | }, |
| 339 | + | ||
| 340 | + apiTreeSelectProps: { | ||
| 341 | + params: { deviceProfileId }, | ||
| 342 | + }, | ||
| 337 | placeholder: '请选择属性', | 343 | placeholder: '请选择属性', |
| 344 | + onChange: (value: string, option: Record<'label' | 'value' | any, string>) => { | ||
| 345 | + const { detail }: any = option || {}; | ||
| 346 | + if (value && detail?.dataType.type === 'STRUCT') { | ||
| 347 | + } | ||
| 348 | + setFieldsValue({ | ||
| 349 | + structuralOption: | ||
| 350 | + value && detail?.dataType.type === 'STRUCT' | ||
| 351 | + ? JSON.stringify(detail?.dataType.specs) | ||
| 352 | + : null, | ||
| 353 | + }); | ||
| 354 | + }, | ||
| 338 | ...createPickerSearch(), | 355 | ...createPickerSearch(), |
| 339 | }; | 356 | }; |
| 340 | }, | 357 | }, |
| 341 | }, | 358 | }, |
| 342 | { | 359 | { |
| 360 | + field: 'structuralOption', | ||
| 361 | + label: '存储结构体的数据进行选择操作', | ||
| 362 | + component: 'Input', | ||
| 363 | + ifShow: false, | ||
| 364 | + }, | ||
| 365 | + { | ||
| 366 | + field: 'structural', | ||
| 367 | + label: '选择结构体', | ||
| 368 | + colProps: { span: 8 }, | ||
| 369 | + ifShow: ({ model }) => | ||
| 370 | + model.structuralOption && unref(selectWidgetKeys).componentKey === 'ComponentStructural', | ||
| 371 | + component: 'Select', | ||
| 372 | + componentProps: ({ formModel, formActionType }) => { | ||
| 373 | + const { setFieldsValue } = formActionType; | ||
| 374 | + const { structuralOption } = formModel || {}; | ||
| 375 | + return { | ||
| 376 | + mode: 'multiple', | ||
| 377 | + getPopupContainer: () => document.body, | ||
| 378 | + placeholder: '请选择结构体参数', | ||
| 379 | + options: structuralOption | ||
| 380 | + ? JSON.parse(structuralOption)?.map((item) => ({ | ||
| 381 | + label: item.functionName, | ||
| 382 | + value: item.identifier, | ||
| 383 | + })) | ||
| 384 | + : [], | ||
| 385 | + onChange(value, option) { | ||
| 386 | + if (value?.length && option?.length) { | ||
| 387 | + const array = new Map(option.map((item) => [item.value, item.label])); | ||
| 388 | + const filteredLabels = value.map((value) => array.get(value) || ''); | ||
| 389 | + setFieldsValue({ | ||
| 390 | + structuralLabel: filteredLabels?.length ? filteredLabels : [], | ||
| 391 | + }); | ||
| 392 | + } | ||
| 393 | + }, | ||
| 394 | + }; | ||
| 395 | + }, | ||
| 396 | + }, | ||
| 397 | + { | ||
| 398 | + field: 'structuralLabel', | ||
| 399 | + label: '结构体名称', | ||
| 400 | + colProps: { span: 8 }, | ||
| 401 | + ifShow: false, | ||
| 402 | + component: 'Select', | ||
| 403 | + componentProps: { | ||
| 404 | + mode: 'multiple', | ||
| 405 | + getPopupContainer: () => document.body, | ||
| 406 | + }, | ||
| 407 | + }, | ||
| 408 | + | ||
| 409 | + // { | ||
| 410 | + // field: DataSourceField.ATTRIBUTE, | ||
| 411 | + // label: '属性', | ||
| 412 | + // component: 'ApiCascader', | ||
| 413 | + // colProps: { span: 8 }, | ||
| 414 | + // ifShow: () => false, | ||
| 415 | + // changeEvent: 'update:value', | ||
| 416 | + // valueField: 'value', | ||
| 417 | + // componentProps: ({ formModel }) => { | ||
| 418 | + // const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | ||
| 419 | + // return { | ||
| 420 | + // api: async () => { | ||
| 421 | + // try { | ||
| 422 | + // // if (deviceProfileId) { | ||
| 423 | + // // const options = await getDeviceAttributes({ | ||
| 424 | + // // deviceProfileId, | ||
| 425 | + // // }); | ||
| 426 | + | ||
| 427 | + // // const _options = options.map((item) => { | ||
| 428 | + // // item = Object.assign(item, { functionName: item.name }); | ||
| 429 | + // // if (item.detail.dataType.type === DataTypeEnum.STRUCT) { | ||
| 430 | + // // return Object.assign(item, { specs: item.detail.dataType.specs }); | ||
| 431 | + // // } | ||
| 432 | + // // return item; | ||
| 433 | + // // }); | ||
| 434 | + // // return _options; | ||
| 435 | + // // } | ||
| 436 | + // if (deviceProfileId) { | ||
| 437 | + // let option = await getDeviceAttribute({ | ||
| 438 | + // deviceProfileId, | ||
| 439 | + // dataType: | ||
| 440 | + // (isControlComponent(category!) && | ||
| 441 | + // unref(selectWidgetKeys).componentKey !== | ||
| 442 | + // ControlComponentEnum.LATERAL_NUMERICAL_CONTROL) || | ||
| 443 | + // isBooleanComponent(unref(selectWidgetKeys)) | ||
| 444 | + // ? DataTypeEnum.BOOL | ||
| 445 | + // : undefined, | ||
| 446 | + // }); | ||
| 447 | + // if (isControlComponent(category)) { | ||
| 448 | + // // 过滤只读属性 | ||
| 449 | + // option = option.filter( | ||
| 450 | + // (item) => item.accessMode !== ObjectModelAccessModeEnum.READ | ||
| 451 | + // ); | ||
| 452 | + // } | ||
| 453 | + // // 选择控制组件4的时候只能选择属性且是(int double类型) | ||
| 454 | + // if ( | ||
| 455 | + // unref(selectWidgetKeys).componentKey === | ||
| 456 | + // ControlComponentEnum.LATERAL_NUMERICAL_CONTROL | ||
| 457 | + // ) { | ||
| 458 | + // // setFieldsValue({ | ||
| 459 | + // // [DataSourceField.COMMAND_TYPE]: CommandTypeEnum.ATTRIBUTE.toString(), | ||
| 460 | + // // }); | ||
| 461 | + // return option.filter( | ||
| 462 | + // (item) => | ||
| 463 | + // item.detail.dataType.type === DataTypeEnum.NUMBER_INT || | ||
| 464 | + // item.detail.dataType.type == DataTypeEnum.NUMBER_DOUBLE | ||
| 465 | + // ); | ||
| 466 | + // } | ||
| 467 | + // const _options = option.map((item) => { | ||
| 468 | + // item = Object.assign(item, { functionName: item.name }); | ||
| 469 | + // if (item.detail.dataType.type === DataTypeEnum.STRUCT) { | ||
| 470 | + // return Object.assign(item, { specs: item.detail.dataType.specs }); | ||
| 471 | + // } | ||
| 472 | + // return item; | ||
| 473 | + // }); | ||
| 474 | + // return _options; | ||
| 475 | + // } | ||
| 476 | + // } catch (error) {} | ||
| 477 | + // return []; | ||
| 478 | + // }, | ||
| 479 | + // placeholder: '请选择属性', | ||
| 480 | + // showSearch: { | ||
| 481 | + // filter: (inputValue: string, path) => { | ||
| 482 | + // return path.some( | ||
| 483 | + // (option) => option.functionName.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 | ||
| 484 | + // ); | ||
| 485 | + // }, | ||
| 486 | + // matchInputWidth: true, | ||
| 487 | + // }, | ||
| 488 | + // changeOnSelect: true, | ||
| 489 | + // dropdownMatchSelectWidth: true, | ||
| 490 | + // // getPopupContainer: () => document.body, | ||
| 491 | + | ||
| 492 | + // getPopupContainer: (triggerNode) => triggerNode.parentNode, | ||
| 493 | + | ||
| 494 | + // fieldNames: { label: 'functionName', value: 'identifier', children: 'specs' }, | ||
| 495 | + // }; | ||
| 496 | + // }, | ||
| 497 | + // }, | ||
| 498 | + { | ||
| 343 | field: DataSourceField.LONGITUDE_IDENTIFIER, | 499 | field: DataSourceField.LONGITUDE_IDENTIFIER, |
| 344 | label: '经度', | 500 | label: '经度', |
| 345 | component: 'ApiCascader', | 501 | component: 'ApiCascader', |