gaoluyang
2026-06-24 712aa51536236d43e87273e4ce45ac5691dffad8
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
<script lang="ts" setup>
import type { Ref } from 'vue';
 
import type { IotProductApi } from '#/api/iot/product/product';
 
import { computed, inject, ref, watch } from 'vue';
 
import { useVbenModal } from '..\..\..\..\packages\effects\common-ui\src';
import { IOT_PROVIDE_KEY } from '..\..\..\..\packages\constants\src';
 
import { Radio, Textarea } from 'ant-design-vue';
 
import { getThingModelTSLByProductId } from '#/api/iot/thingmodel';
 
const product = inject<Ref<IotProductApi.Product>>(IOT_PROVIDE_KEY.PRODUCT);
 
const viewMode = ref<'editor' | 'view'>('view');
const thingModelTSL = ref<any>({});
const tslString = ref('');
 
const [Modal, modalApi] = useVbenModal({
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      return;
    }
    modalApi.lock();
    try {
      // 加载数据
      thingModelTSL.value = await getThingModelTSLByProductId(
        product?.value?.id || 0,
      );
      // 设置到 values
      tslString.value = JSON.stringify(thingModelTSL.value, null, 2);
    } finally {
      modalApi.unlock();
    }
  },
});
 
/** 只读视图下,格式化后的 TSL 字符串 */
const formattedTSL = computed(() =>
  JSON.stringify(thingModelTSL.value, null, 2),
);
 
/** 编辑器内容变化时,同步到数据对象;编辑过程中 JSON 可能是中间态,解析失败保留原值 */
watch(tslString, (newValue) => {
  try {
    thingModelTSL.value = JSON.parse(newValue);
  } catch {
    // 中间态忽略
  }
});
</script>
 
<template>
  <Modal :footer="false" class="w-3/5" title="物模型 TSL">
    <div class="mx-4">
      <div class="mb-4">
        <Radio.Group v-model:value="viewMode" size="small">
          <Radio.Button value="view">代码视图</Radio.Button>
          <Radio.Button value="editor">编辑器视图</Radio.Button>
        </Radio.Group>
      </div>
      <!-- 代码视图:只读展示(pre / code 必须紧贴,避免显示出空白) -->
      <div
        v-if="viewMode === 'view'"
        class="max-h-[600px] overflow-y-auto rounded border border-gray-200 bg-gray-50 p-3 dark:border-gray-700 dark:bg-gray-800"
      >
        <pre
          class="m-0 whitespace-pre-wrap break-words font-mono text-[13px] leading-normal"
        ><code>{{ formattedTSL }}</code></pre>
      </div>
      <!-- 编辑器视图:可编辑 -->
      <Textarea
        v-else
        v-model:value="tslString"
        :rows="20"
        class="font-mono text-[13px]"
        placeholder="请输入 JSON 格式的物模型 TSL"
      />
    </div>
  </Modal>
</template>