refactor: 智囊三场景去掉话题选择层,直接展示一批问题可点击开问
This commit is contained in:
+25
-109
@@ -1,58 +1,28 @@
|
||||
/** 私人法务页:话题选择 + 换一批 + ChatPanel
|
||||
/** 私人法务页:直接展示一批问题,点击即问
|
||||
* scene='legal', 默认保密模式, 显示风险卡, 启用上传
|
||||
* 顶部含智囊场景切换栏(法务/决策/生活/情绪)
|
||||
*/
|
||||
import { useState, useCallback } from 'react'
|
||||
import { PageLayout } from '@/components/common/PageLayout'
|
||||
import { ChatPanel } from '@/components/common/ChatPanel'
|
||||
import { BrainTrustSwitcher } from '@/components/common/BrainTrustSwitcher'
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card'
|
||||
import { Briefcase, ChevronDown, RefreshCw, Loader2 } from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { api } from '@/lib/api'
|
||||
|
||||
/** 话题类型 */
|
||||
interface Topic {
|
||||
title: string
|
||||
desc: string
|
||||
samples: string[]
|
||||
}
|
||||
|
||||
/** 私人法务:初始兜底话题,换一批时 AI 动态生成 */
|
||||
// 初始兜底话题(同步显示,无 loading)
|
||||
const FALLBACK_TOPICS: Topic[] = [
|
||||
{ title: '劳动用工', desc: '工伤、辞退、欠薪、社保', samples: ['员工工伤后能开除吗?', '员工被辞退要赔多少?', '员工不签合同有何风险?', '社保未缴全被查怎么办?'] },
|
||||
{ title: '合同审查', desc: '违约、条款、效力', samples: ['合同违约金怎么约定?', '对方不履行合同怎么办?', '口头协议有法律效力吗?', '合同条款不公平能改吗?'] },
|
||||
{ title: '债权债务', desc: '欠款、催收、诉讼', samples: ['客户拖欠货款3个月如何催收?', '借条怎么写才有效?', '债务人不还钱能报警吗?', '超过诉讼时效怎么办?'] },
|
||||
{ title: '股东纠纷', desc: '股权、分红、退股', samples: ['合伙人要退股怎么谈?', '股东不出资怎么办?', '分红比例怎么定?', '小股东权益被侵害怎么办?'] },
|
||||
{ title: '税务风险', desc: '稽查、发票、合规', samples: ['收到税务稽查通知怎么办?', '发票开错了怎么处理?', '个体户怎么交税最合理?', '税务罚款能减免吗?'] },
|
||||
{ title: '诉讼仲裁', desc: '起诉、举证、执行', samples: ['打官司要准备哪些证据?', '仲裁和诉讼哪个更快?', '赢了官司对方不执行怎么办?', '诉讼费用怎么算?'] },
|
||||
/** 初始兜底示例问题(覆盖劳动/合同/债务/股权/税务/诉讼高频场景) */
|
||||
const FALLBACK_SAMPLES: string[] = [
|
||||
'员工被辞退要赔多少?',
|
||||
'合同违约金怎么约定?',
|
||||
'客户拖欠货款3个月如何催收?',
|
||||
'合伙人要退股怎么谈?',
|
||||
'收到税务稽查通知怎么办?',
|
||||
'打官司要准备哪些证据?',
|
||||
'员工工伤后能开除吗?',
|
||||
'对方不履行合同怎么办?',
|
||||
'借条怎么写才有效?',
|
||||
'股东不出资怎么办?',
|
||||
'发票开错了怎么处理?',
|
||||
'赢了官司对方不执行怎么办?',
|
||||
]
|
||||
|
||||
export function LegalAdvisor() {
|
||||
const [topics, setTopics] = useState<Topic[]>(FALLBACK_TOPICS)
|
||||
const [selectedTopic, setSelectedTopic] = useState(0)
|
||||
const [topicsCollapsed, setTopicsCollapsed] = useState(false)
|
||||
const [loadingTopics, setLoadingTopics] = useState(false)
|
||||
|
||||
/** 换一批:调用 AI 动态生成话题(避免重复) */
|
||||
const refreshTopics = useCallback(async () => {
|
||||
setLoadingTopics(true)
|
||||
try {
|
||||
const res = await api.getTopics('legal', topics.map((t) => t.title))
|
||||
if (res.topics?.length > 0) {
|
||||
setTopics(res.topics)
|
||||
setSelectedTopic(0)
|
||||
}
|
||||
} catch {
|
||||
// AI 不可用时保持当前话题
|
||||
} finally {
|
||||
setLoadingTopics(false)
|
||||
}
|
||||
}, [topics])
|
||||
|
||||
const currentTopic = topics[selectedTopic]
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
title="私人法务"
|
||||
@@ -60,70 +30,16 @@ export function LegalAdvisor() {
|
||||
>
|
||||
<BrainTrustSwitcher />
|
||||
|
||||
<Card>
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<button
|
||||
onClick={() => setTopicsCollapsed(!topicsCollapsed)}
|
||||
className="flex items-center gap-1.5 text-base font-semibold transition-opacity hover:opacity-70"
|
||||
>
|
||||
<ChevronDown className={cn('h-4 w-4 transition-transform', topicsCollapsed && '-rotate-90')} />
|
||||
法务话题
|
||||
</button>
|
||||
<button
|
||||
onClick={refreshTopics}
|
||||
disabled={loadingTopics}
|
||||
className="flex items-center gap-1 text-xs text-muted-foreground transition-opacity hover:opacity-70 disabled:opacity-50"
|
||||
>
|
||||
{loadingTopics ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <RefreshCw className="h-3.5 w-3.5" />}
|
||||
换一批
|
||||
</button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
{!topicsCollapsed && (
|
||||
<CardContent>
|
||||
{loadingTopics && (
|
||||
<div className="flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
AI 正在生成新话题…
|
||||
</div>
|
||||
)}
|
||||
<div className={cn('grid gap-3 sm:grid-cols-2 lg:grid-cols-3', loadingTopics && 'pointer-events-none opacity-50')}>
|
||||
{topics.map((t, i) => (
|
||||
<button
|
||||
key={t.title + i}
|
||||
onClick={() => setSelectedTopic(i)}
|
||||
className={cn(
|
||||
'flex items-start gap-3 rounded-md border p-3 text-left transition-colors',
|
||||
selectedTopic === i
|
||||
? 'border-primary bg-primary/5 ring-1 ring-primary'
|
||||
: 'border-input hover:bg-accent',
|
||||
)}
|
||||
>
|
||||
<Briefcase className="mt-0.5 h-5 w-5 shrink-0 text-primary" aria-hidden />
|
||||
<div>
|
||||
<p className="text-sm font-medium">{t.title}</p>
|
||||
<p className="mt-0.5 text-xs text-muted-foreground">{t.desc}</p>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{currentTopic && (
|
||||
<ChatPanel
|
||||
scene="legal"
|
||||
samples={currentTopic.samples}
|
||||
topic={currentTopic.title}
|
||||
defaultMode="confidential"
|
||||
placeholder={`描述你的${currentTopic.title}问题…`}
|
||||
showRiskCard
|
||||
enableUpload
|
||||
footer="AI 输出仅供参考,不构成律师、会计师、税务师或医生的正式意见。重大风险事项请寻求执业专业人士复核。"
|
||||
/>
|
||||
)}
|
||||
<ChatPanel
|
||||
scene="legal"
|
||||
samples={FALLBACK_SAMPLES}
|
||||
topic="法务咨询"
|
||||
defaultMode="confidential"
|
||||
placeholder="描述你的法务问题…"
|
||||
showRiskCard
|
||||
enableUpload
|
||||
footer="AI 输出仅供参考,不构成律师、会计师、税务师或医生的正式意见。重大风险事项请寻求执业专业人士复核。"
|
||||
/>
|
||||
</PageLayout>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user