Skip to content

Commit c4e3d75

Browse files
authored
Merge pull request #1713 from ChinoKou/dev
feat: WebUI 添加更新标签页组件以显示可更新插件
2 parents 22b164f + 024bb72 commit c4e3d75

2 files changed

Lines changed: 110 additions & 28 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import type { GitStatus, MaimaiVersion, PluginInfo, PluginLoadProgress, PluginStatsData } from './types'
2+
import { PluginCard } from './PluginCard'
3+
4+
interface UpdatesTabProps {
5+
plugins: PluginInfo[]
6+
searchQuery: string
7+
categoryFilter: string
8+
showCompatibleOnly: boolean
9+
gitStatus: GitStatus | null
10+
maimaiVersion: MaimaiVersion | null
11+
pluginStats: Record<string, PluginStatsData>
12+
loadProgress: PluginLoadProgress | null
13+
onInstall: (plugin: PluginInfo) => void
14+
onUpdate: (plugin: PluginInfo) => void
15+
onUninstall: (plugin: PluginInfo) => void
16+
checkPluginCompatibility: (plugin: PluginInfo) => boolean
17+
needsUpdate: (plugin: PluginInfo) => boolean
18+
getStatusBadge: (plugin: PluginInfo) => React.JSX.Element | null
19+
getIncompatibleReason: (plugin: PluginInfo) => string | null
20+
}
21+
22+
export function UpdatesTab({
23+
plugins,
24+
searchQuery,
25+
categoryFilter,
26+
showCompatibleOnly,
27+
gitStatus,
28+
maimaiVersion,
29+
pluginStats,
30+
loadProgress,
31+
onInstall,
32+
onUpdate,
33+
onUninstall,
34+
checkPluginCompatibility,
35+
needsUpdate,
36+
getStatusBadge,
37+
getIncompatibleReason,
38+
}: UpdatesTabProps) {
39+
// 过滤可更新插件
40+
const filteredPlugins = plugins.filter(plugin => {
41+
// 跳过没有 manifest 的插件
42+
if (!plugin.manifest) {
43+
return false
44+
}
45+
46+
// 只显示已安装且可更新
47+
if (!plugin.installed || !needsUpdate(plugin)) {
48+
return false
49+
}
50+
51+
// 搜索过滤
52+
const matchesSearch = searchQuery === '' ||
53+
plugin.manifest.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
54+
plugin.manifest.description?.toLowerCase().includes(searchQuery.toLowerCase()) ||
55+
(plugin.manifest.keywords && plugin.manifest.keywords.some(k => k.toLowerCase().includes(searchQuery.toLowerCase())))
56+
57+
// 分类过滤
58+
const matchesCategory = categoryFilter === 'all' ||
59+
(plugin.manifest.categories && plugin.manifest.categories.includes(categoryFilter))
60+
61+
// 兼容性过滤
62+
const matchesCompatibility = !showCompatibleOnly ||
63+
!maimaiVersion ||
64+
checkPluginCompatibility(plugin)
65+
66+
return matchesSearch && matchesCategory && matchesCompatibility
67+
})
68+
69+
return (
70+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-5">
71+
{filteredPlugins.map((plugin) => (
72+
<PluginCard
73+
key={plugin.id}
74+
plugin={plugin}
75+
gitStatus={gitStatus}
76+
maimaiVersion={maimaiVersion}
77+
pluginStats={pluginStats}
78+
loadProgress={loadProgress}
79+
onInstall={onInstall}
80+
onUpdate={onUpdate}
81+
onUninstall={onUninstall}
82+
checkPluginCompatibility={checkPluginCompatibility}
83+
needsUpdate={needsUpdate}
84+
getStatusBadge={getStatusBadge}
85+
getIncompatibleReason={getIncompatibleReason}
86+
/>
87+
))}
88+
</div>
89+
)
90+
}

dashboard/src/routes/plugins/index.tsx

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
import { InstallDialog } from './InstallDialog'
3939
import { InstalledTab } from './InstalledTab'
4040
import { MarketplaceTab } from './MarketplaceTab'
41+
import { UpdatesTab } from './UpdatesTab'
4142
import type { GitStatus, MaimaiVersion, MarketplaceSortKey, PluginInfo, PluginLoadProgress } from './types'
4243

4344
// 主导出组件:包装 RestartProvider
@@ -712,25 +713,6 @@ function PluginsPageContent() {
712713
}).length
713714
}
714715

715-
// 过滤插件用于可更新标签页
716-
const filteredUpdatablePlugins = plugins.filter(plugin => {
717-
if (!plugin.manifest) return false
718-
719-
const matchesSearch = searchQuery === '' ||
720-
plugin.manifest.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
721-
plugin.manifest.description?.toLowerCase().includes(searchQuery.toLowerCase()) ||
722-
(plugin.manifest.keywords && plugin.manifest.keywords.some(k => k.toLowerCase().includes(searchQuery.toLowerCase())))
723-
724-
const matchesCategory = categoryFilter === 'all' ||
725-
(plugin.manifest.categories && plugin.manifest.categories.includes(categoryFilter))
726-
727-
const matchesCompatibility = !showCompatibleOnly ||
728-
!maimaiVersion ||
729-
checkPluginCompatibility(plugin)
730-
731-
return plugin.installed && needsUpdate(plugin) && matchesSearch && matchesCategory && matchesCompatibility
732-
})
733-
734716
return (
735717
<ScrollArea className="h-full">
736718
<div className="space-y-6 p-4 sm:p-6">
@@ -969,15 +951,25 @@ function PluginsPageContent() {
969951
getStatusBadge={getStatusBadge}
970952
getIncompatibleReason={getIncompatibleReason}
971953
/>
972-
) : (
973-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
974-
{filteredUpdatablePlugins.map((plugin) => (
975-
<div key={plugin.id}>
976-
{/* PluginCard would go here */}
977-
</div>
978-
))}
979-
</div>
980-
)}
954+
) : activeTab === 'updates' ? (
955+
<UpdatesTab
956+
plugins={plugins}
957+
searchQuery={searchQuery}
958+
categoryFilter={categoryFilter}
959+
showCompatibleOnly={showCompatibleOnly}
960+
gitStatus={gitStatus}
961+
maimaiVersion={maimaiVersion}
962+
pluginStats={pluginStats}
963+
loadProgress={loadProgress}
964+
onInstall={openInstallDialog}
965+
onUpdate={handleUpdate}
966+
onUninstall={handleUninstall}
967+
checkPluginCompatibility={checkPluginCompatibility}
968+
needsUpdate={needsUpdate}
969+
getStatusBadge={getStatusBadge}
970+
getIncompatibleReason={getIncompatibleReason}
971+
/>
972+
) : null}
981973

982974
{/* 安装对话框 */}
983975
<InstallDialog

0 commit comments

Comments
 (0)