Skip to content

Commit

Permalink
feat: bioos大赛第二届 赛事支持
Browse files Browse the repository at this point in the history
  • Loading branch information
yulitao-byte committed Jun 15, 2024
1 parent 2ff8100 commit 3894877
Show file tree
Hide file tree
Showing 17 changed files with 2,215 additions and 170 deletions.
9 changes: 9 additions & 0 deletions docs/zh/activity/help.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
pageType: custom
outline: true
sidebar: false
---

import ActivityHelp from '../../../src/ActivityHelp';

<ActivityHelp />
1,809 changes: 1,647 additions & 162 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
"dependencies": {
"@arco-design/web-react": "^2.61.2",
"@aws-sdk/client-s3": "^3.596.0",
"classnames": "^2.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
202 changes: 202 additions & 0 deletions src/ActivityHelp/TabData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { Message, Spin, Tabs, Typography } from "@arco-design/web-react";
import { IconDownload, IconFile } from "@arco-design/web-react/icon";

import {
AnchorHTMLAttributes,
ImgHTMLAttributes,
TableHTMLAttributes,
useEffect,
useMemo,
useState,
} from "react";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { downloadFile, getTosFile } from "../util";

const Ellipsis = Typography.Ellipsis;

interface FileItem {
name: string;
desc: string;
url: string;
}

export default function TabData() {
const [metadata, setMetadata] = useState<{
aiFiles: FileItem[];
paperFiles: FileItem[];
taskFiles: FileItem[];
}>();

useEffect(() => {
getTosFile(
"https://2ndbioos-competition-data.tos-cn-beijing.volces.com/metadata.json",
{ type: "json" }
).then((result) => {
if (result.status === "ok") {
setMetadata(result.content);
} else {
Message.error(`获取metadata失败:${result.content}`);
}
});
}, []);

return (
<>
<div className="font-medium text-lg mb-6">⛳️ 赛题与数据</div>

<Tabs type="card-gutter">
<Tabs.TabPane key="1" title="论文挑战赛">
<FileCardList files={metadata?.paperFiles} />
<MarkdownUrl url="https://lf-opensource.bytetos.com/obj/opensource-cn/bioos_question1.md" />
</Tabs.TabPane>
<Tabs.TabPane key="2" title="任务挑战赛">
<FileCardList files={metadata?.taskFiles} />
<MarkdownUrl url="https://lf-opensource.bytetos.com/obj/opensource-cn/bioos_question2.md" />
</Tabs.TabPane>
<Tabs.TabPane key="3" title="AI算法赛">
<FileCardList files={metadata?.aiFiles} />
<MarkdownUrl url="https://lf-opensource.bytetos.com/obj/opensource-cn/bioos_question3.md" />
</Tabs.TabPane>
</Tabs>
</>
);
}

function FileCardList({
files,
}: {
files?: {
name: string;
desc: string;
url: string;
}[];
}) {
if (!files?.length) return;

return (
<div
className="pb-8"
style={{
display: "grid",
gap: 16,
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
gridAutoFlow: "dense",
}}
>
{files.map(({ name, desc, url }, index) => {
return (
<section
key={index}
className={`border border-slate-200 border-solid rounded-lg p-4 flex flex-col cursor-pointer overflow-auto hover:shadow-md`}
style={{
height: 140,
background: "linear-gradient(180deg, #f3f7ff 0%, #fff 46.5%)",
}}
onClick={() => {
downloadFile(url);
}}
>
<div className="flex">
<div className="mr-2 pt-1">
<IconFile
style={{ fontSize: 36, color: "rgb(var(--link-6))" }}
/>
</div>

<div className="min-w-0">
<Ellipsis showTooltip className={`text-sm font-medium pb-1`}>
{name}
</Ellipsis>

<Ellipsis
showTooltip={{ position: "right" }}
rows={3}
expandable={false}
className="text-xs text-gray-500"
>
{desc || "-"}
</Ellipsis>
</div>
</div>

<div className="text-xs font-medium mt-auto text-right">
<span style={{ color: "rgb(var(--link-6))" }}>
<IconDownload className="mr-1" />
下载
</span>
</div>
</section>
);
})}
</div>
);
}

function MarkdownUrl({ url }: { url: string }) {
const [status, setStatus] = useState<"loading" | "ok" | "error">("loading");
const [content, setContent] = useState("");

useEffect(() => {
fetch(url).then(
async (res) => {
if (res.ok) {
const md = await res.text();
setContent(md);
setStatus("ok");
} else {
setStatus("error");
}
},
() => {
setStatus("error");
}
);
}, []);

if (status === "loading") {
return <Spin />;
}

if (status === "error") {
return;
}

return (
<div className="px-[20px] py-[20px] bg-slate-50 rounded-lg">
<BioMarkdown md={content} />
</div>
);
}

function BioMarkdown({ md }: { md: string }) {
const componets = useMemo(() => {
return {
a(props: AnchorHTMLAttributes<HTMLAnchorElement>) {
return (
<a
{...props}
// #开头表示自动生成的TOC跳转
target={props.href?.startsWith("#") ? undefined : "_blank"}
/>
);
},
table(props: TableHTMLAttributes<HTMLTableElement>) {
return <table {...props} className={"mdTable"} />;
},
img(props: ImgHTMLAttributes<HTMLImageElement>) {
return <img {...props} className="r-max-w-[90%] r-block r-mx-auto" />;
},
};
}, []);

return (
<Markdown
className="markdown-body"
components={componets}
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
>
{md}
</Markdown>
);
}
9 changes: 9 additions & 0 deletions src/ActivityHelp/TabQA.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function TabQA() {
return (
<>
<div className="font-medium text-lg mb-6">❓️ 账号问题</div>

<div></div>
</>
);
}
135 changes: 135 additions & 0 deletions src/ActivityHelp/TabResult.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Button, Message, Tabs, Upload } from "@arco-design/web-react";
import { UploadItem } from "@arco-design/web-react/es/Upload";
import { IconCheck } from "@arco-design/web-react/icon";
import { PutObjectCommand, S3, S3Client } from "@aws-sdk/client-s3";
import { useState } from "react";

export default function TabResult() {
const [file, setFile] = useState<UploadItem>();
const [uploading, setUploading] = useState(false);

const upload = () => {
if (!file) return;

const formData = new FormData();
formData.append("key", `${file.name}`);
formData.append("file", file.originFile!);

setUploading(true);
fetch("https://paper-challenge.tos-s3-cn-beijing.volces.com", {
method: "POST",
body: formData,
}).then(
(res) => {
if (res.ok) {
setUploading(false);
setFile(undefined);
Message.success(`压缩包提交成功: ${file.name}`);
return;
}

setUploading(false);
setFile(undefined);
Message.error("压缩包提交失败");
},
() => {
setUploading(false);
setFile(undefined);
Message.error("压缩包提交失败");
}
);
};

const upload2 = () => {
const client = new S3Client({
endpoint: "https://tos-s3-cn-beijing.volces.com",
region: "cn-beijing",
credentials: {
accessKeyId: "aaaa",
secretAccessKey: "bbbb",
},
});

client
.send(
new PutObjectCommand({
Bucket: "paper-challenge",
Key: "mm.txt",
Body: "kkk",
})
)
.then(
(res) => {
res;

Message.success("上传成功");
},
(err) => {
Message.error(`上传失败: ${err}`);
}
);
};

return (
<>
<div className="font-medium text-lg mb-6">✍🏻 结果提交</div>

<Tabs type="card-gutter">
<Tabs.TabPane key="1" title="论文挑战赛">
<Upload
className="mb-3"
autoUpload={false}
showUploadList={false}
drag
accept=".zip,.rar"
tip="只能上传 1 个压缩包,压缩包格式仅支持 zip、rar"
onChange={(_, file) => {
setFile(file);
}}
/>

<div style={{ fontSize: 13 }} className="text-gray-500 mb-10">
<div>📢 温馨提示:</div>
<div>
1. 论文挑战赛需要提交选定的论文、复现报告、导出的workspace压缩包,
<span style={{ color: "#D08D06" }} className="font-medium">
以整体压缩包形式提交
</span>
</div>
<div>
2. 压缩包名称请按照大赛提供的格式提交,如:
<span style={{ color: "#D08D06" }} className="font-medium">
参赛团队名称-workspace名称.zip
</span>
</div>
</div>

<div className="font-medium mb-4">
当前已选压缩包:
<span style={{ color: "#1664FF" }}>{file?.name || "-"}</span>
</div>

<div>
<Button
icon={<IconCheck />}
type="primary"
loading={uploading}
disabled={!file}
onClick={() => {
upload();
}}
>
{uploading ? "正在提交" : "确认提交"}
</Button>
</div>
</Tabs.TabPane>
<Tabs.TabPane key="2" title="任务挑战赛">
敬请期待
</Tabs.TabPane>
<Tabs.TabPane key="3" title="AI算法赛">
敬请期待
</Tabs.TabPane>
</Tabs>
</>
);
}
21 changes: 21 additions & 0 deletions src/ActivityHelp/TabSort.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Tabs } from "@arco-design/web-react";

export default function TabSort() {
return (
<>
<div className="font-medium text-lg mb-6">🎉 排行榜</div>

<Tabs type="card-gutter">
<Tabs.TabPane key="1" title="论文挑战赛">
敬请期待
</Tabs.TabPane>
<Tabs.TabPane key="2" title="任务挑战赛">
敬请期待
</Tabs.TabPane>
<Tabs.TabPane key="3" title="AI算法赛">
敬请期待
</Tabs.TabPane>
</Tabs>
</>
);
}
Loading

0 comments on commit 3894877

Please sign in to comment.