HomePage.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. import { useState } from 'react';
  2. import { Button } from '@/client/components/ui/button';
  3. import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/client/components/ui/card';
  4. import { Badge } from '@/client/components/ui/badge';
  5. import { Separator } from '@/client/components/ui/separator';
  6. import {
  7. FileText,
  8. Upload,
  9. Download,
  10. Image,
  11. Settings,
  12. CheckCircle,
  13. Zap,
  14. Package,
  15. Rocket,
  16. Shield,
  17. User,
  18. Check,
  19. Clock,
  20. Calendar,
  21. Infinity
  22. } from 'lucide-react';
  23. import { useNavigate } from 'react-router-dom';
  24. import UserInfoModal from '@/client/home/components/UserInfoModal';
  25. import { useAuth } from '@/client/home/hooks/AuthProvider';
  26. import { useQuery } from '@tanstack/react-query';
  27. import { membershipPlanClient, publicSettingsClient } from '@/client/api';
  28. import type { InferResponseType } from 'hono/client';
  29. export default function HomePage() {
  30. const navigate = useNavigate();
  31. const { user, isAuthenticated } = useAuth();
  32. const [hoveredFeature, setHoveredFeature] = useState<number | null>(null);
  33. const [showUserModal, setShowUserModal] = useState(false);
  34. const [registerEnabled, setRegisterEnabled] = useState(true);
  35. const { data: membershipPlans } = useQuery({
  36. queryKey: ['membership-plans-home'],
  37. queryFn: async () => {
  38. const response = await membershipPlanClient.$get();
  39. if (!response.ok) throw new Error('获取套餐失败');
  40. const data = await response.json();
  41. return data.data.filter((plan: any) => plan.isActive === 1).sort((a: any, b: any) => a.sortOrder - b.sortOrder);
  42. },
  43. });
  44. // 获取首页注册设置状态
  45. useQuery({
  46. queryKey: ['register-setting-public'],
  47. queryFn: async () => {
  48. try {
  49. const res = await publicSettingsClient.registerStatus.$get();
  50. if (res.status === 200) {
  51. const data = await res.json();
  52. setRegisterEnabled(data.enabled);
  53. }
  54. } catch (error) {
  55. console.error('获取注册设置失败:', error);
  56. }
  57. return null;
  58. }
  59. });
  60. const features = [
  61. {
  62. icon: <FileText className="h-8 w-8" />,
  63. title: "元亨Word模板批量处理",
  64. description: "支持.docx格式,最大10MB,智能字段替换",
  65. color: "text-blue-600"
  66. },
  67. {
  68. icon: <Image className="h-8 w-8" />,
  69. title: "智能图片处理",
  70. description: "支持6种图片格式,自动尺寸控制,保持比例",
  71. color: "text-green-600"
  72. },
  73. {
  74. icon: <Upload className="h-8 w-8" />,
  75. title: "Excel数据驱动",
  76. description: "一键导入Excel数据,批量生成个性化文档",
  77. color: "text-purple-600"
  78. },
  79. {
  80. icon: <Settings className="h-8 w-8" />,
  81. title: "灵活配置",
  82. description: "自定义图片尺寸,实时预览,进度跟踪",
  83. color: "text-orange-600"
  84. }
  85. ];
  86. const stats = [
  87. { value: "10MB", label: "Word模板上限", icon: <FileText className="h-5 w-5" /> },
  88. { value: "500MB", label: "图片压缩包上限", icon: <Package className="h-5 w-5" /> },
  89. { value: "1000+", label: "支持像素范围", icon: <Image className="h-5 w-5" /> },
  90. { value: "6种", label: "图片格式支持", icon: <CheckCircle className="h-5 w-5" /> }
  91. ];
  92. return (
  93. <div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-blue-50">
  94. {/* Header Navigation */}
  95. <header className="fixed top-0 left-0 right-0 z-50 bg-white/90 backdrop-blur-sm border-b">
  96. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  97. <div className="flex justify-between items-center h-16">
  98. <div className="flex items-center">
  99. <h1 className="text-xl font-bold text-gray-900">元亨Word</h1>
  100. </div>
  101. <nav className="hidden md:flex items-center space-x-8">
  102. <button
  103. onClick={() => navigate('/templates')}
  104. className="text-gray-700 hover:text-blue-600 transition-colors font-medium"
  105. >
  106. 模板广场
  107. </button>
  108. <button
  109. onClick={() => navigate('/pricing')}
  110. className="text-gray-700 hover:text-blue-600 transition-colors font-medium"
  111. >
  112. 收费标准
  113. </button>
  114. {isAuthenticated ? (
  115. <button
  116. onClick={() => setShowUserModal(true)}
  117. className="flex items-center space-x-2 text-gray-700 hover:text-blue-600 transition-colors font-medium"
  118. >
  119. <User className="h-5 w-5" />
  120. <span>{user?.nickname || user?.username || '个人中心'}</span>
  121. </button>
  122. ) : (
  123. <>
  124. <button
  125. onClick={() => navigate('/login')}
  126. className="text-gray-700 hover:text-blue-600 transition-colors font-medium"
  127. >
  128. 登录
  129. </button>
  130. {registerEnabled && (
  131. <button
  132. // onClick={() => navigate('/register')}
  133. // className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors font-medium"
  134. >
  135. {/* 注册 */}
  136. </button>
  137. )}
  138. </>
  139. )}
  140. </nav>
  141. </div>
  142. </div>
  143. </header>
  144. {/* Hero Section */}
  145. <div className="relative overflow-hidden">
  146. <div className="absolute inset-0 bg-gradient-to-r from-blue-600/5 to-purple-600/5" />
  147. <div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-32 pb-16">
  148. <div className="text-center">
  149. <div className="inline-flex items-center px-4 py-2 rounded-full bg-blue-100 text-blue-800 text-sm font-medium mb-6">
  150. <Zap className="h-4 w-4 mr-2" />
  151. AI驱动的文档批量处理工具
  152. </div>
  153. <h1 className="text-5xl md:text-6xl font-bold text-gray-900 mb-6">
  154. 元亨Word批量处理
  155. <span className="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600">
  156. 增强版
  157. </span>
  158. </h1>
  159. <p className="text-xl text-gray-600 max-w-3xl mx-auto mb-8">
  160. 一键批量生成个性化Word文档,智能图片处理,高效数据驱动,
  161. 让繁琐的文档工作变得简单高效
  162. </p>
  163. <div className="flex flex-col sm:flex-row gap-4 justify-center">
  164. <Button
  165. size="lg"
  166. className="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-8 py-3 text-lg"
  167. onClick={() => navigate('/word-preview')}
  168. >
  169. <Rocket className="h-5 w-5 mr-2" />
  170. 立即开始
  171. </Button>
  172. <Button
  173. size="lg"
  174. variant="outline"
  175. className="border-2 px-8 py-3 text-lg"
  176. onClick={() => document.getElementById('features')?.scrollIntoView({ behavior: 'smooth' })}
  177. >
  178. 了解更多
  179. </Button>
  180. </div>
  181. </div>
  182. </div>
  183. </div>
  184. {/* Stats Section */}
  185. <div className="bg-white/50 backdrop-blur-sm">
  186. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
  187. <div className="grid grid-cols-2 md:grid-cols-4 gap-8">
  188. {stats.map((stat, index) => (
  189. <div key={index} className="text-center">
  190. <div className="flex justify-center mb-3">
  191. <div className="p-3 bg-blue-100 rounded-full">
  192. {stat.icon}
  193. </div>
  194. </div>
  195. <div className="text-3xl font-bold text-gray-900 mb-1">{stat.value}</div>
  196. <div className="text-sm text-gray-600">{stat.label}</div>
  197. </div>
  198. ))}
  199. </div>
  200. </div>
  201. </div>
  202. {/* Features Section */}
  203. <div id="features" className="py-20 bg-white">
  204. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  205. <div className="text-center mb-16">
  206. <h2 className="text-4xl font-bold text-gray-900 mb-4">
  207. 为什么选择我们
  208. </h2>
  209. <p className="text-xl text-gray-600 max-w-2xl mx-auto">
  210. 专业、高效、智能的文档处理解决方案
  211. </p>
  212. </div>
  213. <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
  214. {features.map((feature, index) => (
  215. <Card
  216. key={index}
  217. className={`border-0 shadow-lg transition-all duration-300 hover:shadow-xl hover:-translate-y-1 cursor-pointer ${
  218. hoveredFeature === index ? 'shadow-xl -translate-y-1' : ''
  219. }`}
  220. onMouseEnter={() => setHoveredFeature(index)}
  221. onMouseLeave={() => setHoveredFeature(null)}
  222. onClick={() => navigate('/word-preview')}
  223. >
  224. <CardHeader>
  225. <div className={`p-3 rounded-lg bg-gray-50 inline-block mb-4 ${feature.color}`}>
  226. {feature.icon}
  227. </div>
  228. <CardTitle className="text-xl">{feature.title}</CardTitle>
  229. </CardHeader>
  230. <CardContent>
  231. <CardDescription className="text-base">
  232. {feature.description}
  233. </CardDescription>
  234. </CardContent>
  235. </Card>
  236. ))}
  237. </div>
  238. </div>
  239. </div>
  240. {/* Pricing Section */}
  241. <div className="py-20 bg-gradient-to-br from-gray-50 to-blue-50">
  242. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  243. <div className="text-center mb-16">
  244. <h2 className="text-4xl font-bold text-gray-900 mb-4">
  245. 灵活的会员套餐
  246. </h2>
  247. <p className="text-xl text-gray-600">
  248. 选择最适合您的套餐,享受高效文档处理体验
  249. </p>
  250. </div>
  251. <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
  252. {membershipPlans?.map((plan) => (
  253. <Card
  254. key={plan.id}
  255. className={`relative border-0 shadow-lg hover:shadow-xl transition-all duration-300 hover:-translate-y-1 ${
  256. plan.type === 'yearly' ? 'ring-2 ring-blue-500' : ''
  257. }`}
  258. >
  259. {plan.type === 'yearly' && (
  260. <div className="absolute -top-3 left-1/2 transform -translate-x-1/2">
  261. <Badge className="bg-gradient-to-r from-blue-600 to-purple-600 text-white">
  262. 推荐
  263. </Badge>
  264. </div>
  265. )}
  266. <CardHeader>
  267. <div className="text-center">
  268. <h3 className="text-2xl font-bold mb-2">{plan.name}</h3>
  269. <div className="text-4xl font-bold text-blue-600 mb-2">
  270. ¥{plan.price}
  271. </div>
  272. <p className="text-gray-600">
  273. {plan.durationDays === 0 ? '永久有效' :
  274. plan.durationDays === 1 ? '24小时有效' :
  275. `${plan.durationDays}天有效`}
  276. </p>
  277. </div>
  278. </CardHeader>
  279. <CardContent>
  280. <ul className="space-y-3">
  281. {plan.features?.map((feature: string, index: number) => (
  282. <li key={index} className="flex items-start">
  283. <Check className="h-5 w-5 text-green-500 mr-2 flex-shrink-0 mt-0.5" />
  284. <span className="text-gray-700 text-sm">{feature}</span>
  285. </li>
  286. ))}
  287. </ul>
  288. <Button
  289. className="w-full mt-6 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700"
  290. onClick={() => navigate('/pricing')}
  291. >
  292. 立即选择
  293. </Button>
  294. </CardContent>
  295. </Card>
  296. ))}
  297. </div>
  298. </div>
  299. </div>
  300. {/* How It Works */}
  301. <div className="py-20 bg-white">
  302. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  303. <div className="text-center mb-16">
  304. <h2 className="text-4xl font-bold text-gray-900 mb-4">
  305. 简单三步,完成批量处理
  306. </h2>
  307. <p className="text-xl text-gray-600">
  308. 无需复杂配置,轻松上手
  309. </p>
  310. </div>
  311. <div className="grid md:grid-cols-3 gap-8">
  312. {[
  313. { step: 1, title: "上传模板", description: "选择Word模板文件,支持{字段名}和{%图片名%}占位符", icon: <Upload className="h-8 w-8" /> },
  314. { step: 2, title: "导入数据", description: "上传Excel数据文件,自动匹配模板字段", icon: <FileText className="h-8 w-8" /> },
  315. { step: 3, title: "批量生成", description: "一键生成所有个性化文档,支持批量下载", icon: <Download className="h-8 w-8" /> }
  316. ].map((item, index) => (
  317. <div key={index} className="text-center">
  318. <div className="w-16 h-16 bg-blue-600 text-white rounded-full flex items-center justify-center text-2xl font-bold mx-auto mb-4">
  319. {item.step}
  320. </div>
  321. <h3 className="text-xl font-semibold mb-2">{item.title}</h3>
  322. <p className="text-gray-600">{item.description}</p>
  323. </div>
  324. ))}
  325. </div>
  326. </div>
  327. </div>
  328. {/* Application Scenarios */}
  329. <div className="py-20 bg-white">
  330. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  331. <div className="text-center mb-16">
  332. <h2 className="text-4xl font-bold text-gray-900 mb-4">
  333. 应用场景
  334. </h2>
  335. <p className="text-xl text-gray-600 max-w-3xl mx-auto">
  336. 元亨WORD批量处理广泛应用于各类重复性文档工作场景
  337. </p>
  338. </div>
  339. <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
  340. {[
  341. {
  342. title: "项目资料安装调试表",
  343. description: "批量生成项目安装调试记录表,自动填充项目名称、设备型号、安装位置等关键信息",
  344. icon: <FileText className="h-8 w-8" />,
  345. color: "text-blue-600"
  346. },
  347. {
  348. title: "项目勘察设计点位表",
  349. description: "快速生成勘察设计点位标记文档,包含坐标、尺寸、材质等详细参数",
  350. icon: <Package className="h-8 w-8" />,
  351. color: "text-green-600"
  352. },
  353. {
  354. title: "合同批量生成",
  355. description: "基于标准合同模板,批量生成个性化合同文档,自动填充客户信息、金额等变量",
  356. icon: <Shield className="h-8 w-8" />,
  357. color: "text-purple-600"
  358. },
  359. {
  360. title: "报告文档自动化",
  361. description: "将固定格式的报告模板与数据源结合,自动生成包含不同数据的完整报告",
  362. icon: <FileText className="h-8 w-8" />,
  363. color: "text-orange-600"
  364. },
  365. {
  366. title: "证书批量制作",
  367. description: "批量生成各类证书、证明文件,自动填充获奖者信息、日期、编号等",
  368. icon: <CheckCircle className="h-8 w-8" />,
  369. color: "text-red-600"
  370. },
  371. {
  372. title: "表格数据填充",
  373. description: "将Excel数据批量填充到Word表格模板中,适用于各类统计报表生成",
  374. icon: <Settings className="h-8 w-8" />,
  375. color: "text-indigo-600"
  376. }
  377. ].map((scenario, index) => (
  378. <Card key={index} className="border-0 shadow-lg hover:shadow-xl transition-all duration-300">
  379. <CardHeader>
  380. <div className={`p-3 rounded-lg bg-gray-50 inline-block mb-4 ${scenario.color}`}>
  381. {scenario.icon}
  382. </div>
  383. <CardTitle className="text-xl">{scenario.title}</CardTitle>
  384. </CardHeader>
  385. <CardContent>
  386. <CardDescription className="text-base">
  387. {scenario.description}
  388. </CardDescription>
  389. </CardContent>
  390. </Card>
  391. ))}
  392. </div>
  393. <div className="mt-12 text-center">
  394. <div className="bg-gradient-to-r from-blue-50 to-purple-50 rounded-xl p-8">
  395. <h3 className="text-2xl font-bold text-gray-900 mb-4">核心技术特征</h3>
  396. <p className="text-lg text-gray-700 max-w-4xl mx-auto">
  397. 适用于所有符合"基础格式固定、核心信息可变量替换"特征的文档场景。
  398. 通过自动化"重复的格式排版、固定内容录入"工作,让您专注于"差异化信息填充",
  399. 大幅减少人工冗余操作,提升工作效率10倍以上。
  400. </p>
  401. </div>
  402. </div>
  403. </div>
  404. </div>
  405. {/* CTA Section */}
  406. <div className="py-20 bg-gradient-to-r from-blue-600 to-purple-600">
  407. <div className="max-w-4xl mx-auto text-center px-4 sm:px-6 lg:px-8">
  408. <h2 className="text-4xl font-bold text-white mb-4">
  409. 开始您的文档批量处理之旅
  410. </h2>
  411. <p className="text-xl text-blue-100 mb-8">
  412. 立即体验高效、智能的文档处理方式
  413. </p>
  414. <Button
  415. size="xl"
  416. className="bg-white text-blue-600 hover:bg-gray-100 px-12 py-4 text-xl font-semibold"
  417. onClick={() => navigate('/word-preview')}
  418. >
  419. <Shield className="h-5 w-5 mr-2" />
  420. 免费开始使用(5份以内3次免费体验)
  421. </Button>
  422. </div>
  423. </div>
  424. {/* Footer */}
  425. <footer className="bg-gray-900 text-white py-12">
  426. <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  427. <div className="text-center">
  428. <h3 className="text-2xl font-bold mb-4">元亨Word批量处理工具</h3>
  429. <p className="text-gray-400 mb-6">
  430. 让每一份文档都充满个性,让批量处理变得简单
  431. </p>
  432. <div className="flex justify-center space-x-6">
  433. <Button
  434. variant="ghost"
  435. className="text-white hover:text-blue-400"
  436. onClick={() => navigate('/word-preview')}
  437. >
  438. 立即体验
  439. </Button>
  440. </div>
  441. </div>
  442. </div>
  443. </footer>
  444. <UserInfoModal
  445. isOpen={showUserModal}
  446. onClose={() => setShowUserModal(false)}
  447. />
  448. </div>
  449. );
  450. }