From 34cad6e0df1b0df92fb14f40eb96d3a6d7e8cc92 Mon Sep 17 00:00:00 2001 From: kyuuseiryuu Date: Sat, 24 Jan 2026 02:01:17 +0900 Subject: [PATCH] init --- .gitignore | 34 + README.md | 21 + __test__/data/view-event-content.html | 3163 ++++++++++++++++++ __test__/data/view-event.html | 388 +++ __test__/utils.load-html.test.ts | 18 + __test__/utils.test.ts | 44 + bun-env.d.ts | 17 + bun.lock | 192 ++ bunfig.toml | 2 + index.ts | 0 package.json | 25 + src/App.tsx | 31 + src/components/GamePanel.tsx | 36 + src/components/GameSelector/GameSelector.tsx | 61 + src/components/GameSelector/clubList.ts | 6 + src/components/GameSelector/index.ts | 1 + src/components/GroupMember.tsx | 36 + src/components/GroupingPrediction.tsx | 65 + src/components/PlayerList.tsx | 27 + src/frontend.tsx | 31 + src/global.d.ts | 1 + src/index.css | 44 + src/index.html | 14 + src/index.tsx | 32 + src/logo.svg | 1 + src/react.svg | 8 + src/types.ts | 18 + src/utils.ts | 111 + tsconfig.json | 29 + 29 files changed, 4456 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 __test__/data/view-event-content.html create mode 100644 __test__/data/view-event.html create mode 100644 __test__/utils.load-html.test.ts create mode 100644 __test__/utils.test.ts create mode 100644 bun-env.d.ts create mode 100644 bun.lock create mode 100644 bunfig.toml create mode 100644 index.ts create mode 100644 package.json create mode 100644 src/App.tsx create mode 100644 src/components/GamePanel.tsx create mode 100644 src/components/GameSelector/GameSelector.tsx create mode 100644 src/components/GameSelector/clubList.ts create mode 100644 src/components/GameSelector/index.ts create mode 100644 src/components/GroupMember.tsx create mode 100644 src/components/GroupingPrediction.tsx create mode 100644 src/components/PlayerList.tsx create mode 100644 src/frontend.tsx create mode 100644 src/global.d.ts create mode 100644 src/index.css create mode 100644 src/index.html create mode 100644 src/index.tsx create mode 100644 src/logo.svg create mode 100644 src/react.svg create mode 100644 src/types.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# dependencies (bun install) +node_modules + +# output +out +dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..6576096 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# bun-react-template + +To install dependencies: + +```bash +bun install +``` + +To start a development server: + +```bash +bun dev +``` + +To run for production: + +```bash +bun start +``` + +This project was created using `bun init` in bun v1.2.21. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime. diff --git a/__test__/data/view-event-content.html b/__test__/data/view-event-content.html new file mode 100644 index 0000000..28a74de --- /dev/null +++ b/__test__/data/view-event-content.html @@ -0,0 +1,3163 @@ + + + + + + + + 2026年2月14日 东华乒乓球俱乐部2026年2月开球网ChinaTT积分赛(争霸赛)(内部比赛) - 开球网 - 全国乒乓球积分赛网站 + + + + + + + + + + + + +
+
+ + +
+ +
+
+
+
+ +

登录站点

+

用户名

+

+

密码

+

+

+

+ + + +

+

如果您注册或者登录本网,则表示您同意本协议内容。

+
+
+
+
+ + +

+ 比赛 - +2026年2月14日 东华乒乓球俱乐部2026年2月开球网ChinaTT积分赛(争霸赛)(内部比赛) + +

+
+分享 +
+ + + + +
+ + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+徐子铮 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1950| B2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+卡斯柏 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1893| B3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+周诗博 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1853| B3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+张会坤 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1840| B3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+邵仁爱 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1781| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+中河 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1758| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+林泊辰 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1745| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+Tracy_god +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1730| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+武藏野 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1711| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+chen5274 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1702| C1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+小朗朗 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1689| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+王扬1 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1683| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+清水刘 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1675| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+骏骏 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1665| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+铁板李 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1660| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+金渊1 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1657| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+chasel +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1656| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+魏建菁 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1654| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+森本 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1650| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+胡晓雷 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1648| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+kyle_sz +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1645| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+小卢 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1643| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+陈永 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1640| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+薛高远 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1637| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+贾祎梓 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1627| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+陶静 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1619| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+王升2023 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1619| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+ +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1617| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+石井 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1611| C2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+杨静辉 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1598| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+辛梓1 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1592| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+正手必狂飙 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1591| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+征山乒乓 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1589| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+邵箴言1 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1582| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+宫原清 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1568| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+张昀18 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1563| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+刘延泽 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1561| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+毛妹妹 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1552| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+j4ckzty +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1541| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+邱成龍 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1540| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+east +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1530| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+赵应学 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1527| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+mzy +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1527| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+李悠洋 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1526| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+玄 明琴 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1501| C3 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+姜永日 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1491| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+初学乍练 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1489| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+酉玉焘 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1481| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+孙乐公 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1479| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+李青海 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1464| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+韓范虎 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1458| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+李铮强 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1443| D1 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+六六 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +美女 + + + + + 1370| D2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+Steven1 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1361| D2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+松浦輝 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1339| D2 历史战绩 + +

+ +
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+
+劉睿 +
+

+ + + + 成员 加为好友 +|打招呼 +

+ +

+ + + +性别: +帅哥 + + + + + 1203| D3 历史战绩 + +

+ +
+
+ +
+ + + + + + + + +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/__test__/data/view-event.html b/__test__/data/view-event.html new file mode 100644 index 0000000..088adc4 --- /dev/null +++ b/__test__/data/view-event.html @@ -0,0 +1,388 @@ + + + + + + + + 东华乒乓球俱乐部 - 比赛 - 开球网 - 全国乒乓球积分赛网站 + + + + + + + + + + + + + + +
+
+
+ + +
+ + +
+
+ + +
+ +
+ + +

+俱乐部东华乒乓球俱乐部 +

+ + +
+
    +
  1. +
    +2026年2月14日  东华乒乓球俱乐部2026年2月开球网ChinaTT积分赛(争霸赛)(内部比赛) +
    +
    +

    2026年2月14日 东华乒乓球俱乐部2026年2月开球网ChinaTT积分赛(争霸赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 2月14日 10:00 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 979 次查看  56 人参加  58 人关注
    • +
    +
    +
  2. +
  3. +
    +2026年1月17日  东华乒乓球俱乐部2026年1月份开球网ChinaTT积分赛(激战赛)(内部比赛) +
    +
    +

    2026年1月17日 东华乒乓球俱乐部2026年1月份开球网ChinaTT积分赛(激战赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 1月17日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5595 次查看  42 人参加  51 人关注
    • +
    +
    +
  4. +
  5. +
    +2025年12月13日  东华乒乓球俱乐部2025年12月开球网ChinaTT积分赛(争霸赛)(内部比赛) +
    +
    +

    2025年12月13日 东华乒乓球俱乐部2025年12月开球网ChinaTT积分赛(争霸赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 12月13日 9:30 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5226 次查看  49 人参加  57 人关注
    • +
    +
    +
  6. +
  7. +
    +2025年11月23日  东华乒乓球俱乐部2025年11月份开球网ChinaTT积分赛(激战赛)(内部比赛) +
    +
    +

    2025年11月23日 东华乒乓球俱乐部2025年11月份开球网ChinaTT积分赛(激战赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 11月23日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5812 次查看  49 人参加  43 人关注
    • +
    +
    +
  8. +
  9. +
    +2025年10月5日  东华乒乓球俱乐部2025年10月开球网ChinaTT积分赛(争霸赛)(内部比赛) +
    +
    +

    2025年10月5日 东华乒乓球俱乐部2025年10月开球网ChinaTT积分赛(争霸赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 10月05日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 4610 次查看  48 人参加  56 人关注
    • +
    +
    +
  10. +
  11. +
    +2025年9月14日  东华乒乓球俱乐部2025年9月份开球网ChinaTT积分赛(激战赛)(内部比赛) +
    +
    +

    2025年9月14日 东华乒乓球俱乐部2025年9月份开球网ChinaTT积分赛(激战赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 9月14日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 6554 次查看  48 人参加  40 人关注
    • +
    +
    +
  12. +
  13. +
    +2025年8月24日  东华乒乓球俱乐部2025年8月开球网ChinaTT积分赛(争霸赛)(内部比赛) +
    +
    +

    2025年8月24日 东华乒乓球俱乐部2025年8月开球网ChinaTT积分赛(争霸赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 8月24日 9:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5082 次查看  48 人参加  55 人关注
    • +
    +
    +
  14. +
  15. +
    +2025年7月27日  东华乒乓球俱乐部2025年7月份开球网ChinaTT积分赛(激战赛)(内部比赛) +
    +
    +

    2025年7月27日 东华乒乓球俱乐部2025年7月份开球网ChinaTT积分赛(激战赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 7月27日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5943 次查看  48 人参加  40 人关注
    • +
    +
    +
  16. +
  17. +
    +2025年6月8日  东华乒乓球俱乐部2025年6月开球网ChinaTT积分赛(争霸赛)(内部比赛) +
    +
    +

    2025年6月8日 东华乒乓球俱乐部2025年6月开球网ChinaTT积分赛(争霸赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 6月08日 9:30 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5347 次查看  48 人参加  53 人关注
    • +
    +
    +
  18. +
  19. +
    +2025年5月18日  东华乒乓球俱乐部2025年5月份开球网ChinaTT积分赛(激战赛)(内部比赛) +
    +
    +

    2025年5月18日 东华乒乓球俱乐部2025年5月份开球网ChinaTT积分赛(激战赛)(内部比赛)[个人积分赛]

    +
      +
    • +比赛开始: 5月18日 10:00 + 已结束 + +
    • +
    • 比赛地点: +海外 +日本 +
    • +
    • 发起人: cldws
    • +
    • 5521 次查看  46 人参加  33 人关注
    • +
    +
    +
  20. +
+
 132 12345... 14     直接跳转到
+
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + diff --git a/__test__/utils.load-html.test.ts b/__test__/utils.load-html.test.ts new file mode 100644 index 0000000..844171f --- /dev/null +++ b/__test__/utils.load-html.test.ts @@ -0,0 +1,18 @@ +import { expect, test } from 'bun:test'; +import path from 'path'; +import fs from 'fs'; +import { fetchEventContentHTML, fetchEventListHTML } from '../src/utils'; + +test('load html', async () => { + const saveTo = path.resolve(__dirname, 'data', 'view-event.html'); + const html = await fetchEventListHTML(`47`); + fs.writeFileSync(saveTo, html?? ''); + expect(html?.length).not.toBe(0); +}); + +test('load html', async () => { + const saveTo = path.resolve(__dirname, 'data', 'view-event-content.html'); + const html = await fetchEventContentHTML('167684'); + fs.writeFileSync(saveTo, html?? ''); + expect(html?.length).not.toBe(0); +}); \ No newline at end of file diff --git a/__test__/utils.test.ts b/__test__/utils.test.ts new file mode 100644 index 0000000..5c9b788 --- /dev/null +++ b/__test__/utils.test.ts @@ -0,0 +1,44 @@ +import fs from 'fs'; +import { expect, test } from 'bun:test'; +import path from 'path'; +import { parseEventInfo, parseEventList, sneckGroup } from '../src/utils'; + + +const matchId = '167684'; +const item_id = '7098063'; +test('event list not empty', () => { + const html = fs.readFileSync(path.resolve(__dirname, 'data', 'view-event.html')).toString(); + const list = parseEventList(html); + expect(list.length).toBe(10); + console.log(list[0]?.matchId); +}); + +test('event content not empty', () => { + const html = fs.readFileSync( + path.resolve(__dirname, 'data', 'view-event-content.html') + ).toString(); + const { itemId, players } = parseEventInfo(html); + expect(itemId).toBe(item_id); + expect(players.length).toBeGreaterThan(0); + console.log(players); +}); + +test("group", () => { + const group = sneckGroup(48, 6); + /** + * A B + * [01] [07] + * [02] [08] + * [05] [09] + * [06] [10] + * A B + * [01] [08] + * [07] [02] + * [05] [10] + * [09] [06] + */ + expect(group?.[0]?.[0]).toBe(0); + expect(group?.[0]?.[1]).toBe(11); + expect(group?.[1]?.[0]).toBe(1); + expect(group?.[1]?.[1]).toBe(10); +}) \ No newline at end of file diff --git a/bun-env.d.ts b/bun-env.d.ts new file mode 100644 index 0000000..72f1c26 --- /dev/null +++ b/bun-env.d.ts @@ -0,0 +1,17 @@ +// Generated by `bun init` + +declare module "*.svg" { + /** + * A path to the SVG file + */ + const path: `${string}.svg`; + export = path; +} + +declare module "*.module.css" { + /** + * A record of class names to their corresponding CSS module classes + */ + const classes: { readonly [key: string]: string }; + export = classes; +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..f85aed6 --- /dev/null +++ b/bun.lock @@ -0,0 +1,192 @@ +{ + "lockfileVersion": 1, + "configVersion": 0, + "workspaces": { + "": { + "name": "kaiqiu-rank-list", + "dependencies": { + "@ant-design/icons": "^6.1.0", + "ahooks": "^3.9.6", + "antd": "^6.2.1", + "lodash": "^4.17.23", + "react": "^19", + "react-dom": "^19", + }, + "devDependencies": { + "@types/bun": "latest", + "@types/lodash": "^4.17.23", + "@types/react": "^19", + "@types/react-dom": "^19", + }, + }, + }, + "packages": { + "@ant-design/colors": ["@ant-design/colors@8.0.1", "", { "dependencies": { "@ant-design/fast-color": "^3.0.0" } }, "sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ=="], + + "@ant-design/cssinjs": ["@ant-design/cssinjs@2.0.3", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@emotion/hash": "^0.8.0", "@emotion/unitless": "^0.7.5", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1", "csstype": "^3.1.3", "stylis": "^4.3.4" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-HAo8SZ3a6G8v6jT0suCz1270na6EA3obeJWM4uzRijBhdwdoMAXWK2f4WWkwB28yUufsfk3CAhN1coGPQq4kNQ=="], + + "@ant-design/cssinjs-utils": ["@ant-design/cssinjs-utils@2.0.2", "", { "dependencies": { "@ant-design/cssinjs": "^2.0.1", "@babel/runtime": "^7.23.2", "@rc-component/util": "^1.4.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-Mq3Hm6fJuQeFNKSp3+yT4bjuhVbdrsyXE2RyfpJFL0xiYNZdaJ6oFaE3zFrzmHbmvTd2Wp3HCbRtkD4fU+v2ZA=="], + + "@ant-design/fast-color": ["@ant-design/fast-color@3.0.0", "", {}, "sha512-eqvpP7xEDm2S7dUzl5srEQCBTXZMmY3ekf97zI+M2DHOYyKdJGH0qua0JACHTqbkRnD/KHFQP9J1uMJ/XWVzzA=="], + + "@ant-design/icons": ["@ant-design/icons@6.1.0", "", { "dependencies": { "@ant-design/colors": "^8.0.0", "@ant-design/icons-svg": "^4.4.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-KrWMu1fIg3w/1F2zfn+JlfNDU8dDqILfA5Tg85iqs1lf8ooyGlbkA+TkwfOKKgqpUmAiRY1PTFpuOU2DAIgSUg=="], + + "@ant-design/icons-svg": ["@ant-design/icons-svg@4.4.2", "", {}, "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA=="], + + "@ant-design/react-slick": ["@ant-design/react-slick@2.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "clsx": "^2.1.1", "json2mq": "^0.2.0", "throttle-debounce": "^5.0.0" }, "peerDependencies": { "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg=="], + + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], + + "@emotion/hash": ["@emotion/hash@0.8.0", "", {}, "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="], + + "@emotion/unitless": ["@emotion/unitless@0.7.5", "", {}, "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="], + + "@rc-component/async-validator": ["@rc-component/async-validator@5.1.0", "", { "dependencies": { "@babel/runtime": "^7.24.4" } }, "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA=="], + + "@rc-component/cascader": ["@rc-component/cascader@1.11.0", "", { "dependencies": { "@rc-component/select": "~1.5.0", "@rc-component/tree": "~1.1.0", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-VDiEsskThWi8l0/1Nquc9I4ytcMKQYAb9Jkm6wiX5O5fpcMRsm+b8OulBMbr/b4rFTl/2y2y4GdKqQ+2whD+XQ=="], + + "@rc-component/checkbox": ["@rc-component/checkbox@1.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-08yTH8m+bSm8TOqbybbJ9KiAuIATti6bDs2mVeSfu4QfEnyeF6X0enHVvD1NEAyuBWEAo56QtLe++MYs2D9XiQ=="], + + "@rc-component/collapse": ["@rc-component/collapse@1.2.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw=="], + + "@rc-component/color-picker": ["@rc-component/color-picker@3.0.3", "", { "dependencies": { "@ant-design/fast-color": "^3.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-V7gFF9O7o5XwIWafdbOtqI4BUUkEUkgdBwp6favy3xajMX/2dDqytFaiXlcwrpq6aRyPLp5dKLAG5RFKLXMeGA=="], + + "@rc-component/context": ["@rc-component/context@2.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-HyZbYm47s/YqtP6pKXNMjPEMaukyg7P0qVfgMLzr7YiFNMHbK2fKTAGzms9ykfGHSfyf75nBbgWw+hHkp+VImw=="], + + "@rc-component/dialog": ["@rc-component/dialog@1.8.0", "", { "dependencies": { "@rc-component/motion": "^1.1.3", "@rc-component/portal": "^2.1.0", "@rc-component/util": "^1.5.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-zGksezfULKixYCIWctIhUC2M3zUJrc81JKWbi9dJrQdPaM7J+8vSOrhLoOHHkZFpBpb2Ri6JqnSuGYb2N+FrRA=="], + + "@rc-component/drawer": ["@rc-component/drawer@1.4.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/portal": "^2.1.3", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-Zr1j1LRLDauz4a5JXHEmeYQfvEzfh4CddNa7tszyJnfd5GySYdZ5qLO63Tt2tgG4k+qi6tkFDKmcT46ikZfzbQ=="], + + "@rc-component/dropdown": ["@rc-component/dropdown@1.0.2", "", { "dependencies": { "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.11.0", "react-dom": ">=16.11.0" } }, "sha512-6PY2ecUSYhDPhkNHHb4wfeAya04WhpmUSKzdR60G+kMNVUCX2vjT/AgTS0Lz0I/K6xrPMJ3enQbwVpeN3sHCgg=="], + + "@rc-component/form": ["@rc-component/form@1.6.2", "", { "dependencies": { "@rc-component/async-validator": "^5.1.0", "@rc-component/util": "^1.6.2", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-OgIn2RAoaSBqaIgzJf/X6iflIa9LpTozci1lagLBdURDFhGA370v0+T0tXxOi8YShMjTha531sFhwtnrv+EJaQ=="], + + "@rc-component/image": ["@rc-component/image@1.6.0", "", { "dependencies": { "@rc-component/motion": "^1.0.0", "@rc-component/portal": "^2.1.2", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-tSfn2ZE/oP082g4QIOxeehkmgnXB7R+5AFj/lIFr4k7pEuxHBdyGIq9axoCY9qea8NN0DY6p4IB/F07tLqaT5A=="], + + "@rc-component/input": ["@rc-component/input@1.1.2", "", { "dependencies": { "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-Q61IMR47piUBudgixJ30CciKIy9b1H95qe7GgEKOmSJVJXvFRWJllJfQry9tif+MX2cWFXWJf/RXz4kaCeq/Fg=="], + + "@rc-component/input-number": ["@rc-component/input-number@1.6.2", "", { "dependencies": { "@rc-component/mini-decimal": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w=="], + + "@rc-component/mentions": ["@rc-component/mentions@1.6.0", "", { "dependencies": { "@rc-component/input": "~1.1.0", "@rc-component/menu": "~1.2.0", "@rc-component/textarea": "~1.1.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-KIkQNP6habNuTsLhUv0UGEOwG67tlmE7KNIJoQZZNggEZl5lQJTytFDb69sl5CK3TDdISCTjKP3nGEBKgT61CQ=="], + + "@rc-component/menu": ["@rc-component/menu@1.2.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/overflow": "^1.0.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-VWwDuhvYHSnTGj4n6bV3ISrLACcPAzdPOq3d0BzkeiM5cve8BEYfvkEhNoM0PLzv51jpcejeyrLXeMVIJ+QJlg=="], + + "@rc-component/mini-decimal": ["@rc-component/mini-decimal@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.18.0" } }, "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ=="], + + "@rc-component/motion": ["@rc-component/motion@1.1.6", "", { "dependencies": { "@rc-component/util": "^1.2.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-aEQobs/YA0kqRvHIPjQvOytdtdRVyhf/uXAal4chBjxDu6odHckExJzjn2D+Ju1aKK6hx3pAs6BXdV9+86xkgQ=="], + + "@rc-component/mutate-observer": ["@rc-component/mutate-observer@2.0.1", "", { "dependencies": { "@rc-component/util": "^1.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w=="], + + "@rc-component/notification": ["@rc-component/notification@1.2.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-OX3J+zVU7rvoJCikjrfW7qOUp7zlDeFBK2eA3SFbGSkDqo63Sl4Ss8A04kFP+fxHSxMDIS9jYVEZtU1FNCFuBA=="], + + "@rc-component/overflow": ["@rc-component/overflow@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@rc-component/resize-observer": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-GSlBeoE0XTBi5cf3zl8Qh7Uqhn7v8RrlJ8ajeVpEkNe94HWy5l5BQ0Mwn2TVUq9gdgbfEMUmTX7tJFAg7mz0Rw=="], + + "@rc-component/pagination": ["@rc-component/pagination@1.2.0", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-YcpUFE8dMLfSo6OARJlK6DbHHvrxz7pMGPGmC/caZSJJz6HRKHC1RPP001PRHCvG9Z/veD039uOQmazVuLJzlw=="], + + "@rc-component/picker": ["@rc-component/picker@1.9.0", "", { "dependencies": { "@rc-component/overflow": "^1.0.0", "@rc-component/resize-observer": "^1.0.0", "@rc-component/trigger": "^3.6.15", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "date-fns": ">= 2.x", "dayjs": ">= 1.x", "luxon": ">= 3.x", "moment": ">= 2.x", "react": ">=16.9.0", "react-dom": ">=16.9.0" }, "optionalPeers": ["date-fns", "dayjs", "luxon", "moment"] }, "sha512-OLisdk8AWVCG9goBU1dWzuH5QlBQk8jktmQ6p0/IyBFwdKGwyIZOSjnBYo8hooHiTdl0lU+wGf/OfMtVBw02KQ=="], + + "@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="], + + "@rc-component/progress": ["@rc-component/progress@1.0.2", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ=="], + + "@rc-component/qrcode": ["@rc-component/qrcode@1.1.1", "", { "dependencies": { "@babel/runtime": "^7.24.7" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA=="], + + "@rc-component/rate": ["@rc-component/rate@1.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw=="], + + "@rc-component/resize-observer": ["@rc-component/resize-observer@1.1.1", "", { "dependencies": { "@rc-component/util": "^1.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-NfXXMmiR+SmUuKE1NwJESzEUYUFWIDUn2uXpxCTOLwiRUUakd62DRNFjRJArgzyFW8S5rsL4aX5XlyIXyC/vRA=="], + + "@rc-component/segmented": ["@rc-component/segmented@1.3.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg=="], + + "@rc-component/select": ["@rc-component/select@1.5.1", "", { "dependencies": { "@rc-component/overflow": "^1.0.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-ARXtwfCVnpDJj1bQjh1cimUlNQkZiN72hvtL2G4mKXIYfkokYdA2Vyu2deAfY7kuHSWpmZygVuohQt6TxOYjnA=="], + + "@rc-component/slider": ["@rc-component/slider@1.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-uDhEPU1z3WDfCJhaL9jfd2ha/Eqpdfxsn0Zb0Xcq1NGQAman0TWaR37OWp2vVXEOdV2y0njSILTMpTfPV1454g=="], + + "@rc-component/steps": ["@rc-component/steps@1.2.2", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw=="], + + "@rc-component/switch": ["@rc-component/switch@1.0.3", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw=="], + + "@rc-component/table": ["@rc-component/table@1.9.1", "", { "dependencies": { "@rc-component/context": "^2.0.1", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.1.0", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-FVI5ZS/GdB3BcgexfCYKi3iHhZS3Fr59EtsxORszYGrfpH1eWr33eDNSYkVfLI6tfJ7vftJDd9D5apfFWqkdJg=="], + + "@rc-component/tabs": ["@rc-component/tabs@1.7.0", "", { "dependencies": { "@rc-component/dropdown": "~1.0.0", "@rc-component/menu": "~1.2.0", "@rc-component/motion": "^1.1.3", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-J48cs2iBi7Ho3nptBxxIqizEliUC+ExE23faspUQKGQ550vaBlv3aGF8Epv/UB1vFWeoJDTW/dNzgIU0Qj5i/w=="], + + "@rc-component/textarea": ["@rc-component/textarea@1.1.2", "", { "dependencies": { "@rc-component/input": "~1.1.0", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-9rMUEODWZDMovfScIEHXWlVZuPljZ2pd1LKNjslJVitn4SldEzq5vO1CL3yy3Dnib6zZal2r2DPtjy84VVpF6A=="], + + "@rc-component/tooltip": ["@rc-component/tooltip@1.4.0", "", { "dependencies": { "@rc-component/trigger": "^3.7.1", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg=="], + + "@rc-component/tour": ["@rc-component/tour@2.3.0", "", { "dependencies": { "@rc-component/portal": "^2.2.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.7.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-K04K9r32kUC+auBSQfr+Fss4SpSIS9JGe56oq/ALAX0p+i2ylYOI1MgR83yBY7v96eO6ZFXcM/igCQmubps0Ow=="], + + "@rc-component/tree": ["@rc-component/tree@1.1.0", "", { "dependencies": { "@rc-component/motion": "^1.0.0", "@rc-component/util": "^1.2.1", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-HZs3aOlvFgQdgrmURRc/f4IujiNBf4DdEeXUlkS0lPoLlx9RoqsZcF0caXIAMVb+NaWqKtGQDnrH8hqLCN5zlA=="], + + "@rc-component/tree-select": ["@rc-component/tree-select@1.6.0", "", { "dependencies": { "@rc-component/select": "~1.5.0", "@rc-component/tree": "~1.1.0", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-UvEGmZT+gcVvRwImAZg3/sXw9nUdn4FmCs1rSIMWjEXEIAo0dTGmIyWuLCvs+1rGe9AZ7CHMPiQUEbdadwV0fw=="], + + "@rc-component/trigger": ["@rc-component/trigger@3.9.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/portal": "^2.2.0", "@rc-component/resize-observer": "^1.1.1", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-X8btpwfrT27AgrZVOz4swclhEHTZcqaHeQMXXBgveagOiakTa36uObXbdwerXffgV8G9dH1fAAE0DHtVQs8EHg=="], + + "@rc-component/upload": ["@rc-component/upload@1.1.0", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-LIBV90mAnUE6VK5N4QvForoxZc4XqEYZimcp7fk+lkE4XwHHyJWxpIXQQwMU8hJM+YwBbsoZkGksL1sISWHQxw=="], + + "@rc-component/util": ["@rc-component/util@1.7.0", "", { "dependencies": { "is-mobile": "^5.0.0", "react-is": "^18.2.0" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-tIvIGj4Vl6fsZFvWSkYw9sAfiCKUXMyhVz6kpKyZbwyZyRPqv2vxYZROdaO1VB4gqTNvUZFXh6i3APUiterw5g=="], + + "@rc-component/virtual-list": ["@rc-component/virtual-list@1.0.2", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@rc-component/resize-observer": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-uvTol/mH74FYsn5loDGJxo+7kjkO4i+y4j87Re1pxJBs0FaeuMuLRzQRGaXwnMcV1CxpZLi2Z56Rerj2M00fjQ=="], + + "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], + + "@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="], + + "@types/lodash": ["@types/lodash@4.17.23", "", {}, "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA=="], + + "@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + + "@types/react": ["@types/react@19.2.9", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA=="], + + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + + "ahooks": ["ahooks@3.9.6", "", { "dependencies": { "@babel/runtime": "^7.21.0", "@types/js-cookie": "^3.0.6", "dayjs": "^1.9.1", "intersection-observer": "^0.12.0", "js-cookie": "^3.0.5", "lodash": "^4.17.21", "react-fast-compare": "^3.2.2", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.0", "tslib": "^2.4.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Mr7f05swd5SmKlR9SZo5U6M0LsL4ErweLzpdgXjA1JPmnZ78Vr6wzx0jUtvoxrcqGKYnX0Yjc02iEASVxHFPjQ=="], + + "antd": ["antd@6.2.1", "", { "dependencies": { "@ant-design/colors": "^8.0.1", "@ant-design/cssinjs": "^2.0.3", "@ant-design/cssinjs-utils": "^2.0.2", "@ant-design/fast-color": "^3.0.0", "@ant-design/icons": "^6.1.0", "@ant-design/react-slick": "~2.0.0", "@babel/runtime": "^7.28.4", "@rc-component/cascader": "~1.11.0", "@rc-component/checkbox": "~1.0.1", "@rc-component/collapse": "~1.2.0", "@rc-component/color-picker": "~3.0.3", "@rc-component/dialog": "~1.8.0", "@rc-component/drawer": "~1.4.0", "@rc-component/dropdown": "~1.0.2", "@rc-component/form": "~1.6.2", "@rc-component/image": "~1.6.0", "@rc-component/input": "~1.1.2", "@rc-component/input-number": "~1.6.2", "@rc-component/mentions": "~1.6.0", "@rc-component/menu": "~1.2.0", "@rc-component/motion": "~1.1.6", "@rc-component/mutate-observer": "^2.0.1", "@rc-component/notification": "~1.2.0", "@rc-component/pagination": "~1.2.0", "@rc-component/picker": "~1.9.0", "@rc-component/progress": "~1.0.2", "@rc-component/qrcode": "~1.1.1", "@rc-component/rate": "~1.0.1", "@rc-component/resize-observer": "^1.1.1", "@rc-component/segmented": "~1.3.0", "@rc-component/select": "~1.5.0", "@rc-component/slider": "~1.0.1", "@rc-component/steps": "~1.2.2", "@rc-component/switch": "~1.0.3", "@rc-component/table": "~1.9.1", "@rc-component/tabs": "~1.7.0", "@rc-component/textarea": "~1.1.2", "@rc-component/tooltip": "~1.4.0", "@rc-component/tour": "~2.3.0", "@rc-component/tree": "~1.1.0", "@rc-component/tree-select": "~1.6.0", "@rc-component/trigger": "^3.9.0", "@rc-component/upload": "~1.1.0", "@rc-component/util": "^1.7.0", "clsx": "^2.1.1", "dayjs": "^1.11.11", "scroll-into-view-if-needed": "^3.1.0", "throttle-debounce": "^5.0.2" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-ycw/XX7So4MdrwYKGfvZJdkGiCYUOSTebAIi+ejE95WJ138b11oy/iJg7iH0qydaD/B5sFd7Tz8XfPBuW7CRmw=="], + + "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="], + + "intersection-observer": ["intersection-observer@0.12.2", "", {}, "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="], + + "is-mobile": ["is-mobile@5.0.0", "", {}, "sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ=="], + + "js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="], + + "json2mq": ["json2mq@0.2.0", "", { "dependencies": { "string-convert": "^0.2.0" } }, "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA=="], + + "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], + + "react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="], + + "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], + + "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="], + + "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], + + "resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "screenfull": ["screenfull@5.2.0", "", {}, "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA=="], + + "scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="], + + "string-convert": ["string-convert@0.2.1", "", {}, "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="], + + "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], + + "throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + } +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..9819bf6 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[serve.static] +env = "BUN_PUBLIC_*" \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..843b579 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "bun-react-template", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "bun --hot src/index.tsx", + "build": "bun build ./src/index.html --outdir=dist --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --env='BUN_PUBLIC_*'", + "start": "NODE_ENV=production bun src/index.tsx" + }, + "dependencies": { + "@ant-design/icons": "^6.1.0", + "ahooks": "^3.9.6", + "antd": "^6.2.1", + "lodash": "^4.17.23", + "react": "^19", + "react-dom": "^19" + }, + "devDependencies": { + "@types/bun": "latest", + "@types/lodash": "^4.17.23", + "@types/react": "^19", + "@types/react-dom": "^19" + } +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..ea93c54 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,31 @@ +import { useCallback, useState } from "react"; +import { ClubSelector } from "./components/GameSelector"; +import "./index.css"; +import type { IEventInfo, Player } from "./types"; +import { Drawer, Tabs } from "antd"; +import { PlayerList } from "./components/PlayerList"; +import { GamePanel } from "./components/GamePanel"; + +export function App() { + const [game, setGame] = useState(); + const handleGameClick = useCallback(async (game: IEventInfo) => { + setGame(game); + }, []); + return ( +
+

开球网俱乐部比赛名单

+ + setGame(undefined)} + size={'calc(100vh - 100px)'} + > + + +
+ ); +} + +export default App; diff --git a/src/components/GamePanel.tsx b/src/components/GamePanel.tsx new file mode 100644 index 0000000..a46efe5 --- /dev/null +++ b/src/components/GamePanel.tsx @@ -0,0 +1,36 @@ +import type React from "react"; +import type { IEventInfo, MatchInfo } from "../types"; +import { useRequest } from "ahooks"; +import { Spin, Tabs } from "antd"; +import { PlayerList } from "./PlayerList"; +import { GroupingPrediction } from "./GroupingPrediction"; + +interface Props { + game?: IEventInfo; +} + +export const GamePanel: React.FC = props => { + const fetchPlayers = useRequest(async () => { + if (!props.game) return null; + const info: MatchInfo = await (await fetch(`/api/match/${props.game.matchId}`)).json(); + return info; + }, { refreshDeps: [props] }); + return ( + + + }, + { + key: 'players', + label: '成员列表', + children: + }, + ]} + /> + + ); +} \ No newline at end of file diff --git a/src/components/GameSelector/GameSelector.tsx b/src/components/GameSelector/GameSelector.tsx new file mode 100644 index 0000000..07f0b5b --- /dev/null +++ b/src/components/GameSelector/GameSelector.tsx @@ -0,0 +1,61 @@ +import { Button, Card, Divider, Select, Space, Spin, Typography } from 'antd'; +import type React from 'react'; +import { clubs } from './clubList'; +import { useCallback, useEffect, useState } from 'react'; +import { useRequest } from 'ahooks'; +import { GlobalOutlined } from '@ant-design/icons'; +import type { IEventInfo } from '../../types'; + +interface Props { + onGameClick?: (info: IEventInfo) => void; +} + +export const GameSelector: React.FC = props => { + const requestEvents = useRequest( + async (clubId: string) => (await fetch(`/api/events/${clubId}`)).json() + , { manual: true }) + const [gameList, setGameList] = useState([]); + const [isEmpty, setIsEmpty] = useState(false); + const [clubId, setClubId] = useState(clubs[0].clubId); + const handleClubChange = useCallback(async (clubId: string) => { + const list = await requestEvents.runAsync(clubId); + const activeList = list.filter(e => !e.info.join('').includes('已结束')); + setGameList(activeList); + setIsEmpty(activeList.length === 0); + }, []); + useEffect(() => { + const clubId = clubs[0].clubId; + handleClubChange(clubId); + }, []); + return ( + +