补充个人中心页面api & 首页弹唱查看活动 & 联系客服

This commit is contained in:
Eamon
2026-09-08 16:19:40 +08:00
parent f59e929843
commit 7f03dbfb56
45 changed files with 2146 additions and 1359 deletions

View File

@@ -1,28 +1,17 @@
import type { ColumnDef } from "@tanstack/react-table"
import { SearchIcon } from "lucide-react"
import { fetchMyRefundOrders } from "@/api/order"
import AccountCell from "@/components/composites/accountCell"
import OrderFilterBar from "@/components/composites/orderFilterBar"
import DataTable from "@/components/data-table"
import Page from "@/components/page"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { useOrderFilters } from "@/lib/hooks/useOrderFilters"
import { MY_ORDER_PAGE_SIZE, useMyOrderPage } from "@/lib/hooks/useMyOrderPage"
import { useProducts } from "@/lib/hooks/useProducts"
import {
formatDate,
formatMoney,
type OrderItem,
PACKAGE_OPTIONS,
totalConnections,
} from "@/lib/models/order"
import { MOCK_ORDERS, MOCK_PRODUCTS } from "../mock/orders"
// 后端订单接口就绪后,将 MOCK_ORDERS 替换为 fetchRefundOrders 返回的分页数据
const columns: ColumnDef<OrderItem>[] = [
{
@@ -53,9 +42,9 @@ const columns: ColumnDef<OrderItem>[] = [
cell: ({ row }) => totalConnections(row.original),
},
{
accessorKey: "DayPrice",
accessorKey: "DayCount",
header: "退款时长",
cell: ({ row }) => formatMoney(row.original.DayPrice),
cell: ({ row }) => `${row.original.DayCount}天`,
},
{
accessorKey: "DayPrice",
@@ -68,112 +57,38 @@ const columns: ColumnDef<OrderItem>[] = [
cell: ({ row }) => formatMoney(row.original.PaymentAmount),
},
{
accessorKey: "CouponAmount",
accessorKey: "RefundAmount",
header: "退款金额",
cell: ({ row }) => formatMoney(row.original.CouponAmount),
cell: ({ row }) => formatMoney(row.original.RefundAmount),
},
]
export default function RefundOrdersPage() {
const {
filters,
patch,
handleSearch,
page,
setPage,
pageSize,
handleSizeChange,
filtered,
paged,
} = useOrderFilters(MOCK_ORDERS)
const products = useProducts()
const { filters, patch, load, total, status, page, setPage, paged } =
useMyOrderPage(fetchMyRefundOrders)
return (
<Page>
<div className="bg-white rounded-lg p-4 flex flex-wrap items-end gap-x-4 gap-y-3">
<div className="flex items-center gap-2">
<span className="text-sm text-gray-500 whitespace-nowrap">
日期筛选:
</span>
<Input
type="date"
value={filters.bTime}
onChange={e => patch({ bTime: e.target.value })}
className="w-36"
aria-label="开始时间"
/>
<span className="text-sm text-gray-400">至</span>
<Input
type="date"
value={filters.eTime}
onChange={e => patch({ eTime: e.target.value })}
className="w-36"
aria-label="结束时间"
/>
</div>
<Select
value={filters.productId}
onValueChange={value => patch({ productId: value })}
>
<SelectTrigger className="w-32">
<SelectValue placeholder="全部产品" />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">全部产品</SelectItem>
{MOCK_PRODUCTS.map(product => (
<SelectItem key={product.id} value={String(product.id)}>
{product.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Select
value={filters.packageName}
onValueChange={value => patch({ packageName: value })}
>
<SelectTrigger className="w-32">
<SelectValue placeholder="全部套餐" />
</SelectTrigger>
<SelectContent>
<SelectItem value="0">全部套餐</SelectItem>
{PACKAGE_OPTIONS.map(pkg => (
<SelectItem key={pkg} value={pkg}>
{pkg}
</SelectItem>
))}
</SelectContent>
</Select>
<div className="flex items-center gap-2">
<Input
value={filters.keyword}
onChange={e => patch({ keyword: e.target.value })}
onKeyDown={e => {
if (e.key === "Enter") handleSearch()
}}
placeholder="账号"
className="w-40"
/>
<Button onClick={handleSearch}>
<SearchIcon data-icon="inline-start" />
查询
</Button>
</div>
</div>
<OrderFilterBar
filters={filters}
products={products}
showOrderType={false}
onPatch={patch}
onSearch={() => void load()}
/>
<div className="bg-white rounded-lg p-4 flex flex-col gap-4">
<h3 className="font-semibold text-lg">退货订单管理</h3>
<DataTable
data={paged}
status="done"
status={status}
columns={columns}
pagination={{
page: page - 1,
size: pageSize,
total: filtered.length,
size: MY_ORDER_PAGE_SIZE,
total,
onPageChange: setPage,
onSizeChange: handleSizeChange,
}}
/>
</div>