Files
smartmate/frontend/src/components/assistant/cards/TaskRecordCard.vue
LoveLosita 0b0ed3c61a Version: 0.9.47.dev.260427
后端:
1. execute 节点继续拆职责——超大 execute.go 下沉为 node/execute 子包,按决策流、动作路由、上下文锚点、工具执行、状态快照、工具展示与参数解析拆分;顶层 execute.go 收敛为桥接导出,降低单文件编排/业务/模型/工具逻辑混写
2. 节点公共能力继续沉到 shared——抽出 LLM 纠错回灌、完整上下文调试日志、thinking 开关、统一上下文压缩、可见 assistant 文本持久化等 node_* 公共件,减少 execute 独占实现并为其他节点复用铺路
3. speak 文本整理能力独立收口——新增 speak_text 辅助文件,补齐正文归一化的独立承载,继续收缩 execute 主文件体积

前端:
4. NewAgent 时间线接入 business_card 业务卡片协议——schedule_agent.ts 新增 task_query / task_record 卡片载荷类型与 business_card kind;AssistantPanel 增加业务卡片事件存储、时间线恢复、块渲染分支与 BusinessCardRenderer 接入,同时保留 interrupt / status / tool / reasoning 多块并存
5. 新增任务查询卡片与任务记录卡片组件,并补充 DesignDemo 设计预览页与路由,前端可先行验证 business_card 的视觉与交互落点

文档:
6. 新增 newagent business card 前后端对接说明,明确 timeline kind、payload 结构、卡片分类、前后端发射/渲染约束
2026-04-27 17:35:55 +08:00

181 lines
4.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { TaskRecordCardData, TaskRecordSource } from '@/api/schedule_agent'
const props = defineProps<{
data: TaskRecordCardData
source?: TaskRecordSource
title?: string
summary?: string
}>()
// 对齐首页象限体系
const quadMeta: any = {
1: { title: '重要且紧急', tone: 'danger', color: '#ef4444' },
2: { title: '重要不紧急', tone: 'primary', color: '#3b82f6' },
3: { title: '简单不重要', tone: 'warning', color: '#f59e0b' },
4: { title: '不简单不重要', tone: 'slate', color: '#64748b' }
}
const getBgStyle = (group: number = 2) => {
const bgMap: any = {
1: 'linear-gradient(180deg, #fff1f2 0%, #fff7f7 100%)',
2: 'linear-gradient(180deg, #eef7ff 0%, #f7fbff 100%)',
3: 'linear-gradient(180deg, #fff8df 0%, #fffdf1 100%)',
4: 'linear-gradient(180deg, #f2f5fb 0%, #f8fafc 100%)'
}
return bgMap[group] || bgMap[2]
}
const getTextColor = (group: number = 2) => {
return quadMeta[group]?.color || '#3b82f6'
}
</script>
<template>
<div class="business-card creation-receipt" :style="{ background: getBgStyle(props.data.priority_group) }">
<div class="receipt-inner">
<div class="receipt-header">
<div class="success-ring" :style="{ background: getTextColor(props.data.priority_group) + '20', color: getTextColor(props.data.priority_group) }">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"/></svg>
</div>
<div class="success-msg">
<strong>{{ title || (source === 'quick_note' ? '已帮您记下' : '任务已创建') }}</strong>
<span v-if="data.priority_group">归类至{{ quadMeta[data.priority_group].title }}</span>
</div>
</div>
<div class="task-info-card">
<div class="task-title">{{ data.title }}</div>
<div class="task-footer">
<span class="task-id" v-if="data.id">ID: {{ data.id }}</span>
<span class="task-time" v-if="data.created_at || data.deadline_at">
{{ data.deadline_at ? '截止' + data.deadline_at : '刚刚创建' }}
</span>
</div>
</div>
<div class="receipt-actions">
<button class="btn-outline">修改详情</button>
<button class="btn-fill" :style="{ background: getTextColor(props.data.priority_group) }">打开查看</button>
</div>
</div>
</div>
</template>
<style scoped>
.business-card {
width: 100%;
max-width: 400px;
border-radius: 28px;
border: 1px solid rgba(17, 24, 39, 0.08);
box-shadow: 0 4px 20px rgba(0,0,0,0.02);
overflow: hidden;
transition: all 0.3s;
}
.receipt-inner {
padding: 24px;
display: flex;
flex-direction: column;
gap: 20px;
}
.receipt-header {
display: flex;
gap: 14px;
align-items: center;
}
.success-ring {
width: 44px;
height: 44px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.success-msg {
display: flex;
flex-direction: column;
}
.success-msg strong {
font-size: 15px;
font-weight: 850;
color: #0f172a;
}
.success-msg span {
font-size: 12px;
color: #64748b;
font-weight: 500;
}
.task-info-card {
background: rgba(255, 255, 255, 0.95);
border: 1px solid rgba(0,0,0,0.03);
border-radius: 20px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0,0,0,0.01);
}
.task-title {
font-size: 16px;
font-weight: 800;
color: #1e293b;
margin-bottom: 12px;
line-height: 1.4;
}
.task-footer {
display: flex;
justify-content: space-between;
font-size: 11px;
font-weight: 600;
color: #94a3b8;
border-top: 1px solid #f1f5f9;
padding-top: 10px;
}
.receipt-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.btn-outline {
height: 42px;
border: 1px solid #e2e8f0;
background: white;
border-radius: 12px;
font-size: 13px;
font-weight: 750;
color: #475569;
cursor: pointer;
transition: all 0.2s;
}
.btn-outline:hover {
background: #f8fafc;
}
.btn-fill {
height: 42px;
border: none;
border-radius: 12px;
color: white;
font-size: 13px;
font-weight: 800;
cursor: pointer;
box-shadow: 0 8px 20px rgba(0,0,0,0.1);
transition: all 0.2s;
}
.btn-fill:hover {
filter: brightness(1.1);
transform: translateY(-1px);
}
</style>