feat: BossAi v2.0 UI/UX 重构 + 看板断点续接 + 多轮上下文
- 新增 web2/ 前端:任务卡看板、风险雷达、决策日志、我的团队、快捷指令 - ChatPanel 增强:风险卡置顶、案卡接入、起诉状向导、语音输入 - 事项看板:点击查看详情弹窗、断点续接(恢复历史对话+matterId) - 保密模式恢复:密码验证后重建内存 session,保留多轮上下文 - 多轮对话:ask/ask-stream/ask-analyze 注入 session 历史,AI 有上下文 - 追问优化:紧扣用户问题,不再偏离主题(社保问社保,工伤问工伤) - 对话区可滚动,输入区固定可见 - 状态机放宽:允许从任意非终态转到 pending_expert - session 存活检查端点,后端重启后自动重建 session - DB migration:风险推送表、案卡表 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/** 案卡组件(TASK-009)
|
||||
* 公共组件:展示单张案卡,支持点击和归档
|
||||
*/
|
||||
import { Scale, TrendingUp, Heart, ShieldCheck, Archive } from 'lucide-react'
|
||||
import { cn, MATTER_STATUS_LABELS, MATTER_STATUS_COLORS, SCENE_LABELS, formatRelative } from '@/lib/utils'
|
||||
import type { Matter, Scene } from '@/types'
|
||||
|
||||
const SCENE_ICONS: Record<Scene, typeof Scale> = {
|
||||
legal: Scale,
|
||||
decision: TrendingUp,
|
||||
life: Heart,
|
||||
emotion: ShieldCheck,
|
||||
}
|
||||
|
||||
interface MatterCardProps {
|
||||
matter: Matter
|
||||
onClick?: () => void
|
||||
onArchive?: () => void
|
||||
}
|
||||
|
||||
export function MatterCard({ matter, onClick, onArchive }: MatterCardProps) {
|
||||
const Icon = SCENE_ICONS[matter.scene] || Scale
|
||||
return (
|
||||
<div
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
'group cursor-pointer rounded-xl border bg-card p-3 shadow-sm transition-all hover:shadow-md',
|
||||
MATTER_STATUS_COLORS[matter.status],
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-white/60">
|
||||
<Icon className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-sm font-medium text-foreground">{matter.title}</div>
|
||||
<div className="mt-1 flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<span>{SCENE_LABELS[matter.scene]}</span>
|
||||
<span>·</span>
|
||||
<span>{formatRelative(matter.updated_at)}</span>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<span className={cn('inline-block rounded-full border px-2 py-0.5 text-xs', MATTER_STATUS_COLORS[matter.status])}>
|
||||
{MATTER_STATUS_LABELS[matter.status]}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{onArchive && matter.status === 'closed' && (
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); onArchive() }}
|
||||
className="opacity-0 transition-opacity group-hover:opacity-100"
|
||||
aria-label="归档"
|
||||
>
|
||||
<Archive className="h-4 w-4 text-muted-foreground hover:text-foreground" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user