update:赛事详情

This commit is contained in:
ltx 2026-05-13 18:02:34 +08:00
parent c876bbaa87
commit 002940a41b

View File

@ -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;