/** * AI 取名结果解析(从 ai-name 页面抽出,供创作页与详情弹窗共用) * * 后端返回的 content 可能是: * 1) JSON({ summary, names: [] }) * 2) JSON Lines(每行一个 {type:'summary'|'name'}) * 3) 【名字】+ 拼音/评分/出处… 的标记文本 */ export function parseNameResult(content) { if (!content) return { summary: '', names: [] } let text = String(content).trim() .replace(/^```json\s*/i, '') .replace(/^```\s*/i, '') .replace(/```$/i, '') .trim() const line = parseJsonLines(text) if (line.names.length) return line const marked = parseMarkedText(text) if (marked.names.length) return marked const s = text.indexOf('{') const e = text.lastIndexOf('}') if (s >= 0 && e > s) text = text.substring(s, e + 1) try { const d = JSON.parse(text) return { summary: d.summary || '', names: Array.isArray(d.names) ? d.names : [] } } catch { return { summary: text, names: [] } } } function parseJsonLines(text) { const d = { summary: '', names: [] } String(text || '').split(/\r?\n/).forEach((l) => { l = l.trim() if (!l) return try { const i = JSON.parse(l) if (i.type === 'summary') d.summary = i.content || '' if (i.type === 'name' && i.data) d.names.push(i.data) } catch { /* 忽略非 JSON 行 */ } }) return d } function parseMarkedText(text) { const d = { summary: '', names: [] } const v = String(text || '') const sm = v.match(/整体建议[::]([\s\S]*?)(?=\n\s*【|$)/) if (sm) d.summary = sm[1].trim() const reg = /【([^】]+)】([\s\S]*?)(?=\n\s*【|$)/g let m while ((m = reg.exec(v))) { const body = m[2] || '' const name = resolveNameBlockTitle(m[1], body) d.names.push({ name, pinyin: matchField(body, '拼音'), score: parseInt(matchField(body, '评分')) || 90, source: matchField(body, '出处'), wuxing: matchField(body, '五行'), meaning: matchField(body, '寓意'), tone: matchField(body, '音律'), reason: matchField(body, '推荐'), }) } d.names = d.names.filter(i => i.name).slice(0, 5) return d } function resolveNameBlockTitle(title, body) { const n = String(title || '').trim() if (!['姓名', '名字', '候选名'].includes(n)) return n const fr = /^(拼音|评分|出处|五行|寓意|音律|推荐)[::]/ const line = String(body || '').split(/\r?\n/).map(i => i.trim()).find(i => i && !fr.test(i)) return line ? line.replace(/^姓名[::]/, '').trim() : n } function matchField(body, label) { const r = new RegExp(`${label}[::]([^\\n\\r]*)`) const m = String(body || '').match(r) return m ? m[1].trim() : '' } /** 名字详情展示字段 */ export const NAME_FIELDS = [ { key: 'source', label: '出处' }, { key: 'wuxing', label: '五行' }, { key: 'meaning', label: '寓意' }, { key: 'tone', label: '音律' }, { key: 'reason', label: '推荐' }, ] /** 把名字结果拼成可复制文本 */ export function buildNameCopyText(result) { const names = result?.names || [] if (!names.length) return '' const lines = [] if (result.summary) lines.push(result.summary) names.forEach((item) => { lines.push(`${item.name}${item.score ? `(${item.score}分)` : ''}`) NAME_FIELDS.forEach((f) => { if (item[f.key]) lines.push(`${f.label}:${item[f.key]}`) }) if (item.pinyin) lines.push(`拼音:${item.pinyin}`) lines.push('') }) return lines.join('\n') }