fix: 赛事列表详情弹窗修复

This commit is contained in:
ZhuRui
2026-08-06 09:54:11 +08:00
parent 8c7e8f807c
commit 7f16ccdb30
4 changed files with 158 additions and 100 deletions
+1 -1
View File
@@ -143,7 +143,7 @@ export interface TournamentAdminInfoVO {
/** 退赛人数 */
dropoutCount: string;
/** 允许报名最大人数 */
dtotalLimit: string;
totalLimit: string;
/** 总对阵数 */
matchTotalCount: string;
/** 已完成对阵数 */
@@ -1,5 +1,7 @@
import { defineComponent, reactive } from 'vue';
import { Modal, Descriptions, Image, Radio, Input, Form, message } from 'ant-design-vue';
import { defineComponent, reactive, ref } from 'vue';
import { Modal, Descriptions, Image, Radio, Input, Form, Spin, message } from 'ant-design-vue';
import { useEffect, useState } from '@/hooks';
import { getEventDetail, type TournamentAdminInfoVO } from '../model/services';
import { validateEventAuditSubmit } from '../model/form';
import styles from './EventAuditModal.module.less';
@@ -12,31 +14,6 @@ interface EventAuditModalProps {
onSubmit?: (payload: { approved: boolean; comment: string }) => void;
}
// ===== Mock 数据 =====
const MOCK_DETAIL = {
name: '第二届全国地学羽毛球邀请赛',
eventTime: '2026.05.26 08:00 ~ 2026.05.31 22:00',
descr:
'赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍赛事介绍。',
registerTime: '2026.05.24 08:00 ~ 2026.05.26 22:00',
cancelDeadline: '2026.05.25 22:00',
region: '北京市 北京市 东城区',
address: '李宁体育馆',
venueNo: '李宁体育馆',
publicEvent: '在首页展示赛事',
needIdCard: '无需提供',
needIdCardImage: '无需提供',
createTime: '2026.05.26 08:00',
creator: '张三',
status: '待审核',
enrolledCount: 100,
cancelledCount: 1,
maxCount: 1000,
crossedCount: 50,
completedCount: 50,
cover: 'https://picsum.photos/seed/eventcover/600/300',
};
/**
* 赛事审核弹窗
* 包含:基础信息 + 封面 + 审核操作(通过/未通过 + 审核内容)
@@ -50,7 +27,8 @@ export default defineComponent({
onSubmit: { type: Function, default: undefined },
},
setup(props: EventAuditModalProps) {
const detail = MOCK_DETAIL;
const detail = ref<TournamentAdminInfoVO | null>(null);
const [loading, setLoading] = useState(false);
// 审核表单
const auditForm = reactive({
@@ -58,6 +36,33 @@ export default defineComponent({
comment: '',
});
/** 加载赛事详情 */
const fetchDetail = async (id: string) => {
setLoading(true);
detail.value = null;
try {
const res = await getEventDetail(id);
if (res.code == 200) {
detail.value = res.data;
} else {
message.error(res.msg || '获取赛事详情失败');
}
} catch {
// 网络层已统一提示
} finally {
setLoading(false);
}
};
/** 弹窗打开时重新拉取详情 */
useEffect(() => {
if (props.visible && props.record?.id) {
auditForm.approved = true;
auditForm.comment = '';
fetchDetail(props.record.id);
}
}, [() => props.visible]);
const handleOk = () => {
const check = validateEventAuditSubmit({
approved: auditForm.approved,
@@ -72,63 +77,75 @@ export default defineComponent({
}
};
return () => (
<Modal
visible={props.visible}
title="审核"
width={900}
onCancel={props.onClose}
onOk={handleOk}
okText="提交审核"
cancelText="取消"
centered
destroyOnClose
wrapClassName={styles.eventAuditModalMain}
>
/** 格式化时间范围 */
const formatRange = (start: string, end: string) => {
if (!start && !end) return '-';
return `${start || '?'} ~ ${end || '?'}`;
};
/** 渲染 0/1 开关文本 */
const boolText = (val: string, trueText: string, falseText: string) => {
return val === '1' ? trueText : falseText;
};
/** 渲染详情内容 */
const renderContent = () => {
const d = detail.value!;
return (
<>
{/* ===== 基础信息 ===== */}
<div class={styles.section}>
<div class={styles.sectionTitle}></div>
<Descriptions size="small" bordered column={3} class={styles.desc}>
<Descriptions.Item label="赛事名称">{detail.name}</Descriptions.Item>
<Descriptions.Item label="赛事名称">{d.name || '-'}</Descriptions.Item>
<Descriptions.Item label="赛事时间" span={2}>
{detail.eventTime}
{formatRange(d.startTimeBegin, d.startTimeEnd)}
</Descriptions.Item>
<Descriptions.Item label="赛事说明" span={3}>
{detail.descr}
{d.descr || '-'}
</Descriptions.Item>
<Descriptions.Item label="报名起止时间">{detail.registerTime}</Descriptions.Item>
<Descriptions.Item label="报名起止时间">
{formatRange(d.signupTimeBegin, d.signupTimeEnd)}
</Descriptions.Item>
<Descriptions.Item label="取消报名截止时间" span={2}>
{detail.cancelDeadline}
{d.signupTimeEnd || '-'}
</Descriptions.Item>
<Descriptions.Item label="省市区">{detail.region}</Descriptions.Item>
<Descriptions.Item label="地点">{detail.address}</Descriptions.Item>
<Descriptions.Item label="场地编号">{detail.venueNo}</Descriptions.Item>
<Descriptions.Item label="省市区">{d.venueArea || '-'}</Descriptions.Item>
<Descriptions.Item label="地点">{d.venue || '-'}</Descriptions.Item>
<Descriptions.Item label="场地编号">{d.venueNo || '-'}</Descriptions.Item>
<Descriptions.Item label="公开活动">{detail.publicEvent}</Descriptions.Item>
<Descriptions.Item label="证件号">{detail.needIdCard}</Descriptions.Item>
<Descriptions.Item label="证件图片">{detail.needIdCardImage}</Descriptions.Item>
<Descriptions.Item label="公开活动">
{boolText(d.isPublic, '在首页展示赛事', '非公开')}
</Descriptions.Item>
<Descriptions.Item label="证件号">
{boolText(d.isRequireIdCardNo, '需要提供', '无需提供')}
</Descriptions.Item>
<Descriptions.Item label="证件图片">
{boolText(d.isRequireIdCardImg, '需要提供', '无需提供')}
</Descriptions.Item>
<Descriptions.Item label="创建时间">{detail.createTime}</Descriptions.Item>
<Descriptions.Item label="创建人">{detail.creator}</Descriptions.Item>
<Descriptions.Item label="状态">{detail.status}</Descriptions.Item>
<Descriptions.Item label="报名人数">{detail.enrolledCount}</Descriptions.Item>
<Descriptions.Item label="创建时间">{d.createTime || '-'}</Descriptions.Item>
<Descriptions.Item label="创建人">{d.createNickname || '-'}</Descriptions.Item>
<Descriptions.Item label="状态"></Descriptions.Item>
<Descriptions.Item label="报名人数">{d.signupCount || '0'}</Descriptions.Item>
<Descriptions.Item label="取消报名人数" span={1}>
{detail.cancelledCount}
{d.dropoutCount || '0'}
</Descriptions.Item>
<Descriptions.Item label="最大人数">{detail.maxCount}</Descriptions.Item>
<Descriptions.Item label="对岸数量">{detail.crossedCount}</Descriptions.Item>
<Descriptions.Item label="已完成对岸数量">{detail.completedCount}</Descriptions.Item>
<Descriptions.Item label="最大人数">{d.dtotalLimit || '-'}</Descriptions.Item>
<Descriptions.Item label="对岸数量">{d.matchTotalCount || '0'}</Descriptions.Item>
<Descriptions.Item label="已完成对岸数量">{d.matchCount || '0'}</Descriptions.Item>
</Descriptions>
</div>
{/* ===== 封面 ===== */}
<div class={styles.section}>
<div class={styles.sectionTitle}></div>
<Image src={detail.cover} />
{d.img ? <Image src={d.img} /> : <span style={{ color: '#999' }}></span>}
</div>
{/* ===== 审核操作 ===== */}
@@ -154,6 +171,30 @@ export default defineComponent({
</Form.Item>
</Form>
</div>
</>
);
};
return () => (
<Modal
visible={props.visible}
title="审核"
width={900}
onCancel={props.onClose}
onOk={handleOk}
okText="提交审核"
cancelText="取消"
centered
destroyOnClose
wrapClassName={styles.eventAuditModalMain}
>
{loading.value ? (
<div style={{ textAlign: 'center', padding: '80px 0' }}>
<Spin size="large" />
</div>
) : detail.value ? (
renderContent()
) : null}
</Modal>
);
},
@@ -34,6 +34,16 @@
}
}
// Item 的 class 会同时挂在 label/content 两个同级 td/th 上,不能用后代选择器
.statCell:global(.ant-descriptions-item-content) {
min-width: 60px;
}
.statCellNoWrap:global(.ant-descriptions-item-label),
.statCellNoWrap:global(.ant-descriptions-item-content) {
white-space: nowrap;
}
.group {
margin-bottom: 16px;
@@ -192,7 +192,9 @@ export default defineComponent({
<Descriptions.Item label="省市区">{detail.value.venueArea}</Descriptions.Item>
<Descriptions.Item label="地点">{detail.value.venue}</Descriptions.Item>
<Descriptions.Item label="场地编号">{detail.value.venueNo}</Descriptions.Item>
<Descriptions.Item label="场地编号" class={styles.statCell}>
{detail.value.venueNo || '-'}
</Descriptions.Item>
<Descriptions.Item label="公开活动">
{formatPublic(detail.value.isPublic)}
@@ -200,7 +202,7 @@ export default defineComponent({
<Descriptions.Item label="证件号">
{formatYN(detail.value.isRequireIdCardNo)}
</Descriptions.Item>
<Descriptions.Item label="证件图片">
<Descriptions.Item label="证件图片" class={styles.statCell}>
{formatYN(detail.value.isRequireIdCardImg)}
</Descriptions.Item>
@@ -211,7 +213,12 @@ export default defineComponent({
<Descriptions.Item label="报名人数">{detail.value.signupCount}</Descriptions.Item>
<Descriptions.Item label="退赛人数">{detail.value.dropoutCount}</Descriptions.Item>
<Descriptions.Item label="最大人数">{detail.value.dtotalLimit}</Descriptions.Item>
<Descriptions.Item
label="最大人数"
class={[styles.statCell, styles.statCellNoWrap]}
>
{detail.value.totalLimit || '-'}
</Descriptions.Item>
<Descriptions.Item label="总对阵数">
{detail.value.matchTotalCount}