forked from Gitlink/forgeplus-react
Merge branch 'gitlink_competitions' of https://gitlink.org.cn/Gitlink/forgeplus-react into gitlink_competitions
This commit is contained in:
commit
b6e5600b86
|
|
@ -6,40 +6,16 @@ import right from '../img/schedule/right.webp'
|
|||
import { timelineDir, ruleList } from '../info'
|
||||
import { getDocDetail, getDocList } from '../api'
|
||||
import { history } from 'umi'
|
||||
import { Base64 } from 'js-base64'
|
||||
|
||||
function Schedule(props) {
|
||||
|
||||
const [selectedRule, setSelectedRule] = useState(ruleList[1].id)
|
||||
|
||||
const [ ruleInfo, setRuleInfo ] = useState({
|
||||
headImg: icon,
|
||||
name: '2026年第八届CCF开源创新大赛赛事规则',
|
||||
summary: '原生编程挑战赛,是由阿里云主办,云原生应用平台承办的云原生知名品牌赛事。 自 2015 年开始,大赛已经成功举办了十届,共吸引了超过 91000 支队伍,覆盖 10 余个国家和地区。今年大赛主题全新升级为”全栈观测,智赢未来”,将深度探索全栈可观测技术在 AIOps 智能运…',
|
||||
id: 1
|
||||
})
|
||||
|
||||
const [ruleInfoList, setRuleInfoList] = useState({})
|
||||
|
||||
const [periodList, setPeriodList] = useState([])
|
||||
|
||||
const scheduleList = [
|
||||
{ id: 1, periodId: 1, date: '3月20日', content: '我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 2, periodId: 1, date: '3月28日', content: '我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 3, periodId: 1, date: '3月28日', content: '我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 4, periodId: 1, date: '3月28日', content: '我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 5, periodId: 1, date: '3月28日', content: '我是此日期的具体赛事安排占一行我是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 6, periodId: 2, date: '5月20日', content: '我是此日期的具体赛事安排占一行我是此日期的', status: '报名招募期' },
|
||||
{ id: 7, periodId: 2, date: '5月20日', content: '我是此日期的具体赛事安排占一行我是此日期的', status: '报名招募期' },
|
||||
{ id: 8, periodId: 2, date: '5月20日', content: '我是此日期的具体赛事安排占一行我是此日期的', status: '报名招募期' },
|
||||
{ id: 9, periodId: 3, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 10, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 11, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 12, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 13, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 14, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 15, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' },
|
||||
{ id: 16, periodId: 4, date: '7月20日', content: '行是此日期的具体赛事安排占一行', status: '报名招募期' }
|
||||
]
|
||||
const [scheduleList, setScheduleList] = useState([])
|
||||
|
||||
const [selectedPeriod, setSelectedPeriod] = useState(1)
|
||||
const scheduleRefs = useRef({})
|
||||
|
|
@ -67,7 +43,67 @@ function Schedule(props) {
|
|||
const getList = () => {
|
||||
if (timelineDir) {
|
||||
getDocList(timelineDir).then(res => {
|
||||
setPeriodList(res.rows);
|
||||
// 按时间顺序排列(反转倒序)
|
||||
const sortedRows = res.rows.reverse();
|
||||
setPeriodList(sortedRows);
|
||||
|
||||
// 为每个文章调用getDocDetail接口
|
||||
const scheduleData = [];
|
||||
let processedCount = 0;
|
||||
|
||||
sortedRows.forEach((period, periodIndex) => {
|
||||
getDocDetail(period.id).then(detailRes => {
|
||||
if (detailRes.data && detailRes.data.content) {
|
||||
// Base64解码content字段
|
||||
const decodedContent = Base64.decode(detailRes.data.content);
|
||||
|
||||
// 使用DOMParser解析HTML内容
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(decodedContent, 'text/html');
|
||||
const paragraphs = doc.querySelectorAll('p');
|
||||
|
||||
let scheduleId = scheduleData.length + 1;
|
||||
|
||||
paragraphs.forEach((p) => {
|
||||
const text = p.textContent.trim();
|
||||
if (text) {
|
||||
// 按空格分割,第一个词作为日期,其余作为内容
|
||||
const parts = text.split(/\s+/);
|
||||
if (parts.length > 0) {
|
||||
const date = parts[0];
|
||||
const content = parts.slice(1).join(' ');
|
||||
|
||||
// 创建赛程项
|
||||
scheduleData.push({
|
||||
id: scheduleId++,
|
||||
periodId: period.id,
|
||||
date: date,
|
||||
content: content,
|
||||
status: period.summary || '进行中'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
|
||||
// 当所有文章都处理完成后,更新scheduleList
|
||||
if (processedCount === sortedRows.length) {
|
||||
// 更新scheduleList状态
|
||||
setScheduleList(scheduleData);
|
||||
}
|
||||
|
||||
}).catch(err => {
|
||||
console.error(`获取文章详情失败 (ID: ${period.id}):`, err);
|
||||
processedCount++;
|
||||
|
||||
if (processedCount === sortedRows.length) {
|
||||
setScheduleList(scheduleData);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}).catch(err => {
|
||||
console.error('获取文档列表失败:', err);
|
||||
});
|
||||
|
|
@ -93,16 +129,18 @@ function Schedule(props) {
|
|||
}
|
||||
|
||||
// 滚动到对应赛程项,添加200px余量
|
||||
const firstScheduleOfPeriod = scheduleList.find(schedule => schedule.periodId === periodId)
|
||||
if (firstScheduleOfPeriod && scheduleRefs.current[firstScheduleOfPeriod.id]) {
|
||||
const element = scheduleRefs.current[firstScheduleOfPeriod.id]
|
||||
const container = element.parentElement
|
||||
const offsetTop = element.getBoundingClientRect().top - container.getBoundingClientRect().top
|
||||
if (scheduleList && scheduleList.length > 0) {
|
||||
const firstScheduleOfPeriod = scheduleList.find(schedule => schedule.periodId === periodId)
|
||||
if (firstScheduleOfPeriod && scheduleRefs.current[firstScheduleOfPeriod.id]) {
|
||||
const element = scheduleRefs.current[firstScheduleOfPeriod.id]
|
||||
const container = element.parentElement
|
||||
const offsetTop = element.getBoundingClientRect().top - container.getBoundingClientRect().top
|
||||
|
||||
container.scrollTo({
|
||||
top: offsetTop + container.scrollTop,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
container.scrollTo({
|
||||
top: offsetTop + container.scrollTop,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue