From 486b63b248b103624be54314a16a9d10deafdb04 Mon Sep 17 00:00:00 2001 From: selfrelease Date: Mon, 31 Aug 2026 15:25:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=BB=E5=83=8F=E7=89=B9=E5=BE=81?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A2=9E=E5=88=A0=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 画像特征区域右上角加"添加"按钮,弹窗输入名称和值 - 每个特征hover显示删除图标,点击删除 - 无特征时显示"添加画像特征"入口 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- web2/src/pages/MyProfile.tsx | 103 ++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/web2/src/pages/MyProfile.tsx b/web2/src/pages/MyProfile.tsx index b4f4071..be29485 100644 --- a/web2/src/pages/MyProfile.tsx +++ b/web2/src/pages/MyProfile.tsx @@ -1,5 +1,5 @@ import { useEffect, useState, useCallback } from 'react' -import { UserCircle, History, ChevronRight, ArrowLeft, ChevronDown, Pencil } from 'lucide-react' +import { UserCircle, History, ChevronRight, ArrowLeft, ChevronDown, Pencil, Plus, Trash2 } from 'lucide-react' import { PageLayout } from '@/components/common/PageLayout' import { EmptyState } from '@/components/common/EmptyState' import { LoadingState } from '@/components/common/LoadingState' @@ -432,6 +432,9 @@ export function MyProfile() { const [editing, setEditing] = useState<{ field: string; label: string; value: string; type: 'select' | 'text' } | null>(null) const [editValue, setEditValue] = useState('') const [saving, setSaving] = useState(false) + const [addingFact, setAddingFact] = useState(false) + const [newFactKey, setNewFactKey] = useState('') + const [newFactValue, setNewFactValue] = useState('') const load = useCallback(async () => { setLoading(true) @@ -492,6 +495,39 @@ export function MyProfile() { } } + /** 删除画像特征 */ + const handleDeleteFact = async (key: string) => { + if (!profile) return + try { + // 通过更新空值来删除 + const newFacts = { ...profile.key_facts } + delete newFacts[key] + await api.updateProfile({ key_facts: newFacts }) + setProfile((prev) => prev ? { ...prev, key_facts: newFacts } : prev) + } catch (e) { + setError(e instanceof Error ? e.message : '删除失败') + } + } + + /** 添加画像特征 */ + const handleAddFact = async () => { + if (!newFactKey.trim() || !newFactValue.trim() || !profile) return + setSaving(true) + try { + const key = newFactKey.trim() + const newFacts = { ...profile.key_facts, [key]: newFactValue.trim() } + await api.updateProfile({ key_facts: newFacts }) + setProfile((prev) => prev ? { ...prev, key_facts: newFacts } : prev) + setAddingFact(false) + setNewFactKey('') + setNewFactValue('') + } catch (e) { + setError(e instanceof Error ? e.message : '添加失败') + } finally { + setSaving(false) + } + } + if (loading) return if (error) return if (!profile) return null @@ -625,10 +661,18 @@ export function MyProfile() { const caseFacts = entries.filter(([k]) => !isProfileFact(k)) return ( <> - {/* 画像特征:直接展示(可编辑) */} + {/* 画像特征:直接展示(可编辑/可增删) */} {profileFacts.length > 0 && (
-

画像特征

+
+

画像特征

+ +
{profileFacts.map(([k, v]) => (
@@ -642,12 +686,30 @@ export function MyProfile() { > +
))}
)} + {/* 无画像特征时也显示添加按钮 */} + {profileFacts.length === 0 && ( +
+ +
+ )} {/* 个案事实:折叠展示 */} {caseFacts.length > 0 && (
@@ -778,6 +840,41 @@ export function MyProfile() { + + {/* 添加画像特征弹窗 */} + + + + 添加画像特征 + 填写特征名称和值,保存后生效 + +
+
+ + setNewFactKey(e.target.value)} + placeholder="如:行业、公司规模、地区" + /> +
+
+ + setNewFactValue(e.target.value)} + placeholder="如:科技、小型、上海" + onKeyDown={(e) => e.key === 'Enter' && handleAddFact()} + /> +
+
+ + + + +
+
) }