diff --git a/src/components/GameSelector/GameSelector.tsx b/src/components/GameSelector/GameSelector.tsx index ffe172b..a959d71 100644 --- a/src/components/GameSelector/GameSelector.tsx +++ b/src/components/GameSelector/GameSelector.tsx @@ -1,10 +1,11 @@ -import { Card, Divider, Flex, Select, Skeleton, Space, Statistic, Switch, Typography } from 'antd'; +import { Button, Card, Divider, Flex, Select, Skeleton, Space, Statistic, Switch, Typography } from 'antd'; import type React from 'react'; import { useRequest } from 'ahooks'; import { clubs } from './clubList'; import { useCallback, useEffect, useMemo, useState } from 'react'; import dayjs from 'dayjs'; import type { IEventInfo } from '../../types'; +import { EyeOutlined } from '@ant-design/icons'; interface Props { onGameClick?: (info: IEventInfo) => void; @@ -21,7 +22,7 @@ export const GameSelector: React.FC = props => { const gameList = useMemo(() => { const activeList = requestEvents.data?.map(e => ({ ...e, - finished: e.info.join('').includes('已结束'), + finished: dayjs(e.startDate).isBefore(dayjs()), })); return activeList; }, [requestEvents.data]); @@ -76,16 +77,21 @@ interface EventCardProps { function EventCard(props: EventCardProps) { const { eventInfo: e } = props; - const { y, M, D } = /^(?\d{4})年(?\d+)月(?\d+)日/.exec(e.title)?.groups ?? {} as { y: string; M: string; D: string}; - const hm = /(?\d+:\d+)\b/.exec(e.info.join('\n'))?.groups?.hm ?? '10:00'; - const day = dayjs(`${y}-${M}-${D} ${hm}`); + const day = dayjs(e.startDate); return ( props.onGameClick?.(e)} + actions={[ + + ]} > {e.title} = props => { ?.map((e, i) => ({ ...e, index: i + 1, id: `${i}-${e.name}-${e.score}` })) ?? []; }, [refactoredPlayers, maxPlayerSize]); const [groupLen, setGroupLen] = useState(6); + useEffect(() => { + if (props.players) { + if (players.length < 48) { + setMaxPlayerSize(players.length); + } + if (players.length < 12) { + setGroupLen(1); + } + } + }, [props.players?.length]); const [sneckMode, setSneckMode] = useState(props.sneckMode); const chunkSize = useMemo(() => Math.floor((players.length ?? 0) / groupLen) || 1, [players, groupLen]); const grouped = useMemo(() => { diff --git a/src/types/index.ts b/src/types/index.ts index f10edc0..bea2512 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -8,6 +8,7 @@ export interface IEventInfo { info: string[]; url: string; matchId: string; + startDate: string; } export interface MatchInfo { diff --git a/src/utils/server.ts b/src/utils/server.ts index 3bc7f45..e21eee4 100644 --- a/src/utils/server.ts +++ b/src/utils/server.ts @@ -43,13 +43,13 @@ const htmlRequestHeaders = { * @param tagid 俱乐部 ID */ export async function listEvent(tagid: string): Promise { - const key = `my-kaiqiuwang:evnet:${tagid}`; + const key = `my-kaiqiuwang:club-events:${tagid}`; let html = await redis.get(key).catch(() => ''); if (!html) { html = await fetchEventListHTML(tagid); redis.setex(key, 60 * 60 * REDIS_CACHE_HOUR, html); } - return parseEventList(html); + return await parseEventList(html); } /** @@ -62,21 +62,33 @@ export async function fetchEventListHTML(tagid: string) { return resp.text() ?? ''; } -export function parseEventList(html: string) { +export async function parseEventList(html: string) { const $ = cheerio.load(html); const blockList = $('div.event_list > ol > li'); const list: IEventInfo[] = []; for (const block of blockList) { const titleEl = $(block).find('.event_title'); const title = titleEl.text(); - const url = $(titleEl).find('a').attr('href') ?? ''; - const startDate = $(block).find('ul li:nth-of-type(1)').text().replace('比赛开始: \\t', '').trim(); + const eventPath = $(titleEl).find('a').attr('href') ?? ''; const place = $(block).find('ul li:nth-of-type(2)').text().replace('比赛地点: \\t', '').trim(); + const eventURL = `${BASE_URL}/home/${eventPath}`; + const matchId = /\S+-(\d+).html$/.exec(eventPath)?.[1] ?? ''; + let eventPage = await redis.get(`my-kaiqiuwang:match:${matchId}`) ?? ''; + if (!eventPage) { + eventPage = await fetch(eventURL, { headers: htmlRequestHeaders }).then(res => res.text() ?? ''); + await redis.setex(`my-kaiqiuwang:match:${matchId}`, 60 * 60 * 10, eventPage) + } + const $eventPage = cheerio.load(eventPage); + const eventContent = $eventPage('.event_content').text().replace(/(\r|\n)/g, ',').split(',').filter(Boolean).join(' '); + const { y, M, D, H, m} = /比赛开始:.*?(?\d{4})年(?\d{2})月(?\d{2})日 \w+ (?\d{2}):(?\d{2})/ + .exec(eventContent)?.groups ?? {}; + const startDate = y ? `${y}-${M}-${D} ${H}:${m}` : ''; const event: IEventInfo = { title, - info: [startDate, place], - url: `${BASE_URL}/home/${url}`, - matchId: /\S+-(\d+).html$/.exec(url)?.[1] ?? '', + info: [`比赛时间:${startDate}`, place], + url: eventURL, + startDate, + matchId, } list.push(event); } @@ -117,7 +129,7 @@ export function parseEventInfo(html: string) { } export async function getMatchInfo(matchId: string) { - const key = `my-kaiqiuwang:matchinfo:${matchId}`; + const key = `my-kaiqiuwang:match-member:${matchId}`; let html = await redis.get(key).catch(() => ''); if (!html) { html = await fetchEventContentHTML(matchId);