|
|
|
@ -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> |
|
|
|
|