康鲁杰
2025-03-21 55bcd0b3241addbeb8d4c0d186bc139c6f97d489
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
<template>
  <ContentWrap>
    <el-tabs>
      <el-tab-pane label="基础通信 Topic">
        <Table
          :columns="columns1"
          :data="data1"
          :span-method="createSpanMethod(data1)"
          align="left"
          headerAlign="left"
          border="true"
        />
      </el-tab-pane>
      <el-tab-pane label="物模型通信 Topic">
        <Table
          :columns="columns2"
          :data="data2"
          :span-method="createSpanMethod(data2)"
          align="left"
          headerAlign="left"
          border="true"
        />
      </el-tab-pane>
    </el-tabs>
  </ContentWrap>
</template>
<script setup lang="ts">
import { ProductVO } from '@/api/iot/product'
 
const props = defineProps<{ product: ProductVO }>()
 
// 定义列
const columns1 = reactive([
  { label: '功能', field: 'function', width: 150 },
  { label: 'Topic 类', field: 'topicClass', width: 800 },
  { label: '操作权限', field: 'operationPermission', width: 100 },
  { label: '描述', field: 'description' }
])
 
const columns2 = reactive([
  { label: '功能', field: 'function', width: 150 },
  { label: 'Topic 类', field: 'topicClass', width: 800 },
  { label: '操作权限', field: 'operationPermission', width: 100 },
  { label: '描述', field: 'description' }
])
 
// TODO @haohao:这个,有没可能写到一个枚举里,方便后续维护? /Users/yunai/Java/yudao-ui-admin-vue3/src/views/ai/utils/constants.ts
const data1 = computed(() => {
  if (!props.product || !props.product.productKey) return []
  return [
    {
      function: 'OTA 升级',
      topicClass: `/ota/device/inform/${props.product.productKey}/\${deviceName}`,
      operationPermission: '发布',
      description: '设备上报固件升级信息'
    },
    {
      function: 'OTA 升级',
      topicClass: `/ota/device/upgrade/${props.product.productKey}/\${deviceName}`,
      operationPermission: '订阅',
      description: '固件升级信息下行'
    },
    {
      function: 'OTA 升级',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/ota/firmware/get`,
      operationPermission: '发布',
      description: '设备上报固件升级进度'
    },
    {
      function: 'OTA 升级',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/ota/firmware/get`,
      operationPermission: '发布',
      description: '设备主动拉取固件升级信息'
    },
    {
      function: '设备标签',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/deviceinfo/update`,
      operationPermission: '发布',
      description: '设备上报标签数据'
    },
    {
      function: '设备标签',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/deviceinfo/update_reply`,
      operationPermission: '订阅',
      description: '云端响应标签上报'
    },
    {
      function: '设备标签',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/deviceinfo/delete`,
      operationPermission: '订阅',
      description: '设备删除标签信息'
    },
    {
      function: '设备标签',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/deviceinfo/delete_reply`,
      operationPermission: '订阅',
      description: '云端响应标签删除'
    },
    {
      function: '时钟同步',
      topicClass: `/ext/ntp/${props.product.productKey}/\${deviceName}/request`,
      operationPermission: '发布',
      description: 'NTP 时钟同步请求'
    },
    {
      function: '时钟同步',
      topicClass: `/ext/ntp/${props.product.productKey}/\${deviceName}/response`,
      operationPermission: '订阅',
      description: 'NTP 时钟同步响应'
    },
    {
      function: '设备影子',
      topicClass: `/shadow/update/${props.product.productKey}/\${deviceName}`,
      operationPermission: '发布',
      description: '设备影子发布'
    },
    {
      function: '设备影子',
      topicClass: `/shadow/get/${props.product.productKey}/\${deviceName}`,
      operationPermission: '订阅',
      description: '设备接收影子变更'
    },
    {
      function: '配置更新',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/config/push`,
      operationPermission: '订阅',
      description: '云端主动下推配置信息'
    },
    {
      function: '配置更新',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/config/get`,
      operationPermission: '发布',
      description: '设备端查询配置信息'
    },
    {
      function: '配置更新',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/config/get_reply`,
      operationPermission: '订阅',
      description: '云端响应配置信息'
    },
    {
      function: '广播',
      topicClass: `/broadcast/${props.product.productKey}/\${identifier}`,
      operationPermission: '订阅',
      description: '广播 Topic,identifier 为用户自定义字符串'
    }
  ]
})
 
const data2 = computed(() => {
  if (!props.product || !props.product.productKey) return []
  return [
    {
      function: '属性上报',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/event/property/post`,
      operationPermission: '发布',
      description: '设备属性上报'
    },
    {
      function: '属性上报',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/event/property/post_reply`,
      operationPermission: '订阅',
      description: '云端响应属性上报'
    },
    {
      function: '属性设置',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/service/property/set`,
      operationPermission: '订阅',
      description: '设备属性设置'
    },
    {
      function: '事件上报',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/event/\${tsl.event.identifier}/post`,
      operationPermission: '发布',
      description: '设备事件上报'
    },
    {
      function: '事件上报',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/event/\${tsl.event.identifier}/post_reply`,
      operationPermission: '订阅',
      description: '云端响应事件上报'
    },
    {
      function: '服务调用',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/service/\${tsl.service.identifier}`,
      operationPermission: '订阅',
      description: '设备服务调用'
    },
    {
      function: '服务调用',
      topicClass: `/sys/${props.product.productKey}/\${deviceName}/thing/service/\${tsl.service.identifier}_reply`,
      operationPermission: '发布',
      description: '设备端响应服务调用'
    }
  ]
})
 
// 通用的单元格合并方法生成器
const createSpanMethod = (data: any[]) => {
  // 预处理,计算每个功能的合并行数
  const rowspanMap: Record<number, number> = {}
  let currentFunction = ''
  let startIndex = 0
  let count = 0
 
  data.forEach((item, index) => {
    if (item.function !== currentFunction) {
      if (count > 0) {
        rowspanMap[startIndex] = count
      }
      currentFunction = item.function
      startIndex = index
      count = 1
    } else {
      count++
    }
  })
 
  // 处理最后一组
  if (count > 0) {
    rowspanMap[startIndex] = count
  }
 
  // 返回 span 方法
  return ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
    if (columnIndex === 0) {
      // 仅对“功能”列进行合并
      const rowspan = rowspanMap[rowIndex] || 0
      if (rowspan > 0) {
        return {
          rowspan,
          colspan: 1
        }
      } else {
        return {
          rowspan: 0,
          colspan: 0
        }
      }
    }
  }
}
</script>