json编辑器组件相关
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="json-editor-page layout-padding">
|
||||
<el-card shadow="hover" class="layout-padding-auto">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<div class="header-left">
|
||||
<span class="card-title">自描述 JSON 编辑器</span>
|
||||
<span class="card-desc">每个字段的值自带类型、标签、约束等元数据</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<el-button size="small" @click="loadExample">加载示例</el-button>
|
||||
<el-button size="small" @click="handlePasteJSON">
|
||||
<el-icon><UploadFilled /></el-icon>
|
||||
粘贴 JSON
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" @click="handleCopyJSON">
|
||||
<el-icon><CopyDocument /></el-icon>
|
||||
复制 JSON
|
||||
</el-button>
|
||||
<el-button size="small" type="warning" @click="jsonDialogVisible = true">
|
||||
<el-icon><View /></el-icon>
|
||||
查看 JSON
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="editor-wrapper">
|
||||
<JsonEditor ref="editorRef" v-model="jsonData" @change="handleChange" />
|
||||
</div>
|
||||
|
||||
<div class="footer-bar">
|
||||
<span class="change-hint" v-if="changeLog">{{ changeLog }}</span>
|
||||
<span v-else class="change-hint muted">数据本身即字段定义,每个字段为 {key, type, value, ...} 格式</span>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="jsonDialogVisible" title="JSON 输出" width="800px" :close-on-click-modal="false" destroy-on-close>
|
||||
<pre class="json-output">{{ formattedJSON }}</pre>
|
||||
<template #footer>
|
||||
<el-button @click="jsonDialogVisible = false">关闭</el-button>
|
||||
<el-button type="primary" @click="handleCopyJSON">
|
||||
<el-icon><CopyDocument /></el-icon>
|
||||
复制 JSON
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { CopyDocument, UploadFilled, View } from '@element-plus/icons-vue';
|
||||
import JsonEditor from '/@/components/JsonEditor/index.vue';
|
||||
|
||||
const editorRef = ref<InstanceType<typeof JsonEditor>>();
|
||||
const jsonDialogVisible = ref(false);
|
||||
const changeLog = ref('');
|
||||
|
||||
const jsonData = ref<any>({
|
||||
model: {
|
||||
key: 'model', type: 'string', label: '模型名称',
|
||||
value: 'doubao-seed-2-0-lite-260428',
|
||||
required: true,
|
||||
defaultValue: 'doubao-seed-2-0-lite-260428',
|
||||
},
|
||||
max_tokens: {
|
||||
key: 'max_tokens', type: 'number', label: '最大Token',
|
||||
value: 131072, defaultValue: 131072,
|
||||
fieldConstraint: { min: 1, max: 131072, numberType: 'integer' },
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
role: { key: 'role', type: 'string', value: 'system' },
|
||||
content: '你是一个智能助手',
|
||||
},
|
||||
{
|
||||
role: { key: 'role', type: 'string', value: 'user' },
|
||||
content: [
|
||||
{
|
||||
type: { key: 'type', value: 'text' },
|
||||
text: {
|
||||
key: 'text', type: 'string', label: '用户提示词',
|
||||
value: '', required: true,
|
||||
fieldConstraint: { maxLength: 100000 },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: { key: 'type', value: 'image_url' },
|
||||
image_url: {
|
||||
url: {
|
||||
key: 'url', type: 'upload', label: '参考图片',
|
||||
role: 'image', value: '',
|
||||
fieldConstraint: { accept: 'jpg,png,webp', maxCount: 10, maxSize: 10 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: { key: 'type', value: 'video_url' },
|
||||
video_url: {
|
||||
url: {
|
||||
key: 'url', type: 'upload', label: '参考视频',
|
||||
role: 'video', value: '',
|
||||
fieldConstraint: { accept: 'mp4,mov', maxCount: 3, maxSize: 10240 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: { key: 'type', value: 'input_audio' },
|
||||
input_audio: {
|
||||
url: {
|
||||
key: 'url', type: 'upload', label: '参考音频',
|
||||
role: 'audio', value: '',
|
||||
fieldConstraint: { accept: 'mp3,wav', maxCount: 1, maxSize: 200 },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const formattedJSON = computed(() => JSON.stringify(jsonData.value, null, 2));
|
||||
|
||||
function loadExample() {
|
||||
jsonData.value = {
|
||||
model: {
|
||||
key: 'model', type: 'string', label: '模型名称',
|
||||
value: 'doubao-seed-2-0-lite-260428',
|
||||
required: true,
|
||||
defaultValue: 'doubao-seed-2-0-lite-260428',
|
||||
},
|
||||
max_tokens: {
|
||||
key: 'max_tokens', type: 'number', label: '最大Token',
|
||||
value: 131072, defaultValue: 131072,
|
||||
fieldConstraint: { min: 1, max: 131072, numberType: 'integer' },
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
role: { key: 'role', type: 'string', value: 'system' },
|
||||
content: '你是一个智能助手',
|
||||
},
|
||||
{
|
||||
role: { key: 'role', type: 'string', value: 'user' },
|
||||
content: [
|
||||
{ type: { key: 'type', value: 'text' }, text: { key: 'text', type: 'string', label: '用户提示词', value: '', required: true, fieldConstraint: { maxLength: 100000 } } },
|
||||
{ type: { key: 'type', value: 'image_url' }, image_url: { url: { key: 'url', type: 'upload', label: '参考图片', role: 'image', value: '', fieldConstraint: { accept: 'jpg,png,webp', maxCount: 10, maxSize: 10 } } } },
|
||||
{ type: { key: 'type', value: 'video_url' }, video_url: { url: { key: 'url', type: 'upload', label: '参考视频', role: 'video', value: '', fieldConstraint: { accept: 'mp4,mov', maxCount: 3, maxSize: 10240 } } } },
|
||||
{ type: { key: 'type', value: 'input_audio' }, input_audio: { url: { key: 'url', type: 'upload', label: '参考音频', role: 'audio', value: '', fieldConstraint: { accept: 'mp3,wav', maxCount: 1, maxSize: 200 } } } },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
changeLog.value = '';
|
||||
ElMessage.success('已加载示例数据');
|
||||
}
|
||||
|
||||
function handleChange(data: any) {
|
||||
changeLog.value = `已更新,共 ${JSON.stringify(data).length} 字符`;
|
||||
}
|
||||
|
||||
function handlePasteJSON() {
|
||||
editorRef.value?.openPasteDialog();
|
||||
}
|
||||
|
||||
async function handleCopyJSON() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(formattedJSON.value);
|
||||
ElMessage.success('JSON 已复制到剪贴板');
|
||||
} catch { jsonDialogVisible.value = true; }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.json-editor-page {
|
||||
.card-header {
|
||||
display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;
|
||||
.header-left {
|
||||
.card-title { font-size: 16px; font-weight: 600; }
|
||||
.card-desc { font-size: 12px; color: #94a3b8; margin-left: 12px; }
|
||||
}
|
||||
.header-actions { display: flex; gap: 6px; }
|
||||
}
|
||||
.editor-wrapper {
|
||||
min-height: 300px; max-height: 600px; overflow: auto; padding: 8px 0;
|
||||
border: 1px solid #eef2f6; border-radius: 6px; background: #fff;
|
||||
}
|
||||
.footer-bar {
|
||||
margin-top: 12px; padding: 8px 12px; background: #f8fafc; border-radius: 4px;
|
||||
.change-hint { font-size: 12px; color: #0f172a;
|
||||
&.muted { color: #94a3b8; }
|
||||
}
|
||||
}
|
||||
}
|
||||
.json-output {
|
||||
padding: 16px; background: #1e293b; color: #e2e8f0; border-radius: 6px;
|
||||
font-size: 13px; line-height: 1.6; font-family: 'Consolas', monospace;
|
||||
max-height: 450px; overflow: auto; margin: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user