Skip to content

Commit 9862c23

Browse files
committed
重构布局组件,添加游戏卡片和已玩游戏列表功能,更新Steam API接口调用
1 parent 63eee4a commit 9862c23

10 files changed

Lines changed: 160 additions & 31 deletions

File tree

post/如何愉快的访问Steam api.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ V 社的官方 API 文档,文档的介绍比较详细,但 api 总量少,
1717

1818
## Steam API list
1919

20-
返回了几乎所有可用的 api 而且不需要使用 key ,任何人都可以访问,但是几乎没注释,很难看懂 [https://api.steampowered.com/ISteamWebAPIUtil/GetSupportedAPIList/v0001/](https://api.steampowered.com/ISteamWebAPIUtil/GetSupportedAPIList/v0001/)
20+
非常多 api 而且不需要使用 key ,任何人都可以访问,但是几乎没注释,很难看懂 [https://api.steampowered.com/ISteamWebAPIUtil/GetSupportedAPIList/v0001/](https://api.steampowered.com/ISteamWebAPIUtil/GetSupportedAPIList/v0001/)
2121

2222
## xpaw 大佬整理的 api 文档
2323

24-
非常全,非常详细,伟大![https://steamapi.xpaw.me/](https://steamapi.xpaw.me/)
24+
非常详细,伟大![https://steamapi.xpaw.me/](https://steamapi.xpaw.me/)
25+
26+
## steam 的语言代码
27+
28+
[https://partner.steamgames.com/doc/store/localization/languages?l=schinese](https://partner.steamgames.com/doc/store/localization/languages?l=schinese)

src/components/GameCard.astro

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
import * as steamApi from "../utils/steamApi.ts";
3+
4+
const { img, appid, playtime } = Astro.props;
5+
const playtimeHours = Math.floor(playtime / 60);
6+
7+
const appDetails = (await steamApi.appdetails(appid))?.[appid]?.data;
8+
const name = appDetails?.name|| '';
9+
---
10+
11+
<div class="card">
12+
<img src={img} alt={`${name} image`} />
13+
<div class="card-content">
14+
<h3>{name}</h3>{playtimeHours}
15+
<p>这是一个极简风格的卡片,拥有圆角、阴影和左右结构。</p>
16+
</div>
17+
</div>
18+
19+
<style>
20+
.card {
21+
display: flex;
22+
background: white;
23+
border-radius: 16px;
24+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
25+
overflow: hidden;
26+
max-width: 600px;
27+
width: 90%;
28+
}
29+
30+
.card img {
31+
width: 150px;
32+
height: 150px;
33+
object-fit: cover;
34+
}
35+
36+
.card-content {
37+
padding: 16px;
38+
display: flex;
39+
flex-direction: column;
40+
justify-content: center;
41+
}
42+
43+
.card-content h3 {
44+
margin: 0;
45+
font-size: 1.25rem;
46+
color: #333;
47+
}
48+
49+
.card-content p {
50+
margin-top: 8px;
51+
font-size: 0.95rem;
52+
color: #666;
53+
}
54+
</style>

src/components/PlayedGames.astro

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
import type { PlayedGame } from "../utils/steamApi.ts";
3+
import * as steamApi from "../utils/steamApi.ts";
4+
import { Image } from "astro:assets";
5+
import GameCard from "./GameCard.astro";
6+
7+
let playedGames: PlayedGame[] = await steamApi.playedGames();
8+
let imageUrl = steamApi.chineseImageUrl("322330");
9+
---
10+
11+
<div>
12+
<p>
13+
<!-- {JSON.stringify(steamInfo)} -->
14+
</p>
15+
<Image src={imageUrl} alt="dst game header" width="512" height="512" />
16+
17+
{
18+
playedGames.map((game) => {
19+
const { appid, playtime_forever, img_icon_url } = game;
20+
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
21+
delay(1100);
22+
return (
23+
<GameCard
24+
img={img_icon_url}
25+
playtime={playtime_forever}
26+
appid={appid}
27+
/>
28+
);
29+
})
30+
}
31+
</div>
32+
33+
<style></style>

src/layouts/BaseLayout.astro

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ const { description, keywords ,selected} = Astro.props;
2525
<header id="menu">
2626
<HeadMenu/>
2727
</header>
28-
<main>
2928
<slot />
30-
</main>
3129
<!-- <hr style="width:600px;color:#808080; margin-top: 1rem;" /> -->
3230
<footer>
3331
<!-- <Image src={notByAi} alt="not-by-ai" /> -->
@@ -101,13 +99,6 @@ const { description, keywords ,selected} = Astro.props;
10199
color: black;
102100
}
103101

104-
main {
105-
max-width: 65ch;
106-
flex-grow: 1; /* 使 main 占据剩余空间 */
107-
font-size: 1rem;
108-
line-height: 1.75;
109-
}
110-
111102
footer {
112103
margin-top: 2.1rem;
113104
border-top: 1px solid rgb(227, 232, 247); 顶部边框线

src/layouts/FriendsLayout.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
---
22
import BaseLayout from "./BaseLayout.astro";
3+
import MainLayout from "./MainLayout.astro";
34
---
45

5-
<BaseLayout>
6+
<MainLayout>
67
<div id="cards">
78
<slot>暂时还没有内容哦</slot>
89
</div>
9-
</BaseLayout>
10+
</MainLayout>
1011

1112
<style>
1213
#cards {

src/layouts/MainLayout.astro

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ import BaseLayout from "./BaseLayout.astro";
33
---
44

55
<BaseLayout>
6+
<main>
67
<slot />
8+
</main>
79
</BaseLayout>
810

911
<style>
12+
main {
13+
max-width: 65ch;
14+
flex-grow: 1; /* 使 main 占据剩余空间 */
15+
font-size: 1rem;
16+
line-height: 1.75;
17+
}
1018
</style>

src/pages/friend-links.astro

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,11 @@ import FriendsLayout from "../layouts/FriendsLayout.astro";
1313
icon="https://avatars.githubusercontent.com/u/50075277?v=4"
1414
url="https://krtl.top"
1515
/>
16+
<FriendCard
17+
name="Shikochin"
18+
description="自愚可悖的庸人。"
19+
icon="https://avatars.githubusercontent.com/u/60309542?v=4"
20+
url="https://shikoch.in/"
21+
>
22+
</FriendCard>
1623
</FriendsLayout>

src/pages/lab.astro

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
---
22
import MainLayout from "../layouts/MainLayout.astro";
3-
import { Image } from "astro:assets";
43
import tacImage from "../../public/assets/images/avatar.png";
54
import DropMenu from "../components/DropMenu.astro";
65
import Prose from "../components/Prose.astro";
6+
import { Image } from "astro:assets";
77
import { Content } from "../posts/myUtil.md";
8-
import * as steamApi from "../utils/steamApi.ts";
8+
import PlayedGames from "../components/PlayedGames.astro";
9+
import BaseLayout from "../layouts/BaseLayout.astro";
910
1011
const links = [
1112
{ url: "/blog", name: "blog" },
1213
{ url: "/time-line", name: "time line" },
1314
];
14-
15-
let steamInfo = await steamApi.playedGames();
16-
let imageUrl = await steamApi.chineseImageUrl("322330");
1715
---
1816

19-
<MainLayout description="偶尔会在这乱写" keywords="lab,实验,前端">
17+
<BaseLayout description="偶尔会在这乱写" keywords="lab,实验,前端">
18+
<main>
2019
偶尔会在这乱写
2120
<div id="tac-say">
2221
<Image src={tacImage} alt="Ling avatar" width="128" height="128" />
@@ -26,11 +25,10 @@ let imageUrl = await steamApi.chineseImageUrl("322330");
2625
<Prose>
2726
<Content />
2827
</Prose>
29-
<p>
30-
{JSON.stringify(steamInfo)}
31-
</p>
32-
<Image src={imageUrl} alt="dst game header" width="512" height="512" />
33-
</MainLayout>
28+
29+
<PlayedGames/>
30+
</main>
31+
</BaseLayout>
3432

3533
<style>
3634
.chat-bubble {
@@ -40,4 +38,11 @@ let imageUrl = await steamApi.chineseImageUrl("322330");
4038
background-color: #f9f9f9;
4139
border-radius: 10px;
4240
}
41+
42+
main{
43+
display: flex;
44+
flex-direction: column;
45+
align-items: center;
46+
width: 90rem;
47+
}
4348
</style>

src/posts/myUtil.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ title: 我的工具
55
## 我的工具
66

77
| | |
8-
| ---------- | --------------------------- | -------------------------------------------- | --- |
8+
| ---------- | --------------------------- |
99
| 代码编辑器 | Idea, VsCode, NeoVim |
1010
| 字体 | FireCode, MapleMono |
1111
| 截图 | Snipaste |
@@ -18,4 +18,5 @@ title: 我的工具
1818
| 搜索工具 | EveryThing |
1919
| 安全软件 | 360 安全卫士 |
2020
| 音乐软件 | QQ 音乐,网易云音乐,MusicFox |
21-
| <!-- | 外设 | 毒蝰标准版, G304, G403, Crush 80, 腹灵 MK870 | --> |
21+
22+
<!-- | 外设 | 毒蝰标准版, G304, G403, Crush 80, 腹灵 MK870 | -->

src/utils/steamApi.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { get } from "./utils";
22

33
// 定义表示 Steam 游戏数据的接口
4-
interface PlayedGame {
4+
export interface PlayedGame {
55
appid: number;
66
name: string;
77
playtime_2weeks: number;
@@ -13,12 +13,18 @@ interface PlayedGame {
1313
playtime_deck_forever: number;
1414
}
1515

16-
const BASE_URL = "http://api.steampowered.com";
1716
const { STEAM_API_KEY, STEAM_ID } = import.meta.env;
17+
if (!STEAM_API_KEY) throw Error("STEAM_API_KEY not configured!");
18+
if (!STEAM_ID) throw Error("STEAM_ID not configured!");
1819

20+
const API_URL = "https://api.steampowered.com";
21+
const WEB_URL = "https://store.steampowered.com";
22+
const CDN_URL = "https://shared.fastly.steamstatic.com";
23+
24+
//获取我玩过的游戏列表
1925
export const playedGames = async (): Promise<PlayedGame[]> => {
2026
const path = "/IPlayerService/GetOwnedGames/v0001/";
21-
const res = await get(`${BASE_URL}${path}`, {
27+
const res = await get(`${API_URL}${path}`, {
2228
key: STEAM_API_KEY,
2329
steamid: STEAM_ID,
2430
include_played_free_games: "true", // 包括免费游戏
@@ -33,11 +39,30 @@ const sortPlayedGame = (games: PlayedGame[]): PlayedGame[] => {
3339
);
3440
};
3541

36-
export const chineseImageUrl = (appid: string) => {
37-
return `https://shared.fastly.steamstatic.com/store_item_assets/steam/apps/${appid}/header_schinese.jpg`;
42+
//获取指定应用详情
43+
export const appdetails = async (appid: string) => {
44+
const path = "/api/appdetails";
45+
const res = await get(`${WEB_URL}${path}`, {
46+
appids: appid,
47+
l: "schinese",
48+
cc: "CN",
49+
});
50+
return await res?.json();
3851
};
3952

53+
//获取指定应用中文封面url
54+
export const chineseImageUrl = (appid: string) =>
55+
`${CDN_URL}/store_item_assets/steam/apps/${appid}/header_schinese.jpg`;
56+
57+
//获取指定应用中文封面
4058
export const chineseImage = async (appid: string) => {
4159
const res = await get(chineseImageUrl(appid));
4260
return res?.blob();
4361
};
62+
export const getGlobalAchievement = async (appid: string) => {
63+
const path = "ISteamUserStats/GetGlobalAchievementPercentagesForApp/v0002/";
64+
const res = await get(`${API_URL}${path}`, {
65+
gameid: appid,
66+
});
67+
return await res?.json();
68+
};

0 commit comments

Comments
 (0)