|
|
|
|
@ -82,10 +82,23 @@ function applyOptionsText(element: FormSchemaEditorItem, raw: string) {
|
|
|
|
|
})
|
|
|
|
|
.filter((x): x is { label: string; value: string } => x != null)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function prefillSourceLabel(value?: string) {
|
|
|
|
|
return SIGNUP_PREFILL_SOURCES.find((src) => src.value === value)?.label ?? '不设置预填'
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="form-schema-visual-editor">
|
|
|
|
|
<el-alert
|
|
|
|
|
v-if="purpose === 'signup'"
|
|
|
|
|
type="info"
|
|
|
|
|
:closable="false"
|
|
|
|
|
class="prefill-rule-alert"
|
|
|
|
|
title="报名侧预填对照关系由后端配置"
|
|
|
|
|
description="在每个报名字段中设置「预填对照关系」。选手进入报名页加载当前报名记录时,后端只会在该报名字段为空时按对照关系补值,已填写或已保存的内容不会被覆盖。"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div class="toolbar">
|
|
|
|
|
<el-button type="primary" @click="addField">添加字段</el-button>
|
|
|
|
|
<span class="hint">拖拽左侧把手调整顺序</span>
|
|
|
|
|
@ -140,18 +153,44 @@ function applyOptionsText(element: FormSchemaEditorItem, raw: string) {
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col
|
|
|
|
|
v-if="purpose === 'signup' && element.type !== 'file' && element.type !== SIGNUP_COMMITMENT_TYPE"
|
|
|
|
|
:xs="24"
|
|
|
|
|
:sm="12"
|
|
|
|
|
:span="24"
|
|
|
|
|
>
|
|
|
|
|
<div class="field-label">空值预填</div>
|
|
|
|
|
<el-select v-model="element.prefillFrom" class="w-100">
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="src in SIGNUP_PREFILL_SOURCES"
|
|
|
|
|
:key="src.value"
|
|
|
|
|
:label="src.label"
|
|
|
|
|
:value="src.value"
|
|
|
|
|
/>
|
|
|
|
|
</el-select>
|
|
|
|
|
<div class="prefill-mapping">
|
|
|
|
|
<div class="prefill-mapping-header">
|
|
|
|
|
<span>预填对照关系</span>
|
|
|
|
|
<el-tag size="small" :type="element.prefillFrom ? 'success' : 'info'" effect="plain">
|
|
|
|
|
{{ element.prefillFrom ? '已设置' : '未设置' }}
|
|
|
|
|
</el-tag>
|
|
|
|
|
</div>
|
|
|
|
|
<p class="prefill-mapping-desc">
|
|
|
|
|
后端将报名字段 <code>{{ element.key || '未填写 key' }}</code> 对照到指定用户资料来源;
|
|
|
|
|
报名侧只消费后端返回值,且仅空值时补入。
|
|
|
|
|
</p>
|
|
|
|
|
<el-row :gutter="12">
|
|
|
|
|
<el-col :xs="24" :sm="12">
|
|
|
|
|
<div class="field-label">目标报名字段(schema key)</div>
|
|
|
|
|
<el-input :model-value="element.key" disabled placeholder="请先填写字段 key" />
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :xs="24" :sm="12">
|
|
|
|
|
<div class="field-label">来源用户资料(prefill_from)</div>
|
|
|
|
|
<el-select v-model="element.prefillFrom" class="w-100">
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="src in SIGNUP_PREFILL_SOURCES"
|
|
|
|
|
:key="src.value"
|
|
|
|
|
:label="src.label"
|
|
|
|
|
:value="src.value"
|
|
|
|
|
/>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<div class="prefill-mapping-result">
|
|
|
|
|
<span>当前关系:</span>
|
|
|
|
|
<code>{{ element.key || '报名字段 key' }}</code>
|
|
|
|
|
<span> ← </span>
|
|
|
|
|
<code>{{ element.prefillFrom || '未绑定来源' }}</code>
|
|
|
|
|
<span class="prefill-source-label">{{ prefillSourceLabel(element.prefillFrom) }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col v-if="purpose === 'signup' && element.type === 'file'" :span="24">
|
|
|
|
|
<div class="field-label">文件格式限制(可选)</div>
|
|
|
|
|
@ -223,6 +262,10 @@ function applyOptionsText(element: FormSchemaEditorItem, raw: string) {
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-rule-alert {
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.toolbar .hint {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
@ -272,6 +315,55 @@ function applyOptionsText(element: FormSchemaEditorItem, raw: string) {
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-mapping {
|
|
|
|
|
border: 1px solid var(--el-border-color);
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
background: var(--el-fill-color-lighter);
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-mapping-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: var(--el-text-color-primary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-mapping-desc {
|
|
|
|
|
margin: 0 0 10px;
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-mapping-result {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 4px;
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
color: var(--el-text-color-secondary);
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.prefill-source-label {
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
background: var(--el-fill-color);
|
|
|
|
|
padding: 1px 5px;
|
|
|
|
|
color: var(--el-color-primary);
|
|
|
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.field-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|