147 lines
5.8 KiB
TypeScript
147 lines
5.8 KiB
TypeScript
'use client'
|
||
|
||
import { useState, useRef } from 'react'
|
||
import { UploadCloud, FileAudio, X } from 'lucide-react'
|
||
import Link from 'next/link'
|
||
import { AppShell } from '@/components/app-shell'
|
||
import { cn } from '@/lib/utils'
|
||
|
||
export default function UploadPage() {
|
||
const [file, setFile] = useState<File | null>(null)
|
||
const [title, setTitle] = useState('')
|
||
const [participants, setParticipants] = useState('')
|
||
const [dragOver, setDragOver] = useState(false)
|
||
const inputRef = useRef<HTMLInputElement>(null)
|
||
|
||
const pickFile = (f: File | null | undefined) => {
|
||
if (f) setFile(f)
|
||
}
|
||
|
||
const humanSize = (bytes: number) => {
|
||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(0) + ' KB'
|
||
return (bytes / 1024 / 1024).toFixed(1) + ' MB'
|
||
}
|
||
|
||
return (
|
||
<AppShell>
|
||
<div className="mx-auto max-w-2xl px-5 py-8 md:px-10 md:py-10">
|
||
<header className="mb-8">
|
||
<h1 className="text-[26px] font-semibold tracking-tight">新建会议</h1>
|
||
<p className="mt-1 text-[14px] text-muted-foreground">
|
||
把手机录好的音频文件拖进来,云端自动转写并生成总结
|
||
</p>
|
||
</header>
|
||
|
||
{/* Dropzone */}
|
||
{!file ? (
|
||
<div
|
||
onDragOver={(e) => {
|
||
e.preventDefault()
|
||
setDragOver(true)
|
||
}}
|
||
onDragLeave={() => setDragOver(false)}
|
||
onDrop={(e) => {
|
||
e.preventDefault()
|
||
setDragOver(false)
|
||
pickFile(e.dataTransfer.files?.[0])
|
||
}}
|
||
onClick={() => inputRef.current?.click()}
|
||
className={cn(
|
||
'flex flex-col items-center justify-center rounded-2xl border-2 border-dashed px-6 py-16 transition-all cursor-pointer',
|
||
dragOver
|
||
? 'border-primary bg-primary-subtle'
|
||
: 'border-border bg-surface-elevated hover:border-primary/50 hover:bg-primary-subtle/50',
|
||
)}
|
||
>
|
||
<div className="flex h-14 w-14 items-center justify-center rounded-2xl bg-primary-subtle text-primary">
|
||
<UploadCloud className="h-7 w-7" />
|
||
</div>
|
||
<h3 className="mt-5 text-[17px] font-semibold">拖拽音频文件到这里</h3>
|
||
<p className="mt-1 text-[13px] text-muted-foreground">或点击选择文件</p>
|
||
<p className="mt-4 text-[12px] text-muted-foreground">
|
||
支持 m4a · mp3 · wav · mp4 · opus · 单文件最大 500 MB
|
||
</p>
|
||
<input
|
||
ref={inputRef}
|
||
type="file"
|
||
accept="audio/*,video/mp4"
|
||
className="hidden"
|
||
onChange={(e) => pickFile(e.target.files?.[0])}
|
||
/>
|
||
</div>
|
||
) : (
|
||
<div className="rounded-2xl border border-border bg-surface-elevated p-5">
|
||
<div className="flex items-start gap-4">
|
||
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary-subtle text-primary shrink-0">
|
||
<FileAudio className="h-6 w-6" />
|
||
</div>
|
||
<div className="flex-1 min-w-0">
|
||
<div className="flex items-center justify-between gap-2">
|
||
<h3 className="text-[15px] font-semibold truncate">{file.name}</h3>
|
||
<button
|
||
onClick={() => setFile(null)}
|
||
className="rounded-lg p-1.5 text-muted-foreground hover:bg-surface-muted"
|
||
>
|
||
<X className="h-4 w-4" />
|
||
</button>
|
||
</div>
|
||
<p className="mt-1 text-[13px] text-muted-foreground">{humanSize(file.size)}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Form */}
|
||
<div className="mt-6 space-y-5">
|
||
<div>
|
||
<label className="block text-[13px] font-medium mb-2">会议标题(可选)</label>
|
||
<input
|
||
type="text"
|
||
value={title}
|
||
onChange={(e) => setTitle(e.target.value)}
|
||
placeholder="例:与客户对齐定价"
|
||
className="w-full rounded-xl border border-input bg-surface-elevated px-4 py-3 text-[14px] placeholder:text-muted-foreground/60 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-[13px] font-medium mb-2">
|
||
参与人(可选)
|
||
<span className="ml-2 text-[11px] font-normal text-muted-foreground">
|
||
填上有助于提升总结质量
|
||
</span>
|
||
</label>
|
||
<input
|
||
type="text"
|
||
value={participants}
|
||
onChange={(e) => setParticipants(e.target.value)}
|
||
placeholder="张三, 李四, 客户王总"
|
||
className="w-full rounded-xl border border-input bg-surface-elevated px-4 py-3 text-[14px] placeholder:text-muted-foreground/60 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Actions */}
|
||
<div className="mt-8 flex items-center justify-end gap-3">
|
||
<Link
|
||
href="/"
|
||
className="rounded-full px-5 py-2.5 text-[14px] font-medium text-muted-foreground hover:bg-surface-muted"
|
||
>
|
||
取消
|
||
</Link>
|
||
<button
|
||
disabled={!file}
|
||
className="rounded-full bg-primary px-6 py-2.5 text-[14px] font-medium text-primary-foreground transition-colors hover:bg-primary-light disabled:opacity-40 disabled:cursor-not-allowed"
|
||
>
|
||
开始上传 →
|
||
</button>
|
||
</div>
|
||
|
||
<p className="mt-8 text-center text-[12px] text-muted-foreground">
|
||
上传后 Groq Whisper 转写 · Claude 自动生成要点 / 待办 / 决议
|
||
</p>
|
||
</div>
|
||
</AppShell>
|
||
)
|
||
}
|