feat(tags):

This commit is contained in:
kyuuseiryuu 2026-01-28 17:00:31 +09:00
parent 7df7b70516
commit 95416923c8
6 changed files with 90 additions and 2 deletions

43
src/components/Tags.tsx Normal file
View File

@ -0,0 +1,43 @@
import { useRequest } from "ahooks";
import { Divider, Flex, Skeleton, Tag, Typography } from "antd";
import { EType, type XCXTag } from "../types";
import { useEffect } from "react";
interface Props {
uid?: string;
}
const color: {
[EType.GREEN]: string;
[EType.RED]: string;
[EType.YELLOW]: string;
} = {
[EType.GREEN]: 'success',
[EType.RED]: 'error',
[EType.YELLOW]: 'warning',
};
export default function UserTags(props: Props) {
const fetchTags = useRequest<XCXTag[], []>(async () => (await fetch(`/api/user/${props.uid}/tags`)).json(), {
refreshDeps: [props.uid],
});
if (!props.uid) return null;
return (
<>
<Divider></Divider>
<Flex wrap gap={12} justify="center">
{ fetchTags.loading ? (
<>
<Skeleton.Button active shape="square" />
<Skeleton.Button active shape="square" />
<Skeleton.Button active shape="square" />
</>
) : (
fetchTags.data?.length
? fetchTags.data?.map(e => (
<Tag key={e.eid} color={color[e.etype]}>{e.ename}({e.count})</Tag>
)): (<Typography.Text type="secondary"></Typography.Text>))}
</Flex>
</>
);
}

View File

@ -1,6 +1,6 @@
import { serve } from "bun";
import index from "./index.html";
import { getAdvProfile, getMatchInfo, listEvent } from "./utils";
import { getAdvProfile, getMatchInfo, getPlayerTags, listEvent } from "./utils";
const server = serve({
port: process.env.PORT || 3000,
@ -25,6 +25,13 @@ const server = serve({
const profile = await getAdvProfile(uid);
return Response.json(profile);
},
},
"/api/user/:uid/tags": {
async GET(req) {
const uid = req.params.uid;
const profile = await getPlayerTags(uid);
return Response.json(profile);
},
}
},

View File

@ -6,6 +6,7 @@ import { HomeOutlined } from "@ant-design/icons";
import User from "../components/User";
import React from "react";
import { ChangeBackground } from "../components/ChangeBackground";
import UserTags from "../components/Tags";
function Honor(props: { honors?: XCXProfile['honors'] }) {
if (!props.honors?.length) return null;
@ -31,7 +32,14 @@ function Honor(props: { honors?: XCXProfile['honors'] }) {
}
function Raket(props: { profile?: XCXProfile | null }) {
const { qiupaitype, zhengshoutype, fanshoutype, qiupai, zhengshou, fanshou } = props.profile || {};
const {
qiupaitype = '',
zhengshoutype = '',
fanshoutype = '',
qiupai = '',
zhengshou = '',
fanshou = '',
} = props.profile || {};
if ([qiupaitype, zhengshoutype, fanshoutype].every(e => !e)) {
return null;
}
@ -93,6 +101,7 @@ export default function ProfilePage() {
<Typography.Paragraph>
{profile?.description}
</Typography.Paragraph>
<UserTags uid={profile?.uid} />
<Raket profile={profile} />
<Flex wrap gap={24} justify="center">
<Flex vertical align="center">

View File

@ -1,3 +1,5 @@
export * from './profile';
export * from './tag';
export interface IEventInfo {
title: string;
info: string[];

12
src/types/tag.ts Normal file
View File

@ -0,0 +1,12 @@
export enum EType {
GREEN = "1",
RED = "-1",
YELLOW = "0",
}
export interface XCXTag {
eid: string;
etype: EType;
ename: string;
count: string;
}

View File

@ -5,6 +5,7 @@ import fs from 'fs';
import path from 'path';
import { chunk } from 'lodash';
import type { XCXProfile } from "./types/profile";
import type { XCXTag } from "./types/tag";
const BASE_URL = `https://kaiqiuwang.cc`;
const XCX_BASE_URL = `${BASE_URL}/xcx/public/index.php`;
@ -146,3 +147,17 @@ export async function getAdvProfile(uid: string) {
if (data.code !== 1) return null;
return data.data as XCXProfile;
}
export async function getPlayerTags(uid: string) {
// return JSON.parse(fs.readFileSync(
// path.resolve(__dirname, '..', '__test__', 'data', 'profile.json'),
// ).toString()).data;
if (!/^\d+$/.test(uid)) return null;
if (!uid) return null;
const resp = await fetch(`${XCX_BASE_URL}/api/User/get_tags?uid=${uid}&limitByCount=50&getNegative=true`, {
headers: xcxDefaultHeaders,
});
const data = await resp.json();
if (data.code !== 1) return null;
return (data.data as XCXTag[]).filter(e => Number(e.count) > 0);
}