Skip to content

Commit

Permalink
上一页下一页
Browse files Browse the repository at this point in the history
  • Loading branch information
SleckGen committed Feb 11, 2025
1 parent ce7e2b0 commit ce7d2ba
Showing 1 changed file with 144 additions and 47 deletions.
191 changes: 144 additions & 47 deletions src/pages/LotteryPage/LotteryContentWithDirHandle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@ import { Content } from "antd/es/layout/layout";
import LotteryTree from "./LotteryTree";
import Sider from "antd/es/layout/Sider";
import { useLotteryData } from "./UseLotteryData"; // 引入自定义 hook
import { CloudDownloadOutlined, LoadingOutlined, ReloadOutlined, SaveOutlined } from "@ant-design/icons";
import {
CloudDownloadOutlined,
LoadingOutlined,
ReloadOutlined,
SaveOutlined
} from "@ant-design/icons";
import { WorkshopPageContext } from "../WorkshopPage/WorkshopPageContext";
import { NOTION_DATABASE_LOTTERY,WORKSHOP_TYPES } from "../../services/lottery/lotteryNotionQueries";
import { NOTION_DATABASE_LOTTERY, WORKSHOP_TYPES } from "../../services/lottery/lotteryNotionQueries";

const { Text } = Typography;
const COMMODITY_PATH = 'CodeFunCore/src/main/resources/net/easecation/codefuncore/lottery/notion/';
const COMMODITY_PATH = "CodeFunCore/src/main/resources/net/easecation/codefuncore/lottery/notion/";
const PAGE_SIZE = 15; // 每页显示多少个 WORKSHOP_TYPES

const LotteryContentWithDirHandle: React.FC = () => {
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();

const { dirHandle, ensurePermission, messageApi, readFile, writeFile } = useContext(WorkshopPageContext);
const { dirHandle, ensurePermission, messageApi, readFile, writeFile } =
useContext(WorkshopPageContext);

const [currentType, setCurrentType] = useState<string>(WORKSHOP_TYPES[0]);
const [localJson, setLocalJson] = useState<{ [key: string]: any } | null>(null);
Expand All @@ -27,10 +34,18 @@ const LotteryContentWithDirHandle: React.FC = () => {
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
const [saving, setSaving] = useState(false);

// 分页相关状态
const [currentPage, setCurrentPage] = useState<number>(0);
const totalPages = Math.ceil(WORKSHOP_TYPES.length / PAGE_SIZE);

// 获取 Lottery 数据
const { loading: remoteJsonLoading, fileArray: remoteJsonMapData, refetch } = useLotteryData(NOTION_DATABASE_LOTTERY);
const {
loading: remoteJsonLoading,
fileArray: remoteJsonMapData,
refetch,
} = useLotteryData(NOTION_DATABASE_LOTTERY);

// 切换tab时的状态重置
// 切换 tab 时的状态重置
useEffect(() => {
setLoadingLocalJson(false);
setLocalJson(null);
Expand Down Expand Up @@ -64,47 +79,48 @@ const LotteryContentWithDirHandle: React.FC = () => {
}
}, [dirHandle, currentType, ensurePermission, messageApi]);

// 处理加载远程 Notion 数据
const handleLoadRemoteJson = async (type: string, flush:boolean) => {
// Notion 拉取数据
const handleLoadRemoteJson = async (type: string, flush: boolean) => {
setRemoteJsonLoadingList((prev) => [...prev, type]);
messageApi.open({ key: "processing", type: "loading", content: `正在从 Notion 加载 ${type} ...`, duration: 0 });
messageApi.open({
key: "processing",
type: "loading",
content: `正在从 Notion 加载 ${type} ...`,
duration: 0,
});

// 重新获取 Notion 数据
if(flush) {
if (flush) {
await refetch();
}

setRemoteJsonMap((prev) => ({ ...prev, [type]: remoteJsonMapData[currentType] }));

setRemoteJsonMap((prev) => ({ ...prev, [type]: remoteJsonMapData[type] }));
messageApi.destroy("processing");
setRemoteJsonLoadingList((prev) => prev.filter((item) => item !== type));
messageApi.success(`${type} 处理完成`);
};

const menuItems = WORKSHOP_TYPES.map((value) => ({
key: value,
label: value,
}));


// 在 remoteJsonMapData 加载完毕后,主动更新页面并调用 handleLoadRemoteJson
useEffect(() => {
if (remoteJsonMapData && Object.keys(remoteJsonMapData).length > 0) {
// 获取到数据后,主动调用 handleLoadRemoteJson 来更新页面
handleLoadRemoteJson(currentType,false);
}
}, [remoteJsonMapData, currentType]);
// 在 remoteJsonMapData 加载完毕后,主动更新页面并调用 handleLoadRemoteJson
useEffect(() => {
if (remoteJsonMapData && Object.keys(remoteJsonMapData).length > 0) {
handleLoadRemoteJson(currentType, false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [remoteJsonMapData, currentType]);

// 同步到本地
const handleSyncRemoteJson = async () => {
if (!dirHandle) {
messageApi.error("请选择你的代码中的 commodity 文件夹");
}
if (localJson && remoteJsonMap[currentType]) {
setSaving(true);
const remoteJson = remoteJsonMap[currentType];

try {
await writeFile(`${COMMODITY_PATH}${currentType}.json`, JSON.stringify(remoteJson, null, 4));
await writeFile(
`${COMMODITY_PATH}${currentType}.json`,
JSON.stringify(remoteJson, null, 4)
);
setLocalJson(remoteJson); // 刷新本地 JSON
} catch (error: any) {
messageApi.error("保存文件出错: " + error?.message);
Expand All @@ -116,28 +132,90 @@ useEffect(() => {
}
};

/**
* 获取当前分页下的 WorkshopType 列表
*/
const startIndex = currentPage * PAGE_SIZE;
const endIndex = startIndex + PAGE_SIZE;
const currentPageTypes = WORKSHOP_TYPES.slice(startIndex, endIndex);

/**
* 构造 Menu 的 items
* 这里在顶部和底部各添加两个按钮:“上一页”和“下一页”
*/
const menuItems = [
{
key: "prev-top",
label: "上一页",
disabled: currentPage === 0,
},
...currentPageTypes.map((value) => ({
key: value,
label: value,
})),
{
key: "next-bottom",
label: "下一页",
disabled: currentPage === totalPages - 1 || totalPages <= 1,
},
];

/**
* 点击菜单时的处理
*/
const handleMenuClick = (e: any) => {
if (e.key === "prev-top" || e.key === "prev-bottom") {
setCurrentPage((page) => Math.max(0, page - 1));
return;
}
if (e.key === "next-top" || e.key === "next-bottom") {
setCurrentPage((page) => Math.min(totalPages - 1, page + 1));
return;
}
// 普通菜单项
setCurrentType(e.key);
};

return (
<Layout style={{ padding: "16px 0", background: colorBgContainer, borderRadius: borderRadiusLG }}>
<Layout
style={{
padding: "15px 0",
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
<Sider style={{ background: colorBgContainer }} width={200}>
<Menu
mode="inline"
items={menuItems}
selectedKeys={[currentType]}
onClick={(e) => setCurrentType(e.key)}
style={{ border: 'none' }}
onClick={handleMenuClick}
style={{ border: "none" }}
/>
</Sider>
<Content style={{ padding: "0 24px", minHeight: 280 }}>
<Flex gap={16}>
<Card
style={{ flex: 2, minHeight: "80vh" }}
title={<Space>本地<Button type={'text'} icon={<ReloadOutlined />} onClick={() => loadLocalFile()} disabled={loadingLocalJson} /></Space>}
title={
<Space>
本地
<Button
type={"text"}
icon={<ReloadOutlined />}
onClick={() => loadLocalFile()}
disabled={loadingLocalJson}
/>
</Space>
}
loading={loadingLocalJson}
>
{localFileExists && localJson ? (
<LotteryTree checkable={false} fullJson={localJson} />
) : (
<Text type="warning">{`${currentType}.json 未找到或无法读取`}</Text>
<Text type="warning">
{`${currentType}.json 未找到或无法读取`}
</Text>
)}
</Card>

Expand All @@ -148,40 +226,59 @@ useEffect(() => {
<span>
Notion
{remoteJsonLoadingList.includes(currentType) && (
<span style={{ color: "#faad14", marginLeft: 8, fontSize: 12 }}>
<span
style={{
color: "#faad14",
marginLeft: 8,
fontSize: 12,
}}
>
(正在拉取数据中,请耐心等待...)
</span>
)}
</span>

<Button
type="text"
icon={remoteJsonLoadingList.includes(currentType) ? <LoadingOutlined style={{fontSize: 16}}/> :
<ReloadOutlined style={{fontSize: 14, opacity: 0.65}}/>}
onClick={() => handleLoadRemoteJson(currentType,true)}
icon={
remoteJsonLoadingList.includes(currentType) ? (
<LoadingOutlined style={{ fontSize: 16 }} />
) : (
<ReloadOutlined style={{ fontSize: 14, opacity: 0.65 }} />
)
}
onClick={() => handleLoadRemoteJson(currentType, true)}
disabled={remoteJsonLoadingList.includes(currentType)}
/>
</Space>
}
loading={remoteJsonLoadingList.includes(currentType)}
extra={
remoteJsonMap[currentType] && (
<Button
icon={<SaveOutlined />}
type="primary"
loading={saving}
onClick={handleSyncRemoteJson}
>
<Button icon={<SaveOutlined />} type="primary" loading={saving} onClick={handleSyncRemoteJson}>
同步到本地
</Button>
)
}
>
{remoteJsonMap[currentType] ? (
<LotteryTree checkable={false} fullJson={remoteJsonMap[currentType]} checkedKeys={checkedKeys} setCheckedKeys={setCheckedKeys} />
<LotteryTree
checkable={false}
fullJson={remoteJsonMap[currentType]}
checkedKeys={checkedKeys}
setCheckedKeys={setCheckedKeys}
/>
) : (
<Flex style={{ padding: "32px 0", justifyContent: "center", alignItems: "center" }}>
<Button icon={<CloudDownloadOutlined />} onClick={() => handleLoadRemoteJson(currentType,true)}>
<Flex
style={{
padding: "32px 0",
justifyContent: "center",
alignItems: "center",
}}
>
<Button
icon={<CloudDownloadOutlined />}
onClick={() => handleLoadRemoteJson(currentType, true)}
>
从 Notion 加载
</Button>
</Flex>
Expand All @@ -193,4 +290,4 @@ useEffect(() => {
);
};

export default LotteryContentWithDirHandle;
export default LotteryContentWithDirHandle;

0 comments on commit ce7d2ba

Please sign in to comment.