update:赛事详情
This commit is contained in:
parent
c876bbaa87
commit
002940a41b
@ -54,27 +54,199 @@
|
||||
</ProTable>
|
||||
|
||||
<!-- 赛事详情弹窗 -->
|
||||
<el-dialog title="赛事详情" v-model="isShowDetailDialog" width="80%" style="min-height: 600px;"
|
||||
@closed="clearDetailState">
|
||||
<el-skeleton :rows="12" animated v-if="detailLoading" />
|
||||
<template v-else>
|
||||
<div v-if="formData">
|
||||
<Step1BasicInfo v-model:modelValue="formData.basicInfo" :readonly="true" />
|
||||
<div style="height:50px;"></div>
|
||||
<Step2Units v-model:modelValue="formData.units" :readonly="true" />
|
||||
<div style="height:50px;"></div>
|
||||
<Step3ProjectConfig v-model:modelValue="projectConfigWithRegistrationType" :readonly="true" />
|
||||
<div style="height:50px;"></div>
|
||||
<UserStep4FeeConfig v-model:modelValue="formData.feeConfig" :readonly="true" />
|
||||
<div style="height:100px;"></div>
|
||||
<el-dialog v-model="isShowDetailDialog" width="82%" class="event-detail-dialog"
|
||||
@closed="clearDetailState" :close-on-click-modal="false">
|
||||
<template #header="{ close }">
|
||||
<div class="detail-dialog-custom-header">
|
||||
<div class="detail-dialog-header-badge">赛</div>
|
||||
<span class="detail-dialog-header-title">赛事详情</span>
|
||||
<el-button class="detail-dialog-close-btn" :icon="Close" circle text @click="close" />
|
||||
</div>
|
||||
<el-empty v-else description="暂无详情数据" />
|
||||
</template>
|
||||
|
||||
<el-skeleton :rows="12" animated v-if="detailLoading" style="padding: 24px;" />
|
||||
<template v-else>
|
||||
<div v-if="formData" class="event-detail-content">
|
||||
|
||||
<!-- Hero:封面 + 核心字段 -->
|
||||
<div class="edc-hero">
|
||||
<div class="edc-cover-wrap">
|
||||
<PreviewImage
|
||||
v-if="formData.basicInfo.coverImage"
|
||||
:src="formData.basicInfo.coverImage"
|
||||
width="100%"
|
||||
height="100%"
|
||||
fit="cover"
|
||||
:show-zoom-icon="true"
|
||||
class="edc-cover-img"
|
||||
/>
|
||||
<div v-else class="edc-cover-empty">
|
||||
<el-icon :size="40" color="#c0c4cc"><Picture /></el-icon>
|
||||
<span>暂无封面</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edc-hero-right">
|
||||
<h2 class="edc-event-name">{{ formData.basicInfo.eventName || '-' }}</h2>
|
||||
<div class="edc-badge-row">
|
||||
<el-tag v-if="detailStatusFromList !== null && detailStatusFromList !== undefined" :type="getEventStatusTagType(detailStatusFromList)" size="large" effect="dark">
|
||||
{{ getEventStatusText(detailStatusFromList) }}
|
||||
</el-tag>
|
||||
<el-tag :type="formData.basicInfo.eventType === 0 ? 'primary' : 'info'" size="large">
|
||||
{{ formData.basicInfo.eventType === 0 ? '线上' : formData.basicInfo.eventType === 1 ? '线下' : '-' }}
|
||||
</el-tag>
|
||||
<el-tag type="warning" size="large">
|
||||
{{ registrationTypeText({ registrationType: formData.basicInfo.registrationType }) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="edc-kv-list">
|
||||
<div class="edc-kv-item">
|
||||
<span class="edc-kv-label">赛事地点</span>
|
||||
<span class="edc-kv-val">{{ [formData.basicInfo.provinceName, formData.basicInfo.cityName, formData.basicInfo.districtName].filter(x => x).join(' · ') || '-' }}</span>
|
||||
</div>
|
||||
<div class="edc-kv-item" v-if="formData.basicInfo.detailAddress">
|
||||
<span class="edc-kv-label">详细地址</span>
|
||||
<span class="edc-kv-val">{{ formData.basicInfo.detailAddress }}</span>
|
||||
</div>
|
||||
<div class="edc-kv-item">
|
||||
<span class="edc-kv-label">收费模式</span>
|
||||
<el-tag size="small" :type="getDetailChargeModeTagType(formData.feeConfig.chargeMode)">
|
||||
{{ getDetailChargeModeText(formData.feeConfig.chargeMode) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="edc-kv-item edc-kv-item--block">
|
||||
<span class="edc-kv-label">退款规则</span>
|
||||
<span class="edc-kv-val edc-kv-val--multiline">{{ formatRefundRulesBrief(detailData?.refundRules) }}</span>
|
||||
</div>
|
||||
<div class="edc-kv-item edc-kv-item--block">
|
||||
<span class="edc-kv-label">积分规则</span>
|
||||
<span class="edc-kv-val edc-kv-val--multiline">{{ formatPointsRuleBrief(detailData?.pointsRuleDetail, formData.basicInfo.pointsRuleName) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 报名项目 -->
|
||||
<div class="edc-section" v-if="formData.projectConfig?.projects?.length">
|
||||
<div class="edc-section-hd">
|
||||
<el-icon class="edc-section-icon"><Trophy /></el-icon>
|
||||
<span class="edc-section-title">报名项目</span>
|
||||
<span class="edc-section-count">共 {{ formData.projectConfig.projects.length }} 个</span>
|
||||
</div>
|
||||
<!-- 限报提示条 -->
|
||||
<div class="edc-reg-limit-bar" v-if="formData.projectConfig.registrationLimit">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
<span>限报
|
||||
<strong>{{ formData.projectConfig.registrationLimit.teamProjectLimit ?? 1 }}</strong> 个团队、<strong>{{ formData.projectConfig.registrationLimit.individualProjectLimit ?? 1 }}</strong> 个个人
|
||||
</span>
|
||||
</div>
|
||||
<div class="edc-proj-list">
|
||||
<div class="edc-proj-card" v-for="(proj, pi) in formData.projectConfig.projects" :key="proj.id ?? pi">
|
||||
<div class="edc-proj-hd">
|
||||
<div class="edc-proj-num">{{ pi + 1 }}</div>
|
||||
<div class="edc-proj-info">
|
||||
<span class="edc-proj-name">{{ proj.name }}</span>
|
||||
<div class="edc-proj-tags">
|
||||
<el-tag type="info" size="small" v-if="proj.projectTypeName || proj.parentProjectTypeName">
|
||||
{{ proj.projectTypeName || proj.parentProjectTypeName }}
|
||||
</el-tag>
|
||||
<el-tag type="warning" size="small" v-if="proj.durationMinutes || proj.durationSeconds">
|
||||
{{ proj.durationMinutes ?? 0 }}分{{ proj.durationSeconds ?? 0 }}秒
|
||||
</el-tag>
|
||||
<!-- 仅单价(项目)模式才展示项目单价 -->
|
||||
<el-tag type="success" size="small" v-if="detailChargeMode === 3 && proj.fee !== undefined && proj.fee !== null">
|
||||
¥{{ proj.fee }}
|
||||
</el-tag>
|
||||
<el-tag type="primary" size="small" v-if="proj.limitCount">
|
||||
限报 {{ proj.limitCount }} 人
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edc-group-table" v-if="proj.groups?.length">
|
||||
<div class="edc-group-row edc-group-header">
|
||||
<span>组别名称</span>
|
||||
<span>出生日期范围</span>
|
||||
<span>性别</span>
|
||||
</div>
|
||||
<div class="edc-group-row" v-for="(g, gi) in proj.groups" :key="g.id ?? gi">
|
||||
<span class="edc-group-name">{{ g.groupName || '-' }}</span>
|
||||
<span class="edc-group-date">
|
||||
{{ g.birthDateStart ? g.birthDateStart.slice(0, 10) : '不限' }}
|
||||
~
|
||||
{{ g.birthDateEnd ? g.birthDateEnd.slice(0, 10) : '不限' }}
|
||||
</span>
|
||||
<el-tag size="small" :type="g.gender === 0 ? 'primary' : g.gender === 1 ? 'danger' : ''">
|
||||
{{ g.gender === 0 ? '男' : g.gender === 1 ? '女' : '不限性别' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edc-group-empty" v-else>暂无组别配置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 费用信息 -->
|
||||
<div class="edc-section">
|
||||
<div class="edc-section-hd">
|
||||
<el-icon class="edc-section-icon"><CreditCard /></el-icon>
|
||||
<span class="edc-section-title">费用信息</span>
|
||||
</div>
|
||||
<div class="edc-fee-wrap">
|
||||
<div class="edc-fee-mode-row">
|
||||
<span class="edc-fee-mode-lbl">收费模式</span>
|
||||
<el-tag size="large" :type="getDetailChargeModeTagType(formData.feeConfig.chargeMode)" effect="plain">
|
||||
{{ getDetailChargeModeText(formData.feeConfig.chargeMode) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="edc-fee-price-row" v-if="detailChargeMode === 1 || detailChargeMode === 2">
|
||||
<span class="edc-fee-price-lbl">报名费用</span>
|
||||
<span class="edc-fee-price-val">¥ {{ formData.feeConfig.price ?? 0 }}</span>
|
||||
</div>
|
||||
<div v-if="detailChargeMode === 3 && formData.feeConfig.projects?.length" class="edc-fee-proj-table">
|
||||
<div class="edc-fee-proj-hdr">
|
||||
<span>项目名称</span>
|
||||
<span>费用(元)</span>
|
||||
</div>
|
||||
<div class="edc-fee-proj-row" v-for="proj in formData.feeConfig.projects" :key="proj.id">
|
||||
<span>{{ proj.name }}</span>
|
||||
<span class="edc-fee-proj-price">¥ {{ proj.fee ?? 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-if="detailChargeMode === 0" description="该赛事免费参加" :image-size="60" style="padding: 16px 0;" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 参与单位 -->
|
||||
<div class="edc-section" v-if="formData.units?.units?.length">
|
||||
<div class="edc-section-hd">
|
||||
<el-icon class="edc-section-icon"><OfficeBuilding /></el-icon>
|
||||
<span class="edc-section-title">参与单位</span>
|
||||
</div>
|
||||
<div class="edc-units-row">
|
||||
<div class="edc-unit-card" v-for="unit in formData.units.units" :key="unit.unitName + unit.sort">
|
||||
<div class="edc-unit-avatar">
|
||||
<el-image v-if="unit.logoUrl" :src="unit.logoUrl" fit="contain" class="edc-unit-avatar-img" />
|
||||
<el-icon v-else :size="30" color="#c0c4cc"><OfficeBuilding /></el-icon>
|
||||
</div>
|
||||
<div class="edc-unit-body">
|
||||
<div class="edc-unit-name">{{ unit.unitName || '-' }}</div>
|
||||
<el-tag size="small" type="info" style="margin-top: 4px;">
|
||||
{{ unit.customUnitType || getDetailUnitTypeLabel(unit.unitType) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-empty v-else description="暂无详情数据" style="padding: 60px 0;" />
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="isShowDetailDialog = false">关闭</el-button>
|
||||
</span>
|
||||
<div class="detail-dialog-footer">
|
||||
<el-button @click="isShowDetailDialog = false" size="large" round style="min-width: 120px;">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@ -445,7 +617,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, nextTick, onUnmounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Close, Picture, Loading, CircleCheck, ArrowRight, Plus, Delete } from '@element-plus/icons-vue';
|
||||
import { Close, Picture, Loading, CircleCheck, ArrowRight, Plus, Delete, Calendar, Document, OfficeBuilding, Trophy, CreditCard, InfoFilled } from '@element-plus/icons-vue';
|
||||
import ProTable from '/@/components/ProTable/index.vue';
|
||||
import { formatDate } from '/@/utils/formatTime';
|
||||
import {
|
||||
@ -465,10 +637,7 @@ import {
|
||||
} from '/@/api/match/usereventregistration';
|
||||
import { teamPageGet, teamDetailGet } from '/@/api/match/unitUser';
|
||||
import QRCode from 'qrcodejs2-fixes';
|
||||
import Step1BasicInfo from '/@/views/match/manage/Steps/Step1BasicInfo.vue';
|
||||
import Step2Units from '/@/views/match/manage/Steps/Step2Units.vue';
|
||||
import Step3ProjectConfig from '/@/views/match/manage/Steps/Step3ProjectConfig.vue';
|
||||
import UserStep4FeeConfig from './UserStep4FeeConfig.vue';
|
||||
|
||||
import PreviewImage from '/@/components/PreviewImage/index.vue';
|
||||
|
||||
const tableRef = ref();
|
||||
@ -582,6 +751,11 @@ const eventStatusMap = {
|
||||
'RegistrationEnded': { type: 'warning', text: '报名结束' },
|
||||
'Ongoing': { type: 'primary', text: '比赛中' },
|
||||
'Ended': { type: 'danger', text: '已结束' },
|
||||
0: { type: 'info', text: '未开始' },
|
||||
1: { type: 'success', text: '报名中' },
|
||||
2: { type: 'warning', text: '报名结束' },
|
||||
3: { type: 'primary', text: '比赛中' },
|
||||
4: { type: 'danger', text: '已结束' },
|
||||
};
|
||||
|
||||
const getEventStatusTagType = (status) => {
|
||||
@ -601,6 +775,64 @@ const isEventEnrolling = (row) => {
|
||||
return isEnrolling && canRegister;
|
||||
};
|
||||
|
||||
// -------------------- 赛事详情展示辅助函数 --------------------
|
||||
const getDetailUnitTypeLabel = (v) => {
|
||||
const map = { 0: '主办单位', 1: '承办单位', 2: '协办单位', 3: '赞助单位' };
|
||||
return map[v] ?? '-';
|
||||
};
|
||||
|
||||
const normalizeDetailChargeMode = (mode) => {
|
||||
if (mode === 0 || mode === '0' || mode === 'Free' || mode === 'free') return 0;
|
||||
if (mode === 1 || mode === '1' || mode === 'FixedPrice') return 1;
|
||||
if (mode === 2 || mode === '2' || mode === 'UnitPriceEvent') return 2;
|
||||
if (mode === 3 || mode === '3' || mode === 'UnitPriceProject') return 3;
|
||||
return 0;
|
||||
};
|
||||
|
||||
const detailChargeMode = computed(() => normalizeDetailChargeMode(formData.value.feeConfig?.chargeMode));
|
||||
|
||||
const getDetailChargeModeText = (mode) => {
|
||||
const m = normalizeDetailChargeMode(mode);
|
||||
return ['免费', '定价(赛事)', '单价(赛事)', '单价(项目)'][m] ?? '-';
|
||||
};
|
||||
|
||||
const getDetailChargeModeTagType = (mode) => {
|
||||
const m = normalizeDetailChargeMode(mode);
|
||||
return ['success', 'warning', 'primary', 'info'][m] ?? 'info';
|
||||
};
|
||||
|
||||
const formatPointsRuleBrief = (pointsRuleDetail, pointsRuleName) => {
|
||||
if (!pointsRuleDetail) return pointsRuleName || '-';
|
||||
const ruleName = pointsRuleDetail.ruleName || pointsRuleName || '未命名规则';
|
||||
const participationPoints = pointsRuleDetail.participationPoints ?? 0;
|
||||
const detailLines = (pointsRuleDetail.details ?? []).map((d) => {
|
||||
const start = d?.startRank;
|
||||
const end = d?.endRank;
|
||||
const points = d?.points ?? 0;
|
||||
if (start === undefined || start === null) return `积分 ${points}`;
|
||||
if (end === undefined || end === null || Number(start) === Number(end)) return `第${start}名: ${points}分`;
|
||||
return `第${start}-${end}名: ${points}分`;
|
||||
});
|
||||
const remark = pointsRuleDetail.remark ? `备注: ${pointsRuleDetail.remark}` : '';
|
||||
return [
|
||||
`参赛积分: ${participationPoints}`,
|
||||
...detailLines,
|
||||
remark,
|
||||
].filter(Boolean).join(';\n');
|
||||
};
|
||||
|
||||
const formatRefundRulesBrief = (refundRules) => {
|
||||
if (!Array.isArray(refundRules) || !refundRules.length) return '-';
|
||||
return refundRules.map((r) => {
|
||||
const start = r?.dayStart ?? 0;
|
||||
const end = r?.dayEnd;
|
||||
const range = end === 999 || end === '999' ? `${start}天及以上` : `${start}-${end ?? 0}天`;
|
||||
const percent = r?.deductPercentage ?? 0;
|
||||
const remark = r?.remark ? `(${r.remark})` : '';
|
||||
return `${range}: 扣除${percent}%${remark}`;
|
||||
}).join(';\n');
|
||||
};
|
||||
|
||||
// 展平项目和组别数据用于详情弹窗显示
|
||||
const detailProjectsForDisplay = computed(() => {
|
||||
const list = [];
|
||||
@ -632,6 +864,7 @@ const detailProjectsForDisplay = computed(() => {
|
||||
const isShowDetailDialog = ref(false);
|
||||
const detailLoading = ref(false);
|
||||
const detailData = ref(null);
|
||||
const detailStatusFromList = ref(null);
|
||||
const formData = ref({
|
||||
// 步骤1:基本信息
|
||||
basicInfo: {
|
||||
@ -690,6 +923,7 @@ const projectConfigWithRegistrationType = computed(() => ({
|
||||
const clearDetailState = () => {
|
||||
detailLoading.value = false;
|
||||
detailData.value = null;
|
||||
detailStatusFromList.value = null;
|
||||
formData.value = {
|
||||
basicInfo: {
|
||||
id: undefined,
|
||||
@ -737,6 +971,7 @@ const openDetailDialog = async (row) => {
|
||||
isShowDetailDialog.value = true;
|
||||
detailLoading.value = true;
|
||||
detailData.value = null;
|
||||
detailStatusFromList.value = row?.status ?? row?.eventStatus ?? null;
|
||||
try {
|
||||
const { succeeded, data } = await usereventregistrationDetailGet(eventId);
|
||||
if (!succeeded) {
|
||||
@ -2192,6 +2427,552 @@ const handleCreateOrderAndPay = async () => {
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/* ---- 赛事详情弹窗 ---- */
|
||||
.event-detail-dialog {
|
||||
:deep(.el-dialog__header) {
|
||||
padding: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0;
|
||||
max-height: calc(80vh - 130px);
|
||||
overflow-y: auto;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #c0c4cc transparent;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #c0c4cc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dialog__footer) {
|
||||
border-top: 1px solid #ebeef5;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-dialog-custom-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 20px;
|
||||
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.detail-dialog-header-badge {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
border: 2px solid rgba(255, 255, 255, 0.45);
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail-dialog-header-title {
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
flex: 1;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.detail-dialog-close-btn {
|
||||
color: rgba(255, 255, 255, 0.85) !important;
|
||||
border-color: rgba(255, 255, 255, 0.4) !important;
|
||||
background: rgba(255, 255, 255, 0.12) !important;
|
||||
|
||||
&:hover {
|
||||
color: #fff !important;
|
||||
background: rgba(255, 255, 255, 0.28) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.event-detail-content {
|
||||
padding: 20px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* ---- Hero ---- */
|
||||
.edc-hero {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #fafcff 100%);
|
||||
border: 1px solid #e0ecfd;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
padding: 20px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.edc-cover-wrap {
|
||||
flex-shrink: 0;
|
||||
width: 180px;
|
||||
height: 140px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e0ecfd;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.edc-cover-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.edc-cover-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
color: #c0c4cc;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.edc-hero-right {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.edc-event-name {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1a3c6e;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.edc-badge-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.edc-kv-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.edc-kv-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.edc-kv-item--block {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.edc-kv-label {
|
||||
flex-shrink: 0;
|
||||
color: #909399;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.edc-kv-val {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.edc-kv-val--multiline {
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* ---- Section ---- */
|
||||
.edc-section {
|
||||
border: 1px solid #e0ecfd;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.05);
|
||||
}
|
||||
|
||||
.edc-section-hd {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 13px 18px;
|
||||
background: linear-gradient(90deg, #eef5ff 0%, #f8fbff 100%);
|
||||
border-bottom: 1px solid #e0ecfd;
|
||||
}
|
||||
|
||||
.edc-section-icon {
|
||||
color: #409eff;
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.edc-section-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a3c6e;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.edc-section-count {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
background: #ecf5ff;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* ---- 时间安排 ---- */
|
||||
.edc-time-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.edc-time-card {
|
||||
flex: 1;
|
||||
min-width: 160px;
|
||||
background: #fff;
|
||||
border: 1px solid #dce8fb;
|
||||
border-radius: 10px;
|
||||
padding: 14px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.edc-time-card-label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.edc-time-card-val {
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.edc-time-card-arrow {
|
||||
color: #b0c8f0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.edc-time-card-empty {
|
||||
font-size: 13px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.edc-material-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 10px 16px;
|
||||
background: #fff7e6;
|
||||
border-top: 1px solid #ffe0a0;
|
||||
font-size: 13px;
|
||||
color: #b07d00;
|
||||
|
||||
.el-icon {
|
||||
color: #e6a23c;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 赛事介绍 ---- */
|
||||
.edc-intro {
|
||||
padding: 16px 20px;
|
||||
background: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
color: #303133;
|
||||
word-break: break-word;
|
||||
|
||||
:deep(p) { margin: 6px 0; }
|
||||
:deep(img) { max-width: 100%; border-radius: 4px; }
|
||||
:deep(h1, h2, h3) { margin: 10px 0 6px; }
|
||||
}
|
||||
|
||||
/* ---- 参与单位 ---- */
|
||||
.edc-units-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.edc-unit-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #e0ecfd;
|
||||
border-radius: 10px;
|
||||
background: #f8fbff;
|
||||
min-width: 160px;
|
||||
transition: box-shadow 0.2s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 10px rgba(64, 158, 255, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
.edc-unit-avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: #eef2fa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.edc-unit-avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.edc-unit-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.edc-unit-name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.edc-reg-limit-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 18px;
|
||||
background: #f0f9ff;
|
||||
border-bottom: 1px solid #d6ebff;
|
||||
font-size: 13px;
|
||||
color: #3a7bd5;
|
||||
|
||||
.el-icon {
|
||||
color: #409eff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #1a5fc8;
|
||||
font-size: 15px;
|
||||
margin: 0 1px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 报名项目 ---- */
|
||||
.edc-proj-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.edc-proj-card {
|
||||
border: 1px solid #e0ecfd;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.edc-proj-hd {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 14px;
|
||||
background: linear-gradient(90deg, #f0f7ff, #fafcff);
|
||||
border-bottom: 1px solid #e0ecfd;
|
||||
}
|
||||
|
||||
.edc-proj-num {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
background: linear-gradient(135deg, #409eff, #66b1ff);
|
||||
color: #fff;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
box-shadow: 0 2px 6px rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
.edc-proj-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.edc-proj-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1a3c6e;
|
||||
}
|
||||
|
||||
.edc-proj-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.edc-group-table {
|
||||
padding: 0 14px 12px;
|
||||
}
|
||||
|
||||
.edc-group-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.6fr 90px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f0f4fb;
|
||||
font-size: 13px;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.edc-group-header {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.edc-group-name {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.edc-group-date {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.edc-group-empty {
|
||||
padding: 12px 14px;
|
||||
color: #c0c4cc;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* ---- 费用信息 ---- */
|
||||
.edc-fee-wrap {
|
||||
padding: 16px 20px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.edc-fee-mode-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.edc-fee-mode-lbl {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.edc-fee-price-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.edc-fee-price-lbl {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.edc-fee-price-val {
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.edc-fee-proj-table {
|
||||
border: 1px solid #e0ecfd;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.edc-fee-proj-hdr {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 120px;
|
||||
padding: 8px 14px;
|
||||
background: #f0f7ff;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.edc-fee-proj-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 120px;
|
||||
padding: 10px 14px;
|
||||
border-top: 1px solid #eef2fb;
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
transition: background 0.15s;
|
||||
|
||||
&:hover {
|
||||
background: #f8fbff;
|
||||
}
|
||||
}
|
||||
|
||||
.edc-fee-proj-price {
|
||||
font-weight: 600;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.detail-dialog-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
margin-top: 80px;
|
||||
}
|
||||
@ -2888,6 +3669,10 @@ const handleCreateOrderAndPay = async () => {
|
||||
|
||||
/* 响应式适配 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.edc-rule-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.step-footer--payment {
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user