From 5a483f781e76b805568a684df7c0b6ef44dbf5f5 Mon Sep 17 00:00:00 2001 From: Fox_block Date: Fri, 20 Mar 2026 21:28:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A6=96=E9=A1=B5=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E7=BB=84=E7=9A=84=E5=93=8D=E5=BA=94=E5=BC=8F=E5=B8=83?= =?UTF-8?q?=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 启用 Space 组件的 wrap 属性,允许按钮在空间不足时自动换行 - 使用 useResponsive hook 检测屏幕尺寸 - 根据屏幕尺寸动态调整搜索框、下拉框和按钮的宽度 - 在移动端和平板设备上使用更紧凑的布局 - 添加 flexShrink 属性防止按钮被过度压缩 --- src/components/Home.tsx | 260 ++++++++++++++++++++++++++-------------- 1 file changed, 171 insertions(+), 89 deletions(-) diff --git a/src/components/Home.tsx b/src/components/Home.tsx index 9d67cd0..42decd2 100644 --- a/src/components/Home.tsx +++ b/src/components/Home.tsx @@ -1,9 +1,22 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from "react" -import { Card, Space, Button, Tag, Input, Select, Modal, Drawer, message, InputNumber, Divider } from "antd" +import { + Card, + Space, + Button, + Tag, + Input, + Select, + Modal, + Drawer, + message, + InputNumber, + Divider, +} from "antd" import { SearchOutlined, DeleteOutlined, UndoOutlined } from "@ant-design/icons" import { useTranslation } from "react-i18next" import { match, pinyin } from "pinyin-pro" import { getAvatarFromExtraJson } from "../utils/studentAvatar" +import { useResponsive } from "../hooks/useResponsive" interface student { id: number @@ -81,6 +94,9 @@ interface HomeProps { export const Home: React.FC = ({ canEdit, isPortraitMode = false }) => { const { t } = useTranslation() + const breakpoint = useResponsive() + const isMobile = breakpoint === "xs" || breakpoint === "sm" + const isTablet = breakpoint === "md" const [students, setStudents] = useState([]) const [reasons, setReasons] = useState([]) const [rewards, setRewards] = useState([]) @@ -184,7 +200,8 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = if (!(window as any).api) return const res = await (window as any).api.queryEvents({ limit: 1 }) if (res.success) { - const latest = Array.isArray(res.data) && res.data.length > 0 ? (res.data[0] as scoreEvent) : null + const latest = + Array.isArray(res.data) && res.data.length > 0 ? (res.data[0] as scoreEvent) : null setLatestEvent(latest) logHome("fetchLatestEvent:response", { hasLatest: Boolean(latest), @@ -243,7 +260,10 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = api .onSettingChanged((change: any) => { - if (change?.key === "search_keyboard_layout" && (change?.value === "t9" || change?.value === "qwerty26")) { + if ( + change?.key === "search_keyboard_layout" && + (change?.value === "t9" || change?.value === "qwerty26") + ) { setSearchKeyboardLayout(change.value) } if (change?.key === "disable_search_keyboard") { @@ -278,7 +298,9 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = setShowPinyinKeyboard(false) } - const quickCard = (target as HTMLElement | null)?.closest?.('[data-student-quick-card="true"]') + const quickCard = (target as HTMLElement | null)?.closest?.( + '[data-student-quick-card="true"]' + ) if (!quickCard) { setQuickActionStudentId(null) } @@ -413,7 +435,8 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = }) case "score": return filtered.sort( - (a, b) => getDisplayPoints(b) - getDisplayPoints(a) || a.name.localeCompare(b.name, "zh-CN") + (a, b) => + getDisplayPoints(b) - getDisplayPoints(a) || a.name.localeCompare(b.name, "zh-CN") ) default: return filtered @@ -630,7 +653,10 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = fetchData(true) fetchLatestEvent() emitDataUpdated("events") - logHome("performSubmit:afterSuccessRefreshDispatched", { studentCount: targetStudents.length, delta }) + logHome("performSubmit:afterSuccessRefreshDispatched", { + studentCount: targetStudents.length, + delta, + }) } else { messageApi.warning( t("home.batchPartial", { success: successCount, total: targetStudents.length }) @@ -848,7 +874,9 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = {rankBadge} )} -
+
{student.avatarUrl ? ( = ({ canEdit, isPortraitMode = false }) = pointerEvents: isQuickActionMode ? "auto" : "none", }} > - - + +
= ({ canEdit, isPortraitMode = false }) = } style={{ fontWeight: "bold" }} > - {getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)} + {getDisplayPoints(student) > 0 + ? `+${getDisplayPoints(student)}` + : getDisplayPoints(student)}
@@ -1037,8 +1067,7 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = position: "relative", padding: "8px 10px", borderBottom: isLast ? "none" : "1px solid var(--ss-border-color)", - background: - isQuickActionMode || isSelected ? "rgba(22, 119, 255, 0.06)" : "transparent", + background: isQuickActionMode || isSelected ? "rgba(22, 119, 255, 0.06)" : "transparent", transition: "background-color 160ms ease", }} > @@ -1102,7 +1131,12 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = e.stopPropagation() handleQuickAdjust(student, 1) }} - style={{ minWidth: "44px", height: "26px", borderRadius: "13px", paddingInline: "8px" }} + style={{ + minWidth: "44px", + height: "26px", + borderRadius: "13px", + paddingInline: "8px", + }} > +1 @@ -1113,7 +1147,12 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = e.stopPropagation() handleQuickAdjust(student, -1) }} - style={{ minWidth: "44px", height: "26px", borderRadius: "13px", paddingInline: "8px" }} + style={{ + minWidth: "44px", + height: "26px", + borderRadius: "13px", + paddingInline: "8px", + }} > -1 @@ -1127,11 +1166,17 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = )} 0 ? "success" : getDisplayPoints(student) < 0 ? "error" : "default" + getDisplayPoints(student) > 0 + ? "success" + : getDisplayPoints(student) < 0 + ? "error" + : "default" } style={{ fontWeight: "bold", marginInlineEnd: 0 }} > - {getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)} + {getDisplayPoints(student) > 0 + ? `+${getDisplayPoints(student)}` + : getDisplayPoints(student)} )} @@ -1283,7 +1328,12 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = e.stopPropagation() handleQuickAdjust(student, 1) }} - style={{ minWidth: "44px", height: "28px", borderRadius: "14px", paddingInline: "8px" }} + style={{ + minWidth: "44px", + height: "28px", + borderRadius: "14px", + paddingInline: "8px", + }} > +1 @@ -1294,7 +1344,12 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = e.stopPropagation() handleQuickAdjust(student, -1) }} - style={{ minWidth: "44px", height: "28px", borderRadius: "14px", paddingInline: "8px" }} + style={{ + minWidth: "44px", + height: "28px", + borderRadius: "14px", + paddingInline: "8px", + }} > -1 @@ -1333,7 +1388,9 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = } style={{ fontWeight: "bold", marginInlineEnd: 0 }} > - {getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)} + {getDisplayPoints(student) > 0 + ? `+${getDisplayPoints(student)}` + : getDisplayPoints(student)} {isSelected && ( @@ -2051,35 +2108,31 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = }) }, []) - const batchToolbar = rewardMode - ? null - : !batchMode - ? ( - - ) - : ( - - - - - - - ) + const batchToolbar = rewardMode ? null : !batchMode ? ( + + ) : ( + + + + + + + ) return (
= ({ canEdit, isPortraitMode = false }) = = ({ canEdit, isPortraitMode = false }) = ref={searchAreaRef} style={{ position: "relative", - width: isPortraitMode ? "100%" : "220px", - minWidth: isPortraitMode ? "100%" : undefined, + width: isMobile ? "100%" : isTablet ? "180px" : "220px", + minWidth: isMobile ? "100%" : isTablet ? "150px" : "180px", + flexShrink: isMobile ? 0 : 1, }} > = ({ canEdit, isPortraitMode = false }) = : t9KeyRows.map((row, rowIndex) => (
{row.map((keyItem) => ( - {batchToolbar} @@ -2307,7 +2383,9 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = {t("rewardExchange.currentRewardPoints", { points: rewardStudent.reward_points })}
{affordableRewards.length === 0 ? ( -
{t("rewardExchange.noAffordableRewards")}
+
+ {t("rewardExchange.noAffordableRewards")} +
) : (
{affordableRewards.map((reward) => ( @@ -2328,7 +2406,11 @@ export const Home: React.FC = ({ canEdit, isPortraitMode = false }) = {t("rewardExchange.costLabel", { points: reward.cost_points })}
-