fix ccf专区首页

This commit is contained in:
谢思 2026-07-24 14:27:15 +08:00
parent 1ffbfa2ea9
commit 25fad88ec5
12 changed files with 170 additions and 40 deletions

View File

@ -5,7 +5,7 @@ import Nodata from '../../../Nodata';
import { Spin, Button, Icon } from 'antd';
import { tempConfig, tempEnum } from '../../tempInfo'
import MemberApply from '../../Component/memberApply';
import { getVIPLists, getAuditStatus, applyJoin } from '../../api';
import { getVIPLists, getAuditStatus, applyJoin, getVIPTypeLists, getVIPListByTypeId } from '../../api';
import nodata from '../../img/nodata.png';
import MemberList from '../../Component/memberList';
import {getUniqueIdentifier,getUserName,getBrowserPlatform,getBrowserBrand} from '../../utils';
@ -41,19 +41,117 @@ function CustomVip(props){
useEffect(()=>{
if(id){
setIsSpin(true);
getLists();
getMemberStatus();
}
},[id])
function getLists(){
getVIPLists(id).then(response=>{
if(response && response.data){
setVIPLists(response.data.rows);
setIsSpin(true);
getVIPTypeLists(id).then(res=>{
const typeList = res.data.rows;
// memberCount
fetchMembersByTypes(typeList);
}).finally(() => {
setIsSpin(false);
});
}
}).catch(error=>{setIsSpin(false);})
//
function fetchMembersByTypes(typeList) {
if (!typeList || typeList.length === 0) {
return;
}
// 5
const CONCURRENCY_LIMIT = 5;
const results = new Array(typeList.length);
const totalTypes = typeList.length;
let completedCount = 0;
async function fetchSingleType(type, index) {
const typeId = type.id;
const memberCount = type.memberCount || 0;
const typeName = type.typeName || type.name;
const typeIntroduction = type.typeIntroduction || type.introduction;
let members;
if (memberCount > 500) {
members = await fetchMembersPaginatedSequential(typeId, memberCount, 500);
} else {
members = await fetchMembersOnce(typeId, memberCount);
}
results[index] = {
id: typeId,
typeName: typeName,
typeIntroduction: typeIntroduction,
zoneMemberList: members || []
};
completedCount++;
//
setVIPLists([...results.filter(Boolean)]);
}
//
async function executeInBatches() {
const promises = [];
for (let i = 0; i < typeList.length; i++) {
const type = typeList[i];
promises.push(fetchSingleType(type, i));
//
if (promises.length >= CONCURRENCY_LIMIT) {
await Promise.all(promises);
promises.length = 0;
}
}
if (promises.length > 0) {
await Promise.all(promises);
}
}
executeInBatches()
}
// memberCount > 200
async function fetchMembersPaginatedSequential(typeId, memberCount, pageSize) {
const totalPages = Math.ceil(memberCount / pageSize);
const allMembers = [];
for (let pageNum = 1; pageNum <= totalPages; pageNum++) {
try {
const response = await getVIPListByTypeId(id, {
memberTypeId: typeId,
pageNum,
pageSize
});
if (response && response.data && response.data.rows) {
allMembers.push(...response.data.rows);
}
} catch (error) {
console.error(`分页请求失败: typeId=${typeId}, pageNum=${pageNum}`, error);
}
}
return allMembers;
}
// memberCount <= 200
async function fetchMembersOnce(typeId, memberCount) {
return getVIPListByTypeId(id, {
memberTypeId: typeId,
pageNum: 1,
pageSize: memberCount
}).then(response => {
if (response && response.data && response.data.rows) {
return response.data.rows;
}
return [];
}).catch(() => {
return [];
});
}
function getMemberStatus() {

View File

@ -326,9 +326,9 @@
border: 1px solid rgba(35, 93, 250, 0.13);
transition: all 0.3s ease;
// &:hover {
// transform: translateY(-20px);
// }
&:hover {
transform: translateY(-20px);
}
}
.ccf-vip-avatar {
@ -351,6 +351,12 @@
color: #262626;
margin-bottom: 12px;
text-align: center;
em{
font-style: normal;
color: #466aff;
background: #dee4ff;
padding: 0 2px;
}
}
.ccf-vip-tags {
@ -729,7 +735,7 @@
.ccf-rule-section {
background-image: url('../image/ccf_bk14.png');
background-size: 100% 100%;
padding-bottom: 100px;
padding-bottom: 120px;
.ccf-rule-cards-container {
position: relative;

View File

@ -51,8 +51,8 @@ const ActivityItem = ({ id, keywords, name, summary }) => (
{moment(summary).format("YYYY")}<br />
{moment(summary).format("MM/DD")}
</span>
<div>
<div style={{ color: '#d8ebff' }} className="font-bd"><a href={`/zone/CCF-ODC/newdetail/${id}`}>{name}</a></div>
<div className="flex1">
<div style={{ color: '#d8ebff' }} className="font-bd task-hide"><a href={`/zone/CCF-ODC/newdetail/${id}`} className="task-hide">{name}</a></div>
<div style={{ color: '#d8ebffad' }}><i className="iconfont icon-weizhi font-15 mr5"></i>{keywords}</div>
</div>
</div>
@ -75,7 +75,7 @@ const CCFIntro = ({ zoneInfo, sectionList, role }) => {
}, [sectionList]);
useEffect(() => {
executiveCalendarId && getSubDocList(executiveCalendarId, { pageSize: 1000, pageNum: 1, auditStatus: 1 }).then(result => {
executiveCalendarId && getSubDocList(executiveCalendarId, { pageSize: 100, pageNum: 1, auditStatus: 1 }).then(result => {
if (result && result.data.rows) {
setDocList(result.data.rows);
}

View File

@ -12,6 +12,10 @@ function project({ id }) {
const [ typeList , setTypeList ] = useState([]);
const {communityUserCount, projectCount} = statistics || {}
const handleLinkClick = () => {
window.scrollTo(0, 500);
};
useEffect(()=>{
id && getZoneStatistics(id).then(result => {
if (result && result.data) {
@ -52,7 +56,7 @@ function project({ id }) {
<div className="ccf-project-blue-left">
<img src={ccf_img4} width={130} style={{margin: "0 6px 10px -10px"}}/>
<i className="iconfont icon-a-duobianxing1 font-13 mr10"></i>
<span className="font-38 font-bd mr10">{communityUserCount}+</span>
<span className="font-38 font-bd mr10">{+communityUserCount > 999 ? `999+` : communityUserCount}</span>
<span className="font-15">贡献者</span>
<div className="font-13">联结 CCF 会员搭建全球开源协同创新实践平台</div>
<div className="ccf-project-blue-bottom-1">
@ -60,11 +64,11 @@ function project({ id }) {
<div className="df-center-between ccf-project-blue-bottom-3">
<div className="ccf-project-blue-bottom-3-top"></div>
<div>
<span className="font-38 font-bd">{typeList.length}+</span>
<span className="font-38 font-bd">{typeList.length > 99 ? `99+` : typeList.length}</span>
<div className="opacity8">项目分类数</div>
</div>
<div>
<span className="font-38 font-bd">{projectCount}+</span>
<span className="font-38 font-bd">{+projectCount > 99 ? `99+` : projectCount}</span>
<div className="opacity8">代码库数</div>
</div>
</div>
@ -75,13 +79,13 @@ function project({ id }) {
<img src={icon1} width={46}/>
<div className="font-20 font-bd mt20 mb10">捐赠开源项目库</div>
<div className="font-15 color-5f6">覆盖AI云原生嵌入式等多领域优质开源项目开放共享</div>
{typeId1 ? <Link to={{ pathname: `/zone/CCF-ODC/projects`, state: { id: typeId1 } }}>立即查看</Link> : <a className="unClick">暂未开放</a>}
{typeId1 ? <Link to={{ pathname: `/zone/CCF-ODC/projects`, state: { id: typeId1 } }} onClick={(e) => { handleLinkClick(); }}>立即查看</Link> : <a className="unClick">暂未开放</a>}
</div>
<div className="ccf_proType_2 center">
<img src={icon2} width={46}/>
<div className="font-20 font-bd mt20 mb10">开源学习资源库</div>
<div className="font-15 color-5f6">教程文档工具案例合集一站式开源学习平台</div>
{typeId2 ? <Link to={{ pathname: `/zone/CCF-ODC/projects`, state: { id: typeId2 } }}>立即查看</Link> : <a className="unClick">暂未开放</a>}
{typeId2 ? <Link to={{ pathname: `/zone/CCF-ODC/projects`, state: { id: typeId2 } }} onClick={(e) => { handleLinkClick(); }}>立即查看</Link> : <a className="unClick">暂未开放</a>}
</div>
</div>
</div>

View File

@ -79,7 +79,7 @@ const Registration = ({ sectionList, autoPlay = true }) => {
<div className="ccf-registration-left">
<Slider ref={sliderRef} {...carouselSettings}>
{docList.map(item => {
return <div><div className='width1600' dangerouslySetInnerHTML={{__html: Base64.decode(item.content)}}></div></div>
return <div><div className='' dangerouslySetInnerHTML={{__html: Base64.decode(item.content)}}></div></div>
})}
</Slider>
</div>

View File

@ -45,7 +45,7 @@ function Rule({ sectionList, history }) {
};
});
// .concat(transformedCards)
setRuleCards(transformedCards.concat(transformedCards).concat(transformedCards).concat(transformedCards).concat(transformedCards).concat(transformedCards));
setRuleCards(transformedCards);
}
})
}, [ruleTypeId])
@ -106,10 +106,10 @@ function Rule({ sectionList, history }) {
//
useEffect(() => {
if (!isAutoPlaying || displayCards.length <= 5) return;
if (!isAutoPlaying || ruleCards.length <= 5) return;
const interval = setInterval(nextCard, autoPlayInterval);
return () => clearInterval(interval);
}, [isAutoPlaying, nextCard, displayCards.length]);
}, [isAutoPlaying, nextCard, ruleCards.length]);
//
const handleMouseEnter = useCallback(() => {
@ -173,7 +173,7 @@ function Rule({ sectionList, history }) {
</div>
{/* 导航控制 */}
<div className="ccf-rule-nav">
{ruleCards && ruleCards.length > 5 && <div className="ccf-rule-nav">
<div className="ccf-rule-arrows">
<button
className="ccf-rule-arrow ccf-rule-arrow-left"
@ -192,7 +192,7 @@ function Rule({ sectionList, history }) {
<i className="iconfont icon-arrowRight"></i>
</button>
</div>
</div>
</div>}
</div>
</div>
</div>

View File

@ -24,10 +24,11 @@ function Ccf_vip({id}) {
setVIPLists(result.data.rows.map(item=>{
const {username, imageUrl, memberLevelName, memberTypeName} = item.extendData
return{
name: username,
name: item.title,
imageUrl: imageUrl,
memberLevel: memberLevelName,
typeName: memberTypeName
typeName: memberTypeName,
login: username
}
}));
}
@ -40,7 +41,7 @@ function Ccf_vip({id}) {
const list = response.data.rows && response.data.rows.reduce((acc, item) => {
const members = (item.zoneMemberList || []).map(member => ({
...member,
typeName: item.typeName
typeName: item.typeName,
}));
return acc.concat(members);
}, []);
@ -76,16 +77,18 @@ function Ccf_vip({id}) {
{vipLists && vipLists.length > 0 ? (
<div className="ccf-vip-grid">
{vipLists.map((member, index) => (
<div className="ccf-vip-card" key={member.id}>
<a href={`/${member.login}`} key={member.id}>
<div className="ccf-vip-card">
<div className="ccf-vip-avatar">
<img src={member.imageUrl} alt={member.name} />
</div>
<div className="ccf-vip-name">{member.name}</div>
<div className="ccf-vip-name" dangerouslySetInnerHTML={{__html: member.name}}/>
<div className="ccf-vip-tags">
<span className="ccf-vip-tag">{member.typeName}</span>
<span className="ccf-vip-tag">{member.memberLevel}</span>
</div>
</div>
</a>
))}
</div>
) : (

View File

@ -1,5 +1,5 @@
import React,{ useState , useEffect, useMemo } from 'react';
import { Breadcrumb, Button, Form, Input, Select } from 'antd';
import { Breadcrumb, Button,Form, Input, Select, message } from 'antd';
import { getZoneUrl } from 'educoder';
import MdEditor from '../../../modules/tpm/challengesnew/tpm-md-editor';
import RichEditor from '../../Component/RichEditor';

View File

@ -38,7 +38,6 @@ function ProjectSource(props){
let platform = getBrowserPlatform()
let browser = getBrowserBrand()
let username = getUserName(props.current_user);
getMemberStatus();
// if(!username) uuid = getUniqueIdentifier()
let remark = ` 操作系统:${platform};浏览器:${browser};`
setZoneVisits({url,username,uuid,remark})
@ -58,6 +57,7 @@ function ProjectSource(props){
useEffect(()=>{
if(id){
getTypeList();
getMemberStatus();
}
},[id])

View File

@ -210,6 +210,22 @@ export function getVIPLists(id, params){
})
}
export function getVIPListByTypeId(id, params){
return fetch({
url:`/zone/open/${id}/member/list`,
method: 'get',
params
})
}
export function getVIPTypeLists(id, params){
return fetch({
url:`/zone/open/${id}/memberType/list`,
method: 'get',
params
})
}
/**会员申请状态 */
export function getAuditStatus(id){
return fetch({

View File

@ -15,7 +15,7 @@ function beforeFetch(actionUrl){
service.interceptors.request.use(request => {
let deptId = sessionStorage.getItem('deptId');
request.headers.Authorization = 'ad9cf7c24c0ef721d199f889e9fb2671d76b7655'
// request.headers.Authorization = '2d5f2f54b2d2f9a0fda39ae7ecacc59795058ada'
if (deptId) {
// 用于权限区分
request.headers['Dept-Id'] = deptId

View File

@ -386,9 +386,12 @@
font-size:86px;
color:#ffffff;
font-family: "sanjikai";
padding-bottom: 18px;
margin-top: 90px;
}
.sub_t{
font-size: 18px;
padding-left: 10px;
}
.bannerMenus{
backdrop-filter:blur(44px);