整合小红书页面:内联扫码登录、用户主页、移除独立登录和内容浏览页
- 新增 XiaohongshuPage:顶部搜索栏、登录用户头像/ID、退出按钮 - 未登录时内联显示二维码,无需跳转独立登录页 - 点击笔记作者可打开用户主页 slide-over(复用 UserCard) - 修复用户主页关注/粉丝/获赞数为零:选择器从 .data-area .data-item 改为 .user-interactions > div - 修复用户头像选择器:img.user-image(img 本身带该 class) - backend LoginStatus 新增 avatar/userId 字段,登录状态接口返回头像和用户 ID - 删除 LoginPage、BrowserPage,侧边栏精简为小红书单入口
This commit is contained in:
@@ -49,9 +49,23 @@ export async function checkLoginStatus(page: Page): Promise<LoginStatus> {
|
||||
// Attempt to extract a username from the indicator area.
|
||||
const username = await indicator.textContent().catch(() => null);
|
||||
|
||||
// Attempt to extract the logged-in user's avatar URL.
|
||||
const avatar = await page
|
||||
.$eval(XHS_SELECTORS.login.userAvatar, (el) => el.getAttribute('src') ?? '')
|
||||
.catch(() => '');
|
||||
|
||||
// Attempt to extract the userId from the profile link href.
|
||||
const userLinkHref = await page
|
||||
.$eval(XHS_SELECTORS.login.userLink, (el) => el.getAttribute('href') ?? '')
|
||||
.catch(() => '');
|
||||
const userIdMatch = userLinkHref.match(/\/user\/profile\/([a-f0-9]+)/);
|
||||
const userId = userIdMatch?.[1] ?? '';
|
||||
|
||||
return {
|
||||
loggedIn: true,
|
||||
...(username ? { username: username.trim() } : {}),
|
||||
...(avatar ? { avatar } : {}),
|
||||
...(userId ? { userId } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ export const XHS_SELECTORS = {
|
||||
loggedInIndicator: '.user .link-wrapper .channel',
|
||||
/** The "login" button that opens the QR code modal (if not already shown). */
|
||||
loginButton: '.login-btn',
|
||||
/** Logged-in user's avatar image in the sidebar. */
|
||||
userAvatar: '.user .avatar img',
|
||||
/** Logged-in user's profile link in the sidebar (href contains userId). */
|
||||
userLink: '.user .link-wrapper a',
|
||||
},
|
||||
|
||||
feed: {
|
||||
@@ -108,8 +112,8 @@ export const XHS_SELECTORS = {
|
||||
headerContainer: '.user-info',
|
||||
/** User nickname. */
|
||||
nickname: '.user-info .user-name',
|
||||
/** User avatar image. */
|
||||
avatar: '.user-info .user-image img',
|
||||
/** User avatar image (the img itself carries class user-image). */
|
||||
avatar: '.user-info img.user-image',
|
||||
/** User bio / description text. */
|
||||
description: '.user-info .user-desc',
|
||||
/** User gender icon or text. */
|
||||
@@ -117,7 +121,7 @@ export const XHS_SELECTORS = {
|
||||
/** IP location. */
|
||||
ipLocation: '.user-info .user-ip',
|
||||
/** Follower / following / interaction count elements. */
|
||||
followCount: '.user-info .data-area .data-item',
|
||||
followCount: '.user-info .user-interactions > div',
|
||||
/** Note count (displayed somewhere on the profile page). */
|
||||
noteCountTab: '.reds-tab-item',
|
||||
/** Individual feed items on the user profile. */
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
export interface LoginStatus {
|
||||
loggedIn: boolean;
|
||||
username?: string;
|
||||
avatar?: string;
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
export interface QRCodeResult {
|
||||
|
||||
Reference in New Issue
Block a user