feat(category): 接单平台支持二级分类目录与接单大厅联动展示及限额优化
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
ClockCircleOutlined,
|
||||
PushpinOutlined,
|
||||
QuestionCircleOutlined,
|
||||
@@ -63,7 +64,9 @@ export default function WorkerHallPage() {
|
||||
const queryClient = useQueryClient()
|
||||
const [keywordInput, setKeywordInput] = useState('')
|
||||
const [keyword, setKeyword] = useState('')
|
||||
const [categoryId, setCategoryId] = useState(0)
|
||||
const [primaryCategoryId, setPrimaryCategoryId] = useState(0)
|
||||
const [subCategoryId, setSubCategoryId] = useState(0)
|
||||
const effectiveCategoryId = subCategoryId || primaryCategoryId || 0
|
||||
const [grabbingId, setGrabbingId] = useState(0)
|
||||
const [sharingOrder, setSharingOrder] = useState<WorkOrder | null>(null)
|
||||
const [leaderboardOpen, setLeaderboardOpen] = useState(false)
|
||||
@@ -74,14 +77,14 @@ export default function WorkerHallPage() {
|
||||
const loadMoreRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const ordersQuery = useInfiniteQuery({
|
||||
queryKey: ['worker-hall-orders', keyword, categoryId],
|
||||
queryKey: ['worker-hall-orders', keyword, effectiveCategoryId],
|
||||
initialPageParam: 1,
|
||||
queryFn: ({ pageParam }) =>
|
||||
fetchWorkerHallOrders({
|
||||
keyword,
|
||||
page: Number(pageParam),
|
||||
pageSize: HALL_PAGE_SIZE,
|
||||
categoryId: categoryId || undefined,
|
||||
categoryId: effectiveCategoryId || undefined,
|
||||
}),
|
||||
getNextPageParam: (lastPage) => {
|
||||
const pagination = lastPage.data.pagination
|
||||
@@ -127,7 +130,28 @@ export default function WorkerHallPage() {
|
||||
|
||||
const orders = ordersQuery.data?.pages.flatMap((page) => page.data.items) || []
|
||||
const firstPage = ordersQuery.data?.pages[0]?.data
|
||||
const categories = firstPage?.categories || []
|
||||
const allCategories = firstPage?.categories || []
|
||||
const showSubcategoriesConfig = firstPage?.showSubcategories ?? true
|
||||
|
||||
const primaryCategories = allCategories.filter((c) => !c.parentId)
|
||||
const subCategoriesMap = new Map<number, typeof allCategories>()
|
||||
for (const c of allCategories) {
|
||||
if (c.parentId) {
|
||||
const list = subCategoriesMap.get(c.parentId) || []
|
||||
list.push(c)
|
||||
subCategoriesMap.set(c.parentId, list)
|
||||
}
|
||||
}
|
||||
|
||||
const currentSubCategories = primaryCategoryId
|
||||
? subCategoriesMap.get(primaryCategoryId) || []
|
||||
: []
|
||||
const shouldShowSubcategories = showSubcategoriesConfig && currentSubCategories.length > 0
|
||||
|
||||
function handleSelectPrimaryCategory(nextId: number) {
|
||||
setPrimaryCategoryId(nextId)
|
||||
setSubCategoryId(0)
|
||||
}
|
||||
const worker = profileQuery.data?.data.worker
|
||||
const activeCount = Number(profileQuery.data?.data.summary.activeOrderCount || 0)
|
||||
const pendingAcceptanceCount = hallSummaryQuery.data?.pendingAcceptanceCount || 0
|
||||
@@ -331,28 +355,69 @@ export default function WorkerHallPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 移动端横向滑动分类条 */}
|
||||
{categories.length > 0 ? (
|
||||
<div className="worker-hall-mobile-category-bar">
|
||||
{/* 移动端一级分类/游戏卡片横向滑动条 */}
|
||||
{primaryCategories.length > 0 ? (
|
||||
<div className="worker-hall-game-cards-scroll">
|
||||
<button
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${categoryId === 0 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
setCategoryId(0)
|
||||
}}
|
||||
className={`worker-hall-game-card ${primaryCategoryId === 0 ? 'active' : ''}`}
|
||||
onClick={() => handleSelectPrimaryCategory(0)}
|
||||
>
|
||||
全部
|
||||
<div className="worker-hall-game-icon-box">
|
||||
<AppstoreOutlined
|
||||
style={{
|
||||
fontSize: 20,
|
||||
color: primaryCategoryId === 0 ? 'var(--theme-primary)' : '#64748b',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="worker-hall-game-title">全部</span>
|
||||
</button>
|
||||
{categories.map((category) => (
|
||||
{primaryCategories.map((category) => (
|
||||
<button
|
||||
key={category.categoryId}
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${categoryId === category.categoryId ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
setCategoryId(category.categoryId)
|
||||
}}
|
||||
className={`worker-hall-game-card ${primaryCategoryId === category.categoryId ? 'active' : ''}`}
|
||||
onClick={() => handleSelectPrimaryCategory(category.categoryId)}
|
||||
>
|
||||
{category.name}
|
||||
<div className="worker-hall-game-icon-box">
|
||||
{category.iconUrl ? (
|
||||
<img
|
||||
src={category.iconUrl}
|
||||
alt={category.name}
|
||||
className="worker-hall-game-img"
|
||||
/>
|
||||
) : (
|
||||
<span className="worker-hall-game-initial">{category.name.slice(0, 1)}</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="worker-hall-game-title" title={category.name}>
|
||||
{category.name}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* 移动端二级分类联动条 */}
|
||||
{shouldShowSubcategories ? (
|
||||
<div className="worker-hall-subcat-bar">
|
||||
<span className="worker-hall-subcat-label">业务类型:</span>
|
||||
<button
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${subCategoryId === 0 ? 'active' : ''}`}
|
||||
onClick={() => setSubCategoryId(0)}
|
||||
>
|
||||
全部
|
||||
</button>
|
||||
{currentSubCategories.map((sub) => (
|
||||
<button
|
||||
key={sub.categoryId}
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${subCategoryId === sub.categoryId ? 'active' : ''}`}
|
||||
onClick={() => setSubCategoryId(sub.categoryId)}
|
||||
>
|
||||
{sub.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@@ -442,7 +507,9 @@ export default function WorkerHallPage() {
|
||||
) : null}
|
||||
{order.categoryName ? (
|
||||
<Tag color="blue" className="worker-hall-mobile-tag">
|
||||
{order.categoryName}
|
||||
{order.parentCategoryName
|
||||
? `${order.parentCategoryName} · ${order.categoryName}`
|
||||
: order.categoryName}
|
||||
</Tag>
|
||||
) : null}
|
||||
{order.sharing?.enabled ? (
|
||||
@@ -608,21 +675,75 @@ export default function WorkerHallPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{categories.length > 0 ? (
|
||||
<Tabs
|
||||
size="small"
|
||||
activeKey={String(categoryId)}
|
||||
items={[
|
||||
{ key: '0', label: '全部' },
|
||||
...categories.map((category) => ({
|
||||
key: String(category.categoryId),
|
||||
label: category.name,
|
||||
})),
|
||||
]}
|
||||
onChange={(nextKey) => {
|
||||
setCategoryId(Number(nextKey) || 0)
|
||||
}}
|
||||
/>
|
||||
{/* 桌面端一级分类卡片与二级联动 */}
|
||||
{primaryCategories.length > 0 ? (
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<div className="worker-hall-game-cards-scroll">
|
||||
<button
|
||||
type="button"
|
||||
className={`worker-hall-game-card ${primaryCategoryId === 0 ? 'active' : ''}`}
|
||||
onClick={() => handleSelectPrimaryCategory(0)}
|
||||
>
|
||||
<div className="worker-hall-game-icon-box">
|
||||
<AppstoreOutlined
|
||||
style={{
|
||||
fontSize: 20,
|
||||
color: primaryCategoryId === 0 ? 'var(--theme-primary)' : '#64748b',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="worker-hall-game-title">全部</span>
|
||||
</button>
|
||||
{primaryCategories.map((category) => (
|
||||
<button
|
||||
key={category.categoryId}
|
||||
type="button"
|
||||
className={`worker-hall-game-card ${primaryCategoryId === category.categoryId ? 'active' : ''}`}
|
||||
onClick={() => handleSelectPrimaryCategory(category.categoryId)}
|
||||
>
|
||||
<div className="worker-hall-game-icon-box">
|
||||
{category.iconUrl ? (
|
||||
<img
|
||||
src={category.iconUrl}
|
||||
alt={category.name}
|
||||
className="worker-hall-game-img"
|
||||
/>
|
||||
) : (
|
||||
<span className="worker-hall-game-initial">
|
||||
{category.name.slice(0, 1)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="worker-hall-game-title" title={category.name}>
|
||||
{category.name}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{shouldShowSubcategories ? (
|
||||
<div className="worker-hall-subcat-bar" style={{ marginTop: 8 }}>
|
||||
<span className="worker-hall-subcat-label">业务类型:</span>
|
||||
<button
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${subCategoryId === 0 ? 'active' : ''}`}
|
||||
onClick={() => setSubCategoryId(0)}
|
||||
>
|
||||
全部
|
||||
</button>
|
||||
{currentSubCategories.map((sub) => (
|
||||
<button
|
||||
key={sub.categoryId}
|
||||
type="button"
|
||||
className={`worker-hall-mobile-cat-pill ${subCategoryId === sub.categoryId ? 'active' : ''}`}
|
||||
onClick={() => setSubCategoryId(sub.categoryId)}
|
||||
>
|
||||
{sub.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{shouldWarn ? (
|
||||
@@ -682,7 +803,9 @@ export default function WorkerHallPage() {
|
||||
{productName}
|
||||
</strong>
|
||||
<Typography.Text type="secondary">
|
||||
{order.categoryName || '默认分类'}
|
||||
{order.parentCategoryName
|
||||
? `${order.parentCategoryName} · ${order.categoryName}`
|
||||
: order.categoryName || '默认分类'}
|
||||
</Typography.Text>
|
||||
<Typography.Text type="secondary">
|
||||
订单号:{getDisplayOrderNo(order)}
|
||||
|
||||
Reference in New Issue
Block a user