Blame view

Yi.Vben5.Vue3/packages/effects/common-ui/src/components/json-viewer/index.vue 2.76 KB
515fceeb   “wangming”   框架初始化
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
  <script lang="ts" setup>
  import type { SetupContext } from 'vue';
  
  import type { Recordable } from '@vben/types';
  
  import type {
    JsonViewerAction,
    JsonViewerProps,
    JsonViewerToggle,
    JsonViewerValue,
  } from './types';
  
  import { computed, useAttrs } from 'vue';
  // @ts-ignore
  import VueJsonViewer from 'vue-json-viewer';
  
  import { $t } from '@vben/locales';
  
  import { isBoolean } from '@vben-core/shared/utils';
  
  // @ts-ignore
  import JsonBigint from 'json-bigint';
  
  defineOptions({ name: 'JsonViewer' });
  
  const props = withDefaults(defineProps<JsonViewerProps>(), {
    expandDepth: 1,
    copyable: false,
    sort: false,
    boxed: false,
    theme: 'default-json-theme',
    expanded: false,
    previewMode: false,
    showArrayIndex: true,
    showDoubleQuotes: false,
  });
  
  const emit = defineEmits<{
    click: [event: MouseEvent];
    copied: [event: JsonViewerAction];
    keyClick: [key: string];
    toggle: [param: JsonViewerToggle];
    valueClick: [value: JsonViewerValue];
  }>();
  
  const attrs: SetupContext['attrs'] = useAttrs();
  
  function handleClick(event: MouseEvent) {
    if (
      event.target instanceof HTMLElement &&
      event.target.classList.contains('jv-item')
    ) {
      const pathNode = event.target.closest('.jv-push');
      if (!pathNode || !pathNode.hasAttribute('path')) {
        return;
      }
      const param: JsonViewerValue = {
        path: '',
        value: '',
        depth: 0,
        el: event.target,
      };
  
      param.path = pathNode.getAttribute('path') || '';
      param.depth = Number(pathNode.getAttribute('depth')) || 0;
  
      param.value = event.target.textContent || undefined;
      param.value = JSON.parse(param.value);
      emit('valueClick', param);
    }
    emit('click', event);
  }
  
  // 支持显示 bigint 数据,如较长的订单号
  const jsonData = computed<Record<string, any>>(() => {
    if (typeof props.value !== 'string') {
      return props.value || {};
    }
  
    try {
      return JsonBigint({ storeAsString: true }).parse(props.value);
    } catch (error) {
      console.error('JSON parse error:', error);
      return {};
    }
  });
  
  const bindProps = computed<Recordable<any>>(() => {
    const copyable = {
      copyText: $t('ui.jsonViewer.copy'),
      copiedText: $t('ui.jsonViewer.copied'),
      timeout: 2000,
      ...(isBoolean(props.copyable) ? {} : props.copyable),
    };
  
    return {
      ...props,
      ...attrs,
      value: jsonData.value,
      onCopied: (event: JsonViewerAction) => emit('copied', event),
      onKeyclick: (key: string) => emit('keyClick', key),
      onClick: (event: MouseEvent) => handleClick(event),
      copyable: props.copyable ? copyable : false,
    };
  });
  </script>
  <template>
    <VueJsonViewer v-bind="bindProps">
      <template #copy="slotProps">
        <slot name="copy" v-bind="slotProps"></slot>
      </template>
    </VueJsonViewer>
  </template>
  <style lang="scss">
  @use './style.scss';
  </style>