补充个人中心下的页面
This commit is contained in:
@@ -19,6 +19,20 @@ type ApiResponse<T = undefined> =
|
||||
data: T
|
||||
// 响应头(key 统一小写),用于登录等场景从 header 取数据
|
||||
headers?: Record<string, string>
|
||||
// .NET 分页接口(ApiResultPaged)携带的总条数
|
||||
totalCount?: number
|
||||
}
|
||||
|
||||
export { API_BASE_URL, type ApiResponse, CLIENT_ID, CLIENT_SECRET }
|
||||
// 服务端分页结果
|
||||
type PageResult<T> = {
|
||||
total: number
|
||||
list: T[]
|
||||
}
|
||||
|
||||
export {
|
||||
API_BASE_URL,
|
||||
type ApiResponse,
|
||||
CLIENT_ID,
|
||||
CLIENT_SECRET,
|
||||
type PageResult,
|
||||
}
|
||||
|
||||
51
src/lib/hooks/useOrderFilters.ts
Normal file
51
src/lib/hooks/useOrderFilters.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useMemo, useState } from "react"
|
||||
import {
|
||||
DEFAULT_FILTERS,
|
||||
matchOrders,
|
||||
type OrderFilters,
|
||||
type OrderItem,
|
||||
} from "@/lib/models/order"
|
||||
|
||||
// 订单列表通用筛选/分页逻辑(orders / refundOrders 页面共用)
|
||||
export function useOrderFilters(list: OrderItem[]) {
|
||||
const [filters, setFilters] = useState<OrderFilters>(DEFAULT_FILTERS)
|
||||
const [appliedFilters, setAppliedFilters] =
|
||||
useState<OrderFilters>(DEFAULT_FILTERS)
|
||||
const [page, setPage] = useState(1)
|
||||
const [pageSize, setPageSize] = useState(10)
|
||||
|
||||
const filtered = useMemo(
|
||||
() => matchOrders(list, appliedFilters),
|
||||
[list, appliedFilters],
|
||||
)
|
||||
|
||||
const paged = useMemo(
|
||||
() => filtered.slice((page - 1) * pageSize, page * pageSize),
|
||||
[filtered, page, pageSize],
|
||||
)
|
||||
|
||||
const patch = (partial: Partial<OrderFilters>) =>
|
||||
setFilters({ ...filters, ...partial })
|
||||
|
||||
const handleSearch = () => {
|
||||
setAppliedFilters(filters)
|
||||
setPage(1)
|
||||
}
|
||||
|
||||
const handleSizeChange = (size: number) => {
|
||||
setPageSize(size)
|
||||
setPage(1)
|
||||
}
|
||||
|
||||
return {
|
||||
filters,
|
||||
patch,
|
||||
handleSearch,
|
||||
page,
|
||||
setPage,
|
||||
pageSize,
|
||||
handleSizeChange,
|
||||
filtered,
|
||||
paged,
|
||||
}
|
||||
}
|
||||
2
src/lib/models/auth.ts
Normal file
2
src/lib/models/auth.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// 短信验证码用途
|
||||
export type SMSPurpose = "User_Code" | "FindUser_Code" | "User_Login"
|
||||
10
src/lib/models/cashOut.ts
Normal file
10
src/lib/models/cashOut.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export type CashOutItem = {
|
||||
id: number
|
||||
username: string
|
||||
money: number
|
||||
reason: string
|
||||
alipay_account: string
|
||||
remark: string
|
||||
status: string
|
||||
create_time: string
|
||||
}
|
||||
28
src/lib/models/coupon.ts
Normal file
28
src/lib/models/coupon.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// 优惠券(.NET /api/sells/v1/coupon/*,对应 CouponEntity)
|
||||
export type CouponItem = {
|
||||
Id: number
|
||||
Name: string
|
||||
Remark: string
|
||||
CouponType: number
|
||||
TotalCount?: number
|
||||
GrantCount?: number
|
||||
UsedCount?: number
|
||||
GetLimitCount?: number
|
||||
UseRange: number
|
||||
AllowMinAmount: number
|
||||
CouponValue: number
|
||||
DateRule: number
|
||||
ValidDay: number
|
||||
StartDate: string
|
||||
EndDate: string
|
||||
CreateDate: string
|
||||
IsOverlay: number
|
||||
IsOpen: number
|
||||
Disabled?: number
|
||||
}
|
||||
|
||||
export type CouponQueryParams = {
|
||||
PageIndex?: number
|
||||
PageSize?: number
|
||||
KeyWord?: string
|
||||
}
|
||||
40
src/lib/models/dashboard.ts
Normal file
40
src/lib/models/dashboard.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export type DashboardBalance = {
|
||||
balance: number
|
||||
hCoin: number
|
||||
}
|
||||
|
||||
export type AccountInfo = {
|
||||
phone: string
|
||||
qq: string
|
||||
wechat: string
|
||||
email: string
|
||||
taobao: string
|
||||
}
|
||||
|
||||
export type RecentOrderItem = {
|
||||
date: string
|
||||
product: string
|
||||
plan: string
|
||||
price: number
|
||||
connections: number
|
||||
account: string
|
||||
orderAmount: number
|
||||
paidAmount: number
|
||||
}
|
||||
|
||||
export type ConsumptionStats = {
|
||||
today: number
|
||||
month: number
|
||||
todayRefund: number
|
||||
year: number
|
||||
todayRecharge: number
|
||||
monthRecharge: number
|
||||
monthRefund: number
|
||||
}
|
||||
|
||||
export type IpAccountStats = {
|
||||
using: number
|
||||
total: number
|
||||
expired: number
|
||||
yearConsumption: number
|
||||
}
|
||||
6
src/lib/models/httpRecharge.ts
Normal file
6
src/lib/models/httpRecharge.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export type HttpRechargeItem = {
|
||||
create_time: string
|
||||
ju_money: number
|
||||
pay_type: string
|
||||
pay_money: number
|
||||
}
|
||||
35
src/lib/models/line.ts
Normal file
35
src/lib/models/line.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export type LineItem = {
|
||||
city: string | number
|
||||
daikuan: string | number
|
||||
name: string | number
|
||||
nasname: string | number
|
||||
online: string | number
|
||||
supply: string | number
|
||||
}
|
||||
|
||||
export type LineData = {
|
||||
count: number | string
|
||||
use_count: number | string
|
||||
data: LineItem[]
|
||||
}
|
||||
|
||||
export type LineSearchResult = {
|
||||
data: LineItem[]
|
||||
}
|
||||
|
||||
// IP线路表产品选项
|
||||
export type ProductOption = {
|
||||
id: number
|
||||
name: string
|
||||
l2tp: string
|
||||
sstp: string
|
||||
}
|
||||
|
||||
export const PRODUCTS: ProductOption[] = [
|
||||
{ id: 29, name: "极狐IP", l2tp: "8899", sstp: "4430" },
|
||||
{ id: 3, name: "极光IP", l2tp: "1234", sstp: "4430" },
|
||||
{ id: 27, name: "麒麟IP", l2tp: "123", sstp: "4432" },
|
||||
{ id: 26, name: "猎豹IP", l2tp: "1234", sstp: "4430" },
|
||||
{ id: 28, name: "水滴独享IP", l2tp: "123", sstp: "4432" },
|
||||
{ id: 22, name: "火狐静态IP", l2tp: "888888", sstp: "5908" },
|
||||
]
|
||||
@@ -16,6 +16,58 @@ export type OrderItem = {
|
||||
UpdateTime: string
|
||||
}
|
||||
|
||||
// ==================== 下单接口(php-api /product/CreateOrder) ====================
|
||||
|
||||
export type CreateOrderRequest = {
|
||||
PackageId: number
|
||||
OrderType: number
|
||||
Account: string
|
||||
Pwd: string
|
||||
ConnectCount: number
|
||||
MinPostfix?: number
|
||||
MaxPostfix?: number
|
||||
CouponId?: number
|
||||
UseAccountAmount?: number
|
||||
OPayType: number
|
||||
PayChannel?: number
|
||||
Price?: number
|
||||
}
|
||||
|
||||
export type CreateTestAccountRequest = {
|
||||
ProductId: number
|
||||
PackageId: number
|
||||
Account: string
|
||||
Pwd: string
|
||||
}
|
||||
|
||||
export type OrderInfo = {
|
||||
OrderNo: string
|
||||
OtherPayAmount: number
|
||||
CreateTime: string
|
||||
PayType: number
|
||||
}
|
||||
|
||||
export type CreateOrderData = {
|
||||
OrderInfo: OrderInfo
|
||||
PayData: string
|
||||
}
|
||||
|
||||
// ==================== 管理端订单查询(.NET /api/course/v1/order/*) ====================
|
||||
|
||||
export type OrderQueryParams = {
|
||||
PageIndex?: number
|
||||
PageSize?: number
|
||||
KeyWord?: string
|
||||
OrderTypes?: number[]
|
||||
BTime?: string
|
||||
ETime?: string
|
||||
ProductId?: number
|
||||
PackageId?: number
|
||||
Channel?: string
|
||||
ProductIds?: number[]
|
||||
PackageNames?: string[]
|
||||
}
|
||||
|
||||
export type OrderFilters = {
|
||||
orderType: string
|
||||
productId: string
|
||||
@@ -65,3 +117,61 @@ export function cutAccount(accounts: string, max = 15): string {
|
||||
export function totalConnections(item: OrderItem): number {
|
||||
return item.ConnectCount * item.AccountCount
|
||||
}
|
||||
|
||||
// ==================== 表格展示辅助 ====================
|
||||
|
||||
export function formatMoney(value: number): string {
|
||||
return value.toFixed(2)
|
||||
}
|
||||
|
||||
export function formatDate(value: string): string {
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) return value
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0")
|
||||
const day = String(date.getDate()).padStart(2, "0")
|
||||
return `${year}.${month}.${day}`
|
||||
}
|
||||
|
||||
// 前端筛选(后端筛选接口就绪后可移除)
|
||||
export function matchOrders(
|
||||
list: OrderItem[],
|
||||
filters: OrderFilters,
|
||||
): OrderItem[] {
|
||||
const keyword = filters.keyword.trim()
|
||||
|
||||
return list.filter(order => {
|
||||
if (
|
||||
filters.orderType !== "0" &&
|
||||
order.OrderType !== Number(filters.orderType)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
filters.productId !== "0" &&
|
||||
order.ProductId !== Number(filters.productId)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
filters.packageName !== "0" &&
|
||||
order.PackageName !== filters.packageName
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
keyword &&
|
||||
!order.OrderNo.includes(keyword) &&
|
||||
!order.Accounts.includes(keyword)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (filters.bTime && order.CreateTime.slice(0, 10) < filters.bTime) {
|
||||
return false
|
||||
}
|
||||
if (filters.eTime && order.CreateTime.slice(0, 10) > filters.eTime) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
279
src/lib/models/package.ts
Normal file
279
src/lib/models/package.ts
Normal file
@@ -0,0 +1,279 @@
|
||||
// 短效/长效套餐相关模型(与 php-api.juip.com 的 /http/user/* 接口对应)
|
||||
|
||||
// 短效套餐(已开通)
|
||||
export type DxPackage = {
|
||||
id: number
|
||||
name: string
|
||||
planType: number
|
||||
remainingAmount: number | string
|
||||
durationType: string
|
||||
durationType2?: number
|
||||
expireTime: string
|
||||
isExpired?: boolean | number | string
|
||||
ipAmount?: number
|
||||
}
|
||||
|
||||
// 短效购买记录
|
||||
export type DxOrder = {
|
||||
order_no: string
|
||||
order_type: number | string
|
||||
package_type: string
|
||||
durationType: string
|
||||
money: number | string
|
||||
create_time: string
|
||||
}
|
||||
|
||||
// 长效套餐(已开通)
|
||||
export type CxPackage = {
|
||||
id: number
|
||||
isAbroad: number | string
|
||||
isAbroad2?: number
|
||||
shareType: number | string
|
||||
ipAmount: number
|
||||
expireTime: string
|
||||
isRelayed?: number
|
||||
}
|
||||
|
||||
// 长效购买记录
|
||||
export type CxOrder = {
|
||||
order_no: string
|
||||
order_type: number | string
|
||||
game_type: string
|
||||
ip_count: number
|
||||
money: number | string
|
||||
create_time: string
|
||||
}
|
||||
|
||||
// 已开通长效 IP
|
||||
export type LangIpItem = {
|
||||
id: number
|
||||
packId?: number
|
||||
isRelayed: number
|
||||
isAbroad: number
|
||||
ip: string
|
||||
realIp: string
|
||||
httpPort: number
|
||||
socks5Port: number
|
||||
area: string
|
||||
bandwidth: number
|
||||
lineType: number | string
|
||||
lineType2?: number
|
||||
shareType: number | string
|
||||
shareType2?: number
|
||||
state: number | string
|
||||
username: string
|
||||
password: string
|
||||
expireTime: string
|
||||
isExpired: boolean | number | string
|
||||
gameId?: number
|
||||
isp?: number
|
||||
}
|
||||
|
||||
// 长效 IP 切换记录
|
||||
export type SwitchRecord = {
|
||||
oldIp: string
|
||||
oldArea: string
|
||||
newIp: string
|
||||
newArea: string
|
||||
reason: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
// 服务端分页信息
|
||||
export type Pager = {
|
||||
currentPage: number
|
||||
pageSize?: number
|
||||
totalCount?: number
|
||||
totalPage?: number
|
||||
}
|
||||
|
||||
// 长效 IP 列表查询结果
|
||||
export type LangIpListResult = {
|
||||
items: LangIpItem[]
|
||||
pager: Pager
|
||||
}
|
||||
|
||||
// 长效 IP 切换记录查询结果
|
||||
export type SwitchListResult = {
|
||||
items: SwitchRecord[]
|
||||
pager: Pager
|
||||
}
|
||||
|
||||
// 下单/续费/切换通用返回
|
||||
export type OrderActionResult = {
|
||||
code: number
|
||||
msg?: string
|
||||
}
|
||||
|
||||
// 批量提取的长效 IP
|
||||
export type LangIpExtract = {
|
||||
ip: string
|
||||
httpPort: number
|
||||
socks5Port: number
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
// 短效提取用户凭证(get_user_token)
|
||||
export type UserApiToken = {
|
||||
uid: number | string
|
||||
token: string
|
||||
}
|
||||
|
||||
// 续费/切换下单数据
|
||||
export type RebuyData = {
|
||||
title?: string
|
||||
packId?: number
|
||||
packType?: number
|
||||
periodType: number
|
||||
periodAmount: number
|
||||
durationType?: number
|
||||
ipAmount: number
|
||||
ids?: string
|
||||
isRelayed?: number
|
||||
isAbroad?: number
|
||||
shareType?: number
|
||||
lineType?: number
|
||||
bandwidth?: number
|
||||
}
|
||||
|
||||
// 套餐订单信息(order_type: 2-短效无限量 3-短效包天 5-长效套餐 6-单IP续费 7-切换IP)
|
||||
export type PackageOrderInfo = {
|
||||
order_type: number
|
||||
money: number
|
||||
pay_type?: number
|
||||
data: RebuyData
|
||||
}
|
||||
|
||||
// 长效 IP 切换节点/入口下单数据
|
||||
export type ChangeIpData = {
|
||||
title?: string
|
||||
id: number
|
||||
isAbroad: number
|
||||
cityCode: number
|
||||
isp: number
|
||||
switchPop: 0 | 1
|
||||
data: RebuyData
|
||||
}
|
||||
|
||||
// 短效 API 链接生成参数
|
||||
export type ApiLinkConfig = {
|
||||
pack?: number
|
||||
num: number
|
||||
gt?: number
|
||||
port: number
|
||||
type: number
|
||||
lb: number
|
||||
clb?: string
|
||||
distinct: number
|
||||
isp: number
|
||||
aw: number
|
||||
at: number
|
||||
sp: number
|
||||
csp?: string
|
||||
pt?: number
|
||||
time?: number
|
||||
u?: number | string
|
||||
t?: string
|
||||
}
|
||||
|
||||
// 短效套餐类型
|
||||
export const SHORT_PLAN_DAILY = 21 // 短效包天
|
||||
export const SHORT_PLAN_VOLUME = 22 // 短效包量
|
||||
export const SHORT_PLAN_UNLIMITED = 23 // 短效无限量
|
||||
export const LONG_PLAN = 31 // 长效套餐
|
||||
|
||||
// 套餐周期选项
|
||||
export const PERIOD_OPTIONS = [
|
||||
{ value: 1, label: "按天", unit: "天" },
|
||||
{ value: 7, label: "按周", unit: "周" },
|
||||
{ value: 30, label: "按月", unit: "月" },
|
||||
{ value: 90, label: "按季", unit: "季" },
|
||||
] as const
|
||||
|
||||
// 长效订单类型
|
||||
export const LONG_ORDER_TYPE_LABELS: Record<number, string> = {
|
||||
5: "长效游戏",
|
||||
6: "单IP续费",
|
||||
7: "切换IP",
|
||||
}
|
||||
|
||||
// 短效订单类型
|
||||
export const SHORT_ORDER_TYPE_LABELS: Record<number, string> = {
|
||||
2: "短效无限量",
|
||||
3: "短效包天",
|
||||
4: "短效包量",
|
||||
}
|
||||
|
||||
// 长效 IP 状态
|
||||
export const IP_STATE_LABELS: Record<number, string> = {
|
||||
1: "正常",
|
||||
0: "异常",
|
||||
9: "封禁",
|
||||
}
|
||||
|
||||
// ==================== 字段格式化 ====================
|
||||
|
||||
// 后端的 isExpired 可能返回 true/1/"1",统一转布尔
|
||||
export function parseExpired(
|
||||
value: boolean | number | string | undefined,
|
||||
): boolean {
|
||||
return value === true || value === 1 || value === "1"
|
||||
}
|
||||
|
||||
export function formatExpired(
|
||||
value: boolean | number | string | undefined,
|
||||
): string {
|
||||
return parseExpired(value) ? "已过期" : "未过期"
|
||||
}
|
||||
|
||||
export function formatAbroad(value: number | string | undefined): string {
|
||||
return value === 1 || value === "1" ? "海外" : "国内"
|
||||
}
|
||||
|
||||
export function formatIpState(value: number | string): string {
|
||||
const num = Number(value)
|
||||
return IP_STATE_LABELS[num] ?? String(value)
|
||||
}
|
||||
|
||||
export function formatOrderTypeLabel(
|
||||
labels: Record<number, string>,
|
||||
value: number | string,
|
||||
): string {
|
||||
return labels[Number(value)] ?? String(value)
|
||||
}
|
||||
|
||||
// 提取地区选项
|
||||
export const REGION_OPTIONS = [
|
||||
{ value: "110000", label: "北京市" },
|
||||
{ value: "120000", label: "天津市" },
|
||||
{ value: "130000", label: "河北省" },
|
||||
{ value: "140000", label: "山西省" },
|
||||
{ value: "210000", label: "辽宁省" },
|
||||
{ value: "220000", label: "吉林省" },
|
||||
{ value: "310000", label: "上海市" },
|
||||
{ value: "320000", label: "江苏省" },
|
||||
{ value: "330000", label: "浙江省" },
|
||||
{ value: "340000", label: "安徽省" },
|
||||
{ value: "350000", label: "福建省" },
|
||||
{ value: "360000", label: "江西省" },
|
||||
{ value: "370000", label: "山东省" },
|
||||
{ value: "410000", label: "河南省" },
|
||||
{ value: "420000", label: "湖北省" },
|
||||
{ value: "430000", label: "湖南省" },
|
||||
{ value: "440000", label: "广东省" },
|
||||
{ value: "460000", label: "海南省" },
|
||||
{ value: "500000", label: "重庆市" },
|
||||
{ value: "510000", label: "四川省" },
|
||||
{ value: "520000", label: "贵州省" },
|
||||
{ value: "530000", label: "云南省" },
|
||||
{ value: "610000", label: "陕西省" },
|
||||
{ value: "620000", label: "甘肃省" },
|
||||
{ value: "630000", label: "青海省" },
|
||||
{ value: "230000", label: "黑龙江省" },
|
||||
{ value: "540000", label: "西藏自治区" },
|
||||
{ value: "150000", label: "内蒙古自治区" },
|
||||
{ value: "450000", label: "广西壮族自治区" },
|
||||
{ value: "640000", label: "宁夏回族自治区" },
|
||||
{ value: "650000", label: "新疆维吾尔自治区" },
|
||||
] as const
|
||||
11
src/lib/models/rosorder.ts
Normal file
11
src/lib/models/rosorder.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type RosOrderItem = {
|
||||
id: number
|
||||
username: string
|
||||
product_name: string
|
||||
real_price: number
|
||||
order_no: string
|
||||
user: string
|
||||
phone: string
|
||||
address: string
|
||||
create_time: string
|
||||
}
|
||||
16
src/lib/models/user.ts
Normal file
16
src/lib/models/user.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// 用户(.NET /api/baseinfo/v1/user/*,对应 UserEntity)
|
||||
export type UserItem = {
|
||||
Id: number
|
||||
LoginCode: string
|
||||
Name: string
|
||||
Phone: string
|
||||
Enabled: number
|
||||
PhotoUrl?: string
|
||||
LastLoginDate?: string
|
||||
}
|
||||
|
||||
export type UserQueryParams = {
|
||||
PageIndex?: number
|
||||
PageSize?: number
|
||||
KeyWord?: string
|
||||
}
|
||||
6
src/lib/models/whitelist.ts
Normal file
6
src/lib/models/whitelist.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export type WhiteIpItem = {
|
||||
id: number
|
||||
ip: string
|
||||
createTime: string
|
||||
isLocked: string
|
||||
}
|
||||
@@ -8,3 +8,49 @@ export type Children = { children: ReactNode }
|
||||
export function cn(...inputs: ClassNameValue[]) {
|
||||
return twMerge(inputs)
|
||||
}
|
||||
|
||||
// 以文本文件形式下载内容
|
||||
export function downloadTextFile(filename: string, content: string) {
|
||||
const blob = new Blob([content], { type: "text/plain;charset=utf-8" })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const anchor = document.createElement("a")
|
||||
anchor.href = url
|
||||
anchor.download = filename
|
||||
anchor.style.display = "none"
|
||||
document.body.appendChild(anchor)
|
||||
anchor.click()
|
||||
document.body.removeChild(anchor)
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
// 导出 CSV(带 BOM,避免 Excel 打开中文乱码)
|
||||
export function downloadCsv(
|
||||
filename: string,
|
||||
header: string[],
|
||||
rows: (string | number)[][],
|
||||
) {
|
||||
const lines = [header, ...rows].map(line =>
|
||||
line.map(v => `"${String(v).replaceAll('"', '""')}"`).join(","),
|
||||
)
|
||||
const csv = lines.join("\r\n")
|
||||
const blob = new Blob([`\uFEFF${csv}`], {
|
||||
type: "text/csv;charset=utf-8",
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement("a")
|
||||
a.href = url
|
||||
a.download = filename.endsWith(".csv") ? filename : `${filename}.csv`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
// 服务端未返回总条数时,按当前页数据量估算
|
||||
export function estimateTotal(
|
||||
pagerTotal: number | undefined,
|
||||
page: number,
|
||||
pageSize: number,
|
||||
itemCount: number,
|
||||
): number {
|
||||
if (pagerTotal && pagerTotal > 0) return pagerTotal
|
||||
return itemCount > 0 ? (page - 1) * pageSize + itemCount : 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user