From 756a98943d80d2aa4af6f471906ff5f2d0daf09f Mon Sep 17 00:00:00 2001 From: ZLY Date: Mon, 13 Oct 2025 10:02:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(market):=E9=87=8D=E6=9E=84=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=B8=82=E5=9C=BA=E9=A1=B5=E9=9D=A2=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=92=8C=E5=88=86=E7=B1=BB=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/compIcon.png | Bin 0 -> 988 bytes src/pages/ideContainer/market.tsx | 458 +++++++++++------- .../ideContainer/style/market.module.less | 111 +---- 3 files changed, 315 insertions(+), 254 deletions(-) create mode 100644 public/icons/compIcon.png diff --git a/public/icons/compIcon.png b/public/icons/compIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..958ca0e1e1cc5c7c5f33b4d5b51d40bb85510a75 GIT binary patch literal 988 zcmeAS@N?(olHy`uVBq!ia0vp^(jd&i1|)m0dU|#I$;uuoF`1S$g1QpLoDxN~! zt7h(YcX3HeOA8AHf^rb}eufsH1Y~r0ILMZ?G&eVwmff>wa-H`{3okD%FZVwWveIV} z!=Jh4cX}Qf=iFo3(f8ltyT>1ybLTJrzE`>%B$4xIedFXm&vz<(TKe?;u9wldb`Aey zJZfftvd-Tn4OAb)@Lgm7XSL7s`5B&;-%I)TnQ_6NbFKiEkAOdyj=5I((mz;oq;-AL46O z^;sBBz29@v#$Nxg;fqu|F^2#5jvorH>q+1FF7(3eKN{0*-&uc{Ut@N@=(O~~-2I1& z86AGkHJ|x>`F+RyPm4E{8Utz~oez3>& zJZEYEdc{cp%r#%2gLvNkRQ^*f&&|MJ&;CU!{^VwvJB-`^a@l)o$NZ*Z%zD6#2vZzi+e=XP9!oa&l#0&fS)KPmVvBXMgDY4^g0joPYVwKRjgr z;C@BD#g1l}-K*Blz7YMF>x;F)n}`7a;Czoq3Z)&DxgnZWT9Hv?$L z>ssqMHHLb>U#~y(|HIoCcmFk}OMd&Hzn3|tLPnnf9N2pl)aAS5-diWUR%7@9R9F9X zD#HuYeL`~o_-syZXs>@M`{2;y3Oj~?y63*neu5$bXy_N~m~T7YAE^Iy(`G{4W9^3z z-yhh_Q~l$39BZ5HJZ@+tuKzdn!;be3>%Zp~JS_ZSesBJBcVH|P++EFZAiiGo-|F>G zelkGfFa5RJm#X`GhvokDes53gf4&;%z3*=e&dWarrW0s@{5;PNj<^3m!A>b>zW#AO z_XD|~yYqg9&E|h#FD`Unt^PT$`RpIr4^;kF>UGp)GXAj6-ywN4{l*^F0@?qC? { + const [compList, setCompList] = useState([]); + const [firstLevelCategory, setFirstLevelCategory] = useState('全部'); // 第一层分类:全部,基础,复合 + const [secondLevelCategory, setSecondLevelCategory] = useState('全部'); // 第二层分类:全部,我的,公开,协同 + const { projectComponentData, info } = useSelector((state: any) => state.ideContainer); + const dispatch = useDispatch(); + + // 第一层分类选项 + const firstLevelCategories = [ + { label: '全部', value: '全部' }, + { label: '基础', value: '基础' }, + { label: '复合', value: '复合' } + ]; + + // 第二层分类选项 + const secondLevelCategories = [ + { label: '全部', value: '全部' }, + { label: '我的', value: '我的' }, + { label: '公开', value: '公开' }, + { label: '协同', value: '协同' } + ]; + + // 计算各分类的数量 + const getCategoryCounts = useCallback(() => { + if (!compList) return { + allCount: 0, + basicCount: 0, + compositeCount: 0, + myCount: 0, + publicCount: 0, + teamCount: 0, + myFlowCount: 0, + pubFlowCount: 0 + }; + + // 基础组件数量 (myLibs, pubLibs, teamLibs) + // 需要统计children中的组件数量 + const myCount = compList.myLibs ? compList.myLibs.reduce((acc, cur) => acc + (cur.children ? cur.children.length : 0), 0) : 0; + const publicCount = compList.pubLibs ? compList.pubLibs.reduce((acc, cur) => acc + (cur.children ? cur.children.length : 0), 0) : 0; + const teamCount = compList.teamLibs ? compList.teamLibs.reduce((acc, cur) => acc + (cur.children ? cur.children.length : 0), 0) : 0; + const basicCount = myCount + publicCount + teamCount; + + // 复合组件数量 (myFlow, pubFlow) - 直接统计数组长度 + const myFlowCount = compList.myFlow ? compList.myFlow.length : 0; + const pubFlowCount = compList.pubFlow ? compList.pubFlow.length : 0; + const compositeCount = myFlowCount + pubFlowCount; + + return { + allCount: basicCount + compositeCount, + basicCount, + compositeCount, + myCount, + publicCount, + teamCount, + myFlowCount, + pubFlowCount + }; + }, [compList]); + + // 渲染Tag选择器 + const renderCategoryTage = useCallback(() => { + /* + * 分类规则:先分类(全部,基础,复合) 再分类(全部,我的,公开,协同:复合类型中没有协同组件) + * 目前数据类型中存在的字段: 基础类型 [myLibs,pubLibs,teamLibs], 复合类型[pubFlow,myFlow] + * 需要渲染出两层Tag标签的选择,第一次的选择影响第二层的部分渲染 + * */ + + const counts = getCategoryCounts(); + + // 根据第一层分类动态调整第二层分类选项 + const getFilteredSecondLevelCategories = () => { + // 如果是复合类型,则不显示协同组件选项 + if (firstLevelCategory === '复合') { + return secondLevelCategories.filter(item => item.value !== '协同'); + } + return secondLevelCategories; + }; + + // 获取第二层分类的数量 + const getSecondLevelCount = (category: string) => { + if (firstLevelCategory === '全部') { + switch (category) { + case '全部': + return counts.allCount; + case '我的': + return counts.myCount; + case '公开': + return counts.publicCount + counts.pubFlowCount; + case '协同': + return counts.teamCount; + default: + return 0; + } + } + else if (firstLevelCategory === '基础') { + switch (category) { + case '全部': + return counts.basicCount; + case '我的': + return counts.myCount; + case '公开': + return counts.publicCount; + case '协同': + return counts.teamCount; + default: + return 0; + } + } + else if (firstLevelCategory === '复合') { + switch (category) { + case '全部': + return counts.compositeCount; + case '我的': + return counts.myFlowCount; + case '公开': + return counts.pubFlowCount; + default: + return 0; + } + } + return 0; + }; + + return ( +
+ {/* 第一层分类标签 */} +
+ {firstLevelCategories.map((category) => { + let count = 0; + switch (category.value) { + case '全部': + count = counts.allCount; + break; + case '基础': + count = counts.basicCount; + break; + case '复合': + count = counts.compositeCount; + break; + } + + return ( + { + setFirstLevelCategory(category.value); + // 当切换第一层分类时,默认选中"全部"作为第二层分类 + setSecondLevelCategory('全部'); + }} + > + {category.label} + ({count}) + + ); + })} +
+ + {/* 第二层分类标签 */} +
+ {getFilteredSecondLevelCategories().map((category) => ( + setSecondLevelCategory(category.value)} + > + {category.label} + ({getSecondLevelCount(category.value)}) + + ))} +
+
+ ); + }, [firstLevelCategory, secondLevelCategory, getCategoryCounts]); + + // 渲染组件分类 + const renderComponentCategory = useCallback(() => { + // 根据第一层和第二层分类筛选组件 + let filteredComponents = []; + + // 构建筛选条件 + const conditions = { + includeMyLibs: (firstLevelCategory === '全部' || firstLevelCategory === '基础') && + (secondLevelCategory === '全部' || secondLevelCategory === '我的'), + includePubLibs: (firstLevelCategory === '全部' || firstLevelCategory === '基础') && + (secondLevelCategory === '全部' || secondLevelCategory === '公开'), + includeTeamLibs: (firstLevelCategory === '全部' || firstLevelCategory === '基础') && + (secondLevelCategory === '全部' || secondLevelCategory === '协同'), + includeMyFlow: (firstLevelCategory === '全部' || firstLevelCategory === '复合') && + (secondLevelCategory === '全部' || secondLevelCategory === '我的'), + includePubFlow: (firstLevelCategory === '全部' || firstLevelCategory === '复合') && + (secondLevelCategory === '全部' || secondLevelCategory === '公开') + }; + + // 添加基础组件 + if (conditions.includeMyLibs && compList.myLibs) { + filteredComponents = [...filteredComponents, ...compList.myLibs]; + } + if (conditions.includePubLibs && compList.pubLibs) { + filteredComponents = [...filteredComponents, ...compList.pubLibs]; + } + if (conditions.includeTeamLibs && compList.teamLibs) { + filteredComponents = [...filteredComponents, ...compList.teamLibs]; + } + + // 处理复合组件 + const flowComponents = { label: '复合组件', children: [] }; + if (conditions.includeMyFlow && compList.myFlow) { + flowComponents.children.push(...compList.myFlow); + } + if (conditions.includePubFlow && compList.pubFlow) { + flowComponents.children.push(...compList.pubFlow); + } + + // 如果有复合组件,添加到筛选结果中 + if (flowComponents.children.length > 0) { + filteredComponents = [...filteredComponents, flowComponents]; + } + + // 如果没有组件,显示提示信息 + if (filteredComponents.length === 0) { + return ( +
+ 暂无组件数据 +
+ ); + } + + // 渲染组件 + return ( + + {filteredComponents.map((category, index) => { + // 确保category有children属性 + if (!category || !category.children || category.children.length === 0) { + return null; + } + + return ( + + {category.label} + + } + > + {category.children.map((component, compIndex) => ( + <> +
+
+ + {component.label} +
+ {/*两种状态 未添加的是primary 已添加的是secondary*/} + +
+ + + ))} +
+ ); + }).filter(item => item !== null)} +
+ ); + }, [compList, firstLevelCategory, secondLevelCategory]); + + useEffect(() => { + const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}'); + const componentData = JSON.parse(sessionStorage.getItem(`compLibs${userInfo.userId}`)); + setCompList(componentData); + }, []); + return (
{/* 头部搜索区域 */}
- 组件市场 - 发现和使用高质量的组件,提升开发效率 + 组件仓库
} - style={{ width: 400, marginRight: 16 }} + style={{ marginRight: 16 }} />
- } color="arcoblue">高级筛选 +
- - - {/* 分类导航 */} + {/* tag样式选择器 */}
-
- {categories.map(category => ( - - {category.name} ({category.count}) - - ))} -
+ {renderCategoryTage()}
- {/* 组件列表 */} -
- - {components.map(component => ( - - -
-
- {component.name} - {component.category} -
- {component.description} -
- -
-
-
- - {component.author} -
-
- - {component.updateTime} -
-
- -
- {component.tags.map((tag, index) => ( - {tag} - ))} -
-
+ -
-
-
- - {component.downloads.toLocaleString()} -
-
- - {component.rating} -
-
-
- 安装 -
-
-
- - ))} -
+
+ {renderComponentCategory()}
); }; -export default Market; +export default Market; \ No newline at end of file diff --git a/src/pages/ideContainer/style/market.module.less b/src/pages/ideContainer/style/market.module.less index b090cc2..8ce8a26 100644 --- a/src/pages/ideContainer/style/market.module.less +++ b/src/pages/ideContainer/style/market.module.less @@ -19,107 +19,44 @@ } .category-section { - margin: 20px 0; - - .category-list { - display: flex; - flex-wrap: wrap; - gap: 12px; + margin-top: 20px; + } - .category-tag { - cursor: pointer; - transition: all 0.2s; + .component-section { + :global(.arco-collapse-item ) { + border-bottom: none; + } - &:hover { - transform: translateY(-2px); - } + :global(.arco-collapse-item-content-box) { + background-color: #fff; + } - .category-count { - color: #86909c; - } - } + :global(.arco-collapse-item-header) { + border-bottom: none; + color: #6D7278; } - } - .components-section { - .component-col { - margin-bottom: 20px; + :global(.arco-collapse-item-header-right) { + padding-left: 0; } - .component-card { - height: 100%; + .component-list { display: flex; - flex-direction: column; - - .card-header { - flex: 1; - margin-bottom: 16px; - - .component-title { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 8px; - } - } - - .card-content { - flex: 1; - margin-bottom: 16px; - - .component-meta { - display: flex; - gap: 16px; - margin-bottom: 12px; - - .meta-item { - display: flex; - align-items: center; - gap: 4px; - font-size: 12px; - color: #86909c; - } - } - - .component-tags { - display: flex; - flex-wrap: wrap; - gap: 8px; - } - } + justify-content: space-between; + align-items: center; + padding-top: 10px; - .card-footer { + .component-info { display: flex; - justify-content: space-between; align-items: center; - border-top: 1px solid #f2f3f5; - padding-top: 16px; - - .component-stats { - display: flex; - gap: 16px; - - .stat-item { - display: flex; - align-items: center; - gap: 4px; - font-size: 12px; - color: #86909c; - } - } - - .component-actions { - .install-btn { - color: #626aea; - cursor: pointer; - font-weight: 500; - &:hover { - color: #4169e1; - } - } + img { + width: 40px; + height: 40px; + margin-right: 10px; } } } } + }