refactor: 画像key_facts分组(画像特征+个案事实折叠)
- 画像特征(地区/公司类型/团队/财务等稳定属性)直接展示 - 个案事实(工伤详情/合同条款/解除原因等案件细节)默认折叠 - 点击"个案事实(N)"可展开查看 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState, useCallback } from 'react'
|
||||
import { UserCircle, History, ChevronRight, ArrowLeft } from 'lucide-react'
|
||||
import { UserCircle, History, ChevronRight, ArrowLeft, ChevronDown } from 'lucide-react'
|
||||
import { PageLayout } from '@/components/common/PageLayout'
|
||||
import { EmptyState } from '@/components/common/EmptyState'
|
||||
import { LoadingState } from '@/components/common/LoadingState'
|
||||
@@ -341,7 +341,23 @@ const SOURCE_LABELS: Record<string, string> = {
|
||||
manual: '用户确认',
|
||||
}
|
||||
|
||||
/** 常问话题中文映射 */
|
||||
/** 画像特征 key(稳定的用户属性,直接展示) */
|
||||
const PROFILE_FACT_KEYS = new Set([
|
||||
'region', 'company_type', 'team_ability', 'industry', 'company_size',
|
||||
'role', 'risk_tolerance', 'communication_style', 'decision_style',
|
||||
'market_potential', 'financial_status', 'financial_situation',
|
||||
'cash_flow', 'asset_status', 'liability', 'revenue', 'profit_status',
|
||||
'business_model', 'funding_stage', 'expansion_plan', 'competitor',
|
||||
'customer_concentration', 'supply_chain', 'employee_count',
|
||||
'shareholder_structure', 'partnership',
|
||||
])
|
||||
|
||||
/** 判断 key 属于画像特征还是个案事实 */
|
||||
function isProfileFact(key: string): boolean {
|
||||
return PROFILE_FACT_KEYS.has(key.toLowerCase())
|
||||
}
|
||||
|
||||
|
||||
const TOPIC_LABELS: Record<string, string> = {
|
||||
'contract review': '合同审查',
|
||||
'work-life balance': '工作生活平衡',
|
||||
@@ -407,6 +423,7 @@ export function MyProfile() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [currentHistory, setCurrentHistory] = useState<ProfileHistory | null>(null)
|
||||
const [showCaseFacts, setShowCaseFacts] = useState(false)
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true)
|
||||
@@ -545,19 +562,51 @@ export function MyProfile() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{profile.key_facts && Object.keys(profile.key_facts).length > 0 && (
|
||||
<div className="border-b pb-2">
|
||||
<p className="mb-1 text-xs text-muted-foreground">关键事实</p>
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3">
|
||||
{Object.entries(profile.key_facts).map(([k, v]) => (
|
||||
<div key={k} className="flex items-center justify-between text-xs">
|
||||
<span className="text-muted-foreground">{translateFactKey(k)}</span>
|
||||
<span className="font-medium">{translateFactValue(v)}</span>
|
||||
{profile.key_facts && Object.keys(profile.key_facts).length > 0 && (() => {
|
||||
const entries = Object.entries(profile.key_facts)
|
||||
const profileFacts = entries.filter(([k]) => isProfileFact(k))
|
||||
const caseFacts = entries.filter(([k]) => !isProfileFact(k))
|
||||
return (
|
||||
<>
|
||||
{/* 画像特征:直接展示 */}
|
||||
{profileFacts.length > 0 && (
|
||||
<div className="border-b pb-2">
|
||||
<p className="mb-1 text-xs text-muted-foreground">画像特征</p>
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3">
|
||||
{profileFacts.map(([k, v]) => (
|
||||
<div key={k} className="flex items-center justify-between text-xs">
|
||||
<span className="text-muted-foreground">{translateFactKey(k)}</span>
|
||||
<span className="font-medium">{translateFactValue(v)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
{/* 个案事实:折叠展示 */}
|
||||
{caseFacts.length > 0 && (
|
||||
<div className="border-b pb-2">
|
||||
<button
|
||||
onClick={() => setShowCaseFacts(!showCaseFacts)}
|
||||
className="mb-1 flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<ChevronDown className={cn('h-3 w-3 transition-transform', !showCaseFacts && '-rotate-90')} />
|
||||
个案事实({caseFacts.length})
|
||||
</button>
|
||||
{showCaseFacts && (
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3">
|
||||
{caseFacts.map(([k, v]) => (
|
||||
<div key={k} className="flex items-center justify-between text-xs">
|
||||
<span className="text-muted-foreground">{translateFactKey(k)}</span>
|
||||
<span className="font-medium">{translateFactValue(v)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})()}
|
||||
|
||||
{profile.common_scenes && profile.common_scenes.length > 0 && (
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
Reference in New Issue
Block a user