Files
ApiServer-Web-admin_dashboa…/src/components/marketing/DiscountDetailDialog.vue
T
2025-11-13 15:05:54 +08:00

296 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog
v-model="visible"
:title="dialogTitle"
width="600px"
:close-on-click-modal="false"
@close="handleClose"
>
<div v-if="detailData" class="detail-content">
<table class="detail-table">
<!-- 优惠码特有字段 -->
<tr v-if="type === 'code'">
<td class="label">优惠码</td>
<td class="value">{{ detailData.code }}</td>
</tr>
<!-- 名称 -->
<tr>
<td class="label">{{ type === 'code' ? '名称' : '代金券名称' }}</td>
<td class="value">{{ detailData.name }}</td>
</tr>
<!-- 备注 -->
<tr>
<td class="label">备注</td>
<td class="value secondary">{{ detailData.note || '无' }}</td>
</tr>
<!-- 优惠类型仅优惠码 -->
<tr v-if="type === 'code'" class="alternate">
<td class="label">优惠类型</td>
<td class="value">
<span :class="['type-tag', detailData.percentage ? 'percentage' : 'amount']">
{{ detailData.percentage ? '百分比折扣' : '固定金额' }}
</span>
</td>
</tr>
<!-- 优惠值/面额 -->
<tr :class="type === 'code' ? '' : 'alternate'">
<td class="label">{{ type === 'code' ? '优惠值' : '面额' }}</td>
<td class="value">
<span v-if="detailData.percentage" class="highlight-value percentage">
{{ (detailData.percentage / 100).toFixed(0) }}%
</span>
<span v-else class="highlight-value amount">
¥{{ (detailData.amount / 100).toFixed(2) }}
</span>
</td>
</tr>
<!-- 最低消费 -->
<tr>
<td class="label">最低消费</td>
<td class="value">¥{{ (detailData.minAmount / 100).toFixed(2) }}</td>
</tr>
<!-- 最大抵扣 -->
<tr>
<td class="label">最大抵扣</td>
<td class="value">
<span v-if="detailData.maxAmount">¥{{ (detailData.maxAmount / 100).toFixed(2) }}</span>
<span v-else class="secondary">无限制</span>
</td>
</tr>
<!-- 最大使用次数 -->
<tr class="alternate">
<td class="label">最大使用次数</td>
<td class="value">
<span v-if="detailData.maxTimes">{{ detailData.maxTimes }}</span>
<span v-else class="secondary">无限制</span>
</td>
</tr>
<!-- 单用户次数 -->
<tr>
<td class="label">单用户次数</td>
<td class="value">
<span v-if="detailData.userTimes">{{ detailData.userTimes }}</span>
<span v-else class="secondary">无限制</span>
</td>
</tr>
<!-- 有效期仅代金券 -->
<tr v-if="type === 'coupon'" class="alternate">
<td class="label">有效期()</td>
<td class="value">
{{ detailData.duration ? (detailData.duration / 86400).toFixed(0) + '天' : '-' }}
</td>
</tr>
<!-- 有效期开始 -->
<tr :class="type === 'coupon' ? '' : 'alternate'">
<td class="label">{{ type === 'code' ? '有效期开始' : '发放时间开始' }}</td>
<td class="value">{{ formatISODate(detailData.startTime) }}</td>
</tr>
<!-- 有效期结束 -->
<tr :class="type === 'coupon' ? 'alternate' : ''">
<td class="label">{{ type === 'code' ? '有效期结束' : '发放时间结束' }}</td>
<td class="value">{{ formatISODate(detailData.endTime) }}</td>
</tr>
<!-- 续费可用 -->
<tr :class="type === 'coupon' ? '' : 'alternate'">
<td class="label">续费可用</td>
<td class="value">
<span :class="['status-icon', detailData.renew ? 'success' : 'danger']">
{{ detailData.renew ? '✓ 是' : '✗ 否' }}
</span>
</td>
</tr>
<!-- 同类型可叠加 -->
<tr :class="type === 'coupon' ? 'alternate' : ''">
<td class="label">同类型可叠加</td>
<td class="value">
<span :class="['status-icon', detailData.canStacking ? 'success' : 'danger']">
{{ detailData.canStacking ? '✓ 是' : '✗ 否' }}
</span>
</td>
</tr>
<!-- 其他类型可叠加 -->
<tr :class="type === 'coupon' ? '' : 'alternate'">
<td class="label">其他类型可叠加</td>
<td class="value">
<span :class="['status-icon', detailData.canCombine ? 'success' : 'danger']">
{{ detailData.canCombine ? '✓ 是' : '✗ 否' }}
</span>
</td>
</tr>
<!-- 创建时间 -->
<tr :class="type === 'coupon' ? 'alternate' : ''">
<td class="label">创建时间</td>
<td class="value timestamp">{{ formatISODate(detailData.CreatedAt) }}</td>
</tr>
<!-- 更新时间 -->
<tr>
<td class="label">更新时间</td>
<td class="value timestamp">{{ formatISODate(detailData.UpdatedAt) }}</td>
</tr>
</table>
</div>
<template #footer>
<el-button @click="handleClose">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
type: {
type: String,
required: true,
validator: (value) => ['code', 'coupon'].includes(value)
},
detailData: {
type: Object,
default: null
}
})
const emit = defineEmits(['update:modelValue'])
const visible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
const dialogTitle = computed(() => {
return props.type === 'code' ? '优惠码详情' : '代金券详情'
})
// 格式化ISO 8601日期字符串
const formatISODate = (isoStr) => {
if (!isoStr) return '-'
try {
const date = new Date(isoStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
} catch {
return isoStr
}
}
const handleClose = () => {
emit('update:modelValue', false)
}
</script>
<style scoped>
.detail-content {
max-height: 500px;
overflow-y: auto;
padding: 10px;
}
.detail-table {
width: 100%;
border-collapse: collapse;
}
.detail-table tr {
border-bottom: 1px solid #f0f0f0;
}
.detail-table tr.alternate {
background-color: #fafafa;
}
.detail-table td {
padding: 12px 8px;
}
.detail-table .label {
width: 140px;
color: #606266;
font-weight: 500;
}
.detail-table .value {
color: #303133;
}
.detail-table .value.secondary {
color: #606266;
}
.detail-table .value.timestamp {
color: #909399;
font-size: 13px;
}
/* 类型标签 */
.type-tag {
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
display: inline-block;
}
.type-tag.percentage {
background-color: #f0f9ff;
color: #67c23a;
}
.type-tag.amount {
background-color: #eff6ff;
color: #409eff;
}
/* 突出显示的值 */
.highlight-value {
font-weight: bold;
font-size: 18px;
}
.highlight-value.percentage {
color: #67c23a;
}
.highlight-value.amount {
color: #f56c6c;
}
/* 状态图标 */
.status-icon.success {
color: #67c23a;
}
.status-icon.danger {
color: #f56c6c;
}
.secondary {
color: #909399;
}
</style>