diff --git a/public/icons/compIcon.png b/public/icons/compIcon.png new file mode 100644 index 0000000..958ca0e Binary files /dev/null and b/public/icons/compIcon.png differ diff --git a/src/pages/ideContainer/market.tsx b/src/pages/ideContainer/market.tsx index fb3bc83..41a0f20 100644 --- a/src/pages/ideContainer/market.tsx +++ b/src/pages/ideContainer/market.tsx @@ -1,198 +1,322 @@ -import React from 'react'; -import { Card, Grid, Input, Tag, Typography, Divider, Avatar } from '@arco-design/web-react'; -import { - IconSearch, - IconStar, - IconDownload, - IconUser, - IconCalendar, - IconFilter -} from '@arco-design/web-react/icon'; +import React, { useEffect, useState, useCallback } from 'react'; +import { Card, Grid, Input, Tag, Typography, Divider, Collapse, Button } from '@arco-design/web-react'; +import { IconSearch, IconSync } from '@arco-design/web-react/icon'; import styles from './style/market.module.less'; +import { useSelector, useDispatch } from 'react-redux'; const { Row, Col } = Grid; const { Title, Text } = Typography; -// 模拟组件数据 -const components = [ - { - id: 1, - name: '数据表格', - description: '功能强大的数据展示表格,支持排序、筛选、分页等功能', - author: '张三', - avatar: '', - downloads: 12560, - rating: 4.8, - tags: ['数据展示', '表格', '交互'], - category: '数据展示', - updateTime: '2023-10-15' - }, - { - id: 2, - name: '表单生成器', - description: '可视化表单构建工具,支持多种表单元素和校验规则', - author: '李四', - avatar: '', - downloads: 8920, - rating: 4.6, - tags: ['表单', '生成器', '可视化'], - category: '表单', - updateTime: '2023-10-18' - }, - { - id: 3, - name: '图表组件', - description: '基于ECharts的图表组件库,支持多种图表类型', - author: '王五', - avatar: '', - downloads: 15630, - rating: 4.9, - tags: ['图表', '数据可视化', 'ECharts'], - category: '数据可视化', - updateTime: '2023-10-10' - }, - { - id: 4, - name: '流程设计器', - description: '可视化流程设计工具,支持拖拽式流程编排', - author: '赵六', - avatar: '', - downloads: 6750, - rating: 4.5, - tags: ['流程', '设计器', '可视化'], - category: '流程', - updateTime: '2023-10-20' - }, - { - id: 5, - name: '文件上传', - description: '支持多种文件格式上传,包含进度显示和校验功能', - author: '孙七', - avatar: '', - downloads: 9800, - rating: 4.7, - tags: ['文件', '上传', '工具'], - category: '工具', - updateTime: '2023-10-12' - }, - { - id: 6, - name: '通知中心', - description: '系统通知管理组件,支持多种通知类型和样式', - author: '周八', - avatar: '', - downloads: 5420, - rating: 4.3, - tags: ['通知', '消息', '系统'], - category: '反馈', - updateTime: '2023-10-05' - }, -]; - -// 分类数据 -const categories = [ - { id: 1, name: '全部组件', count: 24 }, - { id: 2, name: '数据展示', count: 8 }, - { id: 3, name: '表单', count: 6 }, - { id: 4, name: '数据可视化', count: 5 }, - { id: 5, name: '流程', count: 3 }, - { id: 6, name: '工具', count: 7 }, - { id: 7, name: '反馈', count: 4 }, -]; const Market: React.FC = () => { + 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; } } } } + }