feat: app 端 ui 设计完成

This commit is contained in:
liqupan
2026-01-28 19:10:19 +08:00
commit a4e7898e94
149 changed files with 11302 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
import React, { useState } from 'react';
import { ChevronLeft, ChevronDown, MessageSquare, BookOpen, Send, HelpCircle, FileText } from 'lucide-react';
interface HelpFeedbackProps {
onBack: () => void;
}
const FAQS = [
{
q: "如何连接 Link-X 设备?",
a: "请确保设备已开机长按电源键3秒蓝灯闪烁。在首页点击底部导航栏的「操控」或在个人中心点击「我的设备」进行搜索配对。"
},
{
q: "订阅会员后权益未生效?",
a: "数据同步可能存在延迟,请尝试下拉刷新个人中心页面,或在设置中点击「恢复购买」。如仍有问题,请提交反馈工单。"
},
{
q: "如何创建自定义剧本?",
a: "Wei AI Pro 用户可在「剧本馆」点击右上角的「+」号进入编辑器支持设置时间轴、震动波形及AI对话逻辑。"
},
{
q: "应用是否会保存我的隐私数据?",
a: "Wei AI 采用端对端加密技术。默认情况下,所有对话记录与震动偏好仅保存在您的本地设备上,除非您手动开启云备份。"
}
];
const HelpFeedback: React.FC<HelpFeedbackProps> = ({ onBack }) => {
const [openFaqIndex, setOpenFaqIndex] = useState<number | null>(0);
const [feedbackText, setFeedbackText] = useState('');
const [isSending, setIsSending] = useState(false);
const toggleFaq = (index: number) => {
setOpenFaqIndex(openFaqIndex === index ? null : index);
};
const handleSendFeedback = () => {
if (!feedbackText.trim()) return;
setIsSending(true);
setTimeout(() => {
setIsSending(false);
setFeedbackText('');
alert('反馈已收到,指挥中心正在分析...');
}, 1500);
};
return (
<div className="fixed inset-0 z-[60] bg-[#0F1014] flex flex-col h-full overflow-hidden animate-in slide-in-from-right duration-300">
{/* Header */}
<div className="relative z-20 pt-safe-top px-4 py-3 flex items-center justify-between border-b border-white/5 bg-[#0F1014]/80 backdrop-blur-md">
<button onClick={onBack} className="p-2 -ml-2 text-white/70 hover:text-white active:scale-95 transition-transform">
<ChevronLeft size={24} />
</button>
<h1 className="text-base font-bold text-white tracking-wider"></h1>
<div className="w-8"></div>
</div>
<div className="flex-1 overflow-y-auto no-scrollbar p-5 pb-20">
{/* Quick Actions */}
<div className="grid grid-cols-2 gap-4 mb-8">
<button className="bg-[#1C1F26]/60 p-4 rounded-xl border border-white/5 flex flex-col items-center justify-center gap-2 active:scale-[0.98] transition-transform">
<div className="w-10 h-10 rounded-full bg-[#8B5CF6]/10 flex items-center justify-center text-[#8B5CF6]">
<BookOpen size={20} />
</div>
<span className="text-sm font-bold text-white">使</span>
</button>
<button className="bg-[#1C1F26]/60 p-4 rounded-xl border border-white/5 flex flex-col items-center justify-center gap-2 active:scale-[0.98] transition-transform">
<div className="w-10 h-10 rounded-full bg-[#3B82F6]/10 flex items-center justify-center text-[#3B82F6]">
<MessageSquare size={20} />
</div>
<span className="text-sm font-bold text-white"></span>
</button>
</div>
{/* FAQ Section */}
<div className="mb-8">
<h3 className="text-xs font-bold text-[#64748B] uppercase tracking-widest mb-4 flex items-center gap-2">
<HelpCircle size={12} />
</h3>
<div className="space-y-2">
{FAQS.map((faq, i) => {
const isOpen = openFaqIndex === i;
return (
<div key={i} className="bg-[#1C1F26]/40 border border-white/5 rounded-xl overflow-hidden transition-all duration-300">
<button
onClick={() => toggleFaq(i)}
className="w-full p-4 flex items-center justify-between text-left"
>
<span className={`text-sm font-medium ${isOpen ? 'text-[#8B5CF6]' : 'text-[#E2E8F0]'}`}>
{faq.q}
</span>
<ChevronDown size={16} className={`text-[#64748B] transition-transform duration-300 ${isOpen ? 'rotate-180' : ''}`} />
</button>
<div className={`overflow-hidden transition-all duration-300 ${isOpen ? 'max-h-40 opacity-100' : 'max-h-0 opacity-0'}`}>
<div className="px-4 pb-4 pt-0 text-xs text-[#94A3B8] leading-relaxed border-t border-white/5 mt-2">
<div className="pt-3">{faq.a}</div>
</div>
</div>
</div>
);
})}
</div>
</div>
{/* Feedback Form */}
<div>
<h3 className="text-xs font-bold text-[#64748B] uppercase tracking-widest mb-4 flex items-center gap-2">
<FileText size={12} />
</h3>
<div className="bg-[#1C1F26]/60 border border-white/5 rounded-xl p-4">
<textarea
value={feedbackText}
onChange={(e) => setFeedbackText(e.target.value)}
placeholder="请描述您遇到的问题或建议..."
className="w-full bg-transparent text-sm text-white placeholder-[#64748B] focus:outline-none min-h-[100px] resize-none"
/>
<div className="flex justify-between items-center mt-3 pt-3 border-t border-white/5">
<span className="text-[10px] text-[#64748B]"> jpg, png </span>
<button
onClick={handleSendFeedback}
disabled={!feedbackText.trim() || isSending}
className={`flex items-center gap-2 px-4 py-2 rounded-lg text-xs font-bold transition-all ${
feedbackText.trim() && !isSending
? 'bg-[#8B5CF6] text-white shadow-[0_0_15px_rgba(139,92,246,0.3)]'
: 'bg-[#334155] text-[#94A3B8] cursor-not-allowed'
}`}
>
{isSending ? (
<span>...</span>
) : (
<>
<Send size={12} />
</>
)}
</button>
</div>
</div>
</div>
<div className="mt-8 text-center">
<p className="text-[10px] text-[#475569]">Service Code: 884-HELP-V2</p>
</div>
</div>
</div>
);
};
export default HelpFeedback;