From 6194222289494a5894e879f449f665dd30e103a1 Mon Sep 17 00:00:00 2001 From: zhaoying Date: Mon, 2 Feb 2026 16:25:17 +0800 Subject: [PATCH 1/3] docs: add comments to the src/hooks directory --- web/src/hooks/useBreadcrumbManager.ts | 94 +++++++++++++++-------- web/src/hooks/useNavigationBreadcrumbs.ts | 41 +++++++--- web/src/hooks/useRouteGuard.ts | 53 +++++++++---- 3 files changed, 130 insertions(+), 58 deletions(-) diff --git a/web/src/hooks/useBreadcrumbManager.ts b/web/src/hooks/useBreadcrumbManager.ts index 54095925..161fbb65 100644 --- a/web/src/hooks/useBreadcrumbManager.ts +++ b/web/src/hooks/useBreadcrumbManager.ts @@ -1,25 +1,52 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:24:44 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:24:44 + */ +/** + * useBreadcrumbManager Hook + * + * Manages breadcrumb navigation for knowledge base pages with: + * - Dynamic breadcrumb generation based on folder/document paths + * - Separate breadcrumb handling for list and detail views + * - Click handlers for navigation between folders + * - Support for custom callbacks + * + * @hook + */ + import { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { useMenu } from '@/store/menu'; import type { MenuItem } from '@/store/menu'; +/** Breadcrumb item interface */ export interface BreadcrumbItem { id: string; name: string; type?: 'knowledgeBase' | 'folder' | 'document'; } +/** Breadcrumb path structure */ export interface BreadcrumbPath { - knowledgeBaseFolderPath: BreadcrumbItem[]; // 知识库文件夹路径 - knowledgeBase?: BreadcrumbItem; // 知识库信息 - documentFolderPath: BreadcrumbItem[]; // 文档文件夹路径 - document?: BreadcrumbItem; // 文档信息 + /** Knowledge base folder path */ + knowledgeBaseFolderPath: BreadcrumbItem[]; + /** Knowledge base information */ + knowledgeBase?: BreadcrumbItem; + /** Document folder path */ + documentFolderPath: BreadcrumbItem[]; + /** Document information */ + document?: BreadcrumbItem; } +/** Options for breadcrumb manager */ export interface BreadcrumbOptions { + /** Callback when knowledge base menu is clicked */ onKnowledgeBaseMenuClick?: () => void; + /** Callback when knowledge base folder is clicked */ onKnowledgeBaseFolderClick?: (folderId: string, folderPath: BreadcrumbItem[]) => void; - // 新增:区分面包屑类型 + /** Breadcrumb type: list or detail view */ breadcrumbType?: 'list' | 'detail'; } @@ -27,14 +54,15 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { const { allBreadcrumbs, setCustomBreadcrumbs } = useMenu(); const navigate = useNavigate(); + /** Update breadcrumbs based on current path and type */ const updateBreadcrumbs = useCallback((breadcrumbPath: BreadcrumbPath) => { const breadcrumbType = options?.breadcrumbType || 'list'; - // 对于详情页面,直接使用固定的知识库管理面包屑,不依赖可能被污染的 allBreadcrumbs + /** For detail pages, use fixed knowledge base breadcrumb */ let baseBreadcrumbs: MenuItem[] = []; if (breadcrumbType === 'detail') { - // 详情页面:始终使用固定的知识库管理面包屑 + /** Detail page: always use fixed knowledge base management breadcrumb */ baseBreadcrumbs = [ { id: 6, @@ -61,14 +89,14 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { } ]; } else { - // 列表页面:从 space 获取基础面包屑,但确保包含知识库管理 + /** List page: get base breadcrumbs from space, ensure knowledge base management is included */ const spaceBreadcrumbs = allBreadcrumbs['space'] || []; const knowledgeBaseMenuIndex = spaceBreadcrumbs.findIndex(item => item.path === '/knowledge-base'); if (knowledgeBaseMenuIndex >= 0) { baseBreadcrumbs = spaceBreadcrumbs.slice(0, knowledgeBaseMenuIndex + 1); } else { - // 如果没有找到知识库菜单,使用默认的知识库管理面包屑 + /** If knowledge base menu not found, use default knowledge base management breadcrumb */ baseBreadcrumbs = [ { id: 6, @@ -99,7 +127,7 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { const filteredBaseBreadcrumbs = baseBreadcrumbs; - // 给"知识库管理"添加点击事件 + /** Add click event to "Knowledge Base Management" */ const breadcrumbsWithClick = filteredBaseBreadcrumbs.map((item) => { if (item.path === '/knowledge-base') { return { @@ -109,10 +137,10 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { e?.stopPropagation(); if (options?.onKnowledgeBaseMenuClick) { - // 如果提供了回调函数,执行回调 + /** If callback provided, execute callback */ options.onKnowledgeBaseMenuClick(); } else if (breadcrumbType === 'detail') { - // 知识库详情页面:没有回调函数时,返回到知识库列表页面 + /** Knowledge base detail page: return to knowledge base list page when no callback */ navigate('/knowledge-base', { state: { resetToRoot: true, @@ -129,7 +157,7 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { let customBreadcrumbs: MenuItem[] = [...breadcrumbsWithClick]; if (breadcrumbType === 'list') { - // 知识库列表页面:只显示知识库文件夹路径 + /** Knowledge base list page: only show knowledge base folder path */ customBreadcrumbs = [ ...breadcrumbsWithClick, ...breadcrumbPath.knowledgeBaseFolderPath.map((folder, index) => ({ @@ -158,11 +186,11 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { e?.preventDefault(); e?.stopPropagation(); - // 如果有回调函数,直接调用回调函数来更新状态 + /** If callback provided, call callback to update state */ if (options?.onKnowledgeBaseFolderClick) { options.onKnowledgeBaseFolderClick(folder.id, breadcrumbPath.knowledgeBaseFolderPath.slice(0, index + 1)); } else { - // 否则使用导航(兜底逻辑) + /** Otherwise use navigation (fallback logic) */ navigate('/knowledge-base', { state: { navigateToFolder: folder.id, @@ -175,11 +203,11 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { })), ]; } else { - // 知识库详情页面:显示知识库名称 + 文档文件夹路径 + 文档名称 + /** Knowledge base detail page: show knowledge base name + document folder path + document name */ customBreadcrumbs = [ ...breadcrumbsWithClick, - // 添加知识库名称 + /** Add knowledge base name */ ...(breadcrumbPath.knowledgeBase ? [{ id: 0, parent: 0, @@ -205,27 +233,27 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { onClick: (e?: React.MouseEvent) => { e?.preventDefault(); e?.stopPropagation(); - // 返回到知识库详情页的根目录 + /** Return to knowledge base detail page root directory */ const navigationState = { fromKnowledgeBaseList: true, knowledgeBaseFolderPath: breadcrumbPath.knowledgeBaseFolderPath, - resetToRoot: true, // 添加重置到根目录的标志 - refresh: true, // 添加刷新标志 - timestamp: Date.now(), // 添加时间戳确保状态变化 + resetToRoot: true, /** Add flag to reset to root directory */ + refresh: true, /** Add refresh flag */ + timestamp: Date.now(), /** Add timestamp to ensure state change */ }; - // 使用当前页面路径进行导航,避免不必要的路由变化 + /** Use current page path for navigation to avoid unnecessary route changes */ const currentPath = window.location.pathname; const targetPath = `/knowledge-base/${breadcrumbPath.knowledgeBase!.id}/private`; if (currentPath === targetPath) { - // 如果已经在目标页面,直接更新状态而不导航 + /** If already on target page, update state directly without navigation */ navigate(targetPath, { state: navigationState, - replace: true // 使用 replace 避免历史记录堆积 + replace: true /** Use replace to avoid history stack buildup */ }); } else { - // 如果不在目标页面,正常导航 + /** If not on target page, navigate normally */ navigate(targetPath, { state: navigationState }); @@ -234,7 +262,7 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { }, }] : []), - // 添加文档文件夹路径 + /** Add document folder path */ ...breadcrumbPath.documentFolderPath.map((folder, index) => ({ id: 0, parent: 0, @@ -260,24 +288,24 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { onClick: (e?: React.MouseEvent) => { e?.preventDefault(); e?.stopPropagation(); - // 返回到知识库详情页的对应文件夹 + /** Return to corresponding folder in knowledge base detail page */ const navigationState = { fromKnowledgeBaseList: true, knowledgeBaseFolderPath: breadcrumbPath.knowledgeBaseFolderPath, navigateToDocumentFolder: folder.id, documentFolderPath: breadcrumbPath.documentFolderPath.slice(0, index + 1), - refresh: true, // 添加刷新标志 - timestamp: Date.now(), // 添加时间戳确保状态变化 + refresh: true, /** Add refresh flag */ + timestamp: Date.now(), /** Add timestamp to ensure state change */ }; navigate(`/knowledge-base/${breadcrumbPath.knowledgeBase!.id}/private`, { state: navigationState, - replace: true // 使用 replace 避免历史记录堆积 + replace: true /** Use replace to avoid history stack buildup */ }); return false; }, })), - // 添加文档名称(如果存在) + /** Add document name (if exists) */ ...(breadcrumbPath.document ? [{ id: 0, parent: 0, @@ -300,12 +328,12 @@ export const useBreadcrumbManager = (options?: BreadcrumbOptions) => { disposable: false, appSystem: null, subs: [], - // 文档名称不可点击 + /** Document name is not clickable */ }] : []), ]; } - // 根据面包屑类型使用不同的键,实现独立的面包屑路径 + /** Use different keys based on breadcrumb type to implement independent breadcrumb paths */ const breadcrumbKey = breadcrumbType === 'list' ? 'space' : 'space-detail'; diff --git a/web/src/hooks/useNavigationBreadcrumbs.ts b/web/src/hooks/useNavigationBreadcrumbs.ts index c314399b..2b9cd06a 100644 --- a/web/src/hooks/useNavigationBreadcrumbs.ts +++ b/web/src/hooks/useNavigationBreadcrumbs.ts @@ -1,7 +1,30 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:24:49 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:24:49 + */ +/** + * useNavigationBreadcrumbs Hook + * + * Automatically updates breadcrumbs based on current route: + * - Matches current path against menu structure + * - Supports dynamic routes with parameters + * - Handles nested menu hierarchies + * - Updates breadcrumbs on route changes + * + * @hook + */ + import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import { useMenu } from '@/store/menu'; +/** + * Hook to automatically update breadcrumbs based on navigation. + * + * @param source - Menu source type ('space' or 'manage') + */ export const useNavigationBreadcrumbs = (source: 'space' | 'manage' = 'manage') => { const location = useLocation(); const { allMenus, updateBreadcrumbs } = useMenu(); @@ -10,26 +33,26 @@ export const useNavigationBreadcrumbs = (source: 'space' | 'manage' = 'manage') const currentPath = location.pathname; const menus = allMenus[source] || []; - // 查找匹配的菜单项并构建keyPath + /** Find matching menu item and build key path */ const findMenuKeyPath = (menuList: any[], parentKeys: string[] = []): string[] | null => { let bestMatch: { path: string; parentId?: string; score: number } | null = null; for (const menu of menuList) { - // 检查子菜单 + /** Check submenus */ if (menu.subs && menu.subs.length > 0) { const menuPath = menu.path ? (menu.path[0] !== '/' ? '/' + menu.path : menu.path) : ''; for (const sub of menu.subs) { if (sub.path) { const subPath = sub.path[0] !== '/' ? '/' + sub.path : sub.path; - // 精确匹配优先 + /** Exact match has priority */ if (subPath === currentPath) { return [sub.path, `${menu.id}`]; } console.log('menuPath', menuPath) - // 动态路由匹配 + /** Dynamic route matching */ if (subPath.includes(':')) { - // 检查是否在父菜单下 + /** Check if under parent menu */ if (menuPath && currentPath.startsWith(menuPath + '/')) { const relativePath = currentPath.replace(menuPath, ''); const pathSegments = subPath.split('/'); @@ -42,7 +65,7 @@ export const useNavigationBreadcrumbs = (source: 'space' | 'manage' = 'manage') } } } - // 直接匹配子菜单路径 + /** Direct match submenu path */ const pathSegments = subPath.split('/'); const currentSegments = currentPath.split('/'); if (pathSegments.length === currentSegments.length) { @@ -57,14 +80,14 @@ export const useNavigationBreadcrumbs = (source: 'space' | 'manage' = 'manage') } } - // 检查主菜单 + /** Check main menu */ if (menu.path) { const menuPath = menu.path[0] !== '/' ? '/' + menu.path : menu.path; - // 精确匹配优先 + /** Exact match has priority */ if (menuPath === currentPath) { return [menu.path, ...parentKeys].reverse(); } - // 动态路由匹配 + /** Dynamic route matching */ if (menuPath.includes(':')) { const pathSegments = menuPath.split('/'); const currentSegments = currentPath.split('/'); diff --git a/web/src/hooks/useRouteGuard.ts b/web/src/hooks/useRouteGuard.ts index 0bf6d485..900fab2c 100644 --- a/web/src/hooks/useRouteGuard.ts +++ b/web/src/hooks/useRouteGuard.ts @@ -1,27 +1,44 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:24:54 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:24:54 + */ +/** + * useRouteGuard Hook + * + * Provides route authentication and permission checking: + * - Validates user authentication status + * - Checks route permissions against menu structure + * - Redirects unauthorized users + * - Monitors route changes + * + * @hook + */ + import { useEffect } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { useMenu, type MenuItem } from '@/store/menu' -// 模拟认证状态检查函数 +/** Check authentication status */ export const checkAuthStatus = (): boolean => { - // 在实际应用中,这里应该检查localStorage或cookie中的认证信息 - // 这里为了演示,我们假设首页不需要认证,其他页面需要认证 - return true; // 暂时返回true以便测试 + /** In production, check localStorage or cookie for auth info */ + return true; /** Temporarily return true for testing */ }; -// 递归检查路由是否存在于菜单数据中 +/** Recursively check if route exists in menu data */ export const checkRoutePermission = (menus: MenuItem[], currentPath: string): boolean => { - // 首页和知识库相关页面默认有权限 + /** Home and knowledge base pages have default permission */ if (currentPath === '/' || currentPath.includes('knowledge-detail') || currentPath.includes('knowledge-base')) { return true; } for (const menu of menus) { - // 检查当前菜单的path是否匹配 + /** Check if current menu path matches */ if (menu.path && currentPath.includes(menu.path)) { return true; } - // 递归检查子菜单 + /** Recursively check submenus */ if (menu.subs && menu.subs.length > 0) { if (checkRoutePermission(menu.subs, currentPath)) { return true; @@ -32,40 +49,44 @@ export const checkRoutePermission = (menus: MenuItem[], currentPath: string): bo return false; }; -// 路由守卫Hook,用于处理路由权限检查 +/** + * Route guard hook for handling route permission checks. + * + * @param source - Menu source type ('space' or 'manage') + */ export const useRouteGuard = (source: 'space' | 'manage') => { const navigate = useNavigate(); const location = useLocation(); const { allMenus } = useMenu(); const menus = allMenus[source]; - // 确保在路由变化时重新执行所有检查逻辑 + /** Re-execute all checks on route changes */ useEffect(() => { - // 模拟认证检查逻辑 + /** Simulate authentication check */ const isAuthenticated = checkAuthStatus(); if (!isAuthenticated && location.pathname !== '/') { - // TODO: 未认证用户重定向到登录页(这里是首页) + /** Redirect unauthenticated users to home/login page */ navigate('/', { replace: true }); return; } - // 认证通过后,检查路由权限 + /** After authentication, check route permissions */ if (isAuthenticated && location.pathname !== '/' && location.pathname !== '/not-found') { const hasPermission = checkRoutePermission(menus, location.pathname); if (!hasPermission) { - // 无权限访问该路由,重定向到无权限页面 + /** No permission, redirect to no-permission page */ // navigate('/no-permission', { replace: true }); } } }, [navigate, location.pathname, location.search, location.hash, menus]); - // 返回当前路径和权限状态,确保组件能感知到路由变化 + /** Return current path and permission status */ return { currentPath: location.pathname, search: location.search, hash: location.hash, - isChecking: false, // 可以扩展添加加载状态 + isChecking: false, /** Can be extended to add loading state */ }; }; From 9a38e8a4a09edc7c55843f7e72a43844d9a19700 Mon Sep 17 00:00:00 2001 From: zhaoying Date: Mon, 2 Feb 2026 16:37:32 +0800 Subject: [PATCH 2/3] docs: add comments to the src/routes & src/store & src/utils directory --- web/src/routes/index.tsx | 56 ++++-- web/src/store/locale.ts | 41 +++-- web/src/store/menu.ts | 40 ++++- web/src/store/user.ts | 36 +++- web/src/utils/apiKeyReplacer.ts | 30 +++- web/src/utils/auth.ts | 21 ++- web/src/utils/common.ts | 32 +++- web/src/utils/event.md | 198 ---------------------- web/src/utils/format.ts | 34 ++-- web/src/utils/request.ts | 115 +++++++++---- web/src/utils/stream.ts | 68 +++++++- web/src/utils/timezones.ts | 290 +++++++++++++++++--------------- web/src/utils/yamlExport.ts | 20 ++- 13 files changed, 546 insertions(+), 435 deletions(-) delete mode 100644 web/src/utils/event.md diff --git a/web/src/routes/index.tsx b/web/src/routes/index.tsx index 21eaeab8..09479f59 100644 --- a/web/src/routes/index.tsx +++ b/web/src/routes/index.tsx @@ -1,23 +1,39 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:33:11 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:33:11 + */ +/** + * Route Configuration + * + * Manages application routing with: + * - Dynamic route generation from JSON configuration + * - Lazy loading of components for code splitting + * - Nested route support + * - Component mapping validation + * - Hash-based routing + * + * @module routes + */ + import { lazy, type LazyExoticComponent, type ComponentType, type ReactNode } from 'react'; import { createHashRouter, createRoutesFromElements, Route } from 'react-router-dom'; -// 导入路由配置JSON +/** Import route configuration JSON */ import routesConfig from './routes.json'; -import Ontology from '@/views/Ontology'; -// 递归函数,用于生成路由元素 - -// 递归收集所有路由中的element +/** Recursively collect all element names from routes */ function collectElements(routes: RouteConfig[]): Set { const elements = new Set(); function traverse(routeList: RouteConfig[]) { routeList.forEach(route => { - // 添加当前路由的element + /** Add current route's element */ elements.add(route.element); - // 递归处理子路由 + /** Recursively process child routes */ if (route.children && route.children.length > 0) { traverse(route.children); } @@ -28,15 +44,15 @@ function collectElements(routes: RouteConfig[]): Set { return elements; } -// 直接定义组件映射表,避免动态路径解析问题 +/** Component mapping table - maps element names to lazy-loaded components */ const componentMap: Record>> = { - // 布局组件 + /** Layout components */ AuthLayout: lazy(() => import('@/components/Layout/AuthLayout')), AuthSpaceLayout: lazy(() => import('@/components/Layout/AuthSpaceLayout')), BasicLayout: lazy(() => import('@/components/Layout/BasicLayout')), LoginLayout: lazy(() => import('@/components/Layout/LoginLayout')), NoAuthLayout: lazy(() => import('@/components/Layout/NoAuthLayout')), - // 视图组件 + /** View components */ Index: lazy(() => import('@/views/Index')), Home: lazy(() => import('@/views/Home')), UserMemory: lazy(() => import('@/views/UserMemory')), @@ -78,7 +94,7 @@ const componentMap: Record>> = NotFound: lazy(() => import('@/views/NotFound')) }; -// 检查并报告缺失的组件 +/** Check and report missing components */ const allElements = collectElements(routesConfig); allElements.forEach(elementName => { if (!componentMap[elementName]) { @@ -86,23 +102,27 @@ allElements.forEach(elementName => { } }); -// 确保NotFound组件总是存在作为兜底 +/** Ensure NotFound component always exists as fallback */ if (!componentMap['NotFound']) { componentMap['NotFound'] = lazy(() => import('@/views/NotFound/index.tsx')); } -// 路由配置类型定义 +/** Route configuration type definition */ interface RouteConfig { + /** Route path */ path?: string; + /** Component element name */ element: string; + /** Component file path (optional) */ componentPath?: string; + /** Child routes */ children?: RouteConfig[]; } -// 递归函数,用于生成路由元素 +/** Recursively generate route elements from configuration */ const generateRoutes = (routes: RouteConfig[]): ReactNode => { return routes.map((route, index) => { - // 获取组件 + /** Get component from mapping */ const componentKey = route.element as keyof typeof componentMap; const Component = componentMap[componentKey]; @@ -111,7 +131,7 @@ const generateRoutes = (routes: RouteConfig[]): ReactNode => { return null; } - // 如果有子路由 + /** If has child routes, create nested route */ if (route.children) { return ( }> @@ -120,7 +140,7 @@ const generateRoutes = (routes: RouteConfig[]): ReactNode => { ); } - // 如果有path属性,则为普通路由 + /** If has path property, create regular route */ if (route.path) { return } />; } @@ -129,7 +149,7 @@ const generateRoutes = (routes: RouteConfig[]): ReactNode => { }); }; -// 创建路由 +/** Create hash router from route configuration */ const router = createHashRouter( createRoutesFromElements( generateRoutes(routesConfig) diff --git a/web/src/store/locale.ts b/web/src/store/locale.ts index 4fbd79ed..ef9d6263 100644 --- a/web/src/store/locale.ts +++ b/web/src/store/locale.ts @@ -1,11 +1,22 @@ /* - * @Description: - * @Version: 0.0.1 - * @Author: yujiangping - * @Date: 2026-01-05 17:22:23 - * @LastEditors: yujiangping - * @LastEditTime: 2026-01-15 21:02:43 + * @Author: ZhaoYing + * @Date: 2026-02-02 16:33:22 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:33:22 */ +/** + * Locale Store + * + * Manages internationalization (i18n) and localization with: + * - Language switching (English/Chinese) + * - Timezone management + * - Ant Design locale configuration + * - Custom Tour component translations + * - Day.js timezone support + * + * @store + */ + import { create } from 'zustand' import enUS from 'antd/locale/en_US'; import zhCN from 'antd/locale/zh_CN'; @@ -14,13 +25,12 @@ import dayjs from 'dayjs' import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; import i18n from '@/i18n'; -import { timezoneToAntdLocaleMap } from '@/utils/timezones'; -// 扩展dayjs插件 +/** Extend dayjs with timezone plugins */ dayjs.extend(utc); dayjs.extend(timezone); -// 自定义中文 locale,修改 Tour 组件的按钮文字 +/** Custom Chinese locale with modified Tour component button text */ const customZhCN: Locale = { ...zhCN, Tour: { @@ -31,7 +41,7 @@ const customZhCN: Locale = { }, }; -// 自定义英文 locale,修改 Tour 组件的按钮文字 +/** Custom English locale with modified Tour component button text */ const customEnUS: Locale = { ...enUS, Tour: { @@ -43,19 +53,27 @@ const customEnUS: Locale = { }; +/** Internationalization state interface */ interface I18nState { + /** Current language code */ language: string; + /** Ant Design locale object */ locale: Locale; + /** Current timezone */ timeZone: string; + /** Change application language */ changeLanguage: (language: string) => void; + /** Change timezone (triggers page reload) */ changeTimeZone: (timeZone: string) => void; } +/** Initialize from localStorage or use defaults */ const initialTimeZone = localStorage.getItem('timeZone') || 'Asia/Shanghai' const initialLanguage = localStorage.getItem('language') || 'en' const initialLocale = initialLanguage === 'en' ? customEnUS : customZhCN i18n.changeLanguage(initialLanguage) +/** Internationalization store */ export const useI18n = create((set, get) => ({ language: initialLanguage, locale: initialLocale, @@ -68,8 +86,9 @@ export const useI18n = create((set, get) => ({ changeTimeZone: (timeZone: string) => { const { timeZone: lastTimeZone } = get() set({ timeZone }) + /** Reload page if timezone changed */ if (lastTimeZone !== timeZone) { window.location.reload() } }, -})) \ No newline at end of file +})) diff --git a/web/src/store/menu.ts b/web/src/store/menu.ts index 63b9adf9..2aa5df3a 100644 --- a/web/src/store/menu.ts +++ b/web/src/store/menu.ts @@ -1,6 +1,26 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:33:34 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:33:34 + */ +/** + * Menu Store + * + * Manages application menu and breadcrumb navigation with: + * - Menu loading from JSON configuration + * - Sidebar collapse state + * - Breadcrumb generation from menu paths + * - Custom breadcrumb support + * - Separate menu contexts (space/manage) + * + * @store + */ + import { create } from 'zustand' import AllMenus from './menu.json' +/** Menu item interface */ export interface MenuItem { id: number; parent: number; @@ -22,20 +42,32 @@ export interface MenuItem { master?: string | null; disposable?: boolean; appSystem?: string | null; - subs: MenuItem[] | null; + subs?: MenuItem[] | null; onClick?: (e?: React.MouseEvent) => void | boolean; } + +/** Menu state interface */ interface MenuState { + /** Sidebar collapsed state */ collapsed: boolean; + /** Toggle sidebar collapse */ toggleSider: () => void; + /** All menus by context */ allMenus: Record<'space' | 'manage', MenuItem[]>; + /** All breadcrumbs by context */ allBreadcrumbs: Record<'space' | 'manage' | string, MenuItem[]>; + /** Load menus for specific context */ loadMenus: (source: 'space' | 'manage') => void; + /** Update breadcrumbs based on key path */ updateBreadcrumbs: (keyPath: string[], source: 'space' | 'manage') => void; + /** Set custom breadcrumbs */ setCustomBreadcrumbs: (breadcrumbs: MenuItem[], source: string) => void; } +/** Initialize breadcrumbs from localStorage */ const initBreadcrumbs = localStorage.getItem('breadcrumbs') || '[]' + +/** Menu store */ export const useMenu = create((set, get) => ({ collapsed: localStorage.getItem('collapsed') === 'true', allMenus: { @@ -61,7 +93,7 @@ export const useMenu = create((set, get) => ({ console.log('updateBreadcrumbs paths:', paths); if (paths.length === 3) { - // 三级菜单:[subSubPath, subId, menuId] + /** Three-level menu: [subSubPath, subId, menuId] */ const menuId = paths[2]; const subId = paths[1]; const subSubPath = paths[0]; @@ -81,7 +113,7 @@ export const useMenu = create((set, get) => ({ } } } else { - // 原有逻辑处理一级和二级菜单 + /** Original logic for one-level and two-level menus */ const matchedMenu: MenuItem | undefined = menus.find(menu => menu.path === paths[paths.length - 1] || `${menu.id}` === paths[1]); if (matchedMenu) { @@ -107,4 +139,4 @@ export const useMenu = create((set, get) => ({ set({ allBreadcrumbs }) localStorage.setItem('breadcrumbs', JSON.stringify(allBreadcrumbs)) }, -})) \ No newline at end of file +})) diff --git a/web/src/store/user.ts b/web/src/store/user.ts index 75d10812..505cb768 100644 --- a/web/src/store/user.ts +++ b/web/src/store/user.ts @@ -1,3 +1,22 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:33:54 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:33:54 + */ +/** + * User Store + * + * Manages user authentication and profile with: + * - User information storage + * - Login/logout functionality + * - Token management (access & refresh) + * - Workspace storage type + * - Navigation guards for workspace access + * + * @store + */ + import { create } from 'zustand' import { clearAuthData } from '@/utils/auth'; import type { User } from '@/views/UserManagement/types' @@ -5,6 +24,7 @@ import { getUsers, refreshToken, logout } from '@/api/user' import { getWorkspaceStorageType } from '@/api/workspaces'; import { cookieUtils } from '@/utils/request' +/** Login information interface */ export interface LoginInfo { access_token: string; expires_at: string; @@ -12,24 +32,37 @@ export interface LoginInfo { refresh_token: string; token_type: 'bearer' } + +/** User state interface */ export interface UserState { + /** Current user information */ user: User; + /** Login token information */ loginInfo: LoginInfo; + /** Workspace storage type */ storageType: string | null; + /** Update login information */ updateLoginInfo: (values: LoginInfo) => void; + /** Get user information */ getUserInfo: (flag?: boolean) => void; + /** Clear user information */ clearUserInfo: () => void; + /** Logout user */ logout: () => void; + /** Get workspace storage type */ getStorageType: () => void; + /** Check and redirect if workspace not set */ checkJump: () => void; } +/** Pages that don't require workspace */ export const whitePage = [ '/conversation', '/login', '/invite-register' ] +/** User store */ export const useUser = create((set, get) => ({ user: localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user') || '{}') as User : {} as User, loginInfo: {} as LoginInfo, @@ -101,9 +134,10 @@ export const useUser = create((set, get) => ({ const localUser = JSON.parse(localStorage.getItem('user') || '{}') as User; const hash = window.location.hash; + /** Redirect to index if user has no workspace and not on whitelist page */ if (localUser.id && (!localUser.current_workspace_id || localUser.current_workspace_id === '') && !whitePage.find(vo => hash.includes(vo))) { console.log('whitePage', whitePage.find(vo => hash.includes(vo))) window.location.href = '/#/index' } }, -})) \ No newline at end of file +})) diff --git a/web/src/utils/apiKeyReplacer.ts b/web/src/utils/apiKeyReplacer.ts index a2914e46..561f146d 100644 --- a/web/src/utils/apiKeyReplacer.ts +++ b/web/src/utils/apiKeyReplacer.ts @@ -1,13 +1,27 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:34:04 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:34:04 + */ /** - * API密钥替换工具 + * API Key Replacer Utility + * + * Provides functions to mask and detect API keys in text for security purposes. + * Supports multiple API key formats (service, agent, multi-agent, workflow). + * + * @module apiKeyReplacer */ +/** API key pattern definitions for different types */ const API_KEY_PATTERNS = { service: /sk-service-[A-Za-z0-9_-]+/g, agent: /sk-agent-[A-Za-z0-9_-]+/g, multiAgent: /sk-multi_agent-[A-Za-z0-9_-]+/g, workflow: /sk-workflow-[A-Za-z0-9_-]+/g } + +/** API key prefix definitions */ const API_KEY_PREFIX = { service: 'sk-service-', agent: 'sk-agent-', @@ -16,9 +30,9 @@ const API_KEY_PREFIX = { } /** - * 替换文本中的API密钥为*号 - * @param text 原始文本 - * @returns 替换后的文本 + * Replace API keys in text with asterisks + * @param text - Original text + * @returns Text with masked API keys */ export const maskApiKeys = (text: string): string => { if (!text) return text @@ -37,10 +51,10 @@ export const maskApiKeys = (text: string): string => { } /** - * 检测文本中是否包含API密钥 - * @param text 待检测文本 - * @returns 是否包含API密钥 + * Detect if text contains API keys + * @param text - Text to check + * @returns Whether text contains API keys */ export const hasApiKeys = (text: string): boolean => { return Object.values(API_KEY_PATTERNS).some(pattern => pattern.test(text)) -} \ No newline at end of file +} diff --git a/web/src/utils/auth.ts b/web/src/utils/auth.ts index 5ec30028..b7c55188 100644 --- a/web/src/utils/auth.ts +++ b/web/src/utils/auth.ts @@ -1,7 +1,26 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:34:12 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:34:12 + */ +/** + * Authentication Utility + * + * Provides functions to clear authentication data and redirect to login. + * + * @module auth + */ + import { cookieUtils } from './request' + +/** + * Clear all authentication data and cookies + * Removes user info, breadcrumbs, and all cookies + */ export const clearAuthData = () => { console.log("Clearing auth data and redirecting to login"); localStorage.removeItem('user') localStorage.removeItem('breadcrumbs') cookieUtils.clear(); -} \ No newline at end of file +} diff --git a/web/src/utils/common.ts b/web/src/utils/common.ts index 19841f57..360ee1fa 100644 --- a/web/src/utils/common.ts +++ b/web/src/utils/common.ts @@ -1,14 +1,34 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:34:23 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:34:23 + */ +/** + * Common Utility Functions + * + * Provides general-purpose utility functions. + * + * @module common + */ + +/** + * Generate a random string with specified length and character types + * @param length - Length of the string (default: 12) + * @param isHasSpecialChars - Whether to include special characters (default: true) + * @returns Random string + */ export const randomString = (length: number = 12, isHasSpecialChars: boolean = true) => { - // 定义字符集:大写字母、小写字母、数字和特殊字符 + /** Define character sets: uppercase, lowercase, numbers, and special characters */ const uppercaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const lowercaseChars = 'abcdefghijklmnopqrstuvwxyz'; const numberChars = '0123456789'; const specialChars = '!@#$%^&*_+-=|;:,.?'; - // 合并所有字符集 + /** Combine all character sets */ let allChars = uppercaseChars + lowercaseChars + numberChars; - // 确保至少包含每种类型的字符 + /** Ensure at least one character of each type */ let str = uppercaseChars[Math.floor(Math.random() * uppercaseChars.length)] + lowercaseChars[Math.floor(Math.random() * lowercaseChars.length)] + @@ -18,11 +38,11 @@ export const randomString = (length: number = 12, isHasSpecialChars: boolean = t str+= specialChars[Math.floor(Math.random() * specialChars.length)]; } - // 填充剩余的字符,使总长度为12 + /** Fill remaining characters to reach desired length */ for (let i = 4; i < length; i++) { str += allChars[Math.floor(Math.random() * allChars.length)]; } - // 打乱密码字符顺序 + /** Shuffle the string characters */ return str.split('').sort(() => Math.random() - 0.5).join(''); - } \ No newline at end of file + } diff --git a/web/src/utils/event.md b/web/src/utils/event.md deleted file mode 100644 index 6c6b24d5..00000000 --- a/web/src/utils/event.md +++ /dev/null @@ -1,198 +0,0 @@ -event: workflow_start -data: {"execution_id": "exec_ee8aa953bc1945fd", "workspace_id": "d17cd62d-a725-4fc0-813b-1093f2dfdee4", "timestamp": "2026-01-12T17:27:44.493693"} - -event: node_start -data: {"node_id": "start_1767619616140_r7icy36oq", "conversation_id": "52ccf281-35a1-4ce1-b691-15d09d81d2ce", "execution_id": "exec_ee8aa953bc1945fd", "timestamp": "2026-01-12T09:27:44.500650+00:00"} - -event: node_end -data: {"node_id": "start_1767619616140_r7icy36oq", "conversation_id": null, "execution_id": null, "timestamp": "2026-01-12T09:27:44.501772+00:00"} - -event: node_start -data: {"node_id": "tool_1767667989240_zimikmfgm", "conversation_id": "52ccf281-35a1-4ce1-b691-15d09d81d2ce", "execution_id": "exec_ee8aa953bc1945fd", "timestamp": "2026-01-12T09:27:44.502310+00:00"} - -event: node_end -data: {"node_id": "tool_1767667989240_zimikmfgm", "conversation_id": null, "execution_id": null, "timestamp": "2026-01-12T09:27:45.011357+00:00"} - -event: node_start -data: {"node_id": "llm_1767620955373_9kda2cnuy", "conversation_id": "52ccf281-35a1-4ce1-b691-15d09d81d2ce", "execution_id": "exec_ee8aa953bc1945fd", "timestamp": "2026-01-12T09:27:45.011953+00:00"} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6839\u636e", "full_content": "\u6839\u636e", "chunk_index": 1, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6700\u65b0\u7684", "full_content": "\u6839\u636e\u6700\u65b0\u7684", "chunk_index": 2, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5929\u6c14", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14", "chunk_index": 3, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u4fe1\u606f\uff0c\u676d\u5dde", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde", "chunk_index": 4, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5", "chunk_index": 5, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5982\u4e0b\uff1a\n\n- **2", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2", "chunk_index": 6, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "026\u5e74", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e74", "chunk_index": 7, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "1\u670812\u65e5", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5", "chunk_index": 8, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff08\u661f\u671f\u4e00\uff09**\uff1a", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a", "chunk_index": 9, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29", "chunk_index": 10, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u57282\u2103\u81f3", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f3", "chunk_index": 11, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "15\u2103\u4e4b\u95f4\uff0c", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c", "chunk_index": 12, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n", "chunk_index": 13, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "- **2026", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026", "chunk_index": 14, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5e741\u670813", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813", "chunk_index": 15, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u65e5\uff08\u661f\u671f\u4e8c\uff09**", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**", "chunk_index": 16, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff1a\u6674\u5929\uff0c\u6c14\u6e29", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29", "chunk_index": 17, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u8303\u56f4\u4e3a5\u2103", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103", "chunk_index": 18, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u81f316\u2103", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103", "chunk_index": 19, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357", "chunk_index": 20, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3", "chunk_index": 21, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u7ea7\u3002\n- **2", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2", "chunk_index": 22, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "026\u5e741\u6708", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u6708", "chunk_index": 23, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "14\u65e5\uff08\u661f\u671f\u4e09", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09", "chunk_index": 24, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff09**\uff1a\u6674", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674", "chunk_index": 25, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5929\uff0c\u6c14\u6e29\u4e0a\u5347", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347", "chunk_index": 26, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u52306\u2103\u81f32", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f32", "chunk_index": 27, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "1\u2103\uff0c\u897f\u5357", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357", "chunk_index": 28, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n", "chunk_index": 29, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6b64\u5916\uff0c\u6709\u62a5\u9053", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053", "chunk_index": 30, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde", "chunk_index": 31, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696", "chunk_index": 32, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff0c\u672a\u6765\u81f3\u5c11\u4e94", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94", "chunk_index": 33, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5929\u5185\u6c14\u6e29\u5c06", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06", "chunk_index": 34, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u7a33\u5b9a\u7ef4\u6301\u572818", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818", "chunk_index": 35, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "~20\u00b0C", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C", "chunk_index": 36, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765", "chunk_index": 37, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7", "chunk_index": 38, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7", "chunk_index": 39, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd", "chunk_index": 40, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e", "chunk_index": 41, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3", "chunk_index": 42, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f", "chunk_index": 43, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5730\u533a\u6700\u4f4e\u6c14\u6e29-", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-", "chunk_index": 44, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "1\uff5e2\u2103\uff0c\u5c71\u533a", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a", "chunk_index": 45, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "-2\uff5e-", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-", "chunk_index": 46, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "5\u2103\uff0c\u90e8\u5206", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206", "chunk_index": 47, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216", "chunk_index": 48, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192", "chunk_index": 49, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696", "chunk_index": 50, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06", "chunk_index": 51, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10", "chunk_index": 52, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u56de\u6696\uff0c\u4f46\u65e9\u665a", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10\u56de\u6696\uff0c\u4f46\u65e9\u665a", "chunk_index": 53, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u6e29\u5dee\u8f83\u5927\uff0c\u8bf7", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10\u56de\u6696\uff0c\u4f46\u65e9\u665a\u6e29\u5dee\u8f83\u5927\uff0c\u8bf7", "chunk_index": 54, "is_prefix": null, "is_suffix": null} - -event: message -data: {"node_id": "llm_1767620955373_9kda2cnuy", "chunk": "\u9002\u65f6\u8c03\u6574\u7740\u88c5\u3002", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10\u56de\u6696\uff0c\u4f46\u65e9\u665a\u6e29\u5dee\u8f83\u5927\uff0c\u8bf7\u9002\u65f6\u8c03\u6574\u7740\u88c5\u3002", "chunk_index": 55, "is_prefix": null, "is_suffix": null} - -event: node_end -data: {"node_id": "llm_1767620955373_9kda2cnuy", "conversation_id": null, "execution_id": null, "timestamp": "2026-01-12T09:27:52.991637+00:00"} - -event: node_start -data: {"node_id": "end_1767619619942_unxlhspyr", "conversation_id": "52ccf281-35a1-4ce1-b691-15d09d81d2ce", "execution_id": "exec_ee8aa953bc1945fd", "timestamp": "2026-01-12T09:27:52.992194+00:00"} - -event: message -data: {"node_id": "end_1767619619942_unxlhspyr", "chunk": " \n{'search_type': 'web', 'query': '\u676d\u5dde\u5929\u6c14 ', 'total_results': 10, 'page_num': 1, 'page_size': 10, 'results': [{'title': '\u8f70\u8f70\u70c8\u70c8,\u6301\u7eed20\u00b0C!\u676d\u5dde\u5347\u6e29\u65f6\u95f4\u786e\u5b9a', 'url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'snippet': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'display_url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'rank': 1}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'url': 'http://www.rrfrro.cn/hangzhou/60/', 'snippet': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'display_url': 'http://www.rrfrro.cn/hangzhou/60/', 'rank': 2}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'url': 'http://www.ctonw.cn/hangzhou/60/', 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'display_url': 'http://www.ctonw.cn/hangzhou/60/', 'rank': 3}, {'title': '\u3010\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'snippet': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'display_url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'rank': 4}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'url': 'http://www.rfgza.cn/hangzhou/', 'snippet': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'display_url': 'http://www.rfgza.cn/hangzhou/', 'rank': 5}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'url': 'http://www.pzoby.cn/hangzhou/', 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'display_url': 'http://www.pzoby.cn/hangzhou/', 'rank': 6}, {'title': '\u3010\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'snippet': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'display_url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'rank': 7}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a5', 'url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'snippet': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'display_url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'rank': 8}, {'title': '\u676d\u5dde', 'url': 'https://weather.cma.cn/web/weather/58457.html', 'snippet': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'display_url': 'https://weather.cma.cn/web/weather/58457.html', 'rank': 9}, {'title': '\u676d\u5dde\u5e02\u6700\u8fd130\u5929\u5929\u6c14\u67e5\u8be2', 'url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'snippet': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'display_url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'rank': 10}], 'answer': '', 'references': [{'id': 1, 'url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'title': '\u8f70\u8f70\u70c8\u70c8,\u6301\u7eed20\u00b0C!\u676d\u5dde\u5347\u6e29\u65f6\u95f4\u786e\u5b9a', 'date': '2026-01-11 22:02:18', 'content': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'icon': 'https://baijiahao.baidu.com/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': '\u767e\u5bb6\u53f7', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'web_extensions': {'images': [{'url': 'https://pic.rmb.bdstatic.com/bjh/news/2bd0aad3d981df25b071da7bbc5aa7f0.jpeg', 'height': '959', 'width': '640'}, {'url': 'https://pic.rmb.bdstatic.com/bjh/news/ad5520b673892709291b325a26cfcaef.jpeg', 'height': '480', 'width': '640'}, {'url': 'https://pic.rmb.bdstatic.com/bjh/news/7847e90f6b48eb4d0125d2670b045bb3.jpeg', 'height': '960', 'width': '640'}]}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 2, 'url': 'http://www.rrfrro.cn/hangzhou/60/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'date': '2026-01-10 17:40:29', 'content': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 3, 'url': 'http://www.ctonw.cn/hangzhou/60/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'date': '2026-01-09 13:14:07', 'content': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 4, 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'title': '\u3010\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'date': '2026-01-10 00:00:00', 'content': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'icon': 'https://b.bdstatic.com/searchbox/mappconsole/image/20181217/2ab53364-e12b-43fe-bacf-4806ff35d6b8.jpg', 'web_anchor': '', 'type': 'web', 'website': '\u667a\u80fd\u5c0f\u7a0b\u5e8f\u95e8\u6237', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 5, 'url': 'http://www.rfgza.cn/hangzhou/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'date': '2026-01-07 18:28:04', 'content': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 6, 'url': 'http://www.pzoby.cn/hangzhou/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'date': '2026-01-08 14:20:52', 'content': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 7, 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'title': '\u3010\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'date': '2026-01-09 00:00:00', 'content': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'icon': 'https://b.bdstatic.com/searchbox/mappconsole/image/20181217/2ab53364-e12b-43fe-bacf-4806ff35d6b8.jpg', 'web_anchor': '', 'type': 'web', 'website': '\u667a\u80fd\u5c0f\u7a0b\u5e8f\u95e8\u6237', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 8, 'url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a5', 'date': '2026-01-09 16:28:09', 'content': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'icon': 'https://www.ip138.com/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': 'iP138\u67e5\u8be2\u7f51', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 9, 'url': 'https://weather.cma.cn/web/weather/58457.html', 'title': '\u676d\u5dde', 'date': '2026-01-09 12:00:00', 'content': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '\u4e2d\u56fd\u6c14\u8c61\u5c40\u7f51\u7ad9', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 1, 'markdown_text': ''}, {'id': 10, 'url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'title': '\u676d\u5dde\u5e02\u6700\u8fd130\u5929\u5929\u6c14\u67e5\u8be2', 'date': '2026-01-09 20:52:24', 'content': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'icon': 'http://www.ip.cn/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': '\u53a6\u95e8\u65f6\u7a7a\u79d1\u6280\u6709\u9650\u516c\u53f8', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}]} ", "full_content": "\u6839\u636e\u6700\u65b0\u7684\u5929\u6c14\u4fe1\u606f\uff0c\u676d\u5dde\u8fd1\u671f\u7684\u5929\u6c14\u72b6\u51b5\u5982\u4e0b\uff1a\n\n- **2026\u5e741\u670812\u65e5\uff08\u661f\u671f\u4e00\uff09**\uff1a\u591a\u4e91\u8f6c\u6674\uff0c\u6c14\u6e29\u57282\u2103\u81f315\u2103\u4e4b\u95f4\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670813\u65e5\uff08\u661f\u671f\u4e8c\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u8303\u56f4\u4e3a5\u2103\u81f316\u2103\uff0c\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce\uff0c\u98ce\u529b\u5c0f\u4e8e3\u7ea7\u3002\n- **2026\u5e741\u670814\u65e5\uff08\u661f\u671f\u4e09\uff09**\uff1a\u6674\u5929\uff0c\u6c14\u6e29\u4e0a\u5347\u52306\u2103\u81f321\u2103\uff0c\u897f\u5357\u98ce\u5c0f\u4e8e3\u7ea7\u3002\n\n\u6b64\u5916\uff0c\u6709\u62a5\u9053\u6307\u51fa\uff0c\u4e0b\u5468\u676d\u5dde\u5c06\u8fce\u6765\u4e00\u6ce2\u663e\u8457\u56de\u6696\uff0c\u672a\u6765\u81f3\u5c11\u4e94\u5929\u5185\u6c14\u6e29\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73\uff0c\u5e26\u6765\u6301\u7eed\u7684\u6696\u610f\u3002\u4e0d\u8fc7\uff0c\u5728\u6b64\u4e4b\u524d\uff0c\u53d7\u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd\uff0c\u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d\uff0c\u5e73\u539f\u5730\u533a\u6700\u4f4e\u6c14\u6e29-1\uff5e2\u2103\uff0c\u5c71\u533a-2\uff5e-5\u2103\uff0c\u90e8\u5206\u5730\u65b9\u4f1a\u6709\u8584\u51b0\u6216\u51b0\u51bb\u73b0\u8c61\uff0c\u63d0\u9192\u5927\u5bb6\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002\n\n\u603b\u4f53\u6765\u770b\uff0c\u676d\u5dde\u5373\u5c06\u4ece\u5bd2\u51b7\u4e2d\u9010\u6e10\u56de\u6696\uff0c\u4f46\u65e9\u665a\u6e29\u5dee\u8f83\u5927\uff0c\u8bf7\u9002\u65f6\u8c03\u6574\u7740\u88c5\u3002 \n{'search_type': 'web', 'query': '\u676d\u5dde\u5929\u6c14 ', 'total_results': 10, 'page_num': 1, 'page_size': 10, 'results': [{'title': '\u8f70\u8f70\u70c8\u70c8,\u6301\u7eed20\u00b0C!\u676d\u5dde\u5347\u6e29\u65f6\u95f4\u786e\u5b9a', 'url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'snippet': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'display_url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'rank': 1}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'url': 'http://www.rrfrro.cn/hangzhou/60/', 'snippet': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'display_url': 'http://www.rrfrro.cn/hangzhou/60/', 'rank': 2}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'url': 'http://www.ctonw.cn/hangzhou/60/', 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'display_url': 'http://www.ctonw.cn/hangzhou/60/', 'rank': 3}, {'title': '\u3010\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'snippet': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'display_url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'rank': 4}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'url': 'http://www.rfgza.cn/hangzhou/', 'snippet': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'display_url': 'http://www.rfgza.cn/hangzhou/', 'rank': 5}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'url': 'http://www.pzoby.cn/hangzhou/', 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'display_url': 'http://www.pzoby.cn/hangzhou/', 'rank': 6}, {'title': '\u3010\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'snippet': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'display_url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'rank': 7}, {'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a5', 'url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'snippet': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'display_url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'rank': 8}, {'title': '\u676d\u5dde', 'url': 'https://weather.cma.cn/web/weather/58457.html', 'snippet': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'display_url': 'https://weather.cma.cn/web/weather/58457.html', 'rank': 9}, {'title': '\u676d\u5dde\u5e02\u6700\u8fd130\u5929\u5929\u6c14\u67e5\u8be2', 'url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'snippet': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'display_url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'rank': 10}], 'answer': '', 'references': [{'id': 1, 'url': 'https://baijiahao.baidu.com/s?id=1854029343683148825&wfr=spider&for=pc', 'title': '\u8f70\u8f70\u70c8\u70c8,\u6301\u7eed20\u00b0C!\u676d\u5dde\u5347\u6e29\u65f6\u95f4\u786e\u5b9a', 'date': '2026-01-11 22:02:18', 'content': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'icon': 'https://baijiahao.baidu.com/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': '\u767e\u5bb6\u53f7', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u9633\u5149\u6301\u7eed\u5728\u7ebf,\u6628\u5929\u7684\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29\u3002\u676d\u5dde\u4e0b\u5468\u7684\u56de\u6696\u53ef\u8c13\u8f70\u8f70\u70c8\u70c8,\u540e\u7eed\u81f3\u5c115\u5929\u6c14\u6e29\u90fd\u5c06\u7a33\u5b9a\u7ef4\u6301\u572818~20\u00b0C\u7684\u9ad8\u4f4d\u6c34\u5e73,\u6696\u610f\u6301\u7eed\u5728\u7ebf! \u5f31\u51b7\u7a7a\u6c14\u5f71\u54cd \u201c\u81f3\u51b7\u65f6\u523b\u201d\u5728\u660e\u5929\u65e9\u6668\u51fa\u73b0 \u8fd9\u4e2a\u53cc\u4f11\u65e5,\u676d\u5dde\u7684\u4f53\u611f\u771f\u662f\u5927\u4e0d\u76f8\u540c\u3002\u6628\u5929\u5728\u6674\u5929\u548c\u6696\u98ce\u7684\u52a9\u529b\u4e0b,\u6c14\u6e29\u4e00\u8dc3\u51b2\u783417\u00b0C,\u521b\u4e0b\u672c\u6708\u4ee5\u6765\u7684\u6700\u9ad8\u6c14\u6e29,\u6696\u610f\u5341\u8db3\u3002 \u7136\u800c\u5230\u4e86\u4eca\u5929,\u5c3d\u7ba1\u540c\u6837\u662f\u6674\u7a7a\u4e07\u91cc,\u4f46\u53d7\u51b7\u7a7a\u6c14\u5f71\u54cd,\u98ce\u5411\u7531\u504f\u5357\u8f6c\u4e3a\u504f\u5317,\u6c14\u6e29\u6500\u5347\u4e4f\u529b,\u9884\u8ba1\u6700\u9ad8\u6c14\u6e29\u4ec510\u00b0C\u5de6\u53f3,\u8f83\u6628\u5929\u9aa4\u964d7\u00b0C,\u5bd2\u610f\u518d\u5ea6\u56de\u5f52\u3002 \u660e\u5929\u65e9\u6668\u5c06\u662f\u672c\u8f6e\u51b7\u7a7a\u6c14\u5f71\u54cd\u4e0b\u7684\u201c\u81f3\u51b7\u65f6\u523b\u201d,\u6700\u4f4e\u6c14\u6e29\u5e73\u539f\u5730\u533a-1\uff5e2\u2103,\u6709\u8584\u51b0;\u5c71\u533a-2\uff5e-5\u2103,\u6709\u51b0\u51bb\u3002\u6668\u5bd2\u660e\u663e,\u5927\u5bb6\u52a1\u5fc5\u6ce8\u610f\u6dfb\u8863\u4fdd\u6696\u3002', 'web_extensions': {'images': [{'url': 'https://pic.rmb.bdstatic.com/bjh/news/2bd0aad3d981df25b071da7bbc5aa7f0.jpeg', 'height': '959', 'width': '640'}, {'url': 'https://pic.rmb.bdstatic.com/bjh/news/ad5520b673892709291b325a26cfcaef.jpeg', 'height': '480', 'width': '640'}, {'url': 'https://pic.rmb.bdstatic.com/bjh/news/7847e90f6b48eb4d0125d2670b045bb3.jpeg', 'height': '960', 'width': '640'}]}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 2, 'url': 'http://www.rrfrro.cn/hangzhou/60/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'date': '2026-01-10 17:40:29', 'content': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670812\u65e5(\u661f\u671f\u4e00) 15:07\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u591a\u4e91\u8f6c\u6674 2\u2103~15\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u4e2d\u7b49 \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e91\u8f6c\u66742\u2103~15\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66745\u2103~16\u2103\u4e1c\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66746\u2103~21\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66748\u2103~20\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670816\u65e5(\u661f\u671f\u4e94) \u591a\u4e919\u2103~21\u2103\u4e1c\u98ce\u8f6c\u5317\u98ce<3\u7ea7 2026\u5e7401\u670817\u65e5(\u661f\u671f\u516d) \u591a\u4e91\u8f6c\u5c0f\u96e811\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670818\u65e5(\u661f\u671f\u65e5) \u591a\u4e91\u8f6c\u5c0f\u96e89\u2103~19\u2103\u4e1c\u5317\u98ce\u8f6c\u5317\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 3, 'url': 'http://www.ctonw.cn/hangzhou/60/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929', 'date': '2026-01-09 13:14:07', 'content': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4009\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e292\u2103,\u6700\u9ad8\u6c14\u6e2912\u2103,\u897f\u5357\u98ce<3\u7ea7,30845\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a560\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003! \u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670809\u65e5(\u661f\u671f\u4e94) 13:14\u65f6\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103~12\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 -\u676d\u5dde\u5929\u6c14\u9884\u62a530(\u4e00\u4e2a\u6708)\u300140\u300160\u5929\u67e5\u8be2,\u676d\u5dde\u672a\u676560\u5929\u5929\u6c14\u8d8b\u52bf\u9884\u62a5 2026\u5e7401\u670809\u65e5(\u661f\u671f\u4e94) \u66742\u2103~12\u2103\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670810\u65e5(\u661f\u671f\u516d) \u66742\u2103~12\u2103\u5317\u98ce\u8f6c\u897f\u98ce<3\u7ea7 2026\u5e7401\u670811\u65e5(\u661f\u671f\u65e5) \u66740\u2103~9\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670812\u65e5(\u661f\u671f\u4e00) \u591a\u4e912\u2103~12\u2103\u897f\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670813\u65e5(\u661f\u671f\u4e8c) \u66744\u2103~16\u2103\u4e1c\u98ce\u8f6c\u5357\u98ce<3\u7ea7 2026\u5e7401\u670814\u65e5(\u661f\u671f\u4e09) \u66745\u2103~19\u2103\u4e1c\u5357\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 2026\u5e7401\u670815\u65e5(\u661f\u671f\u56db) \u66746\u2103~18\u2103\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7 \u6e29\u99a8\u63d0\u9192:\u676d\u5dde\u5929\u6c1460\u5929\u67e5\u8be2\u7ed3\u679c\u4e2d,8-60\u5929\u9884\u62a5\u5c5e\u4e8e\u5ba2\u89c2\u9884\u62a5\u4ea7\u54c1,\u53cd\u6620\u7684\u662f\u672a\u6765\u5929\u6c14\u53d8\u5316\u8d8b\u52bf,\u5177\u6709\u4e0d\u786e\u5b9a\u6027,\u8bf7\u968f\u65f6\u5173\u6ce8\u6700\u65b0\u51c6\u786e\u9884\u62a5\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 4, 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249369&pinyin=putuo', 'title': '\u3010\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u897f\u6e56\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'date': '2026-01-10 00:00:00', 'content': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'icon': 'https://b.bdstatic.com/searchbox/mappconsole/image/20181217/2ab53364-e12b-43fe-bacf-4806ff35d6b8.jpg', 'web_anchor': '', 'type': 'web', 'website': '\u667a\u80fd\u5c0f\u7a0b\u5e8f\u95e8\u6237', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde\u897f\u6e56 [\u5207\u6362]\u826f 43 2026-01-10 6 \u00b0\u6674\u4f53\u611f3\u00b0\u897f\u98ce2\u7ea7\u6e7f\u5ea674%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u4e0b\u96e8,\u653e\u5fc3\u51fa\u95e8\u5427\u676d\u5dde\u897f\u6e5624\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 6\u00b0c 09\u65f6 9\u00b0c 10\u65f6 11\u00b0c 11\u65f6 12\u00b0c 12\u65f6 12\u00b0c 13\u65f6 12\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 12\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 7\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 4\u00b0c 02\u65f6 3\u00b0c 03\u65f6 2\u00b0c 04\u65f6 1\u00b0c 05\u65f6 1\u00b0c 06\u65f6 -0\u00b0c 07\u65f6 -0\u00b0c\u4eca\u5929 01\u670810\u65e5\u6674 4~13\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 -0~9\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670812\u65e5\u6674\u8f6c\u591a\u4e91 -1~14\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 3~17\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 5~16\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674\u8f6c\u591a\u4e91 5~18\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u9634 4~18\u00b0c\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u9634\u8f6c\u591a\u4e91 5~16\u00b0c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e00 01\u670819\u65e5\u9634 4~14\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u4f18\u4f18\u661f\u671f\u4e8c 01\u670820\u65e5\u9634 4~15\u00b0c\u5317\u98ce ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 5, 'url': 'http://www.rfgza.cn/hangzhou/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'date': '2026-01-07 18:28:04', 'content': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 2\u2103 ~ 10\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 6, 'url': 'http://www.pzoby.cn/hangzhou/', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929', 'date': '2026-01-08 14:20:52', 'content': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4008\u65e5(\u661f\u671f\u56db) 14:20\u65f6\u9884\u8ba1,\u676d\u5dde\u4eca\u65e5\u5929\u6c14\u6674,\u6700\u4f4e\u6c14\u6e291\u2103,\u6700\u9ad8\u6c14\u6e2911\u2103,\u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce<3\u7ea7,96080\u5929\u6c14\u7ad9\u63d0\u9192\u60a8\u5bc6\u5207\u5173\u6ce8\u676d\u5dde\u5929\u6c14\u9884\u62a530\u5929,\u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002\u5929\u6709\u4e0d\u6d4b\u98ce\u4e91,\u67e5\u8be2\u7ed3\u679c\u5076\u6709\u8bef\u5dee,\u4ec5\u4f9b\u53c2\u8003!\u6d59\u6c5f\u676d\u5dde\u5929\u6c14\u9884\u62a5 - \u6d59\u6c5f\u7701\u676d\u5dde\u5e02\u6c14\u8c61\u5c4001\u670808\u65e5(\u661f\u671f\u56db) 14:20\u66f4\u65b0 \u4eca\u65e5\u676d\u5dde\u5929\u6c14\u9884\u62a5\u8be6\u60c5 \u6674 1\u2103 ~ 11\u2103 <3\u7ea7 \u7d2b\u5916\u7ebf\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002 \u8fd0\u52a8\u6307\u6570:\u6781\u4e0d\u6613\u53d1 \u65e0\u9700\u62c5\u5fc3\u8fc7\u654f,\u53ef\u653e\u5fc3\u5916\u51fa,\u4eab\u53d7\u751f\u6d3b\u3002 \u8840\u7cd6\u6307\u6570:\u5f3a \u6d82\u64e6SPF\u5927\u4e8e15\u3001PA+\u9632\u6652\u62a4\u80a4\u54c1\u3002', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 7, 'url': 'http://s5uxsw.smartapps.cn/pages/tianqiyubao/yubaojingdian?id=249379&pinyin=shangchengqu', 'title': '\u3010\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a5\u3011\u676d\u5dde\u676d\u5dde\u5b8b\u57ce\u5929\u6c14\u9884\u62a53\u5929\u3001\u4e00\u5468\u300110\u5929\u300115\u5929\u300130\u5929\u300140\u5929\u666f\u533a\u5929\u6c14\u9884\u62a5\u67e5\u8be2\u2014\u5929\u6c14\u7f51', 'date': '2026-01-09 00:00:00', 'content': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'icon': 'https://b.bdstatic.com/searchbox/mappconsole/image/20181217/2ab53364-e12b-43fe-bacf-4806ff35d6b8.jpg', 'web_anchor': '', 'type': 'web', 'website': '\u667a\u80fd\u5c0f\u7a0b\u5e8f\u95e8\u6237', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde\u5b8b\u57ce [\u5207\u6362]\u826f 55 2026-01-09 -1 \u00b0\u6674\u4f53\u611f-4\u00b0\u897f\u5357\u98ce 2\u7ea7\u6e7f\u5ea671%\u672a\u6765\u4e24\u5c0f\u65f6\u4e0d\u4f1a\u6709\u96ea\u3002\u591c\u6df1\u4e86,\u6ce8\u610f\u4f11\u606f\u54e6\uff5e\u676d\u5dde\u5b8b\u57ce24\u5c0f\u65f6\u9884\u62a5 \u73b0\u5728 -1\u00b0c 04\u65f6 2\u00b0c 05\u65f6 2\u00b0c 06\u65f6 2\u00b0c 07\u65f6 2\u00b0c 08\u65f6 2\u00b0c 09\u65f6 4\u00b0c 10\u65f6 6\u00b0c 11\u65f6 8\u00b0c 12\u65f6 10\u00b0c 13\u65f6 11\u00b0c 14\u65f6 12\u00b0c 15\u65f6 13\u00b0c 16\u65f6 13\u00b0c 17\u65f6 11\u00b0c 18\u65f6 9\u00b0c 19\u65f6 8\u00b0c 20\u65f6 8\u00b0c 21\u65f6 7\u00b0c 22\u65f6 6\u00b0c 23\u65f6 6\u00b0c 00\u65f6 5\u00b0c 01\u65f6 5\u00b0c 02\u65f6 5\u00b0c\u4eca\u5929 01\u670809\u65e5\u6674 -1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670810\u65e5\u6674 3~14\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670811\u65e5\u6674 2~12\u00b0c\u4e1c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e00 01\u670812\u65e5\u591a\u4e91\u8f6c\u6674 4~13\u00b0c\u897f\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e8c 01\u670813\u65e5\u6674 1~10\u00b0c\u897f\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e09 01\u670814\u65e5\u591a\u4e91\u8f6c\u6674 1~13\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u56db 01\u670815\u65e5\u591a\u4e91\u8f6c\u6674 4~16\u00b0c\u897f\u5357\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u4e94 01\u670816\u65e5\u6674 6~13\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u516d 01\u670817\u65e5\u6674 4~12\u00b0c\u5317\u98ce 2\u7ea7\u826f\u826f\u661f\u671f\u65e5 01\u670818\u65e5\u6674 3~12\u00b0c\u5317\u98ce ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 8, 'url': 'https://qq.ip138.com/weather/zhejiang/hangzhou_2zhou.htm', 'title': '\u676d\u5dde\u5929\u6c14\u9884\u62a5', 'date': '2026-01-09 16:28:09', 'content': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'icon': 'https://www.ip138.com/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': 'iP138\u67e5\u8be2\u7f51', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '2026-01-09 \u6674 2\u2103\uff5e 12\u2103 2026-01-10 \u6674 2026-01-11 \u6674 0\u2103\uff5e \u591a\u4e91 \u6674 2026-01-14 \u6674 \u6674 \u4e1c\u5317\u98ce\u8f6c\u897f\u5357\u98ce \u6674\u8f6c\u9634 ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}, {'id': 9, 'url': 'https://weather.cma.cn/web/weather/58457.html', 'title': '\u676d\u5dde', 'date': '2026-01-09 12:00:00', 'content': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'icon': '', 'web_anchor': '', 'type': 'web', 'website': '\u4e2d\u56fd\u6c14\u8c61\u5c40\u7f51\u7ad9', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': '\u676d\u5dde 2026/01/12 15:25\u66f4\u65b0 12.8 \u2103 1012hpa 25% 0mm \u897f\u5357\u98ce\u5fae\u98ce 7\u5929\u5929\u6c14\u9884\u62a5(2026/01/12 12:00\u53d1\u5e03) \u661f\u671f\u4e00 01/12 \u591a\u4e91 \u897f\u5357\u98ce \u5fae\u98ce 15\u2103 2\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e8c 01/13 \u6674 \u4e1c\u98ce \u5fae\u98ce 16\u2103 5\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e09 01/14 \u6674 \u897f\u5357\u98ce \u5fae\u98ce 21\u2103 6\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u56db 01/15 \u6674 \u4e1c\u5317\u98ce \u5fae\u98ce 20\u2103 8\u2103 \u6674 \u897f\u5357\u98ce \u5fae\u98ce \u661f\u671f\u4e94 01/16 \u591a\u4e91 \u4e1c\u98ce \u5fae\u98ce 21\u2103 9\u2103 \u591a\u4e91 \u5317\u98ce \u5fae\u98ce \u661f\u671f\u516d ', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 1, 'markdown_text': ''}, {'id': 10, 'url': 'https://www.ip.cn/tianqi/zhejiang/hangzhou/history.html', 'title': '\u676d\u5dde\u5e02\u6700\u8fd130\u5929\u5929\u6c14\u67e5\u8be2', 'date': '2026-01-09 20:52:24', 'content': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'icon': 'http://www.ip.cn/favicon.ico', 'web_anchor': '', 'type': 'web', 'website': '\u53a6\u95e8\u65f6\u7a7a\u79d1\u6280\u6709\u9650\u516c\u53f8', 'video': None, 'image': None, 'is_aladdin': False, 'aladdin': None, 'snippet': ' \u676d\u5dde\u5929\u6c14:2025-12-13\u81f32026-01-12 \u5929\u6c14 \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u65e5 12\u670813\u65e5 \u5c0f\u96e8\u8f6c\u6674 2\u2103\uff5e9\u2103 \u65e5\u51fa06:46 \u65e5\u843d17:00 12\u670814\u65e5 \u6674 1\u2103\uff5e10\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:00 12\u670815\u65e5 \u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:47 \u65e5\u843d17:01 12\u670816\u65e5 \u9634\u8f6c\u591a\u4e91 8\u2103\uff5e18\u2103 \u65e5\u51fa06:48 \u65e5\u843d17:01 12\u670817\u65e5 \u591a\u4e91\u8f6c\u6674 5\u2103\uff5e14\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:01 12\u670818\u65e5 \u591a\u4e91\u8f6c\u6674 8\u2103\uff5e15\u2103 \u65e5\u51fa06:49 \u65e5\u843d17:02 12\u670819\u65e5 \u591a\u4e91\u8f6c\u6674 11\u2103\uff5e22\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:02 12\u670820\u65e5 \u591a\u4e91\u8f6c\u5c0f\u96e8 6\u2103\uff5e21\u2103 \u65e5\u51fa06:50 \u65e5\u843d17:03 12\u670821\u65e5 \u9634\u8f6c\u6674 4\u2103\uff5e8\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:03 12\u670822\u65e5 \u9634\u8f6c\u6674 8\u2103\uff5e10\u2103 \u65e5\u51fa06:51 \u65e5\u843d17:04 12\u670823\u65e5 \u9634\u8f6c\u5c0f\u96e8 7\u2103\uff5e16\u2103 \u65e5\u51fa06:52 \u65e5\u843d17:04 12\u670824\u65e5 \u4e2d\u96e8\u8f6c\u5c0f\u96e8', 'web_extensions': {'images': None}, 'rerank_score': 1, 'authority_score': 0.5, 'markdown_text': ''}]} ", "chunk_index": 1, "is_prefix": null, "is_suffix": true} - -event: node_end -data: {"node_id": "end_1767619619942_unxlhspyr", "conversation_id": null, "execution_id": null, "timestamp": "2026-01-12T09:27:53.026022+00:00"} - -event: workflow_end -data: {"execution_id": "exec_ee8aa953bc1945fd", "status": "completed", "elapsed_time": 8.532952, "timestamp": "2026-01-12T17:27:53.026645"} - diff --git a/web/src/utils/format.ts b/web/src/utils/format.ts index e0342327..07983f1a 100644 --- a/web/src/utils/format.ts +++ b/web/src/utils/format.ts @@ -1,32 +1,46 @@ -/** - * 格式化日期时间 - * @param value 时间戳(毫秒)或日期字符串 - * @param format 目标格式,支持 YYYY-MM-DD HH:mm:ss、YYYY/MM/DD HH:mm:ss、HH:mm 等 - * @returns 格式化后的日期时间字符串 +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:34:43 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:34:43 */ +/** + * Format Utility + * + * Provides date/time formatting functions with timezone support. + * + * @module format + */ + import dayjs from 'dayjs'; import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; -// 扩展dayjs插件 +/** Extend dayjs with timezone plugins */ dayjs.extend(utc); dayjs.extend(timezone); + +/** + * Format date/time with timezone support + * @param value - Timestamp (milliseconds) or date string + * @param format - Target format, supports YYYY-MM-DD HH:mm:ss, YYYY/MM/DD HH:mm:ss, HH:mm, etc. + * @returns Formatted date/time string + */ export const formatDateTime = ( value: string | number | null | undefined, format: string = 'YYYY-MM-DD HH:mm:ss' ): string => { if (!value) return ''; - // 检查日期是否有效 + /** Check if date is valid */ if (!dayjs(value).isValid()) { return ''; } - // 每次调用都获取最新的时区设置 + /** Get current timezone setting from localStorage */ const currentTimeZone = localStorage.getItem('timeZone') || 'Asia/Shanghai'; dayjs.tz.setDefault(currentTimeZone); - // 使用最新时区格式化日期 + /** Format date with current timezone */ return dayjs.tz(value).format(format); }; - diff --git a/web/src/utils/request.ts b/web/src/utils/request.ts index e7112ded..7f85f4ce 100644 --- a/web/src/utils/request.ts +++ b/web/src/utils/request.ts @@ -1,3 +1,22 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:35:15 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:35:15 + */ +/** + * HTTP Request Utility Module + * + * Provides axios-based HTTP client with: + * - Automatic token refresh on 401 errors + * - Request/response interceptors + * - Cookie-based authentication + * - Error handling and user notifications + * - File upload/download support + * + * @module request + */ + import axios from 'axios'; import type { AxiosRequestConfig } from 'axios'; import { clearAuthData } from './auth'; @@ -5,6 +24,9 @@ import { message } from 'antd'; import { refreshTokenUrl, refreshToken, loginUrl, logoutUrl } from '@/api/user' import i18n from '@/i18n' +/** + * Standard API response structure + */ export interface ResponseData { code: number; msg: string; @@ -12,6 +34,10 @@ export interface ResponseData { error: string; time: number; } + +/** + * Paginated data structure + */ interface data { "items": Record[]; "page": { @@ -22,21 +48,22 @@ interface data { } } - export const API_PREFIX = '/api' -// 创建axios实例 + +// Create axios instance const service = axios.create({ - baseURL: API_PREFIX, // 与vite.config.ts中的代理配置对应 - // timeout: 10000, // 请求超时时间 + baseURL: API_PREFIX, // Corresponds to proxy config in vite.config.ts + // timeout: 10000, // Request timeout withCredentials: false, headers: { 'Content-Type': 'application/json' }, }); -// 是否正在刷新token +// Token refresh state let isRefreshing = false; -// 存储待重试的请求队列 + +// Queue for pending requests during token refresh interface RequestQueueItem { config: AxiosRequestConfig; resolve: (token: string) => void; @@ -44,7 +71,7 @@ interface RequestQueueItem { } let requests: RequestQueueItem[] = []; -// 请求拦截器 +// Request interceptor service.interceptors.request.use( (config) => { if (!config.headers.Authorization) { @@ -59,13 +86,16 @@ service.interceptors.request.use( return config; }, (error) => { - // 对请求错误做些什么 - console.error('请求错误:', error); + // Handle request errors + console.error('Request error:', error); return Promise.reject(error); } ); -// 刷新token的函数 +/** + * Refresh authentication token + * @returns New access token + */ const tokenRefresh = async (): Promise => { try { const refresh_token = cookieUtils.get('refreshToken'); @@ -75,16 +105,16 @@ const tokenRefresh = async (): Promise => { if (!refresh_token) { throw new Error(i18n.t('common.refreshTokenNotExist')); } - // 使用原生axios调用refresh接口,避免触发拦截器导致的循环调用 + // Use native axios to call refresh API, avoiding interceptor circular calls const response: any = await refreshToken(); const newToken = response.access_token; cookieUtils.set('authToken', newToken); return newToken; } catch (error) { - // 如果refresh接口也返回401,则退出登录 + // If refresh API also returns 401, logout clearAuthData(); message.warning(i18n.t('common.loginExpired')); - // 这里可以添加重定向到登录页的逻辑 + // Redirect to login page if (!window.location.hash.includes('#/login')) { window.location.href = `/#/login`; } @@ -92,13 +122,13 @@ const tokenRefresh = async (): Promise => { } }; -// 响应拦截器 +// Response interceptor service.interceptors.response.use( (response) => { - // 对响应数据做点什么 + // Process response data const { data: responseData } = response; - // 如果响应数据不是对象,直接返回 + // If response data is not an object, return directly if (!responseData || typeof responseData !== 'object') { return responseData; } @@ -110,7 +140,7 @@ service.interceptors.response.use( case 200: return data !== undefined ? data : responseData; case 401: - // 处理未授权情况 + // Handle unauthorized return handle401Error(response.config); default: if (code === undefined) { @@ -123,18 +153,18 @@ service.interceptors.response.use( } }, (error) => { - // 如果是取消请求,不显示错误提示 + // If request was cancelled, don't show error message if (axios.isCancel(error) || error.name === 'AbortError' || error.code === 'ERR_CANCELED') { return Promise.reject(error); } - // 处理网络错误、超时等 + // Handle network errors, timeouts, etc. let msg = error.response?.data?.error || error.response?.error; const status = error?.response ? error.response.status : error; - // 服务器响应了但状态码不在2xx范围 + // Server responded but status code is not in 2xx range switch (status) { case 401: - // 处理未授权情况 + // Handle unauthorized return handle401Error(error.config); case 403: msg = i18n.t('common.permissionDenied'); @@ -165,9 +195,13 @@ service.interceptors.response.use( } ); -// 处理401错误的函数 +/** + * Handle 401 unauthorized errors with token refresh + * @param config - Original request configuration + * @returns Retried request with new token + */ const handle401Error = async (config: AxiosRequestConfig): Promise => { - // 如果是refresh接口本身返回401,则直接退出登录 + // If refresh API itself returns 401, logout directly if (config.url === refreshTokenUrl) { clearAuthData(); message.warning(i18n.t('common.loginExpired')); @@ -184,39 +218,39 @@ const handle401Error = async (config: AxiosRequestConfig): Promise => { return Promise.reject(new Error(i18n.t('common.publicApiCannotRefreshToken'))); } - // 如果正在刷新token,则将当前请求加入队列 + // If token refresh is in progress, queue the request if (isRefreshing) { return new Promise((resolve, reject) => { requests.push({ config, resolve, reject }); }).then((token) => { - // 使用新token重新发送请求 + // Retry request with new token config.headers = config.headers || {}; config.headers.Authorization = `Bearer ${token}`; return service(config); }); } - // 开始刷新token + // Start token refresh isRefreshing = true; try { const newToken = await tokenRefresh(); - // 更新队列中所有请求的token并重新发送 + // Update token for all queued requests and resolve them requests.forEach(({ config, resolve }) => { config.headers = config.headers || {}; config.headers.Authorization = `Bearer ${newToken}`; resolve(newToken); }); - // 清空队列 + // Clear queue requests = []; - // 使用新token重新发送当前请求 + // Retry current request with new token config.headers = config.headers || {}; config.headers.Authorization = `Bearer ${newToken}`; return service(config); } catch (error) { - // 刷新token失败,清空队列并拒绝所有请求 + // Token refresh failed, clear queue and reject all requests requests.forEach(({ reject }) => { reject(error as Error); }); @@ -232,6 +266,12 @@ interface ObjectWithPush { [key: string]: string | number | boolean | object | null | undefined; } +/** + * Filter and clean request parameters + * - Removes null/undefined values + * - Trims string values + * - Handles objects with _push flag + */ function paramFilter(params: Record = {}) { Object.keys(params).forEach(key => { @@ -255,7 +295,9 @@ function paramFilter(params: Record(url: string, data?: unknown, config?: AxiosRequestConfig): Promise { return service.get(url, { @@ -307,10 +349,13 @@ export const request = { -// 获取父级域名 +/** + * Get parent domain for cookie setting + * @returns Parent domain or IP address + */ const getParentDomain = () => { const hostname = window.location.hostname - // 检查是否为IP地址 + // Check if it's an IP address if (/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) { return hostname } @@ -318,7 +363,9 @@ const getParentDomain = () => { return parts.length > 2 ? `.${parts.slice(-2).join('.')}` : hostname } -// Cookie操作工具 +/** + * Cookie utility functions + */ export const cookieUtils = { set: (name: string, value: string, domain = getParentDomain()) => { document.cookie = `${name}=${value}; domain=${domain}; path=/; secure; samesite=strict` diff --git a/web/src/utils/stream.ts b/web/src/utils/stream.ts index be2220da..ba0e4b98 100644 --- a/web/src/utils/stream.ts +++ b/web/src/utils/stream.ts @@ -1,3 +1,21 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:35:43 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:35:43 + */ +/** + * Server-Sent Events (SSE) Stream Utility Module + * + * Provides SSE handling with: + * - Automatic token refresh on 401 errors + * - SSE message parsing and JSON decoding + * - HTML entity decoding + * - Stream buffering for incomplete messages + * + * @module stream + */ + import { message } from 'antd'; import i18n from '@/i18n' import { cookieUtils } from './request' @@ -9,7 +27,10 @@ const API_PREFIX = '/api' let isRefreshing = false; let refreshPromise: Promise | null = null; -// Refresh token function for SSE +/** + * Refresh authentication token for SSE requests + * @returns New access token + */ const refreshTokenForSSE = async (): Promise => { if (isRefreshing && refreshPromise) { return refreshPromise; @@ -42,10 +63,19 @@ const refreshTokenForSSE = async (): Promise => { return refreshPromise; }; +/** + * SSE message structure + */ export interface SSEMessage { event?: string data?: string | object } + +/** + * Parse SSE string format to JSON objects + * @param sseString - Raw SSE string data + * @returns Array of parsed SSE messages + */ export function parseSSEToJSON(sseString: string) { const events: SSEMessage[] = [] const lines = sseString.trim().split('\n') @@ -77,9 +107,14 @@ export function parseSSEToJSON(sseString: string) { return events } +/** + * Parse SSE data content with HTML entity decoding + * @param dataContent - Raw data content string + * @returns Parsed object or original string + */ function parseDataContent(dataContent: string): string | object { try { - // 第一层解码:HTML实体 + // First layer: HTML entity decoding let unescaped = dataContent .replace(/"/g, '"') .replace(/&/g, '&') @@ -87,15 +122,15 @@ function parseDataContent(dataContent: string): string | object { .replace(/>/g, '>') .replace(/'/g, "'") - // 解析第一层JSON + // Parse first layer JSON const firstParse = JSON.parse(unescaped) - // 如果data字段是字符串且包含JSON,解析data层但保持chunk为字符串 + // If data field is a string containing JSON, parse data layer but keep chunk as string if (firstParse.data && typeof firstParse.data === 'string' && firstParse.data.includes("{")) { try { firstParse.data = JSON.parse(firstParse.data) } catch { - // 保持原字符串 + // Keep original string } } @@ -105,6 +140,14 @@ function parseDataContent(dataContent: string): string | object { } } +/** + * Make SSE request with authentication + * @param url - API endpoint + * @param data - Request payload + * @param token - Authentication token + * @param config - Additional request configuration + * @returns Fetch response + */ const makeSSERequest = async (url: string, data: any, token: string, config = { headers: {} }) => { return fetch(`${API_PREFIX}${url}`, { method: 'POST', @@ -117,6 +160,13 @@ const makeSSERequest = async (url: string, data: any, token: string, config = { }); }; +/** + * Handle SSE stream with automatic token refresh and message parsing + * @param url - API endpoint + * @param data - Request payload + * @param onMessage - Callback for each parsed message + * @param config - Additional request configuration + */ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMessage[]) => void, config = { headers: {} }) => { try { let token = cookieUtils.get('authToken'); @@ -153,7 +203,7 @@ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMe const reader = response.body.getReader(); const decoder = new TextDecoder(); - let buffer = ''; // 添加缓冲区来处理不完整的消息 + let buffer = ''; // Buffer for handling incomplete messages while (true) { const { done, value } = await reader.read(); @@ -162,9 +212,9 @@ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMe const chunk = decoder.decode(value, { stream: true }); buffer += chunk; - // 处理完整的事件 + // Process complete events const events = buffer.split('\n\n'); - buffer = events.pop() || ''; // 保留最后一个可能不完整的事件 + buffer = events.pop() || ''; // Keep last potentially incomplete event for (const event of events) { if (event.trim() && onMessage) { @@ -173,7 +223,7 @@ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMe } } - // 处理剩余的缓冲区内容 + // Process remaining buffer content if (buffer.trim() && onMessage) { onMessage(parseSSEToJSON(buffer) ?? {}); } diff --git a/web/src/utils/timezones.ts b/web/src/utils/timezones.ts index 5a096424..bf5ea277 100644 --- a/web/src/utils/timezones.ts +++ b/web/src/utils/timezones.ts @@ -1,3 +1,23 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:37:10 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:37:10 + */ +/** + * Timezone Configuration Module + * + * Provides: + * - Major world timezone list + * - Timezone to Ant Design locale mapping + * - Dayjs locale imports + * + * Note: Timezone display names are in i18n translation files (zh.ts and en.ts) + * Use i18n.t('timezones.timezone_name') to get localized timezone display names + * + * @module timezones + */ + import en_US from 'antd/locale/en_US'; import en_GB from 'antd/locale/en_GB'; import de_DE from 'antd/locale/de_DE'; @@ -12,157 +32,159 @@ import 'dayjs/locale/de' import 'dayjs/locale/en-gb' import 'dayjs/locale/en' -// 全世界主要时区列表 +/** + * Major world timezones list + */ export const timezones = [ - 'America/Los_Angeles', // 美国洛杉矶 - 'America/New_York', // 美国纽约 - 'Europe/London', // 英国伦敦 - 'Europe/Berlin', // 德国柏林 - 'Europe/Moscow', // 俄罗斯莫斯科 - 'Asia/Kolkata', // 印度加尔各答 - 'Asia/Shanghai', // 中国上海 + 'America/Los_Angeles', // Los Angeles, USA + 'America/New_York', // New York, USA + 'Europe/London', // London, UK + 'Europe/Berlin', // Berlin, Germany + 'Europe/Moscow', // Moscow, Russia + 'Asia/Kolkata', // Kolkata, India + 'Asia/Shanghai', // Shanghai, China - // 亚洲 - // 'Asia/Tokyo', // 日本东京 - // 'Asia/Singapore', // 新加坡 - // 'Asia/Hong_Kong', // 中国香港 - // 'Asia/Taipei', // 中国台北 - // 'Asia/Seoul', // 韩国首尔 - // 'Asia/Bangkok', // 泰国曼谷 - // 'Asia/Jakarta', // 印度尼西亚雅加达 - // 'Asia/Manila', // 菲律宾马尼拉 - // 'Asia/Dubai', // 阿联酋迪拜 - // 'Asia/Tashkent', // 乌兹别克斯坦塔什干 - // 'Asia/Riyadh', // 沙特阿拉伯利雅得 - // 'Asia/Baku', // 阿塞拜疆巴库 - // 'Asia/Istanbul', // 土耳其伊斯坦布尔 + // Asia + // 'Asia/Tokyo', // Tokyo, Japan + // 'Asia/Singapore', // Singapore + // 'Asia/Hong_Kong', // Hong Kong, China + // 'Asia/Taipei', // Taipei, Taiwan + // 'Asia/Seoul', // Seoul, South Korea + // 'Asia/Bangkok', // Bangkok, Thailand + // 'Asia/Jakarta', // Jakarta, Indonesia + // 'Asia/Manila', // Manila, Philippines + // 'Asia/Dubai', // Dubai, UAE + // 'Asia/Tashkent', // Tashkent, Uzbekistan + // 'Asia/Riyadh', // Riyadh, Saudi Arabia + // 'Asia/Baku', // Baku, Azerbaijan + // 'Asia/Istanbul', // Istanbul, Turkey - // 欧洲 - // 'Europe/Paris', // 法国巴黎 - // 'Europe/Rome', // 意大利罗马 - // 'Europe/Madrid', // 西班牙马德里 - // 'Europe/Amsterdam', // 荷兰阿姆斯特丹 - // 'Europe/Vienna', // 奥地利维也纳 - // 'Europe/Stockholm', // 瑞典斯德哥尔摩 - // 'Europe/Oslo', // 挪威奥斯陆 - // 'Europe/Copenhagen', // 丹麦哥本哈根 - // 'Europe/Zurich', // 瑞士苏黎世 - // 'Europe/Athens', // 希腊雅典 - // 'Europe/Warsaw', // 波兰华沙 - // 'Europe/Prague', // 捷克布拉格 - // 'Europe/Budapest', // 匈牙利布达佩斯 - // 'Europe/Belgrade', // 塞尔维亚贝尔格莱德 + // Europe + // 'Europe/Paris', // Paris, France + // 'Europe/Rome', // Rome, Italy + // 'Europe/Madrid', // Madrid, Spain + // 'Europe/Amsterdam', // Amsterdam, Netherlands + // 'Europe/Vienna', // Vienna, Austria + // 'Europe/Stockholm', // Stockholm, Sweden + // 'Europe/Oslo', // Oslo, Norway + // 'Europe/Copenhagen', // Copenhagen, Denmark + // 'Europe/Zurich', // Zurich, Switzerland + // 'Europe/Athens', // Athens, Greece + // 'Europe/Warsaw', // Warsaw, Poland + // 'Europe/Prague', // Prague, Czech Republic + // 'Europe/Budapest', // Budapest, Hungary + // 'Europe/Belgrade', // Belgrade, Serbia - // 北美洲 - // 'America/Chicago', // 美国芝加哥 - // 'America/Denver', // 美国丹佛 - // 'America/Toronto', // 加拿大多伦多 - // 'America/Vancouver', // 加拿大温哥华 - // 'America/Mexico_City', // 墨西哥墨西哥城 + // North America + // 'America/Chicago', // Chicago, USA + // 'America/Denver', // Denver, USA + // 'America/Toronto', // Toronto, Canada + // 'America/Vancouver', // Vancouver, Canada + // 'America/Mexico_City', // Mexico City, Mexico - // 南美洲 - // 'America/Sao_Paulo', // 巴西圣保罗 - // 'America/Buenos_Aires', // 阿根廷布宜诺斯艾利斯 - // 'America/Santiago', // 智利圣地亚哥 - // 'America/Lima', // 秘鲁利马 - // 'America/Bogota', // 哥伦比亚波哥大 - // 'America/Caracas', // 委内瑞拉加拉加斯 + // South America + // 'America/Sao_Paulo', // São Paulo, Brazil + // 'America/Buenos_Aires', // Buenos Aires, Argentina + // 'America/Santiago', // Santiago, Chile + // 'America/Lima', // Lima, Peru + // 'America/Bogota', // Bogotá, Colombia + // 'America/Caracas', // Caracas, Venezuela - // // 大洋洲 - // 'Australia/Sydney', // 澳大利亚悉尼 - // 'Australia/Melbourne', // 澳大利亚墨尔本 - // 'Australia/Brisbane', // 澳大利亚布里斯班 - // 'Australia/Perth', // 澳大利亚珀斯 - // 'New_Zealand/Auckland', // 新西兰奥克兰 + // Oceania + // 'Australia/Sydney', // Sydney, Australia + // 'Australia/Melbourne', // Melbourne, Australia + // 'Australia/Brisbane', // Brisbane, Australia + // 'Australia/Perth', // Perth, Australia + // 'New_Zealand/Auckland', // Auckland, New Zealand - // // 非洲 - // 'Africa/Cairo', // 埃及开罗 - // 'Africa/Johannesburg', // 南非约翰内斯堡 - // 'Africa/Lagos', // 尼日利亚拉各斯 - // 'Africa/Casablanca', // 摩洛哥卡萨布兰卡 - // 'Africa/Nairobi', // 肯尼亚内罗毕 - // 'Africa/Addis_Ababa', // 埃塞俄比亚亚的斯亚贝巴 + // Africa + // 'Africa/Cairo', // Cairo, Egypt + // 'Africa/Johannesburg', // Johannesburg, South Africa + // 'Africa/Lagos', // Lagos, Nigeria + // 'Africa/Casablanca', // Casablanca, Morocco + // 'Africa/Nairobi', // Nairobi, Kenya + // 'Africa/Addis_Ababa', // Addis Ababa, Ethiopia - // // 其他 - // 'UTC', // 协调世界时 + // Other + // 'UTC', // Coordinated Universal Time ]; -// 注意:时区显示名称已移至i18n翻译文件中(zh.ts和en.ts) -// 请使用i18n.t('timezones.时区名称')来获取本地化的时区显示名称 - -// 时区与antd本地化文件的映射 -// 键为时区,值为antd本地化文件的名称 +/** + * Timezone to Ant Design locale mapping + * Key: timezone identifier + * Value: Ant Design locale object + */ export const timezoneToAntdLocaleMap: Record = { - // 亚洲 - 'Asia/Shanghai': zh_CN, // 中国上海 - 中文(中国大陆) - 'Asia/Kolkata': hi_IN, // 印度加尔各答 - 印地语 - 'Europe/Moscow': ru_RU, // 俄罗斯莫斯科 - 俄语 - 'Europe/Berlin': de_DE, // 德国柏林 - 德语 - 'Europe/London': en_GB, // 英国伦敦 - 英语(英国) - 'America/New_York': en_US, // 美国纽约 - 英语(美国) - 'America/Los_Angeles': en_US, // 美国洛杉矶 - 英语(美国) + // Asia + 'Asia/Shanghai': zh_CN, // Shanghai, China - Chinese (Mainland) + 'Asia/Kolkata': hi_IN, // Kolkata, India - Hindi + 'Europe/Moscow': ru_RU, // Moscow, Russia - Russian + 'Europe/Berlin': de_DE, // Berlin, Germany - German + 'Europe/London': en_GB, // London, UK - English (UK) + 'America/New_York': en_US, // New York, USA - English (US) + 'America/Los_Angeles': en_US, // Los Angeles, USA - English (US) - // 'Asia/Tokyo': 'ja_JP', // 日本东京 - 日语 - // 'Asia/Singapore': 'en_SG', // 新加坡 - 英语(新加坡) - // 'Asia/Hong_Kong': 'zh_HK', // 中国香港 - 中文(香港) - // 'Asia/Taipei': 'zh_TW', // 中国台北 - 中文(台湾) - // 'Asia/Seoul': 'ko_KR', // 韩国首尔 - 韩语 - // 'Asia/Bangkok': 'th_TH', // 泰国曼谷 - 泰语 - // 'Asia/Jakarta': 'id_ID', // 印度尼西亚雅加达 - 印尼语 - // 'Asia/Manila': 'en_PH', // 菲律宾马尼拉 - 英语(菲律宾) - // 'Asia/Dubai': 'ar_AE', // 阿联酋迪拜 - 阿拉伯语 - // 'Asia/Tashkent': 'uz_UZ', // 乌兹别克斯坦塔什干 - 乌兹别克语 - // 'Asia/Riyadh': 'ar_SA', // 沙特阿拉伯利雅得 - 阿拉伯语 - // 'Asia/Baku': 'az_AZ', // 阿塞拜疆巴库 - 阿塞拜疆语 - // 'Asia/Istanbul': 'tr_TR', // 土耳其伊斯坦布尔 - 土耳其语 + // 'Asia/Tokyo': 'ja_JP', // Tokyo, Japan - Japanese + // 'Asia/Singapore': 'en_SG', // Singapore - English (Singapore) + // 'Asia/Hong_Kong': 'zh_HK', // Hong Kong, China - Chinese (Hong Kong) + // 'Asia/Taipei': 'zh_TW', // Taipei, Taiwan - Chinese (Taiwan) + // 'Asia/Seoul': 'ko_KR', // Seoul, South Korea - Korean + // 'Asia/Bangkok': 'th_TH', // Bangkok, Thailand - Thai + // 'Asia/Jakarta': 'id_ID', // Jakarta, Indonesia - Indonesian + // 'Asia/Manila': 'en_PH', // Manila, Philippines - English (Philippines) + // 'Asia/Dubai': 'ar_AE', // Dubai, UAE - Arabic + // 'Asia/Tashkent': 'uz_UZ', // Tashkent, Uzbekistan - Uzbek + // 'Asia/Riyadh': 'ar_SA', // Riyadh, Saudi Arabia - Arabic + // 'Asia/Baku': 'az_AZ', // Baku, Azerbaijan - Azerbaijani + // 'Asia/Istanbul': 'tr_TR', // Istanbul, Turkey - Turkish - // // 欧洲 - // 'Europe/Paris': 'fr_FR', // 法国巴黎 - 法语 - // 'Europe/Rome': 'it_IT', // 意大利罗马 - 意大利语 - // 'Europe/Madrid': 'es_ES', // 西班牙马德里 - 西班牙语 - // 'Europe/Amsterdam': 'nl_NL', // 荷兰阿姆斯特丹 - 荷兰语 - // 'Europe/Vienna': 'de_AT', // 奥地利维也纳 - 德语(奥地利) - // 'Europe/Stockholm': 'sv_SE', // 瑞典斯德哥尔摩 - 瑞典语 - // 'Europe/Oslo': 'nb_NO', // 挪威奥斯陆 - 挪威语 - // 'Europe/Copenhagen': 'da_DK', // 丹麦哥本哈根 - 丹麦语 - // 'Europe/Zurich': 'de_CH', // 瑞士苏黎世 - 德语(瑞士) - // 'Europe/Athens': 'el_GR', // 希腊雅典 - 希腊语 - // 'Europe/Warsaw': 'pl_PL', // 波兰华沙 - 波兰语 - // 'Europe/Prague': 'cs_CZ', // 捷克布拉格 - 捷克语 - // 'Europe/Budapest': 'hu_HU', // 匈牙利布达佩斯 - 匈牙利语 - // 'Europe/Belgrade': 'sr_RS', // 塞尔维亚贝尔格莱德 - 塞尔维亚语 + // Europe + // 'Europe/Paris': 'fr_FR', // Paris, France - French + // 'Europe/Rome': 'it_IT', // Rome, Italy - Italian + // 'Europe/Madrid': 'es_ES', // Madrid, Spain - Spanish + // 'Europe/Amsterdam': 'nl_NL', // Amsterdam, Netherlands - Dutch + // 'Europe/Vienna': 'de_AT', // Vienna, Austria - German (Austria) + // 'Europe/Stockholm': 'sv_SE', // Stockholm, Sweden - Swedish + // 'Europe/Oslo': 'nb_NO', // Oslo, Norway - Norwegian + // 'Europe/Copenhagen': 'da_DK', // Copenhagen, Denmark - Danish + // 'Europe/Zurich': 'de_CH', // Zurich, Switzerland - German (Switzerland) + // 'Europe/Athens': 'el_GR', // Athens, Greece - Greek + // 'Europe/Warsaw': 'pl_PL', // Warsaw, Poland - Polish + // 'Europe/Prague': 'cs_CZ', // Prague, Czech Republic - Czech + // 'Europe/Budapest': 'hu_HU', // Budapest, Hungary - Hungarian + // 'Europe/Belgrade': 'sr_RS', // Belgrade, Serbia - Serbian - // // 北美洲 - // 'America/Chicago': 'en_US', // 美国芝加哥 - 英语(美国) - // 'America/Denver': 'en_US', // 美国丹佛 - 英语(美国) - // 'America/Toronto': 'en_CA', // 加拿大多伦多 - 英语(加拿大) - // 'America/Vancouver': 'en_CA', // 加拿大温哥华 - 英语(加拿大) - // 'America/Mexico_City': 'es_MX', // 墨西哥墨西哥城 - 西班牙语(墨西哥) + // North America + // 'America/Chicago': 'en_US', // Chicago, USA - English (US) + // 'America/Denver': 'en_US', // Denver, USA - English (US) + // 'America/Toronto': 'en_CA', // Toronto, Canada - English (Canada) + // 'America/Vancouver': 'en_CA', // Vancouver, Canada - English (Canada) + // 'America/Mexico_City': 'es_MX', // Mexico City, Mexico - Spanish (Mexico) - // // 南美洲 - // 'America/Sao_Paulo': 'pt_BR', // 巴西圣保罗 - 葡萄牙语(巴西) - // 'America/Buenos_Aires': 'es_AR', // 阿根廷布宜诺斯艾利斯 - 西班牙语(阿根廷) - // 'America/Santiago': 'es_CL', // 智利圣地亚哥 - 西班牙语(智利) - // 'America/Lima': 'es_PE', // 秘鲁利马 - 西班牙语(秘鲁) - // 'America/Bogota': 'es_CO', // 哥伦比亚波哥大 - 西班牙语(哥伦比亚) - // 'America/Caracas': 'es_VE', // 委内瑞拉加拉加斯 - 西班牙语(委内瑞拉) + // South America + // 'America/Sao_Paulo': 'pt_BR', // São Paulo, Brazil - Portuguese (Brazil) + // 'America/Buenos_Aires': 'es_AR', // Buenos Aires, Argentina - Spanish (Argentina) + // 'America/Santiago': 'es_CL', // Santiago, Chile - Spanish (Chile) + // 'America/Lima': 'es_PE', // Lima, Peru - Spanish (Peru) + // 'America/Bogota': 'es_CO', // Bogotá, Colombia - Spanish (Colombia) + // 'America/Caracas': 'es_VE', // Caracas, Venezuela - Spanish (Venezuela) - // // 大洋洲 - // 'Australia/Sydney': 'en_AU', // 澳大利亚悉尼 - 英语(澳大利亚) - // 'Australia/Melbourne': 'en_AU', // 澳大利亚墨尔本 - 英语(澳大利亚) - // 'Australia/Brisbane': 'en_AU', // 澳大利亚布里斯班 - 英语(澳大利亚) - // 'Australia/Perth': 'en_AU', // 澳大利亚珀斯 - 英语(澳大利亚) - // 'New_Zealand/Auckland': 'en_NZ', // 新西兰奥克兰 - 英语(新西兰) + // Oceania + // 'Australia/Sydney': 'en_AU', // Sydney, Australia - English (Australia) + // 'Australia/Melbourne': 'en_AU', // Melbourne, Australia - English (Australia) + // 'Australia/Brisbane': 'en_AU', // Brisbane, Australia - English (Australia) + // 'Australia/Perth': 'en_AU', // Perth, Australia - English (Australia) + // 'New_Zealand/Auckland': 'en_NZ', // Auckland, New Zealand - English (New Zealand) - // // 非洲 - // 'Africa/Cairo': 'ar_EG', // 埃及开罗 - 阿拉伯语(埃及) - // 'Africa/Johannesburg': 'en_ZA', // 南非约翰内斯堡 - 英语(南非) - // 'Africa/Lagos': 'en_NG', // 尼日利亚拉各斯 - 英语(尼日利亚) - // 'Africa/Casablanca': 'fr_MA', // 摩洛哥卡萨布兰卡 - 法语(摩洛哥) - // 'Africa/Nairobi': 'en_KE', // 肯尼亚内罗毕 - 英语(肯尼亚) - // 'Africa/Addis_Ababa': 'am_ET', // 埃塞俄比亚亚的斯亚贝巴 - 阿姆哈拉语 + // Africa + // 'Africa/Cairo': 'ar_EG', // Cairo, Egypt - Arabic (Egypt) + // 'Africa/Johannesburg': 'en_ZA', // Johannesburg, South Africa - English (South Africa) + // 'Africa/Lagos': 'en_NG', // Lagos, Nigeria - English (Nigeria) + // 'Africa/Casablanca': 'fr_MA', // Casablanca, Morocco - French (Morocco) + // 'Africa/Nairobi': 'en_KE', // Nairobi, Kenya - English (Kenya) + // 'Africa/Addis_Ababa': 'am_ET', // Addis Ababa, Ethiopia - Amharic - // // 其他 - // 'UTC': 'en_US', // 协调世界时 - 默认英语(美国) + // Other + // 'UTC': 'en_US', // Coordinated Universal Time - Default English (US) }; \ No newline at end of file diff --git a/web/src/utils/yamlExport.ts b/web/src/utils/yamlExport.ts index 9a8c0c41..27ab9d39 100644 --- a/web/src/utils/yamlExport.ts +++ b/web/src/utils/yamlExport.ts @@ -1,6 +1,24 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 16:35:32 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 16:35:32 + */ +/** + * YAML Export Utility + * + * Provides functions to export data as YAML files. + * + * @module yamlExport + */ + import yaml from 'js-yaml'; - +/** + * Export data to YAML file + * @param data - Data to export + * @param filename - Output filename (default: 'export.yaml') + */ export const exportToYaml = (data: unknown, filename: string = 'export.yaml') => { const yamlStr = yaml.dump(data); const blob = new Blob([yamlStr], { type: 'text/yaml' }); From a191e32f715d84aa0e52b760e82913567dcff2fa Mon Sep 17 00:00:00 2001 From: zhaoying Date: Mon, 2 Feb 2026 16:14:39 +0800 Subject: [PATCH 3/3] docs: add comments to the src/components directory --- web/src/components/ButtonCheckbox/index.tsx | 42 ++++++++-- web/src/components/CustomSelect/index.tsx | 35 ++++++++ web/src/components/Empty/BodyWrapper.tsx | 22 +++++ web/src/components/Empty/Loading.tsx | 23 ++++- web/src/components/Empty/PageEmpty.tsx | 23 ++++- web/src/components/Empty/PageLoading.tsx | 23 ++++- web/src/components/Empty/index.tsx | 27 ++++++ web/src/components/FormItem/DescWrapper.tsx | 19 +++++ web/src/components/FormItem/LabelWrapper.tsx | 21 +++++ .../components/FormItem/SwitchFormItem.tsx | 30 +++++-- web/src/components/Header/SettingModal.tsx | 37 ++++++-- web/src/components/Header/UserInfoModal.tsx | 54 +++++++++--- web/src/components/Header/index.tsx | 82 +++++++++++------- web/src/components/Layout/AuthLayout.tsx | 35 +++++++- web/src/components/Layout/AuthSpaceLayout.tsx | 38 ++++++++- web/src/components/Layout/BasicLayout.tsx | 28 ++++++- web/src/components/Layout/LayoutBg.tsx | 26 +++++- web/src/components/Layout/LoginLayout.tsx | 21 ++++- web/src/components/Layout/NoAuthLayout.tsx | 21 ++++- web/src/components/Markdown/AudioBlock.tsx | 22 ++++- web/src/components/Markdown/Code.tsx | 32 ++++++- web/src/components/Markdown/CodeBlock.tsx | 27 ++++-- web/src/components/Markdown/CopyBtn.tsx | 19 ++++- web/src/components/Markdown/Link.tsx | 20 ++++- web/src/components/Markdown/MermaidChart.tsx | 23 +++++ web/src/components/Markdown/Paragraph.tsx | 19 ++++- web/src/components/Markdown/RbButton.tsx | 19 ++++- web/src/components/Markdown/Svg.tsx | 21 ++++- web/src/components/Markdown/VideoBlock.tsx | 21 ++++- web/src/components/Markdown/index.tsx | 67 +++++++++++---- web/src/components/PageScrollList/index.tsx | 39 ++++++++- web/src/components/PageTabs/index.tsx | 20 +++++ web/src/components/RadioGroupCard/index.tsx | 42 +++++++++- web/src/components/RbAlert/index.tsx | 22 +++++ web/src/components/RbCard/Card.tsx | 45 ++++++++++ web/src/components/RbCard/index.tsx | 73 ---------------- web/src/components/RbDrawer/index.tsx | 31 +++++-- web/src/components/RbModal/Confirm.tsx | 63 -------------- web/src/components/RbModal/index.tsx | 27 ++++-- web/src/components/RbSlider/index.tsx | 34 ++++++-- web/src/components/SearchInput/index.tsx | 38 ++++++++- web/src/components/SiderMenu/index.tsx | 74 +++++++++++----- web/src/components/SliderInput/index.tsx | 42 +++++++++- .../components/SortableList/DragHandle.tsx | 17 ++++ .../SortableList/SortableListItem.tsx | 19 ++++- .../SortableList/SortableListItemContext.tsx | 18 +++- web/src/components/SortableList/index.tsx | 38 ++++++++- web/src/components/SortableList/types.ts | 17 ++++ web/src/components/StatusTag/index.tsx | 21 +++++ web/src/components/Table/index.module.css | 3 - web/src/components/Table/index.tsx | 84 ++++++++++++++----- web/src/components/Tag/index.tsx | 21 +++++ web/src/components/Upload/UploadImages.tsx | 74 +++++++++++----- web/src/views/KnowledgeBase/index.tsx | 2 +- .../views/MemoryExtractionEngine/index.tsx | 31 +++---- 55 files changed, 1417 insertions(+), 375 deletions(-) delete mode 100644 web/src/components/RbCard/index.tsx delete mode 100644 web/src/components/RbModal/Confirm.tsx delete mode 100644 web/src/components/Table/index.module.css diff --git a/web/src/components/ButtonCheckbox/index.tsx b/web/src/components/ButtonCheckbox/index.tsx index 65813809..4b43f18a 100644 --- a/web/src/components/ButtonCheckbox/index.tsx +++ b/web/src/components/ButtonCheckbox/index.tsx @@ -1,14 +1,36 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:01:59 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:46:05 + */ + +/** + * ButtonCheckbox - A custom checkbox component styled as a button + * + * This component provides a button-like interface for checkbox functionality, + * with support for custom icons and visual states (checked/unchecked). + * + * @component + */ + import { type FC, type ReactNode, useEffect } from 'react'; import { type RadioGroupProps } from 'antd'; import clsx from 'clsx' - +// Button checkbox component props interface ButtonCheckboxProps extends Omit { + /** Whether the checkbox is checked */ checked?: boolean; + /** Callback fired when value changes (for side effects) */ onValueChange?: (checked: boolean) => void; + /** Callback fired when checkbox state changes */ onChange?: (checked: boolean) => void; + /** Icon path for unchecked state */ icon?: string; + /** Icon path for checked state */ checkedIcon?: string; + /** Button content */ children?: ReactNode } @@ -20,13 +42,14 @@ const ButtonCheckbox: FC = ({ checkedIcon, children, }) => { - // 监听value变化 + // Listen to value changes and trigger side effects via onValueChange callback useEffect(() => { if (onValueChange) { onValueChange(checked); } }, [checked, onValueChange]); + // Toggle checked state when button is clicked const handleChange = () => { if (onChange) { onChange(!checked); @@ -34,11 +57,18 @@ const ButtonCheckbox: FC = ({ } return ( -
+
+ {/* Display unchecked icon when not checked */} {icon && !checked && } + {/* Display checked icon when checked */} {checkedIcon && checked && } {children}
diff --git a/web/src/components/CustomSelect/index.tsx b/web/src/components/CustomSelect/index.tsx index f93014c9..ea5ca718 100644 --- a/web/src/components/CustomSelect/index.tsx +++ b/web/src/components/CustomSelect/index.tsx @@ -1,31 +1,61 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:02:17 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:46:29 + */ +/** + * CustomSelect - A select component that fetches options from an API + * + * This component extends Ant Design's Select with automatic data fetching, + * search functionality, and customizable option formatting. + * + * @component + */ + import { useEffect, useState, useMemo, type FC, type Key } from 'react'; import { Select } from 'antd'; import type { SelectProps, DefaultOptionType } from 'antd/es/select'; import { useTranslation } from 'react-i18next'; + import { request } from '@/utils/request'; +// Generic option type for API response data interface OptionType { [key: string]: Key | string | number; } +// API response structure interface ApiResponse { items?: T[]; } interface CustomSelectProps extends Omit { + /** API endpoint URL to fetch options */ url: string; + /** Query parameters for the API request */ params?: Record; + /** Key name for option value in response data */ valueKey?: string; + /** Key name for option label in response data */ labelKey?: string; + /** Placeholder text for the select */ placeholder?: string; + /** Whether to show "All" option */ hasAll?: boolean; + /** Custom text for "All" option */ allTitle?: string; + /** Function to format/transform the options data */ format?: (items: OptionType[]) => OptionType[]; + /** Whether to enable search functionality */ showSearch?: boolean; + /** Property name to filter options by */ optionFilterProp?: string; + /** Custom filter function for search */ filterOption?: (inputValue: string, option?: DefaultOptionType) => boolean; } +// Default filter function for search - performs case-insensitive substring matching const defaultFilterOption = (inputValue: string, option?: DefaultOptionType): boolean => { if (!option || !inputValue) return true; const label = String(option.children || option.label || ''); @@ -47,8 +77,10 @@ const CustomSelect: FC = ({ }) => { const { t } = useTranslation(); const [options, setOptions] = useState([]); + // Memoize params to prevent unnecessary re-fetches const memoizedParams = useMemo(() => params, [JSON.stringify(params)]); + // Fetch options from API when url or params change useEffect(() => { request.get>(url, memoizedParams).then((res) => { const data = Array.isArray(res) ? res : res?.items || []; @@ -56,6 +88,7 @@ const CustomSelect: FC = ({ }); }, [url, memoizedParams]); + // Apply custom format function if provided const displayOptions = format ? format(options) : options; return ( @@ -66,7 +99,9 @@ const CustomSelect: FC = ({ filterOption={filterOption || defaultFilterOption} {...props} > + {/* Optional "All" option for selecting all items */} {hasAll && {allTitle || t('common.all')}} + {/* Render options from API data */} {displayOptions.map((option) => ( {String(option[labelKey])} diff --git a/web/src/components/Empty/BodyWrapper.tsx b/web/src/components/Empty/BodyWrapper.tsx index 9cdeb0e8..22bd226a 100644 --- a/web/src/components/Empty/BodyWrapper.tsx +++ b/web/src/components/Empty/BodyWrapper.tsx @@ -1,19 +1,41 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:02:47 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:47:24 + */ +/** + * BodyWrapper Component + * + * A wrapper component that conditionally renders loading, empty, or content states. + * Simplifies state management for data-driven components. + * + * @component + */ + import type { FC, ReactNode } from 'react' + import PageEmpty from './PageEmpty' import PageLoading from './PageLoading' interface BodyWrapperProps { + /** Content to render when not loading or empty */ children: ReactNode + /** Whether to show loading state */ loading?: boolean + /** Whether the content is empty */ empty: boolean } const BodyWrapper: FC = ({ children, loading = false, empty }) => { + // Show loading spinner while data is being fetched if (loading) { return } + // Show empty state when no data is available if (!loading && empty) { return } + // Render actual content when data is loaded and available return children } export default BodyWrapper diff --git a/web/src/components/Empty/Loading.tsx b/web/src/components/Empty/Loading.tsx index c34b5d29..87bbe5dc 100644 --- a/web/src/components/Empty/Loading.tsx +++ b/web/src/components/Empty/Loading.tsx @@ -1,7 +1,28 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:03:52 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:48:41 + */ +/** + * Loading Component + * + * A specialized empty state component that displays a loading animation. + * Uses the Empty component with a loading icon and localized loading messages. + * + * @component + */ + +import { type FC } from 'react'; import { useTranslation } from 'react-i18next' + import LoadingIcon from '@/assets/images/loading.svg' import Empty from './index' -const Loading = ({ size = 200 }: { size?: number }) => { + +/** + * @param size - Icon size in pixels (default: 200) + */ +const Loading: FC<{ size?: number }> = ({ size = 200 }) => { const { t } = useTranslation() return ( { + +/** + * @param size - Icon size in pixels - single number or [width, height] array (default: [240, 210]) + */ +const PageEmpty: FC<{ size?: number | number[] }> = ({ size = [240, 210] }) => { const { t } = useTranslation() return ( { + +/** + * @param size - Icon size in pixels - single number or [width, height] array (default: [240, 210]) + */ +const PageLoading: FC<{ size?: number | number[] }> = ({ size = [240, 210] }) => { const { t } = useTranslation() return ( = ({ @@ -19,14 +41,19 @@ const Empty: FC = ({ className = '', }) => { const { t } = useTranslation(); + // Calculate width and height from size prop (supports single value or [width, height] array) const width = Array.isArray(size) ? size[0] : size ? size : url ? 200 : 88; const height = Array.isArray(size) ? size[1] : size ? size : url ? 200 : 88; + // Use custom subtitle or default translation if subtitle is needed const curSubTitle = isNeedSubTitle ? (subTitle || t('empty.tableEmpty')) : null; return (
+ {/* Empty state icon */} 404 + {/* Optional title */} {title &&
{title}
} + {/* Optional subtitle with conditional styling */} {curSubTitle &&
{curSubTitle}
}
); diff --git a/web/src/components/FormItem/DescWrapper.tsx b/web/src/components/FormItem/DescWrapper.tsx index 300fc2b6..5060b588 100644 --- a/web/src/components/FormItem/DescWrapper.tsx +++ b/web/src/components/FormItem/DescWrapper.tsx @@ -1,6 +1,25 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:05:16 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:05:16 + */ +/** + * DescWrapper Component + * + * A styled wrapper for displaying description text in forms. + * Provides consistent typography and styling for form field descriptions. + * + * @component + */ + import clsx from "clsx"; import type { FC, ReactNode } from "react"; +/** + * @param desc - Description content (string or React node) + * @param className - Additional CSS classes for customization + */ const DescWrapper: FC<{desc: string | ReactNode, className?: string}> = ({desc, className}) => { return (
diff --git a/web/src/components/FormItem/LabelWrapper.tsx b/web/src/components/FormItem/LabelWrapper.tsx index 461250d8..d608462b 100644 --- a/web/src/components/FormItem/LabelWrapper.tsx +++ b/web/src/components/FormItem/LabelWrapper.tsx @@ -1,9 +1,30 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:05:41 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:05:41 + */ +/** + * LabelWrapper Component + * + * A styled wrapper for displaying form field labels with optional child content. + * Provides consistent typography and layout for form labels. + * + * @component + */ + import clsx from "clsx"; import type { FC, ReactNode } from "react"; +/** + * @param title - Label text or React node to display + * @param className - Additional CSS classes for customization + * @param children - Optional child content to render below the label + */ const LabelWrapper: FC<{ title: string | ReactNode, className?: string; children?: ReactNode}> = ({title, className, children}) => { return (
+ {/* Label title with consistent styling */}
{title}
{children}
diff --git a/web/src/components/FormItem/SwitchFormItem.tsx b/web/src/components/FormItem/SwitchFormItem.tsx index e17a8728..8ac52f98 100644 --- a/web/src/components/FormItem/SwitchFormItem.tsx +++ b/web/src/components/FormItem/SwitchFormItem.tsx @@ -1,17 +1,36 @@ -import { Switch, Form, ConfigProvider } from "antd"; -import useSize from 'antd/lib/config-provider/hooks/useSize' +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:06:24 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:50:49 + */ +/** + * SwitchFormItem Component + * + * A form item component that combines a switch control with a label and optional description. + * Provides a consistent layout for switch-based form fields. + * + * @component + */ + +import { Switch, Form } from "antd"; import type { FC, ReactNode } from "react"; -import { useContext } from "react"; import LabelWrapper from './LabelWrapper' import DescWrapper from './DescWrapper' interface SwitchFormItemProps { + /** Label text or React node */ title: string | ReactNode; + /** Optional description text or React node */ desc?: string | ReactNode; + /** Form field name (string or nested path array) */ name: string | string[]; + /** Switch size */ size?: 'small' | 'default' + /** Additional CSS classes */ className?: string; + /** Whether the switch is disabled */ disabled?: boolean; } @@ -23,14 +42,13 @@ const SwitchFormItem: FC = ({ className, disabled }) => { - const componentSize = useSize() - console.log('componentSize', componentSize) - return (
+ {/* Label and description section */} {desc && } + {/* Switch control */} void; + /** Close the settings modal */ handleClose: () => void; } +/** Settings modal component for language and timezone configuration */ const SettingModal = forwardRef((_props, ref) => { const { t } = useTranslation(); const { changeLanguage, language, timeZone, changeTimeZone } = useI18n() const [visible, setVisible] = useState(false); const [form] = Form.useForm(); - const values = Form.useWatch([], form); - - // 封装取消方法,添加关闭弹窗逻辑 + /** Close modal and reset form to initial state */ const handleClose = () => { setVisible(false); form.resetFields(); }; + /** Open modal and populate form with current settings */ const handleOpen = () => { form.setFieldsValue({ language, timeZone }) setVisible(true); }; - // 封装保存方法,添加提交逻辑 + + /** Validate and save settings, update language and timezone if changed */ const handleSave = () => { form .validateFields() - .then(() => { + .then((values) => { const { language: newLanguage, timeZone: newTimeZone } = values if (newLanguage !== language) { changeLanguage(newLanguage); @@ -47,11 +67,12 @@ const SettingModal = forwardRef((_props, ref) => { }); } - // 暴露给父组件的方法 + /** Expose handleOpen and handleClose methods to parent component via ref */ useImperativeHandle(ref, () => ({ handleOpen, handleClose })); + return ( ((_props, ref) => { form={form} layout="vertical" > - {/* 中英文切换 */} + {/* Language selection dropdown */} ((_props, ref) => { options={['zh', 'en'].map(key => ({ label: t(`header.${key}`), value: key }))} /> - {/* 时区切换 */} + {/* Timezone selection dropdown */} void; + /** Close the user info modal */ handleClose: () => void; } +/** User information modal component displaying user details and security settings */ const UserInfoModal = forwardRef((_props, ref) => { const { t } = useTranslation(); const resetPasswordModalRef = useRef(null) const { user } = useUser(); const [visible, setVisible] = useState(false); - // 封装取消方法,添加关闭弹窗逻辑 + /** Close the modal */ const handleClose = () => { setVisible(false); }; + /** Open the modal */ const handleOpen = () => { setVisible(true); }; - // 暴露给父组件的方法 + /** Expose handleOpen and handleClose methods to parent component via ref */ useImperativeHandle(ref, () => ({ handleOpen, handleClose })); + return ( ((_props, ref) => { onCancel={handleClose} footer={null} > + {/* Basic Information Section */}
{t('header.basicInfo')}
-
+ {/* Username */} +
{t('user.username')} {user.username}
-
+ {/* Email */} +
{t('user.email')} {user.email}
-
+ {/* Role */} +
{t('user.role')} {user.is_superuser ? t('user.superuser') : t('user.normalUser')}
-
+ {/* Created Date */} +
{t('user.createdAt')} {formatDateTime(user.created_at, 'YYYY-MM-DD HH:mm:ss')}
-
{t('header.securitySettings')}
+ + {/* Security Settings Section */} +
{t('header.securitySettings')}
-
-
+ {/* Password Change Card */} +
+
-
{t('header.changePassword')}
-
{t('header.changePasswordDesc')}
+
{t('header.changePassword')}
+
{t('header.changePasswordDesc')}
diff --git a/web/src/components/Header/index.tsx b/web/src/components/Header/index.tsx index fac432f5..b58f157b 100644 --- a/web/src/components/Header/index.tsx +++ b/web/src/components/Header/index.tsx @@ -1,16 +1,36 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:07:49 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:07:49 + */ +/** + * AppHeader Component + * + * The main application header that displays breadcrumb navigation and user menu. + * Supports different breadcrumb sources based on the current route. + * + * @component + */ + import { type FC, useRef } from 'react'; -import { Layout, Dropdown, Space, Breadcrumb } from 'antd'; +import { Layout, Dropdown, Breadcrumb } from 'antd'; import type { MenuProps, BreadcrumbProps } from 'antd'; import { UserOutlined, LogoutOutlined, SettingOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; + import { useUser } from '@/store/user'; import { useMenu } from '@/store/menu'; import styles from './index.module.css' import SettingModal, { type SettingModalRef } from './SettingModal' import UserInfoModal, { type UserInfoModalRef } from './UserInfoModal' + const { Header } = Layout; +/** + * @param source - Breadcrumb source type ('space' or 'manage'), defaults to 'manage' + */ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => { const { t } = useTranslation(); const location = useLocation(); @@ -20,21 +40,26 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => { const { user, logout } = useUser(); const { allBreadcrumbs } = useMenu(); - // 根据当前路由动态选择面包屑源 + /** + * Dynamically select breadcrumb source based on current route + * - Knowledge base list: uses 'space' breadcrumb + * - Knowledge base detail: uses 'space-detail' breadcrumb + * - Other pages: uses the passed source prop + */ const getBreadcrumbSource = () => { const pathname = location.pathname; - // 知识库列表页面使用默认的 space 面包屑 + // Knowledge base list page uses default space breadcrumb if (pathname === '/knowledge-base') { return 'space'; } - // 知识库详情相关页面使用独立的面包屑 + // Knowledge base detail pages use independent breadcrumb if (pathname.includes('/knowledge-base/') && pathname !== '/knowledge-base') { return 'space-detail'; } - // 其他页面使用传入的 source + // Other pages use the passed source return source; }; @@ -42,13 +67,12 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => { const breadcrumbs = allBreadcrumbs[breadcrumbSource] || []; - - // 处理退出登录 + /** Handle user logout */ const handleLogout = () => { logout() }; - // 用户下拉菜单配置 + /** User dropdown menu configuration with profile, settings, and logout options */ const userMenuItems: MenuProps['items'] = [ { key: '1', @@ -89,18 +113,25 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => { onClick: handleLogout, }, ]; + + /** + * Format breadcrumb items with proper titles, paths, and click handlers + * - Translates i18n keys to display text + * - Handles custom onClick events + * - Disables navigation for the last breadcrumb item + */ const formatBreadcrumbNames = () => { return breadcrumbs.map((menu, index) => { const item: any = { title: menu.i18nKey ? t(menu.i18nKey) : menu.label, }; - // 如果是最后一项,不设置 path + // If it's the last item, don't set path if (index === breadcrumbs.length - 1) { return item; } - // 如果有自定义 onClick,使用 onClick 并设置 href 为 '#' 以显示手型光标 + // If has custom onClick, use onClick and set href to '#' to show pointer cursor if ((menu as any).onClick) { item.onClick = (e: React.MouseEvent) => { e.preventDefault(); @@ -108,35 +139,26 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => { }; item.href = '#'; } else if (menu.path && menu.path !== '#') { - // 只有当 path 不是 '#' 时才设置 path + // Only set path when path is not '#' item.path = menu.path; } return item; }); } + return (
+ {/* Breadcrumb navigation */} - {/* 语言切换和主题切换按钮 */} - - {/* */} - - {/* 用户信息下拉菜单 */} - -
{user.username}
-
-
+ {/* User info dropdown menu */} + +
{user.username}
+
diff --git a/web/src/components/Layout/AuthLayout.tsx b/web/src/components/Layout/AuthLayout.tsx index a969298d..356f4678 100644 --- a/web/src/components/Layout/AuthLayout.tsx +++ b/web/src/components/Layout/AuthLayout.tsx @@ -1,6 +1,25 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:11:02 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:11:02 + */ +/** + * AuthLayout Component + * + * The main authenticated layout wrapper that provides: + * - Route authentication and permission checks + * - Automatic breadcrumb navigation updates + * - Sidebar navigation and header + * - Token-based authentication validation + * + * @component + */ + import { Outlet } from 'react-router-dom'; import { useEffect, type FC } from 'react'; import { Layout } from 'antd'; + import useRouteGuard from '@/hooks/useRouteGuard'; import { useNavigationBreadcrumbs } from '@/hooks/useNavigationBreadcrumbs'; import AppHeader from '@/components/Header'; @@ -11,13 +30,20 @@ import { cookieUtils } from '@/utils/request'; const { Content } = Layout; -// 认证布局组件,使用useRouteGuard hook进行路由鉴权 +/** + * Authentication layout component that wraps all authenticated pages. + * Handles route guards, breadcrumb navigation, and user authentication. + */ const AuthLayout: FC = () => { const { getUserInfo } = useUser(); - // 使用路由守卫hook处理认证和权限检查 + + // Use route guard hook to handle authentication and permission checks useRouteGuard('manage'); - // 自动更新面包屑导航 + + // Automatically update breadcrumb navigation based on current route useNavigationBreadcrumbs('manage'); + + // Check authentication token and fetch user info on mount useEffect(() => { const authToken = cookieUtils.get('authToken') if (!authToken && !window.location.hash.includes('#/login')) { @@ -29,9 +55,12 @@ const AuthLayout: FC = () => { return ( + {/* Sidebar navigation */} + {/* Header with breadcrumbs and user menu */} + {/* Main content area - renders child routes */} diff --git a/web/src/components/Layout/AuthSpaceLayout.tsx b/web/src/components/Layout/AuthSpaceLayout.tsx index 17ee0bac..d47f13f2 100644 --- a/web/src/components/Layout/AuthSpaceLayout.tsx +++ b/web/src/components/Layout/AuthSpaceLayout.tsx @@ -1,6 +1,26 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:11:43 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:11:43 + */ +/** + * AuthSpaceLayout Component + * + * The authenticated layout wrapper for knowledge base (space) pages that provides: + * - Route authentication and permission checks for space context + * - Automatic breadcrumb navigation updates + * - Sidebar navigation and header configured for space mode + * - Token-based authentication validation + * - Storage type initialization + * + * @component + */ + import { Outlet } from 'react-router-dom'; import { useEffect, type FC } from 'react'; import { Layout } from 'antd'; + import useRouteGuard from '@/hooks/useRouteGuard'; import { useNavigationBreadcrumbs } from '@/hooks/useNavigationBreadcrumbs'; import AppHeader from '@/components/Header'; @@ -11,28 +31,38 @@ import { cookieUtils } from '@/utils/request'; const { Content } = Layout; -// 认证布局组件,使用useRouteGuard hook进行路由鉴权 +/** + * Authentication layout component for knowledge base (space) pages. + * Similar to AuthLayout but configured for space context with storage type management. + */ const AuthSpaceLayout: FC = () => { const { getUserInfo, getStorageType } = useUser(); - // 使用路由守卫hook处理认证和权限检查 + + // Use route guard hook to handle authentication and permission checks for space context useRouteGuard('space'); - // 自动更新面包屑导航 + + // Automatically update breadcrumb navigation based on current route in space context useNavigationBreadcrumbs('space'); + + // Check authentication token, fetch user info and storage type on mount useEffect(() => { const authToken = cookieUtils.get('authToken') if (!authToken && !window.location.hash.includes('#/login')) { window.location.href = `/#/login`; } else { getUserInfo() - getStorageType() + getStorageType() // Fetch storage type for knowledge base operations } }, []); return ( + {/* Sidebar navigation configured for space mode */} + {/* Header with breadcrumbs and user menu configured for space mode */} + {/* Main content area for knowledge base pages - renders child routes */} diff --git a/web/src/components/Layout/BasicLayout.tsx b/web/src/components/Layout/BasicLayout.tsx index 6b3d2904..cadcafb2 100644 --- a/web/src/components/Layout/BasicLayout.tsx +++ b/web/src/components/Layout/BasicLayout.tsx @@ -1,12 +1,35 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:12:42 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:12:42 + */ +/** + * BasicLayout Component + * + * A minimal layout wrapper that provides: + * - User information initialization + * - Storage type initialization + * - Simple container for child routes without navigation UI + * + * Used for pages that don't require sidebar/header (e.g., login, public pages). + * + * @component + */ + import { Outlet } from 'react-router-dom'; import { useEffect, type FC } from 'react'; + import { useUser } from '@/store/user'; -// 基础布局组件,用于展示内容并保留用户信息获取功能 +/** + * Basic layout component for pages without navigation UI. + * Fetches user info and storage type on mount, then renders child routes. + */ const BasicLayout: FC = () => { const { getUserInfo, getStorageType } = useUser(); - // 获取用户信息 + // Fetch user information and storage type on component mount useEffect(() => { getUserInfo(); getStorageType() @@ -14,6 +37,7 @@ const BasicLayout: FC = () => { return (
+ {/* Render child routes without additional UI */}
) diff --git a/web/src/components/Layout/LayoutBg.tsx b/web/src/components/Layout/LayoutBg.tsx index 2cddfb62..ec76f196 100644 --- a/web/src/components/Layout/LayoutBg.tsx +++ b/web/src/components/Layout/LayoutBg.tsx @@ -1,13 +1,37 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:13:20 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:13:20 + */ +/** + * LayoutBg Component + * + * A decorative background component that displays styled background elements. + * Provides visual aesthetics with positioned decorative shapes. + * + * @component + */ + import { type FC } from 'react'; import clsx from 'clsx'; + import styles from './layout.module.css'; +/** + * Background layout component with decorative elements. + * Renders a fixed full-screen background with styled shapes. + */ const LayoutBg: FC = () => { return (
-
+ {/* Top section with decorative background shapes */} +
+ {/* Left decorative element 1 */}
+ {/* Left decorative element 2 */}
+ {/* Right decorative element */}
diff --git a/web/src/components/Layout/LoginLayout.tsx b/web/src/components/Layout/LoginLayout.tsx index ee49e98f..b3c3b8e6 100644 --- a/web/src/components/Layout/LoginLayout.tsx +++ b/web/src/components/Layout/LoginLayout.tsx @@ -1,11 +1,30 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:13:38 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:13:38 + */ +/** + * LoginLayout Component + * + * A minimal layout wrapper for authentication pages (login, register, etc.). + * Provides a simple container without navigation UI or authentication checks. + * + * @component + */ + import { Outlet } from 'react-router-dom'; import { type FC } from 'react'; -// 基础布局组件,用于展示内容并保留用户信息获取功能 +/** + * Login layout component for unauthenticated pages. + * Renders child routes in a simple full-size container. + */ const LoginLayout: FC = () => { return (
+ {/* Render authentication pages (login, register, etc.) */}
) diff --git a/web/src/components/Layout/NoAuthLayout.tsx b/web/src/components/Layout/NoAuthLayout.tsx index a2e6f274..2e6154cf 100644 --- a/web/src/components/Layout/NoAuthLayout.tsx +++ b/web/src/components/Layout/NoAuthLayout.tsx @@ -1,11 +1,30 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:13:55 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:52:17 + */ +/** + * NoAuthLayout Component + * + * A minimal layout wrapper for public pages that don't require authentication. + * Provides a simple container without navigation UI or authentication checks. + * + * @component + */ + import { Outlet } from 'react-router-dom'; import { type FC } from 'react'; -// 基础布局组件,用于展示内容并保留用户信息获取功能 +/** + * No-authentication layout component for public pages. + * Renders child routes in a simple full-size container without any auth requirements. + */ const NoAuthLayout: FC = () => { return (
+ {/* Render public pages without authentication */}
) diff --git a/web/src/components/Markdown/AudioBlock.tsx b/web/src/components/Markdown/AudioBlock.tsx index bd638816..75039d61 100644 --- a/web/src/components/Markdown/AudioBlock.tsx +++ b/web/src/components/Markdown/AudioBlock.tsx @@ -1,15 +1,31 @@ -import { memo } from 'react' +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:14:59 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:14:59 + */ +/** + * AudioBlock Component + * + * Renders audio elements from markdown nodes. + * Extracts audio source URLs and creates HTML audio players with controls. + * + * @component + */ -import type { FC } from 'react' +import { memo, type FC } from 'react' +/** Props interface for AudioBlock component */ interface AudioBlockProps { node: { children: { properties: { src: string } }[] } } + +/** Audio block component that renders audio elements from markdown nodes */ const AudioBlock: FC = (props) => { - // console.log('AudioBlock', props) const { children } = props.node; + /** Extract audio source URLs from node children and filter out empty values */ const srcs = children.map(item => item.properties?.src).filter(item => item) return ( diff --git a/web/src/components/Markdown/Code.tsx b/web/src/components/Markdown/Code.tsx index de60d0de..9aecd977 100644 --- a/web/src/components/Markdown/Code.tsx +++ b/web/src/components/Markdown/Code.tsx @@ -1,22 +1,45 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:15:05 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:15:05 + */ +/** + * Code Component + * + * A versatile code rendering component that supports: + * - Syntax-highlighted code blocks + * - ECharts visualizations + * - SVG rendering + * - Mermaid diagrams + * - Inline code snippets + * + * @component + */ + import { type FC, useMemo } from 'react' import SyntaxHighlighter from 'react-syntax-highlighter'; import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs'; -import CopyBtn from './CopyBtn'; import ReactEcharts from 'echarts-for-react'; + +import CopyBtn from './CopyBtn'; import Svg from './Svg' import MermaidChart from './MermaidChart' - +/** Props interface for Code component */ type ICodeProps = { children: string; className: string; } +/** Code block component that renders syntax-highlighted code or special visualizations */ const Code: FC = (props) => { const { children, className } = props; + /** Extract language from className (e.g., 'language-javascript' -> 'javascript') */ const language = className?.split('-')[1] console.log('Code', props) + // Parse ECharts configuration from code content const charData = useMemo(() => { if (language !== 'echarts') return null; try { @@ -27,6 +50,7 @@ const Code: FC = (props) => { } }, [language, children]) + // Render ECharts visualization if (language === 'echarts') { return ( = (props) => { ) } + // Render SVG content if (language === 'svg') { return ( = (props) => { /> ) } + // Render Mermaid diagram if (language === 'mermaid') { return ( = (props) => { ) } + // Render syntax-highlighted code block with copy button if (className) { return (
@@ -81,6 +108,7 @@ const Code: FC = (props) => {
) } + // Render inline code return {children} } diff --git a/web/src/components/Markdown/CodeBlock.tsx b/web/src/components/Markdown/CodeBlock.tsx index a125a997..a830827d 100644 --- a/web/src/components/Markdown/CodeBlock.tsx +++ b/web/src/components/Markdown/CodeBlock.tsx @@ -1,9 +1,27 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:15:11 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:15:11 + */ +/** + * CodeBlock Component + * + * A standalone code block component for displaying formatted code with: + * - Syntax highlighting + * - Optional copy functionality + * - Configurable size and line numbers + * + * @component + */ + import { type FC } from 'react' import SyntaxHighlighter from 'react-syntax-highlighter'; import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs'; + import CopyBtn from './CopyBtn'; - +/** Props interface for CodeBlock component */ type ICodeBlockProps = { value: string; needCopy?: boolean; @@ -11,12 +29,7 @@ type ICodeBlockProps = { showLineNumbers?: boolean; } -// enum languageType { -// echarts = 'echarts', -// mermaid = 'mermaid', -// svg = 'svg', -// } - +/** Code block component for displaying formatted code with optional copy functionality */ const CodeBlock: FC = ({ value, needCopy = true, diff --git a/web/src/components/Markdown/CopyBtn.tsx b/web/src/components/Markdown/CopyBtn.tsx index 7a371656..f877f7f8 100644 --- a/web/src/components/Markdown/CopyBtn.tsx +++ b/web/src/components/Markdown/CopyBtn.tsx @@ -1,15 +1,31 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:15:21 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:15:21 + */ +/** + * CopyBtn Component + * + * A button component that copies text to clipboard and displays a success message. + * Uses the copy-to-clipboard library for cross-browser compatibility. + * + * @component + */ + import { type FC } from 'react' import { useTranslation } from 'react-i18next' import copy from 'copy-to-clipboard' import { Button, App } from 'antd' - +/** Props interface for CopyBtn component */ type ICopyBtnProps = { value: string; className?: string; style?: React.CSSProperties; } +/** Copy button component that copies text to clipboard and shows success message */ const CopyBtn: FC = ({ value, className, @@ -18,6 +34,7 @@ const CopyBtn: FC = ({ const { t } = useTranslation() const { message } = App.useApp() + /** Copy value to clipboard and show success message */ const handleCopy = () => { copy(value) message.success(t('common.copySuccess')) diff --git a/web/src/components/Markdown/Link.tsx b/web/src/components/Markdown/Link.tsx index f75476ea..9fe6197f 100644 --- a/web/src/components/Markdown/Link.tsx +++ b/web/src/components/Markdown/Link.tsx @@ -1,13 +1,29 @@ -import { memo } from 'react' +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:15:55 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:15:55 + */ +/** + * Link Component + * + * A secure link component that opens URLs in a new tab. + * Includes security attributes (noopener, noreferrer) to prevent security vulnerabilities. + * + * @component + */ +import { memo } from 'react' import type { FC, ReactNode } from 'react' +/** Props interface for Link component */ interface LinkProps { href: string; children: ReactNode; } + +/** Link component that opens in a new tab with security attributes */ const Link: FC = (props) => { - // console.log('Link', props) const { children, href } = props; return {children} } diff --git a/web/src/components/Markdown/MermaidChart.tsx b/web/src/components/Markdown/MermaidChart.tsx index f92bf27e..3d955dd2 100644 --- a/web/src/components/Markdown/MermaidChart.tsx +++ b/web/src/components/Markdown/MermaidChart.tsx @@ -1,8 +1,26 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:16:01 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:16:01 + */ +/** + * MermaidChart Component + * + * Renders Mermaid diagrams as images. + * - Converts Mermaid syntax to SVG + * - Converts SVG to base64 data URL for display + * - Generates unique IDs based on content hash + * + * @component + */ + import { useRef, useEffect, useState, type FC } from 'react' import mermaid from 'mermaid' import CryptoJS from 'crypto-js' import { Image } from 'antd' +/** Initialize Mermaid with default configuration */ mermaid.initialize({ startOnLoad: true, theme: 'default', @@ -12,6 +30,7 @@ mermaid.initialize({ }, }) +/** Convert SVG string to base64 data URL for image display */ const svgToBase64 = (svgGraph: string) => { const svgBytes = new TextEncoder().encode(svgGraph) const blob = new Blob([svgBytes], { type: 'image/svg+xml;charset=utf-8' }) @@ -22,8 +41,11 @@ const svgToBase64 = (svgGraph: string) => { reader.readAsDataURL(blob) }) } + +/** Mermaid chart component that renders Mermaid diagrams as images */ const MermaidChart: FC<{ content: string }> = ({ content }) => { const [chartSvg, setChartSvg] = useState('') + /** Generate unique ID based on content hash to avoid conflicts */ const id = useRef(`mermaidchart_${CryptoJS.MD5(content).toString()}`) useEffect(() => { @@ -33,6 +55,7 @@ const MermaidChart: FC<{ content: string }> = ({ content }) => { drawDiagram() }, [content]) + /** Render Mermaid diagram and convert to base64 image */ const drawDiagram = async function () { const { svg } = await mermaid.render(id.current, content); diff --git a/web/src/components/Markdown/Paragraph.tsx b/web/src/components/Markdown/Paragraph.tsx index 3e5dd73a..04f155dd 100644 --- a/web/src/components/Markdown/Paragraph.tsx +++ b/web/src/components/Markdown/Paragraph.tsx @@ -1,15 +1,30 @@ -import { memo } from 'react' +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:16:06 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:16:06 + */ +/** + * Paragraph Component + * + * A simple paragraph component for rendering markdown paragraphs. + * + * @component + */ +import { memo } from 'react' import type { FC, ReactNode } from 'react' +/** Props interface for Paragraph component */ interface ParagraphProps { node: { children: ReactNode; }; children: string[] } + +/** Paragraph component for rendering markdown paragraphs */ const Paragraph: FC = (props) => { - // console.log('Paragraph', props) const { children } = props return

{children}

diff --git a/web/src/components/Markdown/RbButton.tsx b/web/src/components/Markdown/RbButton.tsx index b165ce27..9af94de8 100644 --- a/web/src/components/Markdown/RbButton.tsx +++ b/web/src/components/Markdown/RbButton.tsx @@ -1,15 +1,32 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:16:10 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:16:10 + */ +/** + * RbButton Component + * + * A button component for rendering buttons in markdown content. + * Wraps Ant Design Button component. + * + * @component + */ + import { memo } from 'react' import type { FC, ReactNode } from 'react' import { Button } from 'antd' +/** Props interface for RbButton component */ interface RbButtonProps { node: { children: ReactNode; }; children: string[] } + +/** Button component for rendering buttons in markdown */ const RbButton: FC = (props) => { - console.log('RbButton', props) const { children } = props; return ( diff --git a/web/src/components/Markdown/Svg.tsx b/web/src/components/Markdown/Svg.tsx index 7618571f..a63a9271 100644 --- a/web/src/components/Markdown/Svg.tsx +++ b/web/src/components/Markdown/Svg.tsx @@ -1,15 +1,28 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:16:14 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:16:14 + */ +/** + * Svg Component + * + * Renders SVG content from string using dangerouslySetInnerHTML. + * Used for displaying SVG code blocks in markdown. + * + * @component + */ + import * as React from 'react'; +/** Props interface for Svg component */ interface SvgProps { content: string; } -/** - * 渲染SVG内容的组件 - */ +/** Component for rendering SVG content from string */ function Svg(props: SvgProps): JSX.Element { const { content } = props; - // console.log('Svg', props) return React.createElement( 'div', diff --git a/web/src/components/Markdown/VideoBlock.tsx b/web/src/components/Markdown/VideoBlock.tsx index 914ddf2d..6127c81d 100644 --- a/web/src/components/Markdown/VideoBlock.tsx +++ b/web/src/components/Markdown/VideoBlock.tsx @@ -1,15 +1,32 @@ -import { memo } from 'react' +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:16:18 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:54:55 + */ +/** + * VideoBlock Component + * + * Renders video elements from markdown nodes. + * Extracts video source URLs and creates HTML video players with controls. + * + * @component + */ +import { memo } from 'react' import type { FC } from 'react' +/** Props interface for VideoBlock component */ interface VideoBlockProps { node: { children: { properties: { src: string } }[] } } + +/** Video block component that renders video elements from markdown nodes */ const VideoBlock: FC = (props) => { - // console.log('VideoBlock', props) const { children } = props.node; + /** Extract video source URLs from node children and filter out empty values */ const srcs = children.map(item => item.properties?.src).filter(item => item) return ( diff --git a/web/src/components/Markdown/index.tsx b/web/src/components/Markdown/index.tsx index 6737f15a..a2fac5ba 100644 --- a/web/src/components/Markdown/index.tsx +++ b/web/src/components/Markdown/index.tsx @@ -1,3 +1,28 @@ +/* + * @Author: ZhaoYing + * @Date: 2026-02-02 15:17:31 + * @Last Modified by: ZhaoYing + * @Last Modified time: 2026-02-02 15:17:31 + */ +/** + * RbMarkdown Component + * + * A comprehensive markdown renderer with support for: + * - Standard markdown syntax (headings, lists, tables, etc.) + * - Code syntax highlighting + * - Math equations (KaTeX) + * - Mermaid diagrams + * - ECharts visualizations + * - SVG rendering + * - Audio/video embedding + * - Interactive form elements + * - HTML comments visibility toggle + * - Editable mode with live preview + * + * @component + */ + +import { useState, useRef, useEffect, type FC } from 'react' import { Image, Input, Select, Form, Checkbox, Radio, ColorPicker, DatePicker, TimePicker, InputNumber, Slider } from 'antd' import ReactMarkdown from 'react-markdown' import RemarkGfm from 'remark-gfm' @@ -5,8 +30,6 @@ import RemarkMath from 'remark-math' import RemarkBreaks from 'remark-breaks' import RehypeKatex from 'rehype-katex' import RehypeRaw from 'rehype-raw' -import type { FC } from 'react' -import { useState, useRef, useEffect } from 'react' import Code from './Code' import VideoBlock from './VideoBlock' @@ -14,14 +37,21 @@ import AudioBlock from './AudioBlock' import Link from './Link' import RbButton from './RbButton' +/** Props interface for RbMarkdown component */ interface RbMarkdownProps { + /** Markdown content to render */ content: string; - showHtmlComments?: boolean; // 是否显示 HTML 注释,默认为 false(隐藏) - editable?: boolean; // 是否可编辑,默认为 false - onContentChange?: (content: string) => void; // 内容变化回调 + /** Whether to display HTML comments (default: false) */ + showHtmlComments?: boolean; + /** Whether the content is editable (default: false) */ + editable?: boolean; + /** Callback fired when content changes in edit mode */ + onContentChange?: (content: string) => void; + /** Additional CSS classes */ className?: string; } +/** Custom component mappings for markdown elements */ const components = { h1: ({ children, ...props }: any) =>

{children}

, h2: ({ children, ...props }: any) =>

{children}

, @@ -38,7 +68,7 @@ const components = { em: ({ children, ...props }: any) => {children}, del: ({ children, ...props }: any) => {children}, span: ({ children, style, ...restProps }: any) => { - // 如果是 HTML 注释的 span,应用特殊样式 + // Apply special styling for HTML comment spans if (style?.color === '#999') { return {children} } @@ -104,30 +134,33 @@ const RbMarkdown: FC = ({ const [editContent, setEditContent] = useState(content) const textareaRef = useRef(null) - // 当外部 content 变化时,同步更新编辑内容 + /** Sync edit content when external content changes */ useEffect(() => { setEditContent(content) }, [content]) - // 处理 textarea 内容变化 + /** Handle textarea content changes and trigger callback */ const handleTextareaChange = (e: React.ChangeEvent) => { const newContent = e.target.value setEditContent(newContent) - // 实时回调内容变化 + /** Trigger real-time content change callback */ onContentChange?.(newContent) } - // 根据参数决定是否将 HTML 注释转换为可见文本 - // 使用特殊的 markdown 语法来显示注释,避免被 rehype-raw 过滤 + /** + * Process content based on showHtmlComments flag + * Converts HTML comments to visible text when showHtmlComments is true + * Uses special span markup to display comments with styling + */ const processedContent = showHtmlComments ? (editable ? editContent : content).replace(//g, (_match, commentContent) => { - // 转换为带样式的文本,使用 标记 + /** Convert to styled text using span with html-comment class */ const escaped = commentContent.trim().replace(//g, '>') return `<!-- ${escaped} -->` }) : (editable ? editContent : content) - // 如果是编辑模式,显示 textarea + /** Render textarea in edit mode */ if (editable) { return (
@@ -138,21 +171,21 @@ const RbMarkdown: FC = ({ } `} - {/* 编辑区域 */} + {/* Edit area with textarea */}
) } - // 处理键盘快捷键 + /** Handle keyboard shortcuts (e.g., Ctrl+C for copy) */ const handleKeyDown = (e: React.KeyboardEvent) => { if ((e.ctrlKey || e.metaKey) && e.key === 'c') { const selection = window.getSelection() @@ -162,7 +195,7 @@ const RbMarkdown: FC = ({ } } - // 预览模式 + /** Render markdown preview mode */ return (