|
1 | | -<script setup> |
| 1 | +<script setup lang="ts"> |
2 | 2 | import JsonEditorVue from 'json-editor-vue' |
3 | 3 | import 'vanilla-jsoneditor/themes/jse-theme-dark.css' |
4 | 4 | import { useI18n } from 'vue-i18n' |
| 5 | +import { Button } from '@/components/ui/button' |
5 | 6 | // import { createAjvValidator } from 'svelte-jsoneditor' |
6 | 7 |
|
7 | 8 | // const validator = createAjvValidator({ schema, schemaDefinitions }) |
8 | 9 | const { t } = useI18n() |
| 10 | +const message = useMessage() |
9 | 11 | const attrs = useAttrs() |
10 | 12 | const model = defineModel() |
11 | 13 |
|
12 | | -watch( |
13 | | - model, |
14 | | - newValue => { |
15 | | - if (typeof newValue !== 'string') return |
16 | | - const trimmed = newValue.trim() |
17 | | - if (!trimmed) return |
18 | | - try { |
19 | | - const formatted = JSON.stringify(JSON.parse(trimmed), null, 2) |
20 | | - if (formatted !== newValue) { |
21 | | - model.value = formatted |
22 | | - } |
23 | | - } catch { |
24 | | - // Swallow parse errors so the editor stays usable while typing |
| 14 | +const formatJson = () => { |
| 15 | + if (typeof model.value !== 'string') { |
| 16 | + message.error(t('Invalid JSON format')) |
| 17 | + return |
| 18 | + } |
| 19 | +
|
| 20 | + const trimmed = model.value.trim() |
| 21 | + if (!trimmed) { |
| 22 | + message.warning(t('JSON content is empty')) |
| 23 | + return |
| 24 | + } |
| 25 | +
|
| 26 | + try { |
| 27 | + const parsed = JSON.parse(trimmed) |
| 28 | + const formatted = JSON.stringify(parsed, null, 2) |
| 29 | + if (formatted !== model.value) { |
| 30 | + model.value = formatted |
| 31 | + message.success(t('JSON formatted successfully')) |
| 32 | + } else { |
| 33 | + message.info(t('JSON is already formatted')) |
25 | 34 | } |
26 | | - }, |
27 | | - { immediate: true } |
28 | | -) |
| 35 | + } catch (error) { |
| 36 | + message.error(t('Invalid JSON format')) |
| 37 | + } |
| 38 | +} |
29 | 39 | </script> |
30 | 40 |
|
31 | 41 | <template> |
32 | 42 | <!-- :validator="validator" 验证器 --> |
33 | | - <div class="w-full"> |
| 43 | + <div class="w-full space-y-2 relative"> |
| 44 | + <div class="flex justify-end absolute top-1 right-1 z-30"> |
| 45 | + <Button variant="outline" size="sm" @click="formatJson"> |
| 46 | + <Icon name="ri:code-s-slash-line" class="size-4" /> |
| 47 | + <!-- <span>{{ t('Format') }}</span> --> |
| 48 | + </Button> |
| 49 | + </div> |
34 | 50 | <JsonEditorVue |
35 | 51 | v-bind="attrs" |
36 | | - mode="text" |
| 52 | + :mode="'text' as any" |
37 | 53 | v-model="model" |
38 | 54 | :mainMenuBar="false" |
39 | 55 | selection="TextSelection" |
|
0 commit comments