返回 AiToEarn
PluginNotInstalled.tsx
根目录 / project / aitoearn-web / src / components / Plugin / PluginNotInstalled.tsx
1 /**
2 * PluginNotInstalled - 插件未安装状态组件
3 * 显示下载引导和安装说明,移动端显示桌面端专用提示
4 */
5
6 'use client'
7
8 import { BookOpen, Chrome, CloudDownload, Github, Monitor, Puzzle } from 'lucide-react'
9 import Link from 'next/link'
10 import { useTranslation } from 'react-i18next'
11 import { useChannelManagerStore } from '@/components/ChannelManager'
12 import { Button } from '@/components/ui/button'
13 import { useIsMobile } from '@/hooks/useIsMobile'
14 import { usePluginStore } from '@/store/plugin'
15 import { PLUGIN_DOWNLOAD_LINKS } from '@/store/plugin/constants'
16
17 /**
18 * 移动端提示组件 - 提示用户前往 PC 端使用插件
19 */
20 function MobilePluginTip() {
21 const { t } = useTranslation('plugin')
22
23 return (
24 <div className="flex flex-col items-center py-6 px-4">
25 {/* 图标 */}
26 <div className="mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10">
27 <Monitor className="h-8 w-8 text-primary" />
28 </div>
29
30 {/* 标题 */}
31 <h3 className="mb-2 text-base font-semibold text-foreground">{t('mobile.title')}</h3>
32
33 {/* 描述 */}
34 <p className="mb-6 max-w-sm text-center text-sm text-muted-foreground">
35 {t('mobile.description')}
36 </p>
37
38 {/* 前往 PC 端提示 */}
39 <div className="mb-6 flex w-full items-center justify-center gap-2 rounded-lg border border-primary/20 bg-primary/5 px-4 py-3">
40 <Monitor className="h-4 w-4 shrink-0 text-primary" />
41 <span className="text-sm font-medium text-primary">{t('mobile.goToPC')}</span>
42 </div>
43
44 {/* 插件介绍卡片 */}
45 <div className="w-full rounded-lg border border-border bg-muted/30 p-5">
46 <div className="mb-2 flex items-center gap-2">
47 <Puzzle className="h-5 w-5 text-muted-foreground" />
48 <span className="text-sm font-medium text-muted-foreground">{t('header.downloadPlugin')}</span>
49 </div>
50 <p className="text-sm leading-relaxed text-muted-foreground">
51 {t('mobile.introduction')}
52 </p>
53 </div>
54 </div>
55 )
56 }
57
58 /**
59 * 插件未安装状态组件
60 */
61 export function PluginNotInstalled() {
62 const { t } = useTranslation('plugin')
63 const isMobile = useIsMobile()
64 const closePluginModal = usePluginStore(state => state.closePluginModal)
65 const closeChannelManager = useChannelManagerStore(state => state.closeModal)
66
67 const handleViewGuide = () => {
68 closePluginModal()
69 closeChannelManager()
70 }
71
72 if (isMobile) {
73 return <MobilePluginTip />
74 }
75
76 return (
77 <div className="flex flex-col items-center py-8 px-4">
78 {/* 图标 */}
79 <div className="mb-6 flex h-20 w-20 items-center justify-center rounded-full bg-primary/10">
80 <Puzzle className="h-10 w-10 text-primary" />
81 </div>
82
83 {/* 标题 */}
84 <h3 className="mb-2 text-lg font-semibold text-foreground">{t('header.downloadPlugin')}</h3>
85
86 {/* 描述 */}
87 <p className="mb-8 max-w-sm text-center text-sm text-muted-foreground">
88 {t('header.downloadDescription')}
89 </p>
90
91 {/* 下载按钮 */}
92 <div className="flex w-full max-w-xs flex-col space-y-3">
93 <Button className="w-full gap-2" asChild>
94 <a href={PLUGIN_DOWNLOAD_LINKS.chrome} target="_blank" rel="noopener noreferrer">
95 <Chrome className="h-4 w-4" />
96 {t('header.chromeWebStore')}
97 </a>
98 </Button>
99
100 <Button variant="outline" className="w-full gap-2" asChild>
101 <a href={PLUGIN_DOWNLOAD_LINKS.china} target="_blank" rel="noopener noreferrer">
102 <CloudDownload className="h-4 w-4" />
103 {t('header.chinaLatestZipDownload')}
104 </a>
105 </Button>
106
107 <Button variant="outline" className="w-full gap-2" asChild>
108 <a href={PLUGIN_DOWNLOAD_LINKS.github} target="_blank" rel="noopener noreferrer">
109 <Github className="h-4 w-4" />
110 {t('header.githubLatestDownload')}
111 </a>
112 </Button>
113 </div>
114
115 {/* 查看安装教程链接 */}
116 <Link
117 href="/websit/plugin-guide"
118 onClick={handleViewGuide}
119 className="mt-6 flex items-center justify-center gap-2 w-full max-w-xs px-4 py-3 rounded-lg bg-amber-50 dark:bg-amber-950/30 border border-amber-200 dark:border-amber-800 text-amber-700 dark:text-amber-400 hover:bg-amber-100 dark:hover:bg-amber-950/50 transition-colors cursor-pointer"
120 >
121 <BookOpen className="h-5 w-5" />
122 <span className="font-medium">{t('header.viewInstallGuide')}</span>
123 </Link>
124 </div>
125 )
126 }
127
127 lines Plain Text