From a8836b361a2c69c90f9c3ac7c05596820f49ee1e Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 23 Jul 2025 15:20:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=E5=90=8C=E5=90=8D?= =?UTF-8?q?=E7=9A=84=20operations=EF=BC=8C=E6=A0=B7=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ServerlessAPIServices.jsx | 93 ++++++++++++++---------- src/css/custom.css | 8 ++ 2 files changed, 61 insertions(+), 40 deletions(-) diff --git a/src/components/ServerlessAPIServices.jsx b/src/components/ServerlessAPIServices.jsx index 5a3c6a3..8975a56 100644 --- a/src/components/ServerlessAPIServices.jsx +++ b/src/components/ServerlessAPIServices.jsx @@ -90,17 +90,21 @@ function getServiceCategoryName(tags) { } /** - * 按日期排序操作列表 + * 按 name 合并操作列表 * @param {Array} operations - 操作列表 - * @param {string} fallbackDate - 备用日期 - * @returns {Array} 排序后的操作列表 + * @returns {Array} 合并并排序后的操作列表 */ -function sortOperationsByDate(operations, fallbackDate) { - return operations.sort((a, b) => { - const dateA = a.created_at || fallbackDate; - const dateB = b.created_at || fallbackDate; - return new Date(dateA) - new Date(dateB); +function mergeOperations(operations) { + // 按 name 合并操作 + const operationMap = new Map(); + operations.forEach((operation) => { + const name = operation.name; + if (!name) return; + if (!operationMap.has(name)) { + operationMap.set(name, operation); + } }); + return Array.from(operationMap.values()); } // ============================================================================ @@ -174,14 +178,6 @@ function FilterControls({ borderRight: '8px solid transparent', }; - const mobileSelectStyle = { - ...selectStyle, - maxWidth: '100px', - fontSize: '12px', - }; - - const isMobile = typeof window !== 'undefined' && window.innerWidth <= 768; - return (
@@ -259,7 +255,7 @@ function FilterControls({ id="category-filter" value={selectedTag} onChange={(e) => onTagChange(e.target.value)} - style={isMobile ? mobileSelectStyle : selectStyle} + style={selectStyle} > {tags.map((tag) => ( @@ -274,7 +270,7 @@ function FilterControls({ {/* 统计信息 */} ( - + {/**/} {/* {operation?.vendor_info?.label || '未知厂商'}*/} {/*{' '}*/} @@ -305,7 +303,7 @@ function ServicesTable({ services, showOperations, hostUrl }) { style={{ wordBreak: 'break-all' }} > {operation.name} - {' '} + {/**/} {/* {new Date(operation.created_at || createdAt).toLocaleDateString(*/} {/* 'zh-CN',*/} @@ -319,7 +317,11 @@ function ServicesTable({ services, showOperations, hostUrl }) { */ const renderServiceInfoCells = (service, operationCount) => ( <> - + @@ -349,15 +354,13 @@ function ServicesTable({ services, showOperations, hostUrl }) { ); return ( - +
- - {showOperations && ( - - )} + + {showOperations && } @@ -392,7 +395,13 @@ function ServicesTable({ services, showOperations, hostUrl }) { -
模型名称 分类简介接口简介接口
{getServiceCategoryName(service.tags) || '-'} + {service.remark ?? ''} @@ -413,7 +422,10 @@ function ServicesTable({ services, showOperations, hostUrl }) { /** * URL 参数管理 Hook */ -function useURLParams(defaultVendor = FILTER_DEFAULTS.ALL, defaultTag = FILTER_DEFAULTS.ALL) { +function useURLParams( + defaultVendor = FILTER_DEFAULTS.ALL, + defaultTag = FILTER_DEFAULTS.ALL, +) { const [selectedVendor, setSelectedVendor] = useState(defaultVendor); const [selectedTag, setSelectedTag] = useState(defaultTag); @@ -516,7 +528,7 @@ function useServicesData(hostUrl) { }; }) .filter(({ tags }) => tags?.length > 0) - .sort(({ created_at: c1 }, { created_at: c2 }) => (c1 < c2 ? 1 : -1)); + .sort(({ name: c1 }, { name: c2 }) => c1.localeCompare(c2)); if (isMounted) { setServices(processedServices); @@ -543,7 +555,9 @@ function useServicesData(hostUrl) { const processedServices = items .filter(({ tags }) => tags?.length > 0) - .sort(({ created_at: c1 }, { created_at: c2 }) => (c1 < c2 ? 1 : -1)); + .sort(({ created_at: c1 }, { created_at: c2 }) => + c1.localeCompare(c2), + ); if (isMounted) { setServices(processedServices); @@ -599,16 +613,13 @@ function useFilteredServices(services, selectedVendor, selectedTag) { // 显示所有厂商的操作 const processedServices = servicesByTag.map((service) => ({ ...service, - filteredOps: sortOperationsByDate( - service.operations || [], - service.created_at, - ), + filteredOps: mergeOperations(service.operations || []), })); setFilteredServices(processedServices); setFilteredOpsCount( processedServices.reduce( - (total, service) => total + (service.operations?.length || 0), + (total, service) => total + (service.filteredOps?.length || 0), 0, ), ); @@ -617,11 +628,10 @@ function useFilteredServices(services, selectedVendor, selectedTag) { const processedServices = servicesByTag .map((service) => ({ ...service, - filteredOps: sortOperationsByDate( + filteredOps: mergeOperations( (service.operations || []).filter( (op) => op?.vendor_info?.label === selectedVendor, ), - service.created_at, ), })) .filter((service) => service.filteredOps.length > 0); @@ -652,7 +662,10 @@ function useFilteredServices(services, selectedVendor, selectedTag) { * @param {string} [props.defaultVendor] - 默认厂商筛选值 * @param {string} [props.defaultTag] - 默认分类筛选值 */ -export default function ServerlessAPIServices({ defaultVendor, defaultTag } = {}) { +export default function ServerlessAPIServices({ + defaultVendor, + defaultTag, +} = {}) { const { siteConfig } = useDocusaurusContext(); const hostUrl = siteConfig.url; diff --git a/src/css/custom.css b/src/css/custom.css index cd98ea4..bafb69e 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -366,4 +366,12 @@ div[id^='headlessui-disclosure-panel'] tr td.relative:nth-child(2) { .menu__caret:before, .menu__link:after { background-size: 1.3rem 1.3rem; +} + +table.serverless-api-services tr:nth-child(2n) { + background-color: unset; +} + +table.serverless-api-services tr:hover td{ + background-color: var(--ifm-table-stripe-background); } \ No newline at end of file -- Gitee