Files
meetnote/web/lib/mock-data.ts
2026-04-13 19:00:17 +08:00

186 lines
6.8 KiB
TypeScript
Raw Permalink 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.
export type MeetingStatus =
| 'pending'
| 'uploading'
| 'transcribing'
| 'summarizing'
| 'done'
| 'failed'
export type Meeting = {
id: string
title: string
date: string // ISO
duration: number // seconds
participants?: string[]
status: MeetingStatus
progress?: number // 0-100
chunksDone?: number
chunksTotal?: number
summary?: {
keyPoints: string[]
todos: { text: string; owner?: string; due?: string }[]
decisions: string[]
keywords: string[]
preview: string
}
transcript?: Array<{
time: number // seconds
speaker: string
text: string
}>
}
export const mockMeetings: Meeting[] = [
{
id: 'm1',
title: '与客户对齐定价',
date: '2026-04-13T14:30:00',
duration: 4980,
participants: ['张三', '李四', '客户王总'],
status: 'transcribing',
progress: 60,
chunksDone: 3,
chunksTotal: 5,
},
{
id: 'm2',
title: '团队周会',
date: '2026-04-13T10:00:00',
duration: 2700,
participants: ['张三', '李四', '王五'],
status: 'done',
summary: {
keyPoints: [
'A 项目完成 80%,进入最后测试阶段',
'B 项目本周进入功能测试',
'下周聚焦 A 项目上线准备,需对齐运营',
],
todos: [
{ text: '整理 A 项目上线 checklist', owner: '张三', due: '周五前' },
{ text: '协调运营团队对接会', owner: '李四', due: '明天' },
{ text: 'B 项目性能压测报告', owner: '王五' },
],
decisions: [
'A 项目上线时间定为下周三',
'B 项目延后一周,优先保质量',
],
keywords: ['周会', '进度', '上线', 'A项目', 'B项目'],
preview:
'本周关键进展A 项目完成 80%进入最后测试阶段B 项目本周进入功能测试。下周聚焦 A 项目上线准备,需要协调运营团队对接...',
},
},
{
id: 'm3',
title: '产品 Review',
date: '2026-04-12T16:00:00',
duration: 3120,
participants: ['产品经理', '设计师', '工程团队'],
status: 'done',
summary: {
keyPoints: [
'确定 Q2 产品路线图三个重点方向',
'移动端体验优化优先级最高',
'AI 功能纳入 Q3 规划',
],
todos: [
{ text: '出 Q2 PRD 初稿', owner: '产品经理', due: '下周一' },
{ text: '设计 Mobile 重构方案', owner: '设计师' },
],
decisions: ['Q2 聚焦移动端', 'AI 功能推迟到 Q3'],
keywords: ['产品', 'Q2', '路线图', '移动端', 'AI'],
preview:
'讨论 Q2 产品路线图确定三个重点1) 移动端体验优化作为最高优先级2) 后台管理 UI 重构3) AI 辅助功能纳入 Q3 规划...',
},
},
{
id: 'm4',
title: '架构评审 · API 网关方案',
date: '2026-04-11T14:00:00',
duration: 5400,
participants: ['技术负责人', '后端团队'],
status: 'done',
summary: {
keyPoints: [
'选型确定 Kong + 自研插件方案',
'Rate limiting 复用 Redis 集群',
'灰度发布走 Canary',
],
todos: [
{ text: '写 Kong POC', owner: '小明', due: '下周五' },
{ text: '梳理现有 API 清单', owner: '小红' },
],
decisions: ['不走 EnvoyKong 生态更成熟', '灰度走 Canary 5%/25%/50%/100%'],
keywords: ['架构', 'API网关', 'Kong', '灰度', 'Redis'],
preview:
'今天主要对齐 API 网关的选型方向,在 Kong 和 Envoy 之间做了对比。最终决定 Kong + 自研插件,主要考虑到 Kong 的生态更成熟,团队学习成本更低...',
},
},
{
id: 'm5',
title: '用户访谈 · A 类客户',
date: '2026-04-10T15:30:00',
duration: 3600,
status: 'failed',
},
]
export function getMeeting(id: string): Meeting | undefined {
return mockMeetings.find((m) => m.id === id)
}
export function formatDuration(seconds: number): string {
const h = Math.floor(seconds / 3600)
const m = Math.floor((seconds % 3600) / 60)
const s = seconds % 60
if (h > 0) return `${h}h ${m}min`
return `${m}min`
}
export function formatTime(seconds: number): string {
const h = Math.floor(seconds / 3600)
const m = Math.floor((seconds % 3600) / 60)
const s = Math.floor(seconds % 60)
if (h > 0) {
return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
}
return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
}
export function groupByDate(meetings: Meeting[]): Record<string, Meeting[]> {
const groups: Record<string, Meeting[]> = {}
for (const m of meetings) {
const day = m.date.slice(0, 10)
if (!groups[day]) groups[day] = []
groups[day].push(m)
}
return groups
}
export function dateLabel(day: string): string {
const today = new Date()
const todayStr = today.toISOString().slice(0, 10)
const yesterday = new Date(today)
yesterday.setDate(today.getDate() - 1)
const yesterdayStr = yesterday.toISOString().slice(0, 10)
if (day === todayStr) return '今天 · ' + day
if (day === yesterdayStr) return '昨天 · ' + day
return day
}
export const mockTranscript = [
{ time: 0, speaker: '张三', text: '大家好,今天主要是对齐一下 Q2 的定价方案pipeline 基本已经 ready 了。' },
{ time: 15, speaker: '李四', text: 'OK, 我这边准备了三个档位的方案,分别是 Basic / Pro / Ultra对应不同的客户规模。' },
{ time: 35, speaker: '客户王总', text: '我们比较关心 Pro 档的 SLA 具体怎么定义,还有超出 quota 之后的处理方式。' },
{ time: 58, speaker: '李四', text: 'Pro 档 SLA 我们承诺 99.9% 可用性,超出 quota 按标准价格 0.01 per request 计费。' },
{ time: 90, speaker: '张三', text: '关于 SLA我建议我们再明确一下 downtime 的定义,尤其是计划内维护是否算。' },
{ time: 110, speaker: '客户王总', text: '同意,计划内维护应该提前通知,并且不计入 SLA。' },
{ time: 130, speaker: '李四', text: '好的,这块我回去更新一下合同模板,会议纪要里也会明确写出来。' },
{ time: 155, speaker: '张三', text: '另外 Pro 档的折扣,我们能给到什么力度?客户这边期望是 15%。' },
{ time: 180, speaker: '客户王总', text: '15% 是我们的底线,毕竟首年采购量会比较大。' },
{ time: 205, speaker: '李四', text: '10% 是我们目前政策能给到的上限15% 需要走特批流程。' },
{ time: 230, speaker: '张三', text: '那就走特批,客户关系比单次毛利重要。我今天去找 CEO 签字。' },
{ time: 260, speaker: '客户王总', text: '感谢。那就这样,合同草稿我们希望周五之前能收到。' },
{ time: 280, speaker: '李四', text: '没问题,周五前一定出。' },
]