2026-08-18 13:33:22 +08:00
|
|
|
|
import type { ColumnDef } from "@tanstack/react-table"
|
|
|
|
|
|
import { SearchIcon } from "lucide-react"
|
2026-08-31 14:49:28 +08:00
|
|
|
|
import AccountCell from "@/components/composites/accountCell"
|
2026-08-18 13:33:22 +08:00
|
|
|
|
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"
|
2026-08-31 14:49:28 +08:00
|
|
|
|
import { useOrderFilters } from "@/lib/hooks/useOrderFilters"
|
2026-08-18 13:33:22 +08:00
|
|
|
|
import {
|
2026-08-31 14:49:28 +08:00
|
|
|
|
formatDate,
|
|
|
|
|
|
formatMoney,
|
2026-08-18 13:33:22 +08:00
|
|
|
|
type OrderItem,
|
|
|
|
|
|
PACKAGE_OPTIONS,
|
|
|
|
|
|
totalConnections,
|
|
|
|
|
|
} from "@/lib/models/order"
|
2026-08-31 14:49:28 +08:00
|
|
|
|
import { MOCK_ORDERS, MOCK_PRODUCTS } from "../mock/orders"
|
2026-08-18 13:33:22 +08:00
|
|
|
|
|
2026-08-31 14:49:28 +08:00
|
|
|
|
// 后端订单接口就绪后,将 MOCK_ORDERS 替换为 fetchRefundOrders 返回的分页数据
|
2026-08-18 13:33:22 +08:00
|
|
|
|
|
|
|
|
|
|
const columns: ColumnDef<OrderItem>[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "CreateTime",
|
|
|
|
|
|
header: "日期",
|
|
|
|
|
|
cell: ({ row }) => formatDate(row.original.CreateTime),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "OrderNo",
|
|
|
|
|
|
header: "订单编号",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "ProductName",
|
|
|
|
|
|
header: "产品",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "PackageName",
|
|
|
|
|
|
header: "套餐",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "Accounts",
|
|
|
|
|
|
header: "账号",
|
|
|
|
|
|
cell: ({ row }) => <AccountCell accounts={row.original.Accounts} />,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "ConnectCount",
|
|
|
|
|
|
header: "连接数",
|
|
|
|
|
|
cell: ({ row }) => totalConnections(row.original),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "DayPrice",
|
|
|
|
|
|
header: "退款时长",
|
|
|
|
|
|
cell: ({ row }) => formatMoney(row.original.DayPrice),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "DayPrice",
|
|
|
|
|
|
header: "退款单价",
|
|
|
|
|
|
cell: ({ row }) => formatMoney(row.original.DayPrice),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "PaymentAmount",
|
|
|
|
|
|
header: "实付金额",
|
|
|
|
|
|
cell: ({ row }) => formatMoney(row.original.PaymentAmount),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
accessorKey: "CouponAmount",
|
|
|
|
|
|
header: "退款金额",
|
|
|
|
|
|
cell: ({ row }) => formatMoney(row.original.CouponAmount),
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
export default function RefundOrdersPage() {
|
2026-08-31 14:49:28 +08:00
|
|
|
|
const {
|
|
|
|
|
|
filters,
|
|
|
|
|
|
patch,
|
|
|
|
|
|
handleSearch,
|
|
|
|
|
|
page,
|
|
|
|
|
|
setPage,
|
|
|
|
|
|
pageSize,
|
|
|
|
|
|
handleSizeChange,
|
|
|
|
|
|
filtered,
|
|
|
|
|
|
paged,
|
|
|
|
|
|
} = useOrderFilters(MOCK_ORDERS)
|
2026-08-18 13:33:22 +08:00
|
|
|
|
|
|
|
|
|
|
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>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="bg-white rounded-lg p-4 flex flex-col gap-4">
|
2026-08-31 14:49:28 +08:00
|
|
|
|
<h3 className="font-semibold text-lg">退款订单管理</h3>
|
2026-08-18 13:33:22 +08:00
|
|
|
|
<DataTable
|
|
|
|
|
|
data={paged}
|
|
|
|
|
|
status="done"
|
|
|
|
|
|
columns={columns}
|
|
|
|
|
|
pagination={{
|
|
|
|
|
|
page: page - 1,
|
|
|
|
|
|
size: pageSize,
|
|
|
|
|
|
total: filtered.length,
|
|
|
|
|
|
onPageChange: setPage,
|
2026-08-31 14:49:28 +08:00
|
|
|
|
onSizeChange: handleSizeChange,
|
2026-08-18 13:33:22 +08:00
|
|
|
|
}}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Page>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|