generated from kgod/ai-review-template
自内部仓库剥离深度优化与 RAG 知识库后的交付版本: - Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强) - 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护 - 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏 - PostgreSQL 运行时 + Alembic 迁移链 Co-Authored-By: Claude <noreply@anthropic.com>
71 lines
2.4 KiB
Vue
71 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref, watch } from 'vue'
|
|
import type { ComponentSubmission } from '../types/resumeAgent'
|
|
import { initialValue, numberValue, stringValue } from '../utils/componentData'
|
|
import FormCard from './shared/FormCard.vue'
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
data: Record<string, unknown>
|
|
value?: unknown
|
|
readOnly?: boolean
|
|
pending?: boolean
|
|
}>(),
|
|
{ value: undefined, readOnly: false, pending: false },
|
|
)
|
|
|
|
const emit = defineEmits<{ submit: [submission: ComponentSubmission] }>()
|
|
const sourceValue = computed(() =>
|
|
typeof props.value === 'string' ? props.value : initialValue(props.data),
|
|
)
|
|
const answer = ref(sourceValue.value)
|
|
const maxLength = computed(() => numberValue(props.data.max_length, 300))
|
|
const fieldName = computed(() => stringValue(props.data.field, 'text'))
|
|
|
|
watch(sourceValue, (next) => {
|
|
answer.value = next
|
|
})
|
|
|
|
function submit() {
|
|
const cleanAnswer = answer.value.trim()
|
|
if (!cleanAnswer || props.readOnly || props.pending) return
|
|
emit('submit', {
|
|
event: 'submit',
|
|
payload: { value: cleanAnswer, [fieldName.value]: cleanAnswer },
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<FormCard
|
|
:eyebrow="stringValue(data.eyebrow, '补充细节')"
|
|
:title="stringValue(data.title ?? data.prompt, '请简单讲讲这段经历')"
|
|
:description="stringValue(data.description ?? data.helper_text, '先写事实即可,我们会在后续帮你整理表达。')"
|
|
:read-only="readOnly"
|
|
:pending="pending"
|
|
>
|
|
<div v-if="readOnly" class="read-only-value">{{ sourceValue || '内容已记录' }}</div>
|
|
<form v-else @submit.prevent="submit">
|
|
<div class="field-group">
|
|
<label class="field-label" :for="`short-text-${fieldName}`">
|
|
{{ stringValue(data.label, '你的回答') }}
|
|
</label>
|
|
<textarea
|
|
:id="`short-text-${fieldName}`"
|
|
v-model="answer"
|
|
class="text-area"
|
|
:maxlength="maxLength"
|
|
:placeholder="stringValue(data.placeholder, '写下关键事实、行动或结果…')"
|
|
:disabled="pending"
|
|
/>
|
|
<p class="field-hint">{{ answer.length }}/{{ maxLength }} 字</p>
|
|
</div>
|
|
<div class="component-actions">
|
|
<button class="primary-button" type="submit" :disabled="!answer.trim() || pending">
|
|
保存并继续
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</FormCard>
|
|
</template>
|