2 Commits

Author SHA1 Message Date
ZhuRui 130a253b83 fix: 优化部分setTime 0 的写法 2026-08-06 11:56:37 +08:00
ZhuRui 15a6d81851 fix: 列表显示、分页优化 2026-08-06 11:39:51 +08:00
36 changed files with 181 additions and 163 deletions
+17 -4
View File
@@ -8,7 +8,7 @@ export interface TournamentAdminOrderPageVO {
/** 订单编号 */ /** 订单编号 */
orderNo: string; orderNo: string;
/** 选手ID */ /** 选手ID */
uniqueId: number; uniqueId: string;
/** 赛事名称 */ /** 赛事名称 */
name: string; name: string;
/** 选手名称 */ /** 选手名称 */
@@ -36,9 +36,9 @@ export interface TournamentAdminOrderPageVO {
/** 支付时间;yyyy.MM.dd HH:mm:ss */ /** 支付时间;yyyy.MM.dd HH:mm:ss */
payTime: string; payTime: string;
/** 订单状态;1=已支付,2=部分退款,3=全部退款,4=已关闭,-1=其他 */ /** 订单状态;1=已支付,2=部分退款,3=全部退款,4=已关闭,-1=其他 */
orderStatus: number; orderStatus: string;
/** 退款状态;1=无退款,2=退款成功,3=退款失败,-1=其他 */ /** 退款状态;1=无退款,2=退款成功,3=退款失败,-1=其他 */
refundStatus: number; refundStatus: string;
} }
/** 订单列表查询参数 */ /** 订单列表查询参数 */
@@ -62,11 +62,24 @@ export interface OrderListQueryParams {
status?: string; status?: string;
/** /**
* 退款状态 * 退款状态
* 不传=全部、0=退款失败,1=退款成功 * 不传=全部、2=退款成功,3=退款失败
*/ */
refundStatus?: string; refundStatus?: string;
} }
/** 订单分页数据(含列表统计字段) */
export interface OrderPageData extends PageData<TournamentAdminOrderPageVO> {
/** 扩展数据 */
exData: {
/** 总订单金额(已支付) */
totalOrderAmount: string;
/** 总实付金额 */
totalActualAmount: string;
/** 总退款金额 */
totalRefundAmount: string;
};
}
/** 分页数据 */ /** 分页数据 */
export interface PageData<T> { export interface PageData<T> {
total: number; total: number;
+2 -2
View File
@@ -1,4 +1,4 @@
import { defineComponent, ref, reactive } from 'vue'; import { defineComponent, ref, reactive, nextTick } from 'vue';
import { useEffect } from '@/hooks'; import { useEffect } from '@/hooks';
import { Modal, Form, Input, Button, message } from 'ant-design-vue'; import { Modal, Form, Input, Button, message } from 'ant-design-vue';
import { TIPS_TEXT, newPasswordRules, confirmNewPasswordRules } from './controller'; import { TIPS_TEXT, newPasswordRules, confirmNewPasswordRules } from './controller';
@@ -34,7 +34,7 @@ export default defineComponent({
useEffect(() => { useEffect(() => {
if (props.visible) { if (props.visible) {
Object.assign(formData, getDefaultForm()); Object.assign(formData, getDefaultForm());
setTimeout(() => formRef.value?.clearValidate(), 0); nextTick().then(() => formRef.value?.clearValidate());
} }
}, [() => props.visible]); }, [() => props.visible]);
+10
View File
@@ -180,3 +180,13 @@ export function usePagination(options: UsePaginationOptions = {}): UsePagination
refresh, refresh,
}; };
} }
/** 将接口返回的分页 total 同步到 pagination(支持 number / 数字字符串,含 0 */
export function syncPaginationTotal(
pagination: Pick<UsePaginationReturn, 'setTotal'>,
total: unknown,
): void {
if (total == null || total === '') return;
const n = Number(total);
if (Number.isFinite(n)) pagination.setTotal(n);
}
@@ -1,4 +1,4 @@
import { defineComponent, ref, reactive, computed } from 'vue'; import { defineComponent, ref, reactive, computed, nextTick } from 'vue';
import { useEffect, useState } from '@/hooks'; import { useEffect, useState } from '@/hooks';
import { import {
Modal, Modal,
@@ -305,7 +305,7 @@ export default defineComponent({
initFormFromRecord(props.record); initFormFromRecord(props.record);
setCropperVisible(false); setCropperVisible(false);
setUploadImageUrl(''); setUploadImageUrl('');
setTimeout(() => formRef.value?.clearValidate(), 0); nextTick().then(() => formRef.value?.clearValidate());
} }
}, [() => props.visible]); }, [() => props.visible]);
+2 -2
View File
@@ -79,7 +79,7 @@ function renderBodyCell({
// 跳转地址列 // 跳转地址列
if (column.dataIndex === 'linkUrl') { if (column.dataIndex === 'linkUrl') {
return <span>{text || '-'}</span>; return <span>{text || '--'}</span>;
} }
// 展示时间列 // 展示时间列
@@ -100,7 +100,7 @@ function renderBodyCell({
if (column.key === 'action') { if (column.key === 'action') {
const isEnabled = record.status === '1'; const isEnabled = record.status === '1';
const { canEdit, canToggleStatus, canDelete } = permissions; const { canEdit, canToggleStatus, canDelete } = permissions;
if (!canEdit && !canToggleStatus && !canDelete) return <span>-</span>; if (!canEdit && !canToggleStatus && !canDelete) return <span>--</span>;
return ( return (
<Space> <Space>
@@ -243,12 +243,12 @@ export function useBannerModel() {
// ===== 渲染工具 ===== // ===== 渲染工具 =====
const renderJumpType = (type: string) => { const renderJumpType = (type: string) => {
const info = JUMP_TYPE_MAP[type] || { label: type || '-', tone: 'default' as const }; const info = JUMP_TYPE_MAP[type] || { label: type || '--', tone: 'default' as const };
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
}; };
const renderStatus = (status: string) => { const renderStatus = (status: string) => {
const info = STATUS_MAP[status] || { label: status || '-', tone: 'default' as const }; const info = STATUS_MAP[status] || { label: status || '--', tone: 'default' as const };
return h(StatusTag, { label: info.label, tone: info.tone, dimmed: info.dimmed }); return h(StatusTag, { label: info.label, tone: info.tone, dimmed: info.dimmed });
}; };
@@ -79,7 +79,7 @@ export default defineComponent({
/** 格式化时间范围 */ /** 格式化时间范围 */
const formatRange = (start: string, end: string) => { const formatRange = (start: string, end: string) => {
if (!start && !end) return '-'; if (!start && !end) return '--';
return `${start || '?'} ~ ${end || '?'}`; return `${start || '?'} ~ ${end || '?'}`;
}; };
@@ -98,25 +98,25 @@ export default defineComponent({
<div class={styles.section}> <div class={styles.section}>
<div class={styles.sectionTitle}></div> <div class={styles.sectionTitle}></div>
<Descriptions size="small" bordered column={3} class={styles.desc}> <Descriptions size="small" bordered column={3} class={styles.desc}>
<Descriptions.Item label="赛事名称">{d.name || '-'}</Descriptions.Item> <Descriptions.Item label="赛事名称">{d.name || '--'}</Descriptions.Item>
<Descriptions.Item label="赛事时间" span={2}> <Descriptions.Item label="赛事时间" span={2}>
{formatRange(d.startTimeBegin, d.startTimeEnd)} {formatRange(d.startTimeBegin, d.startTimeEnd)}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="赛事说明" span={3}> <Descriptions.Item label="赛事说明" span={3}>
{d.descr || '-'} {d.descr || '--'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="报名起止时间"> <Descriptions.Item label="报名起止时间">
{formatRange(d.signupTimeBegin, d.signupTimeEnd)} {formatRange(d.signupTimeBegin, d.signupTimeEnd)}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="取消报名截止时间" span={2}> <Descriptions.Item label="取消报名截止时间" span={2}>
{d.signupTimeEnd || '-'} {d.signupTimeEnd || '--'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="省市区">{d.venueArea || '-'}</Descriptions.Item> <Descriptions.Item label="省市区">{d.venueArea || '--'}</Descriptions.Item>
<Descriptions.Item label="地点">{d.venue || '-'}</Descriptions.Item> <Descriptions.Item label="地点">{d.venue || '--'}</Descriptions.Item>
<Descriptions.Item label="场地编号">{d.venueNo || '-'}</Descriptions.Item> <Descriptions.Item label="场地编号">{d.venueNo || '--'}</Descriptions.Item>
<Descriptions.Item label="公开活动"> <Descriptions.Item label="公开活动">
{boolText(d.isPublic, '在首页展示赛事', '非公开')} {boolText(d.isPublic, '在首页展示赛事', '非公开')}
@@ -128,15 +128,15 @@ export default defineComponent({
{boolText(d.isRequireIdCardImg, '需要提供', '无需提供')} {boolText(d.isRequireIdCardImg, '需要提供', '无需提供')}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="创建时间">{d.createTime || '-'}</Descriptions.Item> <Descriptions.Item label="创建时间">{d.createTime || '--'}</Descriptions.Item>
<Descriptions.Item label="创建人">{d.createNickname || '-'}</Descriptions.Item> <Descriptions.Item label="创建人">{d.createNickname || '--'}</Descriptions.Item>
<Descriptions.Item label="状态"></Descriptions.Item> <Descriptions.Item label="状态"></Descriptions.Item>
<Descriptions.Item label="报名人数">{d.signupCount || '0'}</Descriptions.Item> <Descriptions.Item label="报名人数">{d.signupCount || '0'}</Descriptions.Item>
<Descriptions.Item label="取消报名人数" span={1}> <Descriptions.Item label="取消报名人数" span={1}>
{d.dropoutCount || '0'} {d.dropoutCount || '0'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="最大人数">{d.totalLimit || '-'}</Descriptions.Item> <Descriptions.Item label="最大人数">{d.totalLimit || '--'}</Descriptions.Item>
<Descriptions.Item label="对岸数量">{d.matchTotalCount || '0'}</Descriptions.Item> <Descriptions.Item label="对岸数量">{d.matchTotalCount || '0'}</Descriptions.Item>
<Descriptions.Item label="已完成对岸数量">{d.matchCount || '0'}</Descriptions.Item> <Descriptions.Item label="已完成对岸数量">{d.matchCount || '0'}</Descriptions.Item>
</Descriptions> </Descriptions>
@@ -32,7 +32,7 @@ const PAGE_SIZE = 10;
/** 渲染身份证图片(cover 填充,与封面显示方式一致) */ /** 渲染身份证图片(cover 填充,与封面显示方式一致) */
const renderIdImages = (imgList: string[], singleImg: string) => { const renderIdImages = (imgList: string[], singleImg: string) => {
const urls = imgList.length > 0 ? imgList : singleImg ? [singleImg] : []; const urls = imgList.length > 0 ? imgList : singleImg ? [singleImg] : [];
if (urls.length === 0) return <span>-</span>; if (urls.length === 0) return <span>--</span>;
return ( return (
<Image.PreviewGroup> <Image.PreviewGroup>
<div class={styles.idImageGrid}> <div class={styles.idImageGrid}>
@@ -63,14 +63,14 @@ const PLAYER_COLUMNS = [
key: 'idCard', key: 'idCard',
width: 180, width: 180,
customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) =>
record?.idCard ? record.idCard : <span>-</span>, record?.idCard ? record.idCard : <span>--</span>,
}, },
{ {
title: '证件图片', title: '证件图片',
key: 'idCardImgs', key: 'idCardImgs',
width: 280, width: 280,
customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) =>
record ? renderIdImages(record.idCardImgList || [], record.idCardImg || '') : <span>-</span>, record ? renderIdImages(record.idCardImgList || [], record.idCardImg || '') : <span>--</span>,
}, },
]; ];
@@ -193,7 +193,7 @@ export default defineComponent({
<Descriptions.Item label="省市区">{detail.value.venueArea}</Descriptions.Item> <Descriptions.Item label="省市区">{detail.value.venueArea}</Descriptions.Item>
<Descriptions.Item label="地点">{detail.value.venue}</Descriptions.Item> <Descriptions.Item label="地点">{detail.value.venue}</Descriptions.Item>
<Descriptions.Item label="场地编号" class={styles.statCell}> <Descriptions.Item label="场地编号" class={styles.statCell}>
{detail.value.venueNo || '-'} {detail.value.venueNo || '--'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="公开活动"> <Descriptions.Item label="公开活动">
@@ -217,7 +217,7 @@ export default defineComponent({
label="最大人数" label="最大人数"
class={[styles.statCell, styles.statCellNoWrap]} class={[styles.statCell, styles.statCellNoWrap]}
> >
{detail.value.totalLimit || '-'} {detail.value.totalLimit || '--'}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="总对阵数"> <Descriptions.Item label="总对阵数">
+1 -1
View File
@@ -159,7 +159,7 @@ export default defineComponent({
</a> </a>
) : ( ) : (
<span>-</span> <span>--</span>
)} )}
</> </>
), ),
@@ -1,9 +1,9 @@
import { computed, reactive, toRef, Ref } from 'vue'; import { computed, reactive, toRef, Ref, nextTick } from 'vue';
import { Modal, message } from 'ant-design-vue'; import { Modal, message } from 'ant-design-vue';
import { useState, useDebounce } from '@/hooks'; import { useState, useDebounce } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination } from '@/hooks/usePagination'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination';
import { hasValue, isEmptyValue, safeTransform } from '@/utils'; import { hasValue, isEmptyValue, safeTransform } from '@/utils';
import type { TournamentAdminVO, EventListQueryParams, PageData, ApiResult } from './services'; import type { TournamentAdminVO, EventListQueryParams, PageData, ApiResult } from './services';
import { getEventList, toggleEventOnline } from './services'; import { getEventList, toggleEventOnline } from './services';
@@ -78,9 +78,8 @@ export function useEventListModel() {
// 同步分页总条数 // 同步分页总条数
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
const hasFilter = computed(() => { const hasFilter = computed(() => {
const f = filterForm; const f = filterForm;
@@ -110,7 +109,7 @@ export function useEventListModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
const openDetailModal = (record: any) => { const openDetailModal = (record: any) => {
+4 -5
View File
@@ -30,11 +30,10 @@ const LogContentCell = defineComponent({
}; };
let observer: ResizeObserver | null = null; let observer: ResizeObserver | null = null;
useEffect(() => { useEffect(() => {
const el = textRef.value; if (!textRef.value) return;
if (!el) return;
nextTick(checkOverflow); nextTick(checkOverflow);
observer = new ResizeObserver(checkOverflow); observer = new ResizeObserver(checkOverflow);
observer.observe(el); observer.observe(textRef.value);
return () => { return () => {
observer?.disconnect(); observer?.disconnect();
observer = null; observer = null;
@@ -96,13 +95,13 @@ export default defineComponent({
}) => { }) => {
if (column.key === 'content') { if (column.key === 'content') {
const raw = text || ''; const raw = text || '';
return raw ? <LogContentCell text={raw} /> : <span>-</span>; return raw ? <LogContentCell text={raw} /> : <span>--</span>;
} }
// 有 customRender 的列使用其渲染函数(如操作类型/操作来源的代码→中文映射) // 有 customRender 的列使用其渲染函数(如操作类型/操作来源的代码→中文映射)
if (column.customRender) { if (column.customRender) {
return column.customRender({ text, record, index, column }); return column.customRender({ text, record, index, column });
} }
return <span>{text || '-'}</span>; return <span>{text || '--'}</span>;
}; };
return () => ( return () => (
+2 -2
View File
@@ -1,9 +1,9 @@
import { type VNodeChild } from 'vue'; import { type VNodeChild } from 'vue';
import { ACTION_TYPE_MAP, ACTION_SOURCE_MAP } from './config'; import { ACTION_TYPE_MAP, ACTION_SOURCE_MAP } from './config';
const renderType = (text: string): string => ACTION_TYPE_MAP[text] || text || '-'; const renderType = (text: string): string => ACTION_TYPE_MAP[text] || text || '--';
const renderSource = (text: string): string => ACTION_SOURCE_MAP[text] || text || '-'; const renderSource = (text: string): string => ACTION_SOURCE_MAP[text] || text || '--';
/** /**
* 操作日志页 - 表格列配置(视图层) * 操作日志页 - 表格列配置(视图层)
+7 -4
View File
@@ -2,7 +2,11 @@ import { computed, reactive, toRef, Ref, type UnwrapRef } from 'vue';
import { useDebounce } from '@/hooks'; import { useDebounce } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination, type UsePaginationReturn } from '@/hooks/usePagination'; import {
usePagination,
syncPaginationTotal,
type UsePaginationReturn,
} from '@/hooks/usePagination';
import { hasValue, isEmptyValue, safeTransform } from '@/utils'; import { hasValue, isEmptyValue, safeTransform } from '@/utils';
import { import {
getOperationLogs, getOperationLogs,
@@ -102,9 +106,8 @@ export function useLogModel() {
// 同步分页总条数 // 同步分页总条数
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
const hasFilter = computed(() => { const hasFilter = computed(() => {
return ( return (
@@ -24,7 +24,7 @@ const GENDER_MAP: Record<string, string> = { '1': '男', '2': '女' };
const formatGender = (v: string) => GENDER_MAP[v] ?? v; const formatGender = (v: string) => GENDER_MAP[v] ?? v;
const formatMoney = (v: string) => { const formatMoney = (v: string) => {
const n = parseFloat(v); const n = parseFloat(v);
return isNaN(n) ? '-' : `${n.toFixed(2)}`; return isNaN(n) ? '--' : `${n.toFixed(2)}`;
}; };
const PLAYER_COLUMNS = [ const PLAYER_COLUMNS = [
@@ -55,7 +55,7 @@ const PLAYER_COLUMNS = [
: record.idCardImg : record.idCardImg
? [record.idCardImg] ? [record.idCardImg]
: []; : [];
if (!urls.length) return <span>-</span>; if (!urls.length) return <span>--</span>;
return ( return (
<Space> <Space>
{urls.map((src) => ( {urls.map((src) => (
@@ -102,7 +102,8 @@ const PLAYER_COLUMNS = [
key: 'refundAmount', key: 'refundAmount',
width: 100, width: 100,
align: 'right' as const, align: 'right' as const,
customRender: ({ text }: { text: string }) => (text === '-' || !text ? '-' : formatMoney(text)), customRender: ({ text }: { text: string }) =>
text === '--' || !text ? '--' : formatMoney(text),
}, },
]; ];
@@ -160,7 +161,7 @@ export default defineComponent({
return records.some((r) => { return records.some((r) => {
if (!r) return false; if (!r) return false;
const hasRefundAmount = parseFloat(r.refundAmount || '0') > 0; const hasRefundAmount = parseFloat(r.refundAmount || '0') > 0;
const hasRefundTime = r.refundTime && r.refundTime !== '-'; const hasRefundTime = r.refundTime && r.refundTime !== '--';
return hasRefundAmount && !hasRefundTime; return hasRefundAmount && !hasRefundTime;
}); });
}); });
@@ -329,11 +330,11 @@ export default defineComponent({
</span> </span>
</div> </div>
<div>{r.refundApplyTime}</div> <div>{r.refundApplyTime}</div>
<div>{r.refundTime || '-'}</div> <div>{r.refundTime || '--'}</div>
</div> </div>
<div class={styles.refundCol}> <div class={styles.refundCol}>
<div>退{r.refundMethod}</div> <div>退{r.refundMethod}</div>
<div>退{r.refundOutTradeNo || '-'}</div> <div>退{r.refundOutTradeNo || '--'}</div>
<div>退¥{formatMoney(r.refundedAmount)}</div> <div>退¥{formatMoney(r.refundedAmount)}</div>
</div> </div>
</div> </div>
+3 -9
View File
@@ -230,21 +230,15 @@ export default defineComponent({
<div class={pageStyles.summary}> <div class={pageStyles.summary}>
<span class={pageStyles.summaryItem}> <span class={pageStyles.summaryItem}>
<span class={pageStyles.summaryLabel}></span> <span class={pageStyles.summaryLabel}></span>
<span class={pageStyles.summaryValue}> <span class={pageStyles.summaryValue}>{summary.value.totalOrderAmount}</span>
{summary.value.totalOrderAmount.toFixed(2)}
</span>
</span> </span>
<span class={pageStyles.summaryItem}> <span class={pageStyles.summaryItem}>
<span class={pageStyles.summaryLabel}></span> <span class={pageStyles.summaryLabel}></span>
<span class={pageStyles.summaryValue}> <span class={pageStyles.summaryValue}>{summary.value.totalActualAmount}</span>
{summary.value.totalPaidAmount.toFixed(2)}
</span>
</span> </span>
<span class={pageStyles.summaryItem}> <span class={pageStyles.summaryItem}>
<span class={pageStyles.summaryLabel}>退</span> <span class={pageStyles.summaryLabel}>退</span>
<span class={pageStyles.summaryValue}> <span class={pageStyles.summaryValue}>{summary.value.totalRefundAmount}</span>
{summary.value.totalRefundAmount.toFixed(2)}
</span>
</span> </span>
</div> </div>
+3 -3
View File
@@ -49,9 +49,9 @@ export const ORDER_STATUS_OPTIONS = [
{ value: '4', label: '超时关闭' }, { value: '4', label: '超时关闭' },
] as const; ] as const;
/** 退款状态选项(value 对应 API refundStatus: 不传=全部、0=退款失败,1=退款成功 */ /** 退款状态选项(value 对应 API refundStatus: 不传=全部、2=退款成功,3=退款失败 */
export const REFUND_STATUS_OPTIONS = [ export const REFUND_STATUS_OPTIONS = [
{ value: '', label: '全部' }, { value: '', label: '全部' },
{ value: '1', label: '退款成功' }, { value: '2', label: '退款成功' },
{ value: '0', label: '退款失败' }, { value: '3', label: '退款失败' },
] as const; ] as const;
+3 -1
View File
@@ -11,6 +11,7 @@ import type {
TournamentAdminOrderPageVO, TournamentAdminOrderPageVO,
TournamentAdminOrderInfoVO, TournamentAdminOrderInfoVO,
TournamentAdminOrderInfoPageVO, TournamentAdminOrderInfoPageVO,
OrderPageData,
PageData, PageData,
ApiResult, ApiResult,
} from '@/api/orders/types'; } from '@/api/orders/types';
@@ -24,6 +25,7 @@ export type {
OrderDetailQueryParams, OrderDetailQueryParams,
OrderPlayerListQueryParams, OrderPlayerListQueryParams,
RetryRefundParams, RetryRefundParams,
OrderPageData,
PageData, PageData,
ApiResult, ApiResult,
} from '@/api/orders/types'; } from '@/api/orders/types';
@@ -43,7 +45,7 @@ const retryRefund = '/admin/manager/order/retryRefund';
/** 订单管理 - 订单分页 */ /** 订单管理 - 订单分页 */
export async function getOrderList( export async function getOrderList(
params: OrderListQueryParams, params: OrderListQueryParams,
): Promise<ApiResult<PageData<TournamentAdminOrderPageVO>>> { ): Promise<ApiResult<OrderPageData>> {
return get(orderList, params as Record<string, any>); return get(orderList, params as Record<string, any>);
} }
+29 -41
View File
@@ -1,15 +1,14 @@
import { computed, reactive, toRef, Ref, h } from 'vue'; import { computed, reactive, toRef, Ref, h, nextTick } from 'vue';
import Big from 'big.js';
import { StatusTag, type StatusTagTone } from '@/components'; import { StatusTag, type StatusTagTone } from '@/components';
import { useDebounce } from '@/hooks'; import { useDebounce } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination } from '@/hooks/usePagination'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination';
import { hasValue, isEmptyValue, safeTransform } from '@/utils'; import { hasValue, isEmptyValue, safeTransform } from '@/utils';
import type { import type {
TournamentAdminOrderPageVO, TournamentAdminOrderPageVO,
OrderListQueryParams, OrderListQueryParams,
PageData, OrderPageData,
ApiResult, ApiResult,
} from './services'; } from './services';
import { getOrderList } from './services'; import { getOrderList } from './services';
@@ -23,18 +22,18 @@ import {
export { ORDER_STATUS_OPTIONS, REFUND_STATUS_OPTIONS }; export { ORDER_STATUS_OPTIONS, REFUND_STATUS_OPTIONS };
/** 订单状态 StatusTag 映射 */ /** 订单状态 StatusTag 映射 */
const ORDER_STATUS_MAP: Record<number, { label: string; tone: StatusTagTone }> = { const ORDER_STATUS_MAP: Record<string, { label: string; tone: StatusTagTone }> = {
1: { label: '支付成功', tone: 'success' }, '1': { label: '支付成功', tone: 'success' },
2: { label: '部分退款', tone: 'orange' }, '2': { label: '部分退款', tone: 'orange' },
3: { label: '全部退款', tone: 'primary' }, '3': { label: '全部退款', tone: 'primary' },
4: { label: '已关闭', tone: 'default' }, '4': { label: '已关闭', tone: 'default' },
}; };
/** 退款状态 StatusTag 映射 */ /** 退款状态 StatusTag 映射 */
const REFUND_STATUS_MAP: Record<number, { label: string; tone: StatusTagTone }> = { const REFUND_STATUS_MAP: Record<string, { label: string; tone: StatusTagTone }> = {
1: { label: '无退款', tone: 'default' }, '1': { label: '无退款', tone: 'default' },
2: { label: '退款成功', tone: 'success' }, '2': { label: '退款成功', tone: 'success' },
3: { label: '退款失败', tone: 'danger' }, '3': { label: '退款失败', tone: 'danger' },
}; };
/** /**
@@ -82,12 +81,12 @@ export function useOrderModel() {
data, data,
loading, loading,
run: fetchList, run: fetchList,
} = useRequest<ApiResult<PageData<TournamentAdminOrderPageVO>>>( } = useRequest<ApiResult<OrderPageData>>(() => getOrderList(buildQueryParams()), {
() => getOrderList(buildQueryParams()), refreshDeps: [],
{ refreshDeps: [], formatResult: (res) => res }, formatResult: (res) => res,
); });
const listData = computed<PageData<TournamentAdminOrderPageVO> | undefined>(() => { const listData = computed<OrderPageData | undefined>(() => {
const res = data.value; const res = data.value;
return res ? (res as any).data : undefined; return res ? (res as any).data : undefined;
}); });
@@ -95,26 +94,16 @@ export function useOrderModel() {
const dataSource = computed(() => listData.value?.list || []); const dataSource = computed(() => listData.value?.list || []);
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
/** 金额汇总(API 直接返回,无需前端累加) */
const summary = computed(() => { const summary = computed(() => {
const list = listData.value?.list || []; const d = listData.value;
let totalOrder = new Big(0);
let totalPaid = new Big(0);
let totalRefund = new Big(0);
for (const item of list) {
totalOrder = totalOrder.plus(new Big(item.creatorSignupFee || 0));
totalPaid = totalPaid.plus(new Big(item.creatorSignupFeeActual || 0));
totalRefund = totalRefund.plus(new Big(item.creatorSignupFeeRefund || 0));
}
return { return {
totalOrderAmount: totalOrder.toNumber(), totalOrderAmount: d?.exData?.totalOrderAmount || '0',
totalPaidAmount: totalPaid.toNumber(), totalActualAmount: d?.exData?.totalActualAmount || '0',
totalRefundAmount: totalRefund.toNumber(), totalRefundAmount: d?.exData?.totalRefundAmount || '0',
}; };
}); });
@@ -189,9 +178,9 @@ export function useOrderModel() {
dataIndex: 'orderStatus', dataIndex: 'orderStatus',
key: 'orderStatus', key: 'orderStatus',
width: 100, width: 100,
customRender: ({ text }: { text: number }) => { customRender: ({ text }: { text: string }) => {
const info = ORDER_STATUS_MAP[text] || { const info = ORDER_STATUS_MAP[text] || {
label: String(text ?? '-'), label: String(text ?? '--'),
tone: 'default' as const, tone: 'default' as const,
}; };
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
@@ -203,9 +192,8 @@ export function useOrderModel() {
key: 'refundStatus', key: 'refundStatus',
width: 100, width: 100,
align: 'center' as const, align: 'center' as const,
customRender: ({ text }: { text: number }) => { customRender: ({ text }: { text: string }) => {
if (text === 1) return h('span', '-'); const info = REFUND_STATUS_MAP[text] || { label: '--', tone: 'default' as const };
const info = REFUND_STATUS_MAP[text] || { label: String(text), tone: 'default' as const };
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
}, },
}, },
@@ -224,7 +212,7 @@ export function useOrderModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
return { return {
+1 -1
View File
@@ -36,7 +36,7 @@ export default defineComponent({
/** 渲染操作列 */ /** 渲染操作列 */
const renderAction = (record: any) => { const renderAction = (record: any) => {
if (!canToggleStatus) return <span>-</span>; if (!canToggleStatus) return <span>--</span>;
const isActive = record.status === '1'; const isActive = record.status === '1';
return ( return (
@@ -62,7 +62,7 @@ export function useUserColumns() {
align: 'center' as const, align: 'center' as const,
customRender: ({ text }: { text: string[] }): VNodeChild => { customRender: ({ text }: { text: string[] }): VNodeChild => {
const imgList = Array.isArray(text) ? text : []; const imgList = Array.isArray(text) ? text : [];
if (imgList.length === 0) return '-'; if (imgList.length === 0) return '--';
return h( return h(
Space, Space,
{ size: 4 }, { size: 4 },
+7 -4
View File
@@ -3,7 +3,11 @@ import { Modal, message } from 'ant-design-vue';
import { useState, useDebounce } from '@/hooks'; import { useState, useDebounce } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination, type UsePaginationReturn } from '@/hooks/usePagination'; import {
usePagination,
syncPaginationTotal,
type UsePaginationReturn,
} from '@/hooks/usePagination';
import { hasValue, isEmptyValue, safeTransform } from '@/utils'; import { hasValue, isEmptyValue, safeTransform } from '@/utils';
import { import {
getUserList, getUserList,
@@ -94,9 +98,8 @@ export function useUserModel() {
// 同步分页总条数 // 同步分页总条数
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
// ===== 计算属性 ===== // ===== 计算属性 =====
const hasFilter = computed(() => { const hasFilter = computed(() => {
@@ -1,5 +1,12 @@
import { computed, reactive, toRef, Ref } from 'vue'; import { computed, reactive, toRef, Ref, nextTick } from 'vue';
import { useDebounce, useThrottleFn, useRequest, usePagination, useEffect } from '@/hooks'; import {
useDebounce,
useThrottleFn,
useRequest,
usePagination,
useEffect,
syncPaginationTotal,
} from '@/hooks';
import { getPaymentFlowList, type PaymentFlowVO, type PaymentFlowQueryParams } from './services'; import { getPaymentFlowList, type PaymentFlowVO, type PaymentFlowQueryParams } from './services';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@@ -81,9 +88,8 @@ export function usePaymentsModel() {
// 同步 total 到 pagination // 同步 total 到 pagination
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
// ===== 表格列(dataIndex 对齐 API ===== // ===== 表格列(dataIndex 对齐 API =====
const columns = [ const columns = [
@@ -94,7 +100,7 @@ export function usePaymentsModel() {
dataIndex: 'type', dataIndex: 'type',
key: 'type', key: 'type',
width: 110, width: 110,
customRender: ({ text }: { text: number }) => PAYMENT_TYPE_MAP[text] || text || '-', customRender: ({ text }: { text: number }) => PAYMENT_TYPE_MAP[text] || text || '--',
}, },
{ title: '用户昵称', dataIndex: 'nickname', key: 'nickname', width: 120 }, { title: '用户昵称', dataIndex: 'nickname', key: 'nickname', width: 120 },
{ title: '手机号', dataIndex: 'phone', key: 'phone', width: 140 }, { title: '手机号', dataIndex: 'phone', key: 'phone', width: 140 },
@@ -136,7 +142,7 @@ export function usePaymentsModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
return { return {
@@ -113,7 +113,7 @@ export default defineComponent({
dataIndex: 'type', dataIndex: 'type',
key: 'type', key: 'type',
width: 120, width: 120,
customRender: ({ text }: { text: number }) => TRANSACTION_TYPE_MAP[text] || text || '-', customRender: ({ text }: { text: number }) => TRANSACTION_TYPE_MAP[text] || text || '--',
}, },
{ {
title: '金额', title: '金额',
@@ -162,14 +162,14 @@ export default defineComponent({
dataIndex: 'freezeTime', dataIndex: 'freezeTime',
key: 'freezeTime', key: 'freezeTime',
width: 140, width: 140,
customRender: ({ text }: { text: string }) => text || '-', customRender: ({ text }: { text: string }) => text || '--',
}, },
{ {
title: '解冻时间', title: '解冻时间',
dataIndex: 'unfreezeTime', dataIndex: 'unfreezeTime',
key: 'unfreezeTime', key: 'unfreezeTime',
width: 140, width: 140,
customRender: ({ text }: { text: string }) => text || '-', customRender: ({ text }: { text: string }) => text || '--',
}, },
{ {
title: '关联单号', title: '关联单号',
+1 -1
View File
@@ -30,7 +30,7 @@ function renderBodyCell({
canViewDetail: boolean; canViewDetail: boolean;
}) { }) {
if (column.key === 'action') { if (column.key === 'action') {
if (!canViewDetail) return <span>-</span>; if (!canViewDetail) return <span>--</span>;
return ( return (
<Button type="link" size="small" onClick={() => onViewDetail(record)}> <Button type="link" size="small" onClick={() => onViewDetail(record)}>
@@ -1,4 +1,4 @@
import { computed, reactive, toRef, Ref } from 'vue'; import { computed, reactive, toRef, Ref, nextTick } from 'vue';
import { import {
useState, useState,
useDebounce, useDebounce,
@@ -6,6 +6,7 @@ import {
useRequest, useRequest,
usePagination, usePagination,
useEffect, useEffect,
syncPaginationTotal,
} from '@/hooks'; } from '@/hooks';
import { getWalletList, type WalletSummaryVO, type WalletQueryParams } from './services'; import { getWalletList, type WalletSummaryVO, type WalletQueryParams } from './services';
@@ -111,9 +112,8 @@ export function useWalletModel() {
// 同步 total 到 pagination // 同步 total 到 pagination
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
// ===== 详情弹窗状态 ===== // ===== 详情弹窗状态 =====
const [detailVisible, setDetailVisible] = useState<boolean>(false); const [detailVisible, setDetailVisible] = useState<boolean>(false);
@@ -175,7 +175,7 @@ export function useWalletModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
const handleViewDetail = (record: any) => { const handleViewDetail = (record: any) => {
@@ -153,14 +153,14 @@ export default defineComponent({
const renderItem = (label: string, value: any, isBold = false) => ( const renderItem = (label: string, value: any, isBold = false) => (
<div class={styles.descItem}> <div class={styles.descItem}>
<span class={styles.descLabel}>{label}</span> <span class={styles.descLabel}>{label}</span>
<span class={[styles.descValue, isBold ? styles.descValueBold : '']}>{value || '-'}</span> <span class={[styles.descValue, isBold ? styles.descValueBold : '']}>{value || '--'}</span>
</div> </div>
); );
/** 渲染内容区(加载完成后) */ /** 渲染内容区(加载完成后) */
const renderContent = () => { const renderContent = () => {
const d = detail.value!; const d = detail.value!;
const bankCardTypeLabel = d.bankCardType === 1 ? '个人' : d.bankCardType || '-'; const bankCardTypeLabel = d.bankCardType === 1 ? '个人' : d.bankCardType || '--';
const isPending = d.auditStatus == 0; const isPending = d.auditStatus == 0;
return ( return (
@@ -200,7 +200,7 @@ export default defineComponent({
<div class={styles.section}> <div class={styles.section}>
<div class={styles.sectionTitle}></div> <div class={styles.sectionTitle}></div>
<div class={styles.descGrid}> <div class={styles.descGrid}>
{renderItem('到账支付时间:', d.payTime || '-')} {renderItem('到账支付时间:', d.payTime || '--')}
{renderItem('订单号:', d.orderNo)} {renderItem('订单号:', d.orderNo)}
</div> </div>
</div> </div>
@@ -1,4 +1,4 @@
import { computed, reactive, toRef, Ref, h } from 'vue'; import { computed, reactive, toRef, Ref, h, nextTick } from 'vue';
import { StatusTag, type StatusTagTone } from '@/components'; import { StatusTag, type StatusTagTone } from '@/components';
import { import {
useState, useState,
@@ -7,6 +7,7 @@ import {
useRequest, useRequest,
usePagination, usePagination,
useEffect, useEffect,
syncPaginationTotal,
} from '@/hooks'; } from '@/hooks';
import { getWithdrawList, type WithdrawVO, type WithdrawQueryParams } from './services'; import { getWithdrawList, type WithdrawVO, type WithdrawQueryParams } from './services';
@@ -47,7 +48,7 @@ const PAY_STATUS_MAP: Record<number, { label: string; tone: StatusTagTone }> = {
/** 渲染审核状态 StatusTag */ /** 渲染审核状态 StatusTag */
export function renderAuditStatus(status: number) { export function renderAuditStatus(status: number) {
const info = AUDIT_STATUS_MAP[status] || { const info = AUDIT_STATUS_MAP[status] || {
label: String(status ?? '-'), label: String(status ?? '--'),
tone: 'default' as const, tone: 'default' as const,
}; };
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
@@ -61,12 +62,12 @@ export function renderPayStatus(status: number) {
/** 获取审核状态纯文本(详情弹窗用) */ /** 获取审核状态纯文本(详情弹窗用) */
export function getAuditStatusText(status: number): string { export function getAuditStatusText(status: number): string {
return AUDIT_STATUS_MAP[status]?.label ?? String(status ?? '-'); return AUDIT_STATUS_MAP[status]?.label ?? String(status ?? '--');
} }
/** 获取到账状态纯文本(详情弹窗用) */ /** 获取到账状态纯文本(详情弹窗用) */
export function getPayStatusText(status: number): string { export function getPayStatusText(status: number): string {
return PAY_STATUS_MAP[status]?.label ?? String(status ?? '-'); return PAY_STATUS_MAP[status]?.label ?? String(status ?? '--');
} }
// ============================================================ // ============================================================
@@ -132,9 +133,8 @@ export function useWithdrawModel() {
// 同步 total 到 pagination // 同步 total 到 pagination
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, listData.value?.total);
if (total !== undefined) pagination.setTotal(total); }, [listData]);
}, [data]);
// ===== 审核弹窗状态 ===== // ===== 审核弹窗状态 =====
const [auditVisible, setAuditVisible] = useState<boolean>(false); const [auditVisible, setAuditVisible] = useState<boolean>(false);
@@ -197,7 +197,7 @@ export function useWithdrawModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
/** 打开审核弹窗 */ /** 打开审核弹窗 */
+2 -2
View File
@@ -11,9 +11,9 @@ const { RangePicker } = DatePicker;
*/ */
function renderBodyCell({ column, text }: { column: any; text: any }) { function renderBodyCell({ column, text }: { column: any; text: any }) {
if (column.key === 'type') { if (column.key === 'type') {
return <span>{ACTION_TYPE_MAP[text as number] || text || '-'}</span>; return <span>{ACTION_TYPE_MAP[text as number] || text || '--'}</span>;
} }
return <span>{text || '-'}</span>; return <span>{text || '--'}</span>;
} }
/** /**
+4 -5
View File
@@ -1,9 +1,9 @@
import { computed, reactive, toRef, Ref } from 'vue'; import { computed, reactive, toRef, Ref, nextTick } from 'vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useDebounce, useThrottleFn } from '@/hooks'; import { useDebounce, useThrottleFn } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination } from '@/hooks/usePagination'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination';
import { import {
getOperationLogList, getOperationLogList,
type SysOperationLogVO, type SysOperationLogVO,
@@ -100,8 +100,7 @@ export function useLogModel() {
}); });
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, (data.value as any)?.data?.total);
if (total !== undefined) pagination.setTotal(total);
}, [data]); }, [data]);
// ===== 表格列配置(字段名对齐 API ===== // ===== 表格列配置(字段名对齐 API =====
@@ -139,7 +138,7 @@ export function useLogModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
return { return {
@@ -1,4 +1,4 @@
import { defineComponent, ref, reactive } from 'vue'; import { defineComponent, ref, reactive, nextTick } from 'vue';
import { useEffect } from '@/hooks'; import { useEffect } from '@/hooks';
import { Modal, Form, Input, Tree, Button, Spin, message } from 'ant-design-vue'; import { Modal, Form, Input, Tree, Button, Spin, message } from 'ant-design-vue';
import type { TreeProps } from 'ant-design-vue'; import type { TreeProps } from 'ant-design-vue';
@@ -82,7 +82,7 @@ export default defineComponent({
useEffect(() => { useEffect(() => {
if (props.visible) { if (props.visible) {
initFormFromRecord(props.record); initFormFromRecord(props.record);
setTimeout(() => formRef.value?.clearValidate(), 0); nextTick().then(() => formRef.value?.clearValidate());
} }
}, [() => props.visible]); }, [() => props.visible]);
@@ -44,7 +44,10 @@ export default defineComponent({
width: 90, width: 90,
align: 'center' as const, align: 'center' as const,
customRender: ({ text }: { text: number }) => { customRender: ({ text }: { text: number }) => {
const info = STATUS_MAP[text] || { label: String(text ?? '-'), tone: 'default' as const }; const info = STATUS_MAP[text] || {
label: String(text ?? '--'),
tone: 'default' as const,
};
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
}, },
}, },
+1 -1
View File
@@ -40,7 +40,7 @@ function renderBodyCell({
if (column.key === 'action') { if (column.key === 'action') {
const { canEdit, canDelete } = permissions; const { canEdit, canDelete } = permissions;
if (!canEdit && !canDelete) return <span>-</span>; if (!canEdit && !canDelete) return <span>--</span>;
return ( return (
<Space> <Space>
+4 -5
View File
@@ -1,9 +1,9 @@
import { computed, reactive, toRef, Ref } from 'vue'; import { computed, reactive, toRef, Ref, nextTick } from 'vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useState, useDebounce, useThrottleFn } from '@/hooks'; import { useState, useDebounce, useThrottleFn } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination } from '@/hooks/usePagination'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination';
import { import {
getRoleList, getRoleList,
saveRole, saveRole,
@@ -61,8 +61,7 @@ export function useRoleModel() {
}); });
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, (data.value as any)?.data?.total);
if (total !== undefined) pagination.setTotal(total);
}, [data]); }, [data]);
// ===== 弹窗状态 ===== // ===== 弹窗状态 =====
@@ -108,7 +107,7 @@ export function useRoleModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
/** 新增 */ /** 新增 */
@@ -1,4 +1,4 @@
import { defineComponent, ref, reactive } from 'vue'; import { defineComponent, ref, reactive, nextTick } from 'vue';
import { useEffect, useState } from '@/hooks'; import { useEffect, useState } from '@/hooks';
import { Modal, Form, Input, Select, Button } from 'ant-design-vue'; import { Modal, Form, Input, Select, Button } from 'ant-design-vue';
import { getRoleList, type TournamentAdminRolePageVO } from '../../roles/model/services'; import { getRoleList, type TournamentAdminRolePageVO } from '../../roles/model/services';
@@ -166,7 +166,7 @@ export default defineComponent({
if (props.visible) { if (props.visible) {
initFormFromRecord(props.record); initFormFromRecord(props.record);
setIsResetting(false); setIsResetting(false);
setTimeout(() => formRef.value?.clearValidate(), 0); nextTick().then(() => formRef.value?.clearValidate());
} }
}, [() => props.visible]); }, [() => props.visible]);
+1 -1
View File
@@ -41,7 +41,7 @@ function renderBodyCell({
if (column.key === 'action') { if (column.key === 'action') {
const isActive = record.status === '1'; const isActive = record.status === '1';
const { canEdit, canToggleStatus } = permissions; const { canEdit, canToggleStatus } = permissions;
if (!canEdit && !canToggleStatus) return <span>-</span>; if (!canEdit && !canToggleStatus) return <span>--</span>;
return ( return (
<Space> <Space>
+5 -6
View File
@@ -1,10 +1,10 @@
import { computed, reactive, toRef, Ref, h, ref } from 'vue'; import { computed, reactive, toRef, Ref, h, ref, nextTick } from 'vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { StatusTag, type StatusTagTone } from '@/components'; import { StatusTag, type StatusTagTone } from '@/components';
import { useDebounce, useThrottleFn } from '@/hooks'; import { useDebounce, useThrottleFn } from '@/hooks';
import { useRequest } from '@/hooks/useRequest'; import { useRequest } from '@/hooks/useRequest';
import { useEffect } from '@/hooks/useEffect'; import { useEffect } from '@/hooks/useEffect';
import { usePagination } from '@/hooks/usePagination'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination';
import { import {
getUserList, getUserList,
type TournamentAdminUserVO, type TournamentAdminUserVO,
@@ -102,8 +102,7 @@ export function useUserModel() {
}); });
useEffect(() => { useEffect(() => {
const total = (data.value as any)?.data?.total; syncPaginationTotal(pagination, (data.value as any)?.data?.total);
if (total !== undefined) pagination.setTotal(total);
}, [data]); }, [data]);
// ===== 表格列配置 ===== // ===== 表格列配置 =====
@@ -118,7 +117,7 @@ export function useUserModel() {
width: 100, width: 100,
align: 'center' as const, align: 'center' as const,
customRender: ({ text }: { text: string }) => { customRender: ({ text }: { text: string }) => {
const info = STATUS_MAP[text] || { label: text || '-', tone: 'default' as const }; const info = STATUS_MAP[text] || { label: text || '--', tone: 'default' as const };
return h(StatusTag, { label: info.label, tone: info.tone }); return h(StatusTag, { label: info.label, tone: info.tone });
}, },
}, },
@@ -151,7 +150,7 @@ export function useUserModel() {
if (pageSize !== (pagination as any).pageSize.value) { if (pageSize !== (pagination as any).pageSize.value) {
pagination.setPageSize(pageSize); pagination.setPageSize(pageSize);
} }
setTimeout(fetchList, 0); nextTick().then(() => fetchList());
}; };
// ===== 初始化:加载角色选项 ===== // ===== 初始化:加载角色选项 =====