Commit 8ef4393ef04b1eaf563b2190aed7b8647361eb62
Merge branch 'ww' into 'main'
feat: device profile transport protocol panel modify Description component See merge request huang/yun-teng-iot-front!448
Showing
25 changed files
with
1193 additions
and
123 deletions
| ... | ... | @@ -3,6 +3,7 @@ import { |
| 3 | 3 | TDeviceConfigParams, |
| 4 | 4 | IDeviceConfigAddOrEditModel, |
| 5 | 5 | ProfileRecord, |
| 6 | + RuleChainRecord, | |
| 6 | 7 | } from '/@/api/device/model/deviceConfigModel'; |
| 7 | 8 | import { PaginationResult } from '/#/axios'; |
| 8 | 9 | |
| ... | ... | @@ -36,7 +37,7 @@ export const deviceConfigGetDetail = (id: string) => { |
| 36 | 37 | * 获取规则链 |
| 37 | 38 | */ |
| 38 | 39 | export const deviceConfigGetRuleChain = () => { |
| 39 | - return defHttp.get({ | |
| 40 | + return defHttp.get<RuleChainRecord[]>({ | |
| 40 | 41 | url: EDeviceConfigApi.DEVICE_CONFIG_GET_RULECHAIN, |
| 41 | 42 | }); |
| 42 | 43 | }; | ... | ... |
| ... | ... | @@ -241,3 +241,21 @@ export interface ProfileRecord { |
| 241 | 241 | |
| 242 | 242 | checked?: boolean; |
| 243 | 243 | } |
| 244 | + | |
| 245 | +export interface IDRecord { | |
| 246 | + entityType: string; | |
| 247 | + id: string; | |
| 248 | +} | |
| 249 | + | |
| 250 | +export interface RuleChainRecord { | |
| 251 | + id: IDRecord; | |
| 252 | + createdTime: number; | |
| 253 | + additionalInfo?: any; | |
| 254 | + tenantId: IDRecord; | |
| 255 | + name: string; | |
| 256 | + type: string; | |
| 257 | + firstRuleNodeId: IDRecord; | |
| 258 | + root: boolean; | |
| 259 | + debugMode: boolean; | |
| 260 | + configuration?: any; | |
| 261 | +} | ... | ... |
| ... | ... | @@ -54,8 +54,84 @@ export interface Configuration { |
| 54 | 54 | type: string; |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | +export interface TransportPayloadTypeConfiguration { | |
| 58 | + transportPayloadType: string; | |
| 59 | + deviceTelemetryProtoSchema: string; | |
| 60 | + deviceAttributesProtoSchema: string; | |
| 61 | + deviceRpcRequestProtoSchema: string; | |
| 62 | + deviceRpcResponseProtoSchema: string; | |
| 63 | + enableCompatibilityWithJsonPayloadFormat: boolean; | |
| 64 | + useJsonPayloadFormatForDefaultDownlinkTopics: boolean; | |
| 65 | +} | |
| 66 | + | |
| 67 | +export interface ClientSettings { | |
| 68 | + edrxCycle: string; | |
| 69 | + pagingTransmissionWindow: string; | |
| 70 | + powerMode: string; | |
| 71 | + psmActivityTimer: number; | |
| 72 | + | |
| 73 | + clientOnlyObserveAfterConnect: string; | |
| 74 | + fwUpdateResource: string; | |
| 75 | + fwUpdateStrategy: number; | |
| 76 | + swUpdateResource: string; | |
| 77 | + swUpdateStrategy: number; | |
| 78 | +} | |
| 79 | + | |
| 80 | +export interface Bootstrap { | |
| 81 | + securityMode: string; | |
| 82 | + shortServerId: number; | |
| 83 | + bootstrapServerIs: boolean; | |
| 84 | + host: string; | |
| 85 | + port: number; | |
| 86 | + clientHoldOffTime: number; | |
| 87 | + serverPublicKey?: any; | |
| 88 | + serverCertificate?: any; | |
| 89 | + bootstrapServerAccountTimeout: number; | |
| 90 | + lifetime: number; | |
| 91 | + defaultMinPeriod: number; | |
| 92 | + notifIfDisabled: boolean; | |
| 93 | + binding: string; | |
| 94 | +} | |
| 95 | + | |
| 96 | +export interface Mapping { | |
| 97 | + dataType: string; | |
| 98 | + key: string; | |
| 99 | + oid: string; | |
| 100 | +} | |
| 101 | + | |
| 102 | +export interface CommunicationConfigs { | |
| 103 | + spec: string; | |
| 104 | + mappings: Mapping[]; | |
| 105 | + queryingFrequencyMs: number; | |
| 106 | +} | |
| 107 | + | |
| 57 | 108 | export interface TransportConfiguration { |
| 58 | 109 | type: string; |
| 110 | + deviceTelemetryTopic: string; | |
| 111 | + deviceAttributesTopic: string; | |
| 112 | + | |
| 113 | + // MQTT | |
| 114 | + transportPayloadTypeConfiguration: TransportPayloadTypeConfiguration; | |
| 115 | + | |
| 116 | + // COAP | |
| 117 | + clientSettings: ClientSettings; | |
| 118 | + coapDeviceTypeConfiguration: { | |
| 119 | + coapDeviceType: string; | |
| 120 | + transportPayloadTypeConfiguration: TransportPayloadTypeConfiguration; | |
| 121 | + }; | |
| 122 | + | |
| 123 | + // LWM2M | |
| 124 | + bootstrapServerUpdateEnable: boolean; | |
| 125 | + bootstrap: Bootstrap[]; | |
| 126 | + clientLwM2mSettings: ClientSettings; | |
| 127 | + | |
| 128 | + // SNMP | |
| 129 | + retries: number; | |
| 130 | + timeoutMs: number; | |
| 131 | + communicationConfigs: CommunicationConfigs[]; | |
| 132 | + | |
| 133 | + // TCP | |
| 134 | + scriptId: string; | |
| 59 | 135 | } |
| 60 | 136 | |
| 61 | 137 | export interface ProvisionConfiguration { |
| ... | ... | @@ -85,6 +161,7 @@ export interface DeviceRecord { |
| 85 | 161 | image: string; |
| 86 | 162 | type: string; |
| 87 | 163 | default: boolean; |
| 164 | + defaultRuleChainId: string; | |
| 88 | 165 | } |
| 89 | 166 | |
| 90 | 167 | export interface DeviceModelOfMatterAttrs { | ... | ... |
| 1 | +import { ProfileRecord } from '../device/model/deviceConfigModel'; | |
| 1 | 2 | import { |
| 2 | 3 | CreateOtaPackageParams, |
| 3 | 4 | DefaultDeviceProfileInfo, |
| ... | ... | @@ -129,7 +130,7 @@ export const getDeviceProfileInfos = (params: GetDeviceProfileInfosParams) => { |
| 129 | 130 | }; |
| 130 | 131 | |
| 131 | 132 | export const getDeviceProfileInfoById = (id: string) => { |
| 132 | - return defHttp.get<DeviceProfileRecord>( | |
| 133 | + return defHttp.get<ProfileRecord>( | |
| 133 | 134 | { |
| 134 | 135 | url: `${Api.GET_DEVICE_PROFILE_INFO_BY_ID}/${id}`, |
| 135 | 136 | }, | ... | ... |
| ... | ... | @@ -24,12 +24,11 @@ export interface ScriptRecord { |
| 24 | 24 | id: string; |
| 25 | 25 | creator: string; |
| 26 | 26 | createTime: string; |
| 27 | - updater: string; | |
| 28 | - updateTime: string; | |
| 29 | 27 | name: string; |
| 30 | - convertJs: string; | |
| 31 | - enabled: boolean; | |
| 32 | 28 | tenantId: string; |
| 33 | 29 | description: string; |
| 34 | - status: boolean; | |
| 30 | + convertJs: string; | |
| 31 | + status: number; | |
| 32 | + dataType: string; | |
| 33 | + saveOriginalData: boolean; | |
| 35 | 34 | } | ... | ... |
src/components/Widget/AuthDropDown.vue
0 → 100644
src/components/Widget/AuthIcon.vue
0 → 100644
| ... | ... | @@ -8,7 +8,14 @@ |
| 8 | 8 | centered |
| 9 | 9 | :canFullscreen="false" |
| 10 | 10 | > |
| 11 | - <BasicForm @register="registerForm" /> | |
| 11 | + <BasicForm @register="registerForm"> | |
| 12 | + <template #clientId="{ field, model }"> | |
| 13 | + <div class="flex items-center"> | |
| 14 | + <Input v-model:value="model[field]" placeholder="请输入客户端ID" /> | |
| 15 | + <ReloadOutlined class="ml-3 !text-blue-600" @click="handleCreateUUID" /> | |
| 16 | + </div> | |
| 17 | + </template> | |
| 18 | + </BasicForm> | |
| 12 | 19 | </BasicModal> |
| 13 | 20 | </template> |
| 14 | 21 | |
| ... | ... | @@ -19,10 +26,15 @@ |
| 19 | 26 | import { TokenSchemas, credentialTypeEnum } from '../../config/data'; |
| 20 | 27 | import { saveDeviceToken } from '/@/api/device/deviceManager'; |
| 21 | 28 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 29 | + import { Input } from 'ant-design-vue'; | |
| 30 | + import { buildUUID } from '/@/utils/uuid'; | |
| 31 | + import { ReloadOutlined } from '@ant-design/icons-vue'; | |
| 22 | 32 | export default defineComponent({ |
| 23 | 33 | components: { |
| 24 | 34 | BasicModal, |
| 25 | 35 | BasicForm, |
| 36 | + Input, | |
| 37 | + ReloadOutlined, | |
| 26 | 38 | }, |
| 27 | 39 | emits: ['register'], |
| 28 | 40 | setup() { |
| ... | ... | @@ -36,7 +48,7 @@ |
| 36 | 48 | showSubmitButton: false, |
| 37 | 49 | showResetButton: false, |
| 38 | 50 | wrapperCol: { |
| 39 | - span: 12, | |
| 51 | + span: 16, | |
| 40 | 52 | }, |
| 41 | 53 | }); |
| 42 | 54 | const [registerModal, { closeModal }] = useModalInner(async (data) => { |
| ... | ... | @@ -208,12 +220,17 @@ |
| 208 | 220 | }) |
| 209 | 221 | .catch(() => {}); |
| 210 | 222 | }; |
| 223 | + | |
| 224 | + const handleCreateUUID = () => { | |
| 225 | + setFieldsValue({ clientId: buildUUID() }); | |
| 226 | + }; | |
| 211 | 227 | return { |
| 212 | 228 | registerModal, |
| 213 | 229 | registerForm, |
| 214 | 230 | checkedChange, |
| 215 | 231 | handleCancel, |
| 216 | 232 | handleOk, |
| 233 | + handleCreateUUID, | |
| 217 | 234 | }; |
| 218 | 235 | }, |
| 219 | 236 | }); | ... | ... |
| ... | ... | @@ -27,6 +27,7 @@ |
| 27 | 27 | import { useDrawer } from '/@/components/Drawer'; |
| 28 | 28 | import productDefault from '/@/assets/icons/product-default.svg'; |
| 29 | 29 | import { usePermission } from '/@/hooks/web/usePermission'; |
| 30 | + import { useRoute } from 'vue-router'; | |
| 30 | 31 | |
| 31 | 32 | defineProps<{ |
| 32 | 33 | mode: EnumTableCardMode; |
| ... | ... | @@ -43,7 +44,7 @@ |
| 43 | 44 | const { createMessage } = useMessage(); |
| 44 | 45 | const { createSyncConfirm } = useSyncConfirm(); |
| 45 | 46 | |
| 46 | - const [register, { getFieldsValue }] = useForm({ | |
| 47 | + const [register, { getFieldsValue, setFieldsValue }] = useForm({ | |
| 47 | 48 | showAdvancedButton: true, |
| 48 | 49 | labelWidth: 100, |
| 49 | 50 | compact: true, |
| ... | ... | @@ -83,14 +84,18 @@ |
| 83 | 84 | .map((item) => item.id); |
| 84 | 85 | }); |
| 85 | 86 | |
| 86 | - const getDataSource = async () => { | |
| 87 | + const getDataSource = async (otherParams: Recordable = {}) => { | |
| 87 | 88 | try { |
| 88 | 89 | loading.value = true; |
| 90 | + if (otherParams) { | |
| 91 | + setFieldsValue(otherParams); | |
| 92 | + } | |
| 89 | 93 | const params = getFieldsValue(); |
| 90 | 94 | const { items, total } = await deviceConfigGetQuery({ |
| 91 | 95 | page: pagination.current, |
| 92 | 96 | pageSize: unref(colNumber) * 2, |
| 93 | 97 | ...params, |
| 98 | + ...otherParams, | |
| 94 | 99 | }); |
| 95 | 100 | pagination.total = total; |
| 96 | 101 | dataSource.value = items.map((item) => ({ ...item, checked: false })); |
| ... | ... | @@ -192,9 +197,9 @@ |
| 192 | 197 | throw error; |
| 193 | 198 | } |
| 194 | 199 | }; |
| 195 | - | |
| 200 | + const { query: routeParams } = useRoute(); | |
| 196 | 201 | onMounted(() => { |
| 197 | - getDataSource(); | |
| 202 | + getDataSource(routeParams); | |
| 198 | 203 | }); |
| 199 | 204 | </script> |
| 200 | 205 | |
| ... | ... | @@ -255,7 +260,7 @@ |
| 255 | 260 | <Image |
| 256 | 261 | @click.stop |
| 257 | 262 | :height="144" |
| 258 | - :src="item.image" | |
| 263 | + :src="item.image || IMAGE_FALLBACK" | |
| 259 | 264 | placeholder |
| 260 | 265 | :fallback="IMAGE_FALLBACK" |
| 261 | 266 | /> | ... | ... |
| ... | ... | @@ -3,14 +3,13 @@ |
| 3 | 3 | <Tabs v-model:activeKey="activeKey" @change="handlePanelChange"> |
| 4 | 4 | <Tabs.TabPane key="product" tab="产品"> |
| 5 | 5 | <div class="relative"> |
| 6 | - <DeviceConfigurationStep :ifShowBtn="false" ref="DevConStRef" /> | |
| 7 | - <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> | |
| 6 | + <ProductDescription ref="DevConStRef" :record="record" /> | |
| 8 | 7 | </div> |
| 9 | 8 | </Tabs.TabPane> |
| 10 | 9 | <Tabs.TabPane key="transport" tab="传输配置"> |
| 11 | - <div class="relative"> | |
| 12 | - <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" /> | |
| 13 | - <div class="absolute w-full h-full top-0 cursor-not-allowed"></div> | |
| 10 | + <div> | |
| 11 | + <TransportDescription :record="record" /> | |
| 12 | + <!-- <TransportConfigurationStep :ifShowBtn="false" ref="TransConStRef" /> --> | |
| 14 | 13 | </div> |
| 15 | 14 | </Tabs.TabPane> |
| 16 | 15 | <Tabs.TabPane key="topic" tab="Topic"> |
| ... | ... | @@ -25,13 +24,14 @@ |
| 25 | 24 | <script lang="ts" setup> |
| 26 | 25 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| 27 | 26 | import { Tabs } from 'ant-design-vue'; |
| 28 | - import DeviceConfigurationStep from './step/DeviceConfigurationStep.vue'; | |
| 29 | 27 | import TransportConfigurationStep from './step/TransportConfigurationStep.vue'; |
| 30 | 28 | import PhysicalModelManagementStep from './step/PhysicalModelManagementStep.vue'; |
| 31 | 29 | import { nextTick, ref, unref } from 'vue'; |
| 32 | 30 | import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; |
| 33 | 31 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 34 | 32 | import TopicPanel from './step/TopicPanel.vue'; |
| 33 | + import ProductDescription from './components/ProductDescription.vue'; | |
| 34 | + import { TransportDescription } from './components/TransportDescript'; | |
| 35 | 35 | |
| 36 | 36 | defineEmits(['register']); |
| 37 | 37 | |
| ... | ... | @@ -41,12 +41,11 @@ |
| 41 | 41 | |
| 42 | 42 | const record = ref<DeviceRecord>({} as unknown as DeviceRecord); |
| 43 | 43 | |
| 44 | - const DevConStRef = ref<InstanceType<typeof DeviceConfigurationStep>>(); | |
| 44 | + const DevConStRef = ref<InstanceType<typeof ProductDescription>>(); | |
| 45 | 45 | const TransConStRef = ref<InstanceType<typeof TransportConfigurationStep>>(); |
| 46 | - // const PhysicalModManRef = ref<InstanceType<typeof PhysicalModelManagementStep>>(); | |
| 47 | 46 | |
| 48 | - const setDeviceConfFormData = async (res: Recordable) => { | |
| 49 | - unref(DevConStRef)?.setFormData(res); | |
| 47 | + const setDeviceConfFormData = async () => { | |
| 48 | + unref(DevConStRef)?.renderProductInfo(); | |
| 50 | 49 | }; |
| 51 | 50 | const setTransConfFormData = async (res: Recordable) => { |
| 52 | 51 | await nextTick(); |
| ... | ... | @@ -57,7 +56,7 @@ |
| 57 | 56 | activeKey.value = 'product'; |
| 58 | 57 | record.value = data.record; |
| 59 | 58 | record.value = await deviceConfigGetDetail(data.record.id); |
| 60 | - setDeviceConfFormData(unref(record)); | |
| 59 | + setDeviceConfFormData(); | |
| 61 | 60 | }); |
| 62 | 61 | |
| 63 | 62 | const handlePanelChange = (activeKey: ActiveKey) => { | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { Spin, Image } from 'ant-design-vue'; | |
| 3 | + import { ref, unref, h } from 'vue'; | |
| 4 | + import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; | |
| 5 | + import { RuleChainRecord } from '/@/api/device/model/deviceConfigModel'; | |
| 6 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 7 | + import { findDictItemByCode } from '/@/api/system/dict'; | |
| 8 | + import { SysDictItemResult } from '/@/api/system/model/dictModel'; | |
| 9 | + import { Description, useDescription } from '/@/components/Description'; | |
| 10 | + import { to } from '/@/utils/to'; | |
| 11 | + import productDefaultImage from '/@/assets/icons/product-default.svg'; | |
| 12 | + | |
| 13 | + const loading = ref(false); | |
| 14 | + | |
| 15 | + const props = defineProps<{ | |
| 16 | + record: DeviceRecord; | |
| 17 | + }>(); | |
| 18 | + | |
| 19 | + const data = ref<DeviceRecord>({} as unknown as DeviceRecord); | |
| 20 | + | |
| 21 | + const [register, { setDescProps }] = useDescription({ | |
| 22 | + layout: 'vertical', | |
| 23 | + column: 2, | |
| 24 | + schema: [ | |
| 25 | + { | |
| 26 | + field: 'image', | |
| 27 | + label: '图片', | |
| 28 | + span: 2, | |
| 29 | + render: (val) => { | |
| 30 | + return h(Image, { src: val || productDefaultImage, height: 200 }); | |
| 31 | + }, | |
| 32 | + }, | |
| 33 | + { | |
| 34 | + field: 'deviceType', | |
| 35 | + label: '设备类型', | |
| 36 | + }, | |
| 37 | + { | |
| 38 | + field: 'name', | |
| 39 | + label: '产品名称', | |
| 40 | + }, | |
| 41 | + { | |
| 42 | + field: 'ruleChain', | |
| 43 | + label: '规则链', | |
| 44 | + }, | |
| 45 | + { | |
| 46 | + field: 'queueName', | |
| 47 | + label: '处理队列', | |
| 48 | + }, | |
| 49 | + { | |
| 50 | + field: 'description', | |
| 51 | + label: '描述', | |
| 52 | + render(val) { | |
| 53 | + return h('div', { class: 'min-h-6' }, val); | |
| 54 | + }, | |
| 55 | + }, | |
| 56 | + ], | |
| 57 | + }); | |
| 58 | + | |
| 59 | + const findDeviceType = async (deviceType: string) => { | |
| 60 | + const [error, data] = await to<SysDictItemResult[]>( | |
| 61 | + findDictItemByCode({ dictCode: 'device_type' }) | |
| 62 | + ); | |
| 63 | + if (!error) { | |
| 64 | + const record = data.find((item) => item.itemValue === deviceType); | |
| 65 | + return { deviceType: record?.itemText }; | |
| 66 | + } | |
| 67 | + return {}; | |
| 68 | + }; | |
| 69 | + | |
| 70 | + const findHandleQueue = async (defaultQueueName: string) => { | |
| 71 | + const [error, data] = await to<SysDictItemResult[]>( | |
| 72 | + findDictItemByCode({ dictCode: 'queen_execute_sequence' }) | |
| 73 | + ); | |
| 74 | + if (!error) { | |
| 75 | + const record = data.find((item) => item.itemValue === defaultQueueName); | |
| 76 | + return { queueName: record?.itemText }; | |
| 77 | + } | |
| 78 | + return {}; | |
| 79 | + }; | |
| 80 | + | |
| 81 | + const findRuleChain = async (ruleChain: string) => { | |
| 82 | + const [error, data] = await to<RuleChainRecord[]>(deviceConfigGetRuleChain()); | |
| 83 | + if (!error) { | |
| 84 | + const record = data.find((item) => item.id.id === ruleChain); | |
| 85 | + return { ruleChain: record?.name }; | |
| 86 | + } | |
| 87 | + return {}; | |
| 88 | + }; | |
| 89 | + | |
| 90 | + const renderProductInfo = async () => { | |
| 91 | + try { | |
| 92 | + data.value = {} as unknown as DeviceRecord; | |
| 93 | + loading.value = true; | |
| 94 | + const { defaultRuleChainId, deviceType, defaultQueueName } = props.record; | |
| 95 | + data.value = props.record; | |
| 96 | + const values = await Promise.all([ | |
| 97 | + findDeviceType(deviceType), | |
| 98 | + findHandleQueue(defaultQueueName), | |
| 99 | + findRuleChain(defaultRuleChainId), | |
| 100 | + ]); | |
| 101 | + const value = values.reduce((prev, next) => ({ ...prev, ...next }), {}); | |
| 102 | + data.value = Object.assign(unref(data), value); | |
| 103 | + setDescProps({ data: unref(data) }); | |
| 104 | + } catch (error) { | |
| 105 | + throw error; | |
| 106 | + } finally { | |
| 107 | + loading.value = false; | |
| 108 | + } | |
| 109 | + }; | |
| 110 | + | |
| 111 | + defineExpose({ | |
| 112 | + renderProductInfo, | |
| 113 | + }); | |
| 114 | +</script> | |
| 115 | + | |
| 116 | +<template> | |
| 117 | + <Spin :spinning="loading"> | |
| 118 | + <Description class="product-description" @register="register" /> | |
| 119 | + </Spin> | |
| 120 | +</template> | |
| 121 | + | |
| 122 | +<style lang="less" scoped> | |
| 123 | + .product-description:deep(.ant-image-img) { | |
| 124 | + height: 200px !important; | |
| 125 | + } | |
| 126 | +</style> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 3 | + import { useDescription, Description } from '/@/components/Description'; | |
| 4 | + import { Input } from 'ant-design-vue'; | |
| 5 | + import { h } from 'vue'; | |
| 6 | + import { | |
| 7 | + COAPDeviceTypeEnum, | |
| 8 | + PowerModeEnum, | |
| 9 | + PowerModeNameEnum, | |
| 10 | + TransportPayloadTypeEnum, | |
| 11 | + } from './const'; | |
| 12 | + | |
| 13 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
| 14 | + const props = defineProps<{ | |
| 15 | + record: TransportConfiguration; | |
| 16 | + }>(); | |
| 17 | + | |
| 18 | + const showProtoSchema = (data: TransportConfiguration) => { | |
| 19 | + return ( | |
| 20 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType === | |
| 21 | + TransportPayloadTypeEnum.PROTOBUF && | |
| 22 | + data.coapDeviceTypeConfiguration.coapDeviceType === COAPDeviceTypeEnum.DEFAULT | |
| 23 | + ); | |
| 24 | + }; | |
| 25 | + | |
| 26 | + const showPowerModeIsPSM = (data: TransportConfiguration) => { | |
| 27 | + return data.clientSettings.powerMode === PowerModeNameEnum.PSM; | |
| 28 | + }; | |
| 29 | + | |
| 30 | + const showPowerModeIsEDRX = (data: TransportConfiguration) => { | |
| 31 | + return data.clientSettings.powerMode === PowerModeEnum.E_DRX; | |
| 32 | + }; | |
| 33 | + | |
| 34 | + const [register] = useDescription({ | |
| 35 | + layout: 'vertical', | |
| 36 | + column: 2, | |
| 37 | + data: props.record, | |
| 38 | + schema: [ | |
| 39 | + { | |
| 40 | + field: 'type', | |
| 41 | + label: '接入协议', | |
| 42 | + }, | |
| 43 | + { | |
| 44 | + field: 'coapDeviceType', | |
| 45 | + label: 'COAP设备类型', | |
| 46 | + render: (_, data: TransportConfiguration) => | |
| 47 | + data.coapDeviceTypeConfiguration.coapDeviceType, | |
| 48 | + }, | |
| 49 | + { | |
| 50 | + field: 'coapDeviceType', | |
| 51 | + label: 'COAP设备消息Payload', | |
| 52 | + render: (_, data: TransportConfiguration) => | |
| 53 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration.transportPayloadType, | |
| 54 | + }, | |
| 55 | + { | |
| 56 | + field: 'powerMode', | |
| 57 | + label: '节能模式', | |
| 58 | + render: (_, data: TransportConfiguration) => | |
| 59 | + PowerModeNameEnum[data.clientSettings.powerMode], | |
| 60 | + }, | |
| 61 | + { | |
| 62 | + field: 'psmActivityTimer', | |
| 63 | + label: 'PSM活动计时器', | |
| 64 | + show: showPowerModeIsPSM, | |
| 65 | + render: (_, data: TransportConfiguration) => data.clientSettings.psmActivityTimer, | |
| 66 | + }, | |
| 67 | + { | |
| 68 | + field: 'edrxCycle', | |
| 69 | + label: 'eDRX循环', | |
| 70 | + show: showPowerModeIsEDRX, | |
| 71 | + render: (_, data: TransportConfiguration) => data.clientSettings.edrxCycle, | |
| 72 | + }, | |
| 73 | + { | |
| 74 | + field: 'edrxCycleTime', | |
| 75 | + label: 'eDRX循环时间单位', | |
| 76 | + show: showPowerModeIsEDRX, | |
| 77 | + render: () => '秒', | |
| 78 | + }, | |
| 79 | + { | |
| 80 | + field: 'pagingTransmissionWindow', | |
| 81 | + label: '寻呼传输窗口', | |
| 82 | + show: showPowerModeIsEDRX, | |
| 83 | + render: (_, data: TransportConfiguration) => data.clientSettings.pagingTransmissionWindow, | |
| 84 | + }, | |
| 85 | + { | |
| 86 | + field: 'pagingTransmissionWindowTime', | |
| 87 | + label: '寻呼传输窗口时间单位', | |
| 88 | + show: showPowerModeIsEDRX, | |
| 89 | + render: () => '秒', | |
| 90 | + }, | |
| 91 | + { | |
| 92 | + field: 'unit', | |
| 93 | + label: '时间单位', | |
| 94 | + show: showPowerModeIsPSM, | |
| 95 | + render: () => '秒', | |
| 96 | + }, | |
| 97 | + { | |
| 98 | + field: 'deviceTelemetryProtoSchema', | |
| 99 | + label: '遥测数据 proto schema', | |
| 100 | + span: 2, | |
| 101 | + show: showProtoSchema, | |
| 102 | + render(_, data: TransportConfiguration) { | |
| 103 | + return h(Input.TextArea, { | |
| 104 | + autoSize: true, | |
| 105 | + value: | |
| 106 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
| 107 | + .deviceTelemetryProtoSchema, | |
| 108 | + }); | |
| 109 | + }, | |
| 110 | + }, | |
| 111 | + { | |
| 112 | + field: 'deviceAttributesProtoSchema', | |
| 113 | + label: 'Attributes proto schema', | |
| 114 | + span: 2, | |
| 115 | + show: showProtoSchema, | |
| 116 | + render(_, data: TransportConfiguration) { | |
| 117 | + return h(Input.TextArea, { | |
| 118 | + autoSize: true, | |
| 119 | + value: | |
| 120 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
| 121 | + .deviceAttributesProtoSchema, | |
| 122 | + }); | |
| 123 | + }, | |
| 124 | + }, | |
| 125 | + { | |
| 126 | + field: 'deviceRpcRequestProtoSchema', | |
| 127 | + label: 'RPC 请求 proto schema', | |
| 128 | + span: 2, | |
| 129 | + show: showProtoSchema, | |
| 130 | + render(_, data: TransportConfiguration) { | |
| 131 | + return h(Input.TextArea, { | |
| 132 | + autoSize: true, | |
| 133 | + value: | |
| 134 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
| 135 | + .deviceRpcRequestProtoSchema, | |
| 136 | + }); | |
| 137 | + }, | |
| 138 | + }, | |
| 139 | + { | |
| 140 | + field: 'deviceRpcResponseProtoSchema', | |
| 141 | + label: 'RPC 响应 proto schema', | |
| 142 | + span: 2, | |
| 143 | + show: showProtoSchema, | |
| 144 | + render(_, data: TransportConfiguration) { | |
| 145 | + return h(Input.TextArea, { | |
| 146 | + autoSize: true, | |
| 147 | + value: | |
| 148 | + data.coapDeviceTypeConfiguration.transportPayloadTypeConfiguration | |
| 149 | + .deviceRpcResponseProtoSchema, | |
| 150 | + }); | |
| 151 | + }, | |
| 152 | + }, | |
| 153 | + ], | |
| 154 | + }); | |
| 155 | +</script> | |
| 156 | + | |
| 157 | +<template> | |
| 158 | + <Description @register="register" /> | |
| 159 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 3 | + import { useDescription, Description } from '/@/components/Description'; | |
| 4 | + | |
| 5 | + const props = defineProps<{ | |
| 6 | + record: DeviceRecord['profileData']['transportConfiguration']; | |
| 7 | + }>(); | |
| 8 | + | |
| 9 | + const [register] = useDescription({ | |
| 10 | + layout: 'vertical', | |
| 11 | + column: 2, | |
| 12 | + schema: [ | |
| 13 | + { | |
| 14 | + field: 'type', | |
| 15 | + label: '接入协议', | |
| 16 | + }, | |
| 17 | + ], | |
| 18 | + data: props.record, | |
| 19 | + }); | |
| 20 | +</script> | |
| 21 | + | |
| 22 | +<template> | |
| 23 | + <Description @register="register" /> | |
| 24 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { Input, Tabs } from 'ant-design-vue'; | |
| 3 | + import { computed, h, unref } from 'vue'; | |
| 4 | + import { | |
| 5 | + BindingNameEnum, | |
| 6 | + FirmwareUpdateStrategyNameEnum, | |
| 7 | + PowerModeNameEnum, | |
| 8 | + SecurityModeNameEnum, | |
| 9 | + } from './const'; | |
| 10 | + import { Bootstrap, ClientSettings, DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 11 | + import { CollapseContainer } from '/@/components/Container'; | |
| 12 | + import { useDescription, Description, DescItem } from '/@/components/Description'; | |
| 13 | + | |
| 14 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
| 15 | + const props = defineProps<{ | |
| 16 | + record: TransportConfiguration; | |
| 17 | + }>(); | |
| 18 | + | |
| 19 | + enum TabKeyEnum { | |
| 20 | + LWM2M_MODEL = 'LWM2M Model', | |
| 21 | + BOOTSTRAP = 'Bootstrap', | |
| 22 | + OTHER_SETTINGS = 'Other settings', | |
| 23 | + JSON_CONFIG_PROFILE_DEVICE = 'JSON Config Profile Device', | |
| 24 | + } | |
| 25 | + | |
| 26 | + const getBootstrapSetting = computed(() => { | |
| 27 | + const { record } = props; | |
| 28 | + return record.bootstrap; | |
| 29 | + }); | |
| 30 | + | |
| 31 | + const getOtherSetting = computed(() => { | |
| 32 | + const { record } = props; | |
| 33 | + return record.clientLwM2mSettings; | |
| 34 | + }); | |
| 35 | + | |
| 36 | + const [registerLWM2MModel] = useDescription({ | |
| 37 | + layout: 'vertical', | |
| 38 | + column: 2, | |
| 39 | + data: {}, | |
| 40 | + schema: [ | |
| 41 | + { | |
| 42 | + field: 'objectList', | |
| 43 | + label: '对象列表', | |
| 44 | + render: () => h('div', { class: 'min-h-6' }), | |
| 45 | + }, | |
| 46 | + ], | |
| 47 | + }); | |
| 48 | + | |
| 49 | + const getCollapseTitle = (item: Bootstrap) => { | |
| 50 | + return `LwM2M Server Short server ID: ${item.shortServerId} Security config mode: ${item.securityMode}`; | |
| 51 | + }; | |
| 52 | + | |
| 53 | + const bootstrapDescriptionSchema: DescItem[] = [ | |
| 54 | + { | |
| 55 | + label: '安全配置', | |
| 56 | + field: 'securityMode', | |
| 57 | + render: (_, data: Bootstrap) => SecurityModeNameEnum[data.securityMode], | |
| 58 | + }, | |
| 59 | + { | |
| 60 | + label: '短服务器ID', | |
| 61 | + field: 'shortServerId', | |
| 62 | + }, | |
| 63 | + { | |
| 64 | + label: '主机', | |
| 65 | + field: 'host', | |
| 66 | + }, | |
| 67 | + { | |
| 68 | + label: '端口', | |
| 69 | + field: 'port', | |
| 70 | + }, | |
| 71 | + { | |
| 72 | + label: '延迟时间', | |
| 73 | + field: 'clientHoldOffTime', | |
| 74 | + }, | |
| 75 | + { | |
| 76 | + label: '超时后的账户', | |
| 77 | + field: 'bootstrapServerAccountTimeout', | |
| 78 | + }, | |
| 79 | + { | |
| 80 | + label: '注册生存期', | |
| 81 | + field: 'lifetime', | |
| 82 | + }, | |
| 83 | + { | |
| 84 | + label: '两次通知之间的最小周期', | |
| 85 | + field: 'defaultMinPeriod', | |
| 86 | + }, | |
| 87 | + { | |
| 88 | + label: 'Binding', | |
| 89 | + field: 'binding', | |
| 90 | + span: 2, | |
| 91 | + render: (_, data: Bootstrap) => BindingNameEnum[data.binding], | |
| 92 | + }, | |
| 93 | + { | |
| 94 | + label: '禁用或脱机时的通知存储', | |
| 95 | + field: 'notifIfDisabled', | |
| 96 | + render: (_, data: Bootstrap) => (data.notifIfDisabled ? '启用' : '禁用'), | |
| 97 | + }, | |
| 98 | + ]; | |
| 99 | + console.log(unref(getOtherSetting)); | |
| 100 | + const [registerOtherSettings] = useDescription({ | |
| 101 | + layout: 'vertical', | |
| 102 | + column: 2, | |
| 103 | + data: unref(getOtherSetting), | |
| 104 | + schema: [ | |
| 105 | + { | |
| 106 | + label: '固件更新策略', | |
| 107 | + field: 'fwUpdateStrategy', | |
| 108 | + span: 2, | |
| 109 | + render: (_, data: ClientSettings) => FirmwareUpdateStrategyNameEnum[data.fwUpdateStrategy], | |
| 110 | + }, | |
| 111 | + { | |
| 112 | + label: '固件更新COAP资源', | |
| 113 | + field: 'fwUpdateResource', | |
| 114 | + span: 2, | |
| 115 | + }, | |
| 116 | + { | |
| 117 | + label: '软件更新策略', | |
| 118 | + field: 'swUpdateStrategy', | |
| 119 | + span: 2, | |
| 120 | + render: (_, data: ClientSettings) => FirmwareUpdateStrategyNameEnum[data.swUpdateStrategy], | |
| 121 | + }, | |
| 122 | + { | |
| 123 | + label: '软件更新COAP资源', | |
| 124 | + field: 'swUpdateResource', | |
| 125 | + span: 2, | |
| 126 | + }, | |
| 127 | + { | |
| 128 | + label: '节能模式', | |
| 129 | + field: 'powerMode', | |
| 130 | + render: (_, data: ClientSettings) => PowerModeNameEnum[data.powerMode], | |
| 131 | + }, | |
| 132 | + { | |
| 133 | + label: 'PSM活动计时器', | |
| 134 | + field: 'edrxCycle', | |
| 135 | + }, | |
| 136 | + { | |
| 137 | + label: 'PSM活动计时器单位', | |
| 138 | + field: 'edrxCycleTimeUnit', | |
| 139 | + render: () => '秒', | |
| 140 | + }, | |
| 141 | + { | |
| 142 | + label: '支持复合读/写观察操作', | |
| 143 | + field: '', | |
| 144 | + render: () => '禁用', | |
| 145 | + }, | |
| 146 | + ], | |
| 147 | + }); | |
| 148 | + | |
| 149 | + const [registerJSONConfig] = useDescription({ | |
| 150 | + layout: 'vertical', | |
| 151 | + column: 2, | |
| 152 | + data: props.record, | |
| 153 | + schema: [ | |
| 154 | + { | |
| 155 | + field: 'json', | |
| 156 | + label: 'LWM2M', | |
| 157 | + render: (_, data: TransportConfiguration) => { | |
| 158 | + return h(Input.TextArea, { value: JSON.stringify(data, null, 2), autoSize: true }); | |
| 159 | + }, | |
| 160 | + }, | |
| 161 | + ], | |
| 162 | + }); | |
| 163 | +</script> | |
| 164 | + | |
| 165 | +<template> | |
| 166 | + <Tabs> | |
| 167 | + <Tabs.TabPane :tab="TabKeyEnum.LWM2M_MODEL" :key="TabKeyEnum.LWM2M_MODEL"> | |
| 168 | + <Description @register="registerLWM2MModel" /> | |
| 169 | + </Tabs.TabPane> | |
| 170 | + <Tabs.TabPane :tab="TabKeyEnum.BOOTSTRAP" :key="TabKeyEnum.BOOTSTRAP"> | |
| 171 | + <CollapseContainer | |
| 172 | + v-for="(item, index) in getBootstrapSetting" | |
| 173 | + :key="index" | |
| 174 | + :title="getCollapseTitle(item)" | |
| 175 | + class="mt-4" | |
| 176 | + > | |
| 177 | + <Description | |
| 178 | + layout="vertical" | |
| 179 | + :column="2" | |
| 180 | + :schema="bootstrapDescriptionSchema" | |
| 181 | + :data="item" | |
| 182 | + /> | |
| 183 | + </CollapseContainer> | |
| 184 | + </Tabs.TabPane> | |
| 185 | + <Tabs.TabPane :tab="TabKeyEnum.OTHER_SETTINGS" :key="TabKeyEnum.OTHER_SETTINGS"> | |
| 186 | + <Description @register="registerOtherSettings" /> | |
| 187 | + </Tabs.TabPane> | |
| 188 | + <Tabs.TabPane | |
| 189 | + :tab="TabKeyEnum.JSON_CONFIG_PROFILE_DEVICE" | |
| 190 | + :key="TabKeyEnum.JSON_CONFIG_PROFILE_DEVICE" | |
| 191 | + > | |
| 192 | + <Description @register="registerJSONConfig" /> | |
| 193 | + </Tabs.TabPane> | |
| 194 | + </Tabs> | |
| 195 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 3 | + import { useDescription, Description } from '/@/components/Description'; | |
| 4 | + import { Input } from 'ant-design-vue'; | |
| 5 | + import { h } from 'vue'; | |
| 6 | + import { TransportPayloadTypeEnum } from './const'; | |
| 7 | + | |
| 8 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
| 9 | + const props = defineProps<{ | |
| 10 | + record: TransportConfiguration; | |
| 11 | + }>(); | |
| 12 | + | |
| 13 | + const [register] = useDescription({ | |
| 14 | + layout: 'vertical', | |
| 15 | + column: 2, | |
| 16 | + data: props.record, | |
| 17 | + schema: [ | |
| 18 | + { | |
| 19 | + field: 'type', | |
| 20 | + label: '接入协议', | |
| 21 | + span: 2, | |
| 22 | + }, | |
| 23 | + { | |
| 24 | + field: 'deviceTelemetryTopic', | |
| 25 | + label: '遥测数据主题筛选器', | |
| 26 | + }, | |
| 27 | + { | |
| 28 | + field: 'deviceAttributesTopic', | |
| 29 | + label: '属性主题过滤器', | |
| 30 | + }, | |
| 31 | + { | |
| 32 | + field: 'transportPayloadType', | |
| 33 | + label: 'MQTT设备Payload', | |
| 34 | + render(_, data: TransportConfiguration) { | |
| 35 | + return data.transportPayloadTypeConfiguration.transportPayloadType; | |
| 36 | + }, | |
| 37 | + }, | |
| 38 | + { | |
| 39 | + field: 'enableCompatibilityWithJsonPayloadFormat', | |
| 40 | + label: '启用与其他有效负载格式的兼容性', | |
| 41 | + render(_, data: TransportConfiguration) { | |
| 42 | + return data.transportPayloadTypeConfiguration.enableCompatibilityWithJsonPayloadFormat | |
| 43 | + ? '启用' | |
| 44 | + : '关闭'; | |
| 45 | + }, | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + field: 'deviceTelemetryProtoSchema', | |
| 49 | + label: '遥测数据 proto schema', | |
| 50 | + span: 2, | |
| 51 | + show: (data: TransportConfiguration) => | |
| 52 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
| 53 | + TransportPayloadTypeEnum.PROTOBUF, | |
| 54 | + render(_, data: TransportConfiguration) { | |
| 55 | + return h(Input.TextArea, { | |
| 56 | + autoSize: true, | |
| 57 | + value: data.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema, | |
| 58 | + }); | |
| 59 | + }, | |
| 60 | + }, | |
| 61 | + { | |
| 62 | + field: 'deviceAttributesProtoSchema', | |
| 63 | + label: 'Attributes proto schema', | |
| 64 | + span: 2, | |
| 65 | + show: (data: TransportConfiguration) => | |
| 66 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
| 67 | + TransportPayloadTypeEnum.PROTOBUF, | |
| 68 | + render(_, data: TransportConfiguration) { | |
| 69 | + return h(Input.TextArea, { | |
| 70 | + autoSize: true, | |
| 71 | + value: data.transportPayloadTypeConfiguration.deviceAttributesProtoSchema, | |
| 72 | + }); | |
| 73 | + }, | |
| 74 | + }, | |
| 75 | + { | |
| 76 | + field: 'deviceRpcRequestProtoSchema', | |
| 77 | + label: 'RPC 请求 proto schema', | |
| 78 | + span: 2, | |
| 79 | + show: (data: TransportConfiguration) => | |
| 80 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
| 81 | + TransportPayloadTypeEnum.PROTOBUF, | |
| 82 | + render(_, data: TransportConfiguration) { | |
| 83 | + return h(Input.TextArea, { | |
| 84 | + autoSize: true, | |
| 85 | + value: data.transportPayloadTypeConfiguration.deviceRpcRequestProtoSchema, | |
| 86 | + }); | |
| 87 | + }, | |
| 88 | + }, | |
| 89 | + { | |
| 90 | + field: 'deviceRpcResponseProtoSchema', | |
| 91 | + label: 'RPC 响应 proto schema', | |
| 92 | + span: 2, | |
| 93 | + show: (data: TransportConfiguration) => | |
| 94 | + data.transportPayloadTypeConfiguration.transportPayloadType === | |
| 95 | + TransportPayloadTypeEnum.PROTOBUF, | |
| 96 | + render(_, data: TransportConfiguration) { | |
| 97 | + return h(Input.TextArea, { | |
| 98 | + autoSize: true, | |
| 99 | + value: data.transportPayloadTypeConfiguration.deviceRpcResponseProtoSchema, | |
| 100 | + }); | |
| 101 | + }, | |
| 102 | + }, | |
| 103 | + ], | |
| 104 | + }); | |
| 105 | +</script> | |
| 106 | + | |
| 107 | +<template> | |
| 108 | + <Description @register="register" /> | |
| 109 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { Table } from 'ant-design-vue'; | |
| 3 | + import { computed, h } from 'vue'; | |
| 4 | + import { SNMPDataTypeEnum, SNMPRangeNameEnum } from './const'; | |
| 5 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 6 | + import { CollapseContainer } from '/@/components/Container'; | |
| 7 | + import { DescItem, Description, useDescription } from '/@/components/Description'; | |
| 8 | + | |
| 9 | + type TransportConfiguration = DeviceRecord['profileData']['transportConfiguration']; | |
| 10 | + | |
| 11 | + const props = defineProps<{ | |
| 12 | + record: TransportConfiguration; | |
| 13 | + }>(); | |
| 14 | + | |
| 15 | + const getSNMPList = computed(() => { | |
| 16 | + const { record } = props; | |
| 17 | + return record.communicationConfigs; | |
| 18 | + }); | |
| 19 | + | |
| 20 | + const [register] = useDescription({ | |
| 21 | + layout: 'vertical', | |
| 22 | + column: 2, | |
| 23 | + data: props.record, | |
| 24 | + schema: [ | |
| 25 | + { | |
| 26 | + label: '接入协议', | |
| 27 | + field: 'type', | |
| 28 | + span: 2, | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + label: '超时毫秒', | |
| 32 | + field: 'timeoutMs', | |
| 33 | + }, | |
| 34 | + { | |
| 35 | + label: '重试次数', | |
| 36 | + field: 'retries', | |
| 37 | + }, | |
| 38 | + ], | |
| 39 | + }); | |
| 40 | + | |
| 41 | + const schema: DescItem[] = [ | |
| 42 | + { | |
| 43 | + label: '范围', | |
| 44 | + field: 'spec', | |
| 45 | + render: (val: string) => getTitle(val), | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + label: '查询频率(毫秒)', | |
| 49 | + field: 'queryingFrequencyMs', | |
| 50 | + }, | |
| 51 | + { | |
| 52 | + label: 'Mapping', | |
| 53 | + field: 'mappings', | |
| 54 | + render: (val) => { | |
| 55 | + return h(Table, { | |
| 56 | + size: 'small', | |
| 57 | + bordered: true, | |
| 58 | + pagination: false, | |
| 59 | + columns: [ | |
| 60 | + { | |
| 61 | + title: '数据类型', | |
| 62 | + dataIndex: 'dataType', | |
| 63 | + customRender: ({ text }) => SNMPDataTypeEnum[text], | |
| 64 | + }, | |
| 65 | + { | |
| 66 | + title: 'DataKey', | |
| 67 | + dataIndex: 'key', | |
| 68 | + }, | |
| 69 | + { | |
| 70 | + title: 'OID', | |
| 71 | + dataIndex: 'oid', | |
| 72 | + }, | |
| 73 | + ], | |
| 74 | + dataSource: val, | |
| 75 | + }); | |
| 76 | + }, | |
| 77 | + }, | |
| 78 | + ]; | |
| 79 | + | |
| 80 | + const getTitle = (range: string) => { | |
| 81 | + return SNMPRangeNameEnum[range]; | |
| 82 | + }; | |
| 83 | +</script> | |
| 84 | + | |
| 85 | +<template> | |
| 86 | + <Description @register="register" /> | |
| 87 | + <CollapseContainer | |
| 88 | + v-for="(item, index) in getSNMPList" | |
| 89 | + :key="index" | |
| 90 | + class="mt-4" | |
| 91 | + :title="getTitle(item.spec)" | |
| 92 | + > | |
| 93 | + <Description :data="item" layout="vertical" :column="2" :schema="schema" /> | |
| 94 | + </CollapseContainer> | |
| 95 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { Button, Tag } from 'ant-design-vue'; | |
| 3 | + import { h, onMounted, ref, unref } from 'vue'; | |
| 4 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 5 | + import { ScriptRecord } from '/@/api/scriptmanage/model/scriptModel'; | |
| 6 | + import { getScriptManageMeList } from '/@/api/scriptmanage/scriptManager'; | |
| 7 | + import { Description, useDescription } from '/@/components/Description'; | |
| 8 | + import { useModal } from '/@/components/Modal'; | |
| 9 | + import CoverScriptModal from '/@/views/scriptmanage/converscript/ConverScriptModal.vue'; | |
| 10 | + | |
| 11 | + const props = defineProps<{ | |
| 12 | + record: DeviceRecord['profileData']['transportConfiguration']; | |
| 13 | + }>(); | |
| 14 | + | |
| 15 | + const scriptInfo = ref<ScriptRecord>({} as unknown as ScriptRecord); | |
| 16 | + | |
| 17 | + const [register, { setDescProps }] = useDescription({ | |
| 18 | + layout: 'vertical', | |
| 19 | + column: 2, | |
| 20 | + data: props.record, | |
| 21 | + schema: [ | |
| 22 | + { | |
| 23 | + field: 'type', | |
| 24 | + label: '接入协议', | |
| 25 | + span: 2, | |
| 26 | + }, | |
| 27 | + { | |
| 28 | + field: 'scriptName', | |
| 29 | + label: '转换脚本', | |
| 30 | + render: (value: string) => { | |
| 31 | + return h('div', [ | |
| 32 | + h(Tag, { color: 'blue' }, () => value), | |
| 33 | + h(Button, { type: 'link', onClick: handleTestScript }, () => '测试脚本'), | |
| 34 | + ]); | |
| 35 | + }, | |
| 36 | + }, | |
| 37 | + ], | |
| 38 | + }); | |
| 39 | + | |
| 40 | + const [registerModal, { openModal }] = useModal(); | |
| 41 | + | |
| 42 | + const handleTestScript = () => { | |
| 43 | + openModal(true, { | |
| 44 | + isUpdate: false, | |
| 45 | + isTest: true, | |
| 46 | + record: unref(scriptInfo).id, | |
| 47 | + isText: 'test', | |
| 48 | + isTitle: 'test', | |
| 49 | + }); | |
| 50 | + }; | |
| 51 | + | |
| 52 | + onMounted(() => { | |
| 53 | + getTransforScriptInfo(); | |
| 54 | + }); | |
| 55 | + | |
| 56 | + const getTransforScriptInfo = async () => { | |
| 57 | + try { | |
| 58 | + const list = await getScriptManageMeList(); | |
| 59 | + const record = list.find((item) => item.id === props.record.scriptId); | |
| 60 | + scriptInfo.value = record!; | |
| 61 | + setDescProps({ | |
| 62 | + data: Object.assign(props.record, record, { scriptName: record?.name || '' }), | |
| 63 | + }); | |
| 64 | + } catch (error) {} | |
| 65 | + }; | |
| 66 | +</script> | |
| 67 | + | |
| 68 | +<template> | |
| 69 | + <section> | |
| 70 | + <Description @register="register" /> | |
| 71 | + <CoverScriptModal @register="registerModal" /> | |
| 72 | + </section> | |
| 73 | +</template> | ... | ... |
| 1 | +<script lang="ts" setup> | |
| 2 | + import { computed } from 'vue'; | |
| 3 | + import COAPDescription from './COAPDescription.vue'; | |
| 4 | + import { TransportTypeEnum } from './const'; | |
| 5 | + import DefaultConfiguration from './DefaultConfiguration.vue'; | |
| 6 | + import LWM2MDescription from './LWM2MDescription.vue'; | |
| 7 | + import MQTTConfiguration from './MQTTConfiguration.vue'; | |
| 8 | + import SNMPDescription from './SNMPDescription.vue'; | |
| 9 | + import TCPDescription from './TCPDescription.vue'; | |
| 10 | + import { DeviceRecord } from '/@/api/device/model/deviceModel'; | |
| 11 | + | |
| 12 | + const props = defineProps<{ | |
| 13 | + record: DeviceRecord; | |
| 14 | + }>(); | |
| 15 | + | |
| 16 | + const getTransportInfo = computed(() => { | |
| 17 | + const { record } = props; | |
| 18 | + return record.profileData.transportConfiguration; | |
| 19 | + }); | |
| 20 | +</script> | |
| 21 | + | |
| 22 | +<template> | |
| 23 | + <section> | |
| 24 | + <DefaultConfiguration | |
| 25 | + :record="getTransportInfo" | |
| 26 | + v-if="getTransportInfo.type === TransportTypeEnum.DEFAULT" | |
| 27 | + /> | |
| 28 | + | |
| 29 | + <MQTTConfiguration | |
| 30 | + :record="getTransportInfo" | |
| 31 | + v-if="getTransportInfo.type === TransportTypeEnum.MQTT" | |
| 32 | + /> | |
| 33 | + | |
| 34 | + <COAPDescription | |
| 35 | + :record="getTransportInfo" | |
| 36 | + v-if="getTransportInfo.type === TransportTypeEnum.COAP" | |
| 37 | + /> | |
| 38 | + | |
| 39 | + <LWM2MDescription | |
| 40 | + :record="getTransportInfo" | |
| 41 | + v-if="getTransportInfo.type === TransportTypeEnum.LWM2M" | |
| 42 | + /> | |
| 43 | + | |
| 44 | + <SNMPDescription | |
| 45 | + :record="getTransportInfo" | |
| 46 | + v-if="getTransportInfo.type === TransportTypeEnum.SNMP" | |
| 47 | + /> | |
| 48 | + | |
| 49 | + <TCPDescription | |
| 50 | + :record="getTransportInfo" | |
| 51 | + v-if="getTransportInfo.type === TransportTypeEnum.TCP" | |
| 52 | + /> | |
| 53 | + </section> | |
| 54 | +</template> | ... | ... |
| 1 | +export enum TransportTypeEnum { | |
| 2 | + DEFAULT = 'DEFAULT', | |
| 3 | + MQTT = 'MQTT', | |
| 4 | + COAP = 'COAP', | |
| 5 | + LWM2M = 'LWM2M', | |
| 6 | + SNMP = 'SNMP', | |
| 7 | + TCP = 'TCP', | |
| 8 | +} | |
| 9 | + | |
| 10 | +export enum TransportPayloadTypeEnum { | |
| 11 | + PROTOBUF = 'PROTOBUF', | |
| 12 | + JSON = 'JSON', | |
| 13 | +} | |
| 14 | + | |
| 15 | +export enum COAPDeviceTypeEnum { | |
| 16 | + DEFAULT = 'DEFAULT', | |
| 17 | + EFENTO = 'EFENTO', | |
| 18 | +} | |
| 19 | + | |
| 20 | +export enum COAPDeviceTypeNameEnum { | |
| 21 | + DEFAULT = '默认', | |
| 22 | + EFENTO = 'Efento NB-IoT', | |
| 23 | +} | |
| 24 | + | |
| 25 | +export enum PowerModeEnum { | |
| 26 | + PSM = 'PSM', | |
| 27 | + DRX = 'DRX', | |
| 28 | + E_DRX = 'E_DRX', | |
| 29 | +} | |
| 30 | + | |
| 31 | +export enum PowerModeNameEnum { | |
| 32 | + PSM = 'Power Saving Mode (PSM)', | |
| 33 | + DRX = 'Discontinuous Reception (DRX)', | |
| 34 | + E_DRX = 'Extended Discontinuous Reception (eDRX)', | |
| 35 | +} | |
| 36 | + | |
| 37 | +export enum TimeUnitEnum { | |
| 38 | + MILLISECONDS = 'milliseconds', | |
| 39 | + SECOND = 'second', | |
| 40 | + MINUTE = 'minute', | |
| 41 | + HOUR = 'hour', | |
| 42 | +} | |
| 43 | + | |
| 44 | +export enum SecurityModeNameEnum { | |
| 45 | + NO_SEC = 'No Security', | |
| 46 | + PSK = 'Pre-Shared Key', | |
| 47 | + RPK = 'Raw Public Key', | |
| 48 | + X509 = 'X.509 Certificate', | |
| 49 | +} | |
| 50 | + | |
| 51 | +export enum BindingNameEnum { | |
| 52 | + U = 'U: Client is reachable via the UDP binding at any time.', | |
| 53 | + M = 'M: Client is reachable via the MQTT binding at any time.', | |
| 54 | + H = 'H: Client is reachable via the HTTP binding at any time.', | |
| 55 | + T = 'T: Client is reachable via the TCP binding at any time.', | |
| 56 | + S = 'S: Client is reachable via the SMS binding at any time.', | |
| 57 | + N = 'N: Client MUST send the response to such a request over the Non-IP binding (is supported since LWM', | |
| 58 | + UQ = 'UQ: UDP connection in queue mode (is not supported since LWM2M 1.1)', | |
| 59 | + UQS = 'UQS: both UDP and SMS connections active; UDP in queue mode, SMS in standard mode (is not supported since LWM2M 1.1)', | |
| 60 | + TQ = 'TQ: TCP connection in queue mode (is not supported since LWM2M 1.1)', | |
| 61 | + TQS = 'TQS: both TCP and SMS connections active; TCP in queue mode, SMS in standard mode (is not supported since LWM2M 1.1)\t', | |
| 62 | + SQ = 'SQ: SMS connection in queue mode (is not supported since LWM2M 1.1)', | |
| 63 | +} | |
| 64 | + | |
| 65 | +export const FirmwareUpdateStrategyNameEnum = { | |
| 66 | + 1: 'Push firmware update as binary file using Object 5 and Resource 0 (Package)', | |
| 67 | + 2: 'Auto-generate unique CoAP URL to download the package and push firmware update as Object 5 and', | |
| 68 | + 3: 'Push firmware update as binary file using Object 19 and Resource 0 (Data)', | |
| 69 | +}; | |
| 70 | + | |
| 71 | +export const SoftwareUpdateStrategyNameEnum = { | |
| 72 | + 1: 'Push binary file using Object 9 and Resource 2 (Package)', | |
| 73 | + 2: 'Auto-generate unique CoAP URL to download the package and push software update using Object 9 and', | |
| 74 | +}; | |
| 75 | + | |
| 76 | +export enum SNMPRangeNameEnum { | |
| 77 | + TELEMETRY_QUERYING = 'Telemetry', | |
| 78 | + CLIENT_ATTRIBUTES_QUERYING = 'Client attributes', | |
| 79 | + SHARED_ATTRIBUTES_SETTING = 'Shared attributes', | |
| 80 | + TO_DEVICE_RPC_REQUEST = 'RPC request', | |
| 81 | +} | |
| 82 | + | |
| 83 | +export enum SNMPDataTypeEnum { | |
| 84 | + STRING = '字符串', | |
| 85 | + LONG = '数字', | |
| 86 | + BOOLEAN = '布尔值', | |
| 87 | + DOUBLE = '双精度小数', | |
| 88 | + JSON = 'JSON', | |
| 89 | +} | ... | ... |
| 1 | +export { default as TransportDescription } from './TransportDescription.vue'; | ... | ... |
| ... | ... | @@ -9,17 +9,33 @@ |
| 9 | 9 | </div> |
| 10 | 10 | <div class="form-item2" :style="{ height: dynamicHeight + 'vh' }"> |
| 11 | 11 | <div style="margin-left: 1vw"> |
| 12 | - <h3 v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" style="color: gray"> | |
| 13 | - 查询频率(毫秒*)</h3> | |
| 14 | - <InputNumber v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
| 15 | - v-model:value="queryingFrequencyMs" :min="0" :max="99999999999999999999" style="margin-top: 0.25vh" /> | |
| 12 | + <h3 | |
| 13 | + v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
| 14 | + style="color: gray" | |
| 15 | + > | |
| 16 | + 查询频率(毫秒*)</h3 | |
| 17 | + > | |
| 18 | + <InputNumber | |
| 19 | + v-if="item.spec == 'TELEMETRY_QUERYING' || item.spec == 'CLIENT_ATTRIBUTES_QUERYING'" | |
| 20 | + v-model:value="queryingFrequencyMs" | |
| 21 | + :min="0" | |
| 22 | + :max="99999999999999999999" | |
| 23 | + style="margin-top: 0.25vh" | |
| 24 | + /> | |
| 16 | 25 | <div style="margin-top: 0.65vh"></div> |
| 17 | - <MappingsForm :value="item.mappings" @change="handleMappingsChange" @dynamicAddHeight="dynamicHeight += 4" | |
| 18 | - @dynamicReduceHeight="dynamicHeight -= 4" /> | |
| 26 | + <MappingsForm | |
| 27 | + :value="item.mappings" | |
| 28 | + @change="handleMappingsChange" | |
| 29 | + @dynamicAddHeight="dynamicHeight += 4" | |
| 30 | + @dynamicReduceHeight="dynamicHeight -= 4" | |
| 31 | + /> | |
| 19 | 32 | </div> |
| 20 | 33 | </div> |
| 21 | 34 | <div class="form-item3" :style="{ height: dynamicHeight + 'vh' }"> |
| 22 | - <div style="text-align: center; line-height: 20vh" :style="{ lineHeight: dynamicHeight + 'vh' }"> | |
| 35 | + <div | |
| 36 | + style="text-align: center; line-height: 20vh" | |
| 37 | + :style="{ lineHeight: dynamicHeight + 'vh' }" | |
| 38 | + > | |
| 23 | 39 | <Button size="small" type="default" @click="handleRemove(item, index)"> |
| 24 | 40 | <template #icon> |
| 25 | 41 | <MinusCircleOutlined /> |
| ... | ... | @@ -30,105 +46,105 @@ |
| 30 | 46 | </div> |
| 31 | 47 | </template> |
| 32 | 48 | <script setup lang="ts"> |
| 33 | -import { ref } from 'vue'; | |
| 34 | -import { Button, InputNumber } from 'ant-design-vue'; | |
| 35 | -import { MinusCircleOutlined } from '@ant-design/icons-vue'; | |
| 36 | -import MappingsForm from './MappingsForm.vue'; | |
| 37 | -import { useMessage } from '/@/hooks/web/useMessage'; | |
| 49 | + import { ref } from 'vue'; | |
| 50 | + import { Button, InputNumber } from 'ant-design-vue'; | |
| 51 | + import { MinusCircleOutlined } from '@ant-design/icons-vue'; | |
| 52 | + import MappingsForm from './MappingsForm.vue'; | |
| 53 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
| 38 | 54 | |
| 39 | -const props = defineProps({ | |
| 40 | - item: { | |
| 41 | - type: Object, | |
| 42 | - default: () => { }, | |
| 43 | - }, | |
| 44 | - index: { | |
| 45 | - type: Number, | |
| 46 | - }, | |
| 47 | -}); | |
| 48 | -const emit = defineEmits(['removeItem']); | |
| 49 | -const dynamicHeight = ref(25); | |
| 50 | -const queryingFrequencyMs = ref(5000); | |
| 51 | -const { createMessage } = useMessage(); | |
| 52 | -const handleMappingsChange = (e) => { | |
| 53 | - // eslint-disable-next-line vue/no-mutating-props | |
| 54 | - props.item.mappings = e; | |
| 55 | -}; | |
| 56 | -const handleRemove = (item, index) => { | |
| 57 | - emit('removeItem', item, index); | |
| 58 | -}; | |
| 59 | -//设置回显的高度 | |
| 60 | -const setFieldsValueFunc = () => { | |
| 61 | - dynamicHeight.value = props.item.mappings.length * 3 + props.item.mappings.length + 15; | |
| 62 | - queryingFrequencyMs.value = props.item.queryingFrequencyMs; | |
| 63 | -}; | |
| 64 | -//获取表单的值 | |
| 65 | -const getSnmpFormFunc = () => { | |
| 66 | - if (!props.item.spec || props.item.spec == '' || props.item.spec == undefined) { | |
| 67 | - return createMessage.error('请选择范围'); | |
| 68 | - } | |
| 69 | - if ( | |
| 70 | - props.item.spec == 'TELEMETRY_QUERYING' || | |
| 71 | - props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
| 72 | - ) { | |
| 73 | - if (queryingFrequencyMs.value == null) { | |
| 74 | - return createMessage.error('请填写查询频率'); | |
| 75 | - } | |
| 76 | - } | |
| 77 | - let obj: any = {}; | |
| 78 | - obj = { | |
| 79 | - ...{ spec: props.item.spec }, | |
| 80 | - ...{ mappings: props.item.mappings }, | |
| 81 | - ...{ | |
| 82 | - queryingFrequencyMs: | |
| 83 | - props.item.spec == 'TELEMETRY_QUERYING' || props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
| 84 | - ? queryingFrequencyMs.value | |
| 85 | - : null, | |
| 55 | + const props = defineProps({ | |
| 56 | + item: { | |
| 57 | + type: Object, | |
| 58 | + default: () => {}, | |
| 86 | 59 | }, |
| 60 | + index: { | |
| 61 | + type: Number, | |
| 62 | + }, | |
| 63 | + }); | |
| 64 | + const emit = defineEmits(['removeItem']); | |
| 65 | + const dynamicHeight = ref(25); | |
| 66 | + const queryingFrequencyMs = ref(5000); | |
| 67 | + const { createMessage } = useMessage(); | |
| 68 | + const handleMappingsChange = (e) => { | |
| 69 | + // eslint-disable-next-line vue/no-mutating-props | |
| 70 | + props.item.mappings = e; | |
| 71 | + }; | |
| 72 | + const handleRemove = (item, index) => { | |
| 73 | + emit('removeItem', item, index); | |
| 74 | + }; | |
| 75 | + //设置回显的高度 | |
| 76 | + const setFieldsValueFunc = () => { | |
| 77 | + dynamicHeight.value = props.item.mappings.length * 3 + props.item.mappings.length + 15; | |
| 78 | + queryingFrequencyMs.value = props.item.queryingFrequencyMs; | |
| 87 | 79 | }; |
| 88 | - return obj; | |
| 89 | -}; | |
| 90 | -defineExpose({ | |
| 91 | - getSnmpFormFunc, | |
| 92 | - setFieldsValueFunc, | |
| 93 | - handleMappingsChange, | |
| 94 | -}); | |
| 80 | + //获取表单的值 | |
| 81 | + const getSnmpFormFunc = () => { | |
| 82 | + if (!props.item.spec || props.item.spec == '' || props.item.spec == undefined) { | |
| 83 | + return createMessage.error('请选择范围'); | |
| 84 | + } | |
| 85 | + if ( | |
| 86 | + props.item.spec == 'TELEMETRY_QUERYING' || | |
| 87 | + props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
| 88 | + ) { | |
| 89 | + if (queryingFrequencyMs.value == null) { | |
| 90 | + return createMessage.error('请填写查询频率'); | |
| 91 | + } | |
| 92 | + } | |
| 93 | + let obj: any = {}; | |
| 94 | + obj = { | |
| 95 | + ...{ spec: props.item.spec }, | |
| 96 | + ...{ mappings: props.item.mappings }, | |
| 97 | + ...{ | |
| 98 | + queryingFrequencyMs: | |
| 99 | + props.item.spec == 'TELEMETRY_QUERYING' || props.item.spec == 'CLIENT_ATTRIBUTES_QUERYING' | |
| 100 | + ? queryingFrequencyMs.value | |
| 101 | + : null, | |
| 102 | + }, | |
| 103 | + }; | |
| 104 | + return obj; | |
| 105 | + }; | |
| 106 | + defineExpose({ | |
| 107 | + getSnmpFormFunc, | |
| 108 | + setFieldsValueFunc, | |
| 109 | + handleMappingsChange, | |
| 110 | + }); | |
| 95 | 111 | </script> |
| 96 | 112 | <style lang="less" scoped> |
| 97 | -::-webkit-scrollbar { | |
| 98 | - display: none; | |
| 99 | - width: 0 !important; | |
| 100 | - height: 0 !important; | |
| 101 | - -webkit-appearance: none; | |
| 102 | - background: transparent; | |
| 103 | -} | |
| 104 | - | |
| 105 | -.snmp-form { | |
| 106 | - display: flex; | |
| 107 | - align-items: center; | |
| 108 | - justify-content: space-between; | |
| 109 | - width: 40vw; | |
| 110 | - height: 20vh; | |
| 111 | - border: 0.1px solid #bfbfbf; | |
| 112 | - margin-top: 2vh; | |
| 113 | - | |
| 114 | - .form-item1 { | |
| 115 | - width: 9vw; | |
| 116 | - height: 20vh; | |
| 117 | - border: 0.1px solid #bfbfbf; | |
| 113 | + ::-webkit-scrollbar { | |
| 114 | + display: none; | |
| 115 | + width: 0 !important; | |
| 116 | + height: 0 !important; | |
| 117 | + -webkit-appearance: none; | |
| 118 | + background: transparent; | |
| 118 | 119 | } |
| 119 | 120 | |
| 120 | - .form-item2 { | |
| 121 | - width: 28vw; | |
| 121 | + .snmp-form { | |
| 122 | + display: flex; | |
| 123 | + align-items: center; | |
| 124 | + justify-content: space-between; | |
| 125 | + width: 40vw; | |
| 122 | 126 | height: 20vh; |
| 123 | 127 | border: 0.1px solid #bfbfbf; |
| 124 | - overflow: hidden; | |
| 125 | - overflow-y: scroll; | |
| 126 | - } | |
| 128 | + margin-top: 2vh; | |
| 127 | 129 | |
| 128 | - .form-item3 { | |
| 129 | - width: 2vw; | |
| 130 | - height: 20vh; | |
| 131 | - border: 0.1px solid #bfbfbf; | |
| 130 | + .form-item1 { | |
| 131 | + width: 9vw; | |
| 132 | + height: 20vh; | |
| 133 | + border: 0.1px solid #bfbfbf; | |
| 134 | + } | |
| 135 | + | |
| 136 | + .form-item2 { | |
| 137 | + width: 28vw; | |
| 138 | + height: 20vh; | |
| 139 | + border: 0.1px solid #bfbfbf; | |
| 140 | + overflow: hidden; | |
| 141 | + overflow-y: scroll; | |
| 142 | + } | |
| 143 | + | |
| 144 | + .form-item3 { | |
| 145 | + width: 2vw; | |
| 146 | + height: 20vh; | |
| 147 | + border: 0.1px solid #bfbfbf; | |
| 148 | + } | |
| 132 | 149 | } |
| 133 | -} | |
| 134 | 150 | </style> | ... | ... |