maxkb/ui/src/components/dynamics-form/items/JsonInput.vue
wangdan-fit2cloud 69e35b36aa feat: layout
2025-04-28 18:15:41 +08:00

144 lines
3.6 KiB
Vue

<template>
<div style="width: 100%" class="function-CodemirrorEditor">
<Codemirror
v-bind="$attrs"
ref="cmRef"
v-model="model_value"
:extensions="extensions"
:style="codemirrorStyle"
:tab-size="4"
:autofocus="true"
/>
<div class="function-CodemirrorEditor__format">
<el-button text type="info" @click="format" class="magnify">
<el-icon><DocumentChecked /></el-icon>
</el-button>
</div>
<div class="function-CodemirrorEditor__footer">
<el-button text type="info" @click="openCodemirrorDialog" class="magnify">
<AppIcon iconName="app-magnify" style="font-size: 16px"></AppIcon>
</el-button>
</div>
<!-- Codemirror 弹出层 -->
<el-dialog
v-model="dialogVisible"
:title="$t('dynamicsForm.default.label')"
append-to-body
fullscreen
>
<Codemirror
v-model="cloneContent"
:extensions="extensions"
:style="codemirrorStyle"
:tab-size="4"
:autofocus="true"
style="
height: calc(100vh - 160px) !important;
border: 1px solid #bbbfc4;
border-radius: 4px;
"
/>
<template #footer>
<div class="dialog-footer mt-24">
<el-button type="primary" @click="submitDialog"> {{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { json, jsonParseLinter } from '@codemirror/lang-json'
import { oneDark } from '@codemirror/theme-one-dark'
import { Codemirror } from 'vue-codemirror'
import { linter } from '@codemirror/lint'
import { computed, ref } from 'vue'
import { t } from '@/locales'
const props = withDefaults(defineProps<{ modelValue?: any }>(), { modelValue: () => {} })
const emit = defineEmits(['update:modelValue'])
const cache_model_value_str = ref<string>()
const model_value = computed({
get: () => {
if (cache_model_value_str.value) {
return cache_model_value_str.value
}
return JSON.stringify(props.modelValue, null, 4)
},
set: (v: string) => {
if (!v) {
emit('update:modelValue', JSON.parse('{}'))
} else {
try {
cache_model_value_str.value = v
const result = JSON.parse(v)
emit('update:modelValue', result)
} catch (e) {}
}
}
})
const extensions = [json(), linter(jsonParseLinter()), oneDark]
const codemirrorStyle = {
height: '210px!important',
width: '100%'
}
// 弹出框相关代码
const dialogVisible = ref<boolean>(false)
const cloneContent = ref<string>('')
const openCodemirrorDialog = () => {
cloneContent.value = model_value.value
dialogVisible.value = true
}
const format = () => {
try {
const json_str = JSON.parse(model_value.value)
model_value.value = JSON.stringify(json_str, null, 4)
} catch (e) {}
}
function submitDialog() {
model_value.value = cloneContent.value
dialogVisible.value = false
}
/**
* 校验格式
* @param rule
* @param value
* @param callback
*/
const validate_rules = (rule: any, value: any, callback: any) => {
if (model_value.value) {
try {
JSON.parse(model_value.value)
} catch (e) {
callback(new Error(t('dynamicsForm.tip.requiredMessage')))
return false
}
}
return true
}
defineExpose({ validate_rules: validate_rules })
</script>
<style lang="scss">
.function-CodemirrorEditor__footer {
position: absolute;
bottom: 10px;
right: 10px;
}
.function-CodemirrorEditor {
position: relative;
}
.function-CodemirrorEditor__format {
position: absolute;
top: 10px;
right: 10px;
}
</style>