1
0
Эх сурвалжийг харах

feat: add more event for `jsonViewer` (#5546)

* 为JsonViewer添加事件支持
Netfan 1 сар өмнө
parent
commit
b6b97accb1

+ 42 - 21
packages/effects/common-ui/src/components/json-viewer/index.vue

@@ -3,7 +3,12 @@ import type { SetupContext } from 'vue';
 
 import type { Recordable } from '@vben/types';
 
-import type { JsonViewerProps } from './types';
+import type {
+  JsonViewerAction,
+  JsonViewerProps,
+  JsonViewerToggle,
+  JsonViewerValue,
+} from './types';
 
 import { computed, useAttrs } from 'vue';
 // @ts-ignore
@@ -11,7 +16,7 @@ import VueJsonViewer from 'vue-json-viewer';
 
 import { $t } from '@vben/locales';
 
-import { isBoolean, isString } from '@vben-core/shared/utils';
+import { isBoolean } from '@vben-core/shared/utils';
 
 defineOptions({ name: 'JsonViewer' });
 
@@ -25,15 +30,44 @@ const props = withDefaults(defineProps<JsonViewerProps>(), {
   previewMode: false,
   showArrayIndex: true,
   showDoubleQuotes: false,
-  parseString: true,
 });
 
 const emit = defineEmits<{
-  parseError: [error: Error];
+  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);
+}
+
 const bindProps = computed<Recordable<any>>(() => {
   const copyable = {
     copyText: $t('ui.jsonViewer.copy'),
@@ -45,28 +79,15 @@ const bindProps = computed<Recordable<any>>(() => {
   return {
     ...props,
     ...attrs,
+    onCopied: (event: JsonViewerAction) => emit('copied', event),
+    onKeyclick: (key: string) => emit('keyClick', key),
+    onClick: (event: MouseEvent) => handleClick(event),
     copyable: props.copyable ? copyable : false,
   };
 });
-
-const modelValue = defineModel();
-
-const jsonToShow = computed(() => {
-  if (props.parseString && isString(modelValue.value)) {
-    try {
-      return JSON.parse(modelValue.value);
-    } catch (error) {
-      emit('parseError', error as Error);
-      console.error('Error parsing JSON:', error);
-      return modelValue.value;
-    }
-  } else {
-    return modelValue.value;
-  }
-});
 </script>
 <template>
-  <VueJsonViewer :value="jsonToShow" v-bind="bindProps">
+  <VueJsonViewer v-bind="bindProps">
     <template #copy="slotProps">
       <slot name="copy" v-bind="slotProps"></slot>
     </template>

+ 22 - 2
packages/effects/common-ui/src/components/json-viewer/types.ts

@@ -1,4 +1,6 @@
 export interface JsonViewerProps {
+  /** 要展示的结构数据 */
+  value: any;
   /** 展开深度 */
   expandDepth?: number;
   /** 是否可复制 */
@@ -19,6 +21,24 @@ export interface JsonViewerProps {
   showArrayIndex?: boolean;
   /** 显示双引号 */
   showDoubleQuotes?: boolean;
-  /** 解析字符串 */
-  parseString?: boolean;
+}
+
+export interface JsonViewerAction {
+  action: string;
+  text: string;
+  trigger: HTMLElement;
+}
+
+export interface JsonViewerValue {
+  value: any;
+  path: string;
+  depth: number;
+  el: HTMLElement;
+}
+
+export interface JsonViewerToggle {
+  /** 鼠标事件 */
+  event: MouseEvent;
+  /** 当前展开状态 */
+  open: boolean;
 }

+ 19 - 4
playground/src/views/examples/json-viewer/data.ts

@@ -26,8 +26,8 @@ export const json1 = {
   ],
 };
 
-export const json2 = `
-{
+export const json2 = JSON.parse(`
+  {
 	"id": "chatcmpl-123",
 	"object": "chat.completion",
 	"created": 1677652288,
@@ -46,6 +46,21 @@ export const json2 = `
 		"completion_tokens": 12,
 		"total_tokens": 21,
     "debug_mode": true
-	}
+	},
+  "debug": {
+    "startAt": "2021-08-01T00:00:00Z",
+    "logs": [
+      {
+        "timestamp": "2021-08-01T00:00:00Z",
+        "message": "This is a debug message",
+        "extra":[ "extra1", "extra2" ]
+      },
+      {
+        "timestamp": "2021-08-01T00:00:01Z",
+        "message": "This is another debug message",
+        "extra":[ "extra3", "extra4" ]
+      }
+    ]
+  }
 }
-`;
+  `);

+ 29 - 4
playground/src/views/examples/json-viewer/index.vue

@@ -1,9 +1,23 @@
 <script lang="ts" setup>
+import type { JsonViewerAction, JsonViewerValue } from '@vben/common-ui';
+
 import { JsonViewer, Page } from '@vben/common-ui';
 
-import { Card } from 'ant-design-vue';
+import { Card, message } from 'ant-design-vue';
 
 import { json1, json2 } from './data';
+
+function handleKeyClick(key: string) {
+  message.info(`点击了Key ${key}`);
+}
+
+function handleValueClick(value: JsonViewerValue) {
+  message.info(`点击了Value ${JSON.stringify(value)}`);
+}
+
+function handleCopied(_event: JsonViewerAction) {
+  message.success('已复制JSON');
+}
 </script>
 <template>
   <Page
@@ -11,16 +25,27 @@ import { json1, json2 } from './data';
     description="一个渲染 JSON 结构数据的组件,支持复制、展开等,简单易用"
   >
     <Card title="默认配置">
-      <JsonViewer v-model="json1" />
+      <JsonViewer :value="json1" />
     </Card>
-    <Card title="可复制、默认展开3层、显示边框" class="mt-4">
+    <Card title="可复制、默认展开3层、显示边框、事件处理" class="mt-4">
       <JsonViewer
-        v-model="json2"
+        :value="json2"
         :expand-depth="3"
         copyable
         :sort="false"
+        @key-click="handleKeyClick"
+        @value-click="handleValueClick"
+        @copied="handleCopied"
         boxed
       />
     </Card>
+    <Card title="预览模式" class="mt-4">
+      <JsonViewer
+        :value="json2"
+        copyable
+        preview-mode
+        :show-array-index="false"
+      />
+    </Card>
   </Page>
 </template>