From 0fceeeb2c63c654a6f6e0b604f6ece4db3d8b192 Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 04:11:43 +0800 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96UI=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=A0=B7=E5=BC=8F=E5=92=8C=E4=BA=A4=E4=BA=92=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(RepositoryCard): 增强工具提示在浅色模式下的可读性 feat(ReadmeModal): 添加字体大小类型支持 style(index.css): 改进文本区域和输入框的浅色模式样式 refactor(MarkdownRenderer): 移除行号显示并支持字体大小调整 refactor(RepositoryEditModal): 优化浅色模式下的表单样式和交互 --- src/components/MarkdownRenderer.tsx | 66 +++++-------- src/components/ReadmeModal.tsx | 13 +++ src/components/RepositoryCard.tsx | 16 +-- src/components/RepositoryEditModal.tsx | 129 +++++++++++++------------ src/index.css | 103 ++++++++++++++++++++ 5 files changed, 214 insertions(+), 113 deletions(-) diff --git a/src/components/MarkdownRenderer.tsx b/src/components/MarkdownRenderer.tsx index 00f8e3c2..b722eb1d 100644 --- a/src/components/MarkdownRenderer.tsx +++ b/src/components/MarkdownRenderer.tsx @@ -18,6 +18,7 @@ interface MarkdownRendererProps { enableHtml?: boolean; baseUrl?: string; headingIds?: Map; + fontSize?: 'small' | 'medium' | 'large'; } const REMARK_PLUGINS = [remarkGfm, remarkBreaks]; @@ -92,10 +93,6 @@ const CodeBlock: React.FC<{ } }, [codeText, uiLanguage]); - const codeLines = codeText.split('\n'); - const lineCount = codeLines.length; - const showLineNumbers = lineCount > 3; - const isBashLike = ['bash', 'sh', 'shell', 'zsh'].includes(normalizedLanguage); const isPowerShell = ['powershell', 'ps1'].includes(normalizedLanguage); const isCmdLike = ['cmd', 'bat'].includes(normalizedLanguage); @@ -141,11 +138,6 @@ const CodeBlock: React.FC<{ )}
- {showLineNumbers && ( - - {lineCount} {uiLanguage === 'zh' ? '行' : 'lines'} - - )}
); @@ -481,7 +448,9 @@ const MarkdownImage: React.FC<{ src?: string; alt?: string; baseUrl?: string }> setIsLoading(false); }, []); - const handleRetry = useCallback(() => { + const handleRetry = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); setHasError(false); setIsLoading(true); setImageSizeKnown(false); @@ -784,7 +753,8 @@ const MarkdownRenderer: React.FC = memo(({ shouldRender = true, enableHtml = false, baseUrl, - headingIds + headingIds, + fontSize = 'medium' }) => { const headingCounterRef = useRef(headingIds?.size ?? 0); const headingTextCountMapRef = useRef(new Map()); @@ -796,6 +766,18 @@ const MarkdownRenderer: React.FC = memo(({ const rehypePlugins = enableHtml ? REHYPE_PLUGINS_WITH_HTML : REHYPE_PLUGINS_NO_HTML; + const getProseClass = useCallback(() => { + switch (fontSize) { + case 'small': + return 'prose prose-xs dark:prose-invert'; + case 'large': + return 'prose prose-lg dark:prose-invert'; + case 'medium': + default: + return 'prose prose-sm dark:prose-invert'; + } + }, [fontSize]); + const getHeadingId = useCallback((children: React.ReactNode): string | undefined => { if (headingIds && headingIds.size > 0) { const text = extractTextFromChildren(children); @@ -933,7 +915,7 @@ const MarkdownRenderer: React.FC = memo(({ } return ( -
+
= ({ const currentFontSize = FONT_SIZES[fontSizeIndex].value; + const getFontSizeType = useCallback((): 'small' | 'medium' | 'large' => { + switch (fontSizeIndex) { + case 0: + return 'small'; + case 2: + return 'large'; + case 1: + default: + return 'medium'; + } + }, [fontSizeIndex]); + const extractToc = useCallback((content: string): { items: TocItem[], idMap: Map } => { const items: TocItem[] = []; const idMap = new Map(); @@ -477,6 +489,7 @@ export const ReadmeModal: React.FC = ({ enableHtml={true} baseUrl={repository?.html_url} headingIds={headingIdMap} + fontSize={getFontSizeType()} /> ) : (
diff --git a/src/components/RepositoryCard.tsx b/src/components/RepositoryCard.tsx index 71ce7297..f02243c4 100644 --- a/src/components/RepositoryCard.tsx +++ b/src/components/RepositoryCard.tsx @@ -873,28 +873,28 @@ const RepositoryCardComponent: React.FC = ({
- {/* Description with Tooltip */} + {/* Description with Tooltip - Enhanced for Light Mode */}
isTextTruncated && setShowTooltip(true)} onMouseLeave={() => setShowTooltip(false)} >

{highlightSearchTerm(displayContent.content, searchQuery)}

- {/* Tooltip - Only show when text is actually truncated */} + {/* Enhanced Tooltip - Optimized for Light Mode Readability */} {isTextTruncated && showTooltip && ( -
-
+
+
{highlightSearchTerm(displayContent.content, searchQuery)}
- {/* Arrow */} -
+ {/* Arrow with Light Mode Optimization */} +
)}
diff --git a/src/components/RepositoryEditModal.tsx b/src/components/RepositoryEditModal.tsx index 4e78de2f..cd6e56ec 100644 --- a/src/components/RepositoryEditModal.tsx +++ b/src/components/RepositoryEditModal.tsx @@ -54,7 +54,7 @@ export const RepositoryEditModal: React.FC = ({ onClose, repository }) => { - const { updateRepository, language, customCategories, hiddenDefaultCategoryIds, defaultCategoryOverrides } = useAppStore(); + const { updateRepository, language, customCategories, hiddenDefaultCategoryIds, defaultCategoryOverrides, theme } = useAppStore(); const [formData, setFormData] = useState({ description: '', @@ -589,12 +589,15 @@ export const RepositoryEditModal: React.FC = ({ if (!repository) return null; - // 统一的卡片样式 - const sectionClass = "p-5 bg-white dark:bg-panel-dark rounded-xl border border-black/[0.06] dark:border-white/[0.04]"; - const labelClass = "flex items-center space-x-2 text-sm font-medium text-gray-900 dark:text-text-primary mb-3"; - const inputClass = "w-full px-3 py-2 bg-light-bg dark:bg-white/[0.04] border border-black/[0.06] dark:border-white/[0.04] rounded-lg text-gray-900 dark:text-text-primary placeholder-gray-400 dark:placeholder-text-tertiary focus:outline-none focus:ring-2 focus:ring-brand-violet focus:border-transparent transition-all"; - const buttonSecondaryClass = "flex items-center space-x-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border transition-all"; - const tagClass = "inline-flex items-center px-2.5 py-1 bg-gray-100 text-gray-700 dark:bg-white/[0.04] dark:text-text-secondary border-transparent rounded-md text-sm border border-black/[0.06] dark:border-white/[0.04] dark:border-white/[0.04]"; + // Unified card styles with enhanced light mode optimization + const sectionClass = "p-5 bg-white dark:bg-panel-dark rounded-xl border border-gray-200/80 dark:border-white/[0.04] shadow-sm"; + const labelClass = "flex items-center space-x-2 text-[13px] font-medium text-gray-900 dark:text-text-primary mb-3"; + const inputClass = "w-full px-4 py-3 bg-gray-50/50 dark:bg-white/[0.04] border border-gray-200 dark:border-white/[0.04] rounded-xl text-gray-900 dark:text-text-primary placeholder-gray-400 dark:placeholder-text-tertiary focus:outline-none focus:ring-2 focus:ring-brand-violet/30 focus:border-brand-violet dark:focus:ring-brand-violet/50 dark:focus:border-brand-violet transition-all duration-200 hover:bg-gray-100/50 dark:hover:bg-white/[0.06] hover:border-gray-300 dark:hover:border-white/[0.08] text-[13px] leading-[1.625]"; + const textareaClass = `${inputClass} resize-y min-h-[120px] max-h-[400px] overflow-y-auto scrollbar-auto`; + const buttonSecondaryClass = "flex items-center space-x-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border transition-all duration-200"; + const tagClass = "inline-flex items-center px-2.5 py-1 bg-gray-100 text-gray-700 dark:bg-white/[0.04] dark:text-text-secondary rounded-md text-sm border border-gray-200/80 dark:border-white/[0.04]"; + const infoBoxClass = "mt-3 p-3.5 bg-gradient-to-br from-gray-50 to-white dark:from-white/[0.02] dark:to-white/[0.04] border border-gray-200/80 dark:border-white/[0.04] rounded-xl text-[12px] leading-[1.5] transition-all duration-200"; + const infoTextClass = "text-gray-700 dark:text-text-secondary flex items-start"; return ( = ({ setFormData(prev => ({ ...prev, description: e.target.value })); setEditIntent(prev => ({ ...prev, description: 'keep-custom' })); }} - className={`${inputClass} resize-none`} - rows={3} + className={textareaClass} + rows={5} placeholder={t('输入自定义描述...', 'Enter custom description...')} /> - {/* Save Effect Info - always visible */} + {/* Save Effect Info - Enhanced for Light Mode */} {editIntent.description === 'clear' ? ( -
-

- +

+

+ {t( '描述已清空,保存后将显示"(无描述)"。即使有AI总结或原始描述也不会显示。', @@ -697,9 +700,9 @@ export const RepositoryEditModal: React.FC = ({

) : editIntent.description === 'reset-to-ai' ? ( -
-

- +

+

+ {t( '保存后将清除自定义描述,显示AI总结。如果AI重新分析,描述可能随之变化。', @@ -709,9 +712,9 @@ export const RepositoryEditModal: React.FC = ({

) : editIntent.description === 'reset-to-original' ? ( -
-

- +

+

+ {t( '保存后将清除自定义描述,显示GitHub原始描述。', @@ -721,9 +724,9 @@ export const RepositoryEditModal: React.FC = ({

) : editIntent.description === 'keep-custom' && (formData.description || '').trim() === '' ? ( -
-

- +

+

+ {repository?.ai_summary ? t('当前编辑为空,保存后将显示AI总结。如需清空请点击"清除描述"。', 'Currently empty. AI summary will be shown after saving. Click "Clear" to explicitly clear.') @@ -734,9 +737,9 @@ export const RepositoryEditModal: React.FC = ({

) : editIntent.description === 'keep-custom' && customStatus.description ? ( -
-

- +

+

+ {t( '保存后将使用此自定义描述,优先级高于AI总结和原始描述。', @@ -746,9 +749,9 @@ export const RepositoryEditModal: React.FC = ({

) : editIntent.description === 'keep-custom' && formData.description.trim() !== '' && !customStatus.description ? ( -
-

- +

+

+ {t( '当前内容与AI总结或原始描述一致,保存后将使用自动推断的来源。', @@ -809,10 +812,10 @@ export const RepositoryEditModal: React.FC = ({

- {/* Feature Tip */} -
-

- + {/* Feature Tip - Enhanced */} +

+

+ {t( '描述优先级:自定义描述 > AI总结 > 原始描述。"重置"会清除自定义并回退到对应来源,"清除"会明确清空描述(不显示任何来源)。', @@ -906,11 +909,11 @@ export const RepositoryEditModal: React.FC = ({

- {/* Custom Category Selection Info */} + {/* Custom Category Selection Info - Enhanced */} {editIntent.category === 'keep-custom' && formData.category && ( -
-

- +

+

+ {t( '已选择自定义分类。保存后仓库将固定显示在此分类中,不会随AI分析结果自动变化。建议同时开启分类锁定以防止同步时被覆盖。', @@ -921,11 +924,11 @@ export const RepositoryEditModal: React.FC = ({

)} - {/* Reset Category Info */} + {/* Reset Category Info - Enhanced */} {editIntent.category === 'reset-to-ai' && ( -
-

- +

+

+ {t( '重置为AI分类将清除自定义分类设置,系统会根据AI标签自动推断分类。如果AI标签变化,分类可能会随之改变。', @@ -937,9 +940,9 @@ export const RepositoryEditModal: React.FC = ({ )} {editIntent.category === 'reset-to-original' && ( -

-

- +

+

+ {t( '重置为默认分类将清除自定义分类设置,系统会根据仓库信息(名称、描述、语言等)自动匹配分类。', @@ -950,11 +953,11 @@ export const RepositoryEditModal: React.FC = ({

)} - {/* Clear Category Warning */} + {/* Clear Category Warning - Enhanced */} {editIntent.category === 'clear' && ( -
-

- +

+

+ {t( '清除分类后,仓库将不再有明确的分类归属。系统会尝试根据AI标签自动匹配分类,如果没有匹配到则可能显示在默认分类中。', @@ -965,8 +968,8 @@ export const RepositoryEditModal: React.FC = ({

)} - {/* Category Lock */} -
+ {/* Category Lock - Enhanced */} +
{formData.categoryLocked && formData.category ? ( @@ -1097,38 +1100,38 @@ export const RepositoryEditModal: React.FC = ({
- {/* Status Alert */} + {/* Status Alert - Enhanced */} {formData.tags.length === 0 && ( -
-

+

+

{editIntent.tags === 'clear' ? ( <> - ⚠️ + ⚠️ {t('标签已清空。保存后将不显示任何标签。', 'Tags cleared. No tags will be shown after saving.')} ) : editIntent.tags === 'reset-to-ai' ? ( <> - + {t('将显示AI标签。', 'AI tags will be shown.')} ) : editIntent.tags === 'reset-to-original' ? ( <> - + {t('将显示GitHub Topics。', 'GitHub Topics will be shown.')} ) : repository?.ai_tags && repository.ai_tags.length > 0 ? ( <> - ⚠️ + ⚠️ {t('当前无自定义标签。保存后将显示AI标签。', 'No custom tags. AI tags will be shown after saving.')} ) : repository?.topics && repository.topics.length > 0 ? ( <> - ⚠️ + ⚠️ {t('当前无自定义标签。保存后将显示GitHub Topics。', 'No custom tags. GitHub Topics will be shown after saving.')} ) : ( <> - ⚠️ + ⚠️ {t('无可用标签。', 'No tags available.')} )} @@ -1160,17 +1163,17 @@ export const RepositoryEditModal: React.FC = ({

- {/* Action Buttons */} -
+ {/* Action Buttons - Enhanced */} +
{isOpen && ( -
+
{sortOptions.map((option) => (
-
-

{t('关于AI搜索', 'About AI Search')}

-

- {activeAIConfig - ? t( - '已配置AI服务时,将调用AI进行语义搜索和智能重排序。未配置时使用本地算法根据仓库名称、描述、标签等多维度进行匹配和排序。', - 'When AI service is configured, it will be called for semantic search and intelligent reranking. Otherwise, local algorithms are used to match and rank based on repository name, description, tags, and other dimensions.' - ) - : t( - '此功能使用本地算法进行智能排序。配置AI服务后可启用语义搜索功能,获得更精准的搜索结果。', - 'This feature uses local algorithms for intelligent ranking. Configure an AI service to enable semantic search for more accurate results.' - )} +

+

{t('关于AI搜索', 'About AI Search')}

+

+ {t( + '使用多维度智能加权算法进行搜索和排序:仓库名称(40%)、描述(32%)、标签(25%)、AI摘要(15%)、平台语言(18%)等维度综合评分,支持精确匹配加成和流行度权重。', + 'Uses multi-dimensional intelligent weighted algorithm for search and ranking: repository name (40%), description (32%), tags (25%), AI summary (15%), platform/language (18%) and other dimensions with exact match bonus and popularity weighting.' + )}

-
+
@@ -975,7 +970,7 @@ export const SearchBar: React.FC = () => {
{/* Sort Controls */} -
+
setSearchFilters({ sortBy: value as 'stars' | 'updated' | 'name' | 'starred' })} From 77f1fb0b3ace2399dd5bf38663f016e26bbbbd17 Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:32:52 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat(store):=20=E6=B7=BB=E5=8A=A0=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=8A=B6=E6=80=81=E6=B0=B4=E5=90=88=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 hasHydrated 状态用于检测 store 是否完成水合 在 App 组件中添加加载状态以确保主题正确应用 更新搜索算法权重描述文案 --- src/App.tsx | 18 +++++++++++++++--- src/components/SearchBar.tsx | 4 ++-- src/store/useAppStore.ts | 13 +++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 6e1f8717..3d25a9da 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -51,11 +51,12 @@ const SettingsView = React.memo(() => ); SettingsView.displayName = 'SettingsView'; function App() { - const { - isAuthenticated, - currentView, + const { + isAuthenticated, + currentView, selectedCategory, theme, + hasHydrated, searchResults, repositories, setSelectedCategory, @@ -71,6 +72,17 @@ function App() { } }, [theme]); + // Show loading state while store is hydrating to ensure correct theme is applied + if (!hasHydrated) { + return ( +
+
+ Loading... +
+
+ ); + } + useEffect(() => { let unsubscribe: (() => void) | null = null; let cancelled = false; diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 230c7d85..5065f7eb 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -903,8 +903,8 @@ export const SearchBar: React.FC = () => {

{t('关于AI搜索', 'About AI Search')}

{t( - '使用多维度智能加权算法进行搜索和排序:仓库名称(40%)、描述(32%)、标签(25%)、AI摘要(15%)、平台语言(18%)等维度综合评分,支持精确匹配加成和流行度权重。', - 'Uses multi-dimensional intelligent weighted algorithm for search and ranking: repository name (40%), description (32%), tags (25%), AI summary (15%), platform/language (18%) and other dimensions with exact match bonus and popularity weighting.' + '多维度智能加权算法(累积得分制):名称(0.40分)、路径(0.35分)、自定义描述(0.32分)、描述(0.30分)、Topics(0.25分)、自定义标签(0.24分)、AI标签(0.22分)、平台(0.18分)、AI摘要(0.15分)、语言(0.12分)。支持精确匹配加分(+0.50/+0.30)和流行度加成。', + 'Multi-dimensional weighted algorithm (cumulative scoring): name(0.40), path(0.35), custom desc(0.32), desc(0.30), topics(0.25), custom tags(0.24), AI tags(0.22), platform(0.18), AI summary(0.15), language(0.12). Supports exact match bonus (+0.50/+0.30) and popularity boost.' )}

diff --git a/src/store/useAppStore.ts b/src/store/useAppStore.ts index 9912a231..5e380ded 100644 --- a/src/store/useAppStore.ts +++ b/src/store/useAppStore.ts @@ -145,6 +145,9 @@ interface AppActions { setLanguage: (language: 'zh' | 'en') => void; setSidebarCollapsed: (collapsed: boolean) => void; setReadmeModalOpen: (open: boolean) => void; + + // Hydration state + setHasHydrated: (hydrated: boolean) => void; // Update actions setUpdateNotification: (notification: UpdateNotification | null) => void; @@ -643,6 +646,7 @@ export const useAppStore = create()( collapsedSidebarCategoryCount: 20, assetFilters: defaultPresetFilters, theme: 'dark', + hasHydrated: false, currentView: 'repositories', selectedCategory: 'all', language: 'zh', @@ -1150,6 +1154,9 @@ export const useAppStore = create()( setLanguage: (language) => set({ language }), setSidebarCollapsed: (isSidebarCollapsed) => set({ isSidebarCollapsed }), setReadmeModalOpen: (readmeModalOpen) => set({ readmeModalOpen }), + + // Hydration state + setHasHydrated: (hasHydrated) => set({ hasHydrated }), // Update actions setUpdateNotification: (notification) => set({ updateNotification: notification }), @@ -1488,6 +1495,12 @@ export const useAppStore = create()( ...normalized, }; }, + onRehydrateStorage: () => (state) => { + console.log('Store hydration complete'); + if (state) { + state.setHasHydrated(true); + } + }, } ) ); From 2fc71588448dc6ef5979aaf37ac16938d3dd3b3c Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:40:29 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feat(SearchBar):=20=E6=A0=B9=E6=8D=AEAI?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8A=A8=E6=80=81=E6=98=BE=E7=A4=BA=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A8=A1=E5=BC=8F=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根据activeAIConfig状态动态显示不同的搜索模式说明,当启用AI配置时显示语义搜索模式说明,否则显示本地智能排序说明 --- src/components/SearchBar.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 5065f7eb..5a295d13 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -900,11 +900,16 @@ export const SearchBar: React.FC = () => {
-

{t('关于AI搜索', 'About AI Search')}

+

+ {t('关于AI搜索', 'About AI Search')} +

- {t( - '多维度智能加权算法(累积得分制):名称(0.40分)、路径(0.35分)、自定义描述(0.32分)、描述(0.30分)、Topics(0.25分)、自定义标签(0.24分)、AI标签(0.22分)、平台(0.18分)、AI摘要(0.15分)、语言(0.12分)。支持精确匹配加分(+0.50/+0.30)和流行度加成。', - 'Multi-dimensional weighted algorithm (cumulative scoring): name(0.40), path(0.35), custom desc(0.32), desc(0.30), topics(0.25), custom tags(0.24), AI tags(0.22), platform(0.18), AI summary(0.15), language(0.12). Supports exact match bonus (+0.50/+0.30) and popularity boost.' + {activeAIConfig ? t( + 'AI语义搜索模式:使用配置的AI服务进行智能语义理解和重排序。AI将分析查询意图,理解上下文关系,并提供语义相关的搜索结果。支持自然语言查询和概念匹配。', + 'AI semantic search mode: Uses configured AI service for intelligent semantic understanding and reranking. AI analyzes query intent, understands context, and provides semantically relevant results. Supports natural language queries and concept matching.' + ) : t( + '本地智能排序(累积得分制):名称(0.40分)、路径(0.35分)、自定义描述(0.32分)、描述(0.30分)、Topics(0.25分)、自定义标签(0.24分)、AI标签(0.22分)、平台(0.18分)、AI摘要(0.15分)、语言(0.12分)。支持精确匹配加分(+0.50/+0.30)和流行度加成。', + 'Local intelligent ranking (cumulative scoring): name(0.40), path(0.35), custom desc(0.32), desc(0.30), topics(0.25), custom tags(0.24), AI tags(0.22), platform(0.18), AI summary(0.15), language(0.12). Supports exact match bonus (+0.50/+0.30) and popularity boost.' )}

From 6b056a95b243230a5ec48ba37813f2328631e2a2 Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:44:49 +0800 Subject: [PATCH 6/9] =?UTF-8?q?refactor(App):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E7=8A=B6=E6=80=81=E6=B8=B2=E6=9F=93=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E4=BB=A5=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将加载状态的渲染逻辑移动到useEffect之后,使组件初始化逻辑更清晰 --- src/App.tsx | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 3d25a9da..e57d0279 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -72,17 +72,6 @@ function App() { } }, [theme]); - // Show loading state while store is hydrating to ensure correct theme is applied - if (!hasHydrated) { - return ( -
-
- Loading... -
-
- ); - } - useEffect(() => { let unsubscribe: (() => void) | null = null; let cancelled = false; @@ -111,6 +100,17 @@ function App() { }; }, []); + // Show loading state while store is hydrating to ensure correct theme is applied + if (!hasHydrated) { + return ( +
+
+ Loading... +
+
+ ); + } + const handleCategorySelect = useCallback((category: string) => { setSelectedCategory(category); }, [setSelectedCategory]); From 87a7138c5746e06bbe9bef031afd6890b6ce9f54 Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:27:20 +0800 Subject: [PATCH 7/9] =?UTF-8?q?refactor(App):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E7=8A=B6=E6=80=81=E5=92=8C=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E7=9A=84=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将加载状态的渲染逻辑移到认证检查之前,确保主题正确应用后再进行认证检查 --- src/App.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index e57d0279..36016a72 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -100,17 +100,6 @@ function App() { }; }, []); - // Show loading state while store is hydrating to ensure correct theme is applied - if (!hasHydrated) { - return ( -
-
- Loading... -
-
- ); - } - const handleCategorySelect = useCallback((category: string) => { setSelectedCategory(category); }, [setSelectedCategory]); @@ -119,7 +108,7 @@ function App() { switch (currentView) { case 'repositories': return ( - +
+ Loading... +
+
+ ); + } + if (!isAuthenticated) { return ; } From 856cf8e87529ab38f5028ec57dd9ccb9937b61b6 Mon Sep 17 00:00:00 2001 From: Happy Summer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:28:37 +0800 Subject: [PATCH 8/9] =?UTF-8?q?fix(SearchBar):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=A8=A1=E5=BC=8F=E6=8F=8F=E8=BF=B0=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E4=B8=BA=E5=9B=9E=E9=80=80=E6=A8=A1=E5=BC=8F=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SearchBar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 5a295d13..21985539 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -908,8 +908,8 @@ export const SearchBar: React.FC = () => { 'AI语义搜索模式:使用配置的AI服务进行智能语义理解和重排序。AI将分析查询意图,理解上下文关系,并提供语义相关的搜索结果。支持自然语言查询和概念匹配。', 'AI semantic search mode: Uses configured AI service for intelligent semantic understanding and reranking. AI analyzes query intent, understands context, and provides semantically relevant results. Supports natural language queries and concept matching.' ) : t( - '本地智能排序(累积得分制):名称(0.40分)、路径(0.35分)、自定义描述(0.32分)、描述(0.30分)、Topics(0.25分)、自定义标签(0.24分)、AI标签(0.22分)、平台(0.18分)、AI摘要(0.15分)、语言(0.12分)。支持精确匹配加分(+0.50/+0.30)和流行度加成。', - 'Local intelligent ranking (cumulative scoring): name(0.40), path(0.35), custom desc(0.32), desc(0.30), topics(0.25), custom tags(0.24), AI tags(0.22), platform(0.18), AI summary(0.15), language(0.12). Supports exact match bonus (+0.50/+0.30) and popularity boost.' + '回退模式:基础文本搜索与默认排序。当未配置AI服务时,系统将使用基础文本匹配进行搜索(支持名称、描述、标签、语言等字段),并应用标准的排序和过滤控制。此为轻量级搜索方案,无语义理解能力。', + 'Fallback mode: Basic text search with default sorting. When no AI service is configured, the system uses basic text matching for search (supports name, description, tags, language, etc.) and applies standard sort and filter controls. This is a lightweight search solution without semantic understanding capabilities.' )}

From e5ba02cf3094c6dcbd79956b8f651c2f60f18bc4 Mon Sep 17 00:00:00 2001 From: HappySummer <141414769+SummerRay160@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:37:22 +0800 Subject: [PATCH 9/9] Update src/store/useAppStore.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/store/useAppStore.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/store/useAppStore.ts b/src/store/useAppStore.ts index 5e380ded..e06afd63 100644 --- a/src/store/useAppStore.ts +++ b/src/store/useAppStore.ts @@ -1495,11 +1495,13 @@ export const useAppStore = create()( ...normalized, }; }, - onRehydrateStorage: () => (state) => { - console.log('Store hydration complete'); - if (state) { - state.setHasHydrated(true); + onRehydrateStorage: (state) => (_rehydratedState, error) => { + if (error) { + console.error('Store hydration failed', error); + } else { + console.log('Store hydration complete'); } + state.setHasHydrated(true); }, } )