Files
medical-mall/pages/mall/admin/marketing/coupon/user.uvue

240 lines
10 KiB
Plaintext
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>
<view class="admin-marketing-coupon-user">
<view class="content-body">
<!-- 搜索过滤栏 -->
<view class="filter-card border-shadow">
<view class="filter-row">
<view class="filter-item">
<text class="label-txt">是否有效:</text>
<view class="select-mock">
<text class="select-val">请选择</text>
<text class="arrow-down">▼</text>
</view>
</view>
<view class="filter-item">
<text class="label-txt">领取人:</text>
<input class="search-input" placeholder="请输入领取人" v-model="filter.username" />
</view>
<view class="filter-item filter-long">
<text class="label-txt">优惠券搜索:</text>
<input class="search-input input-wide" placeholder="请输入优惠券名称" v-model="filter.couponName" />
</view>
<view class="btn-query" @click="handleQuery">
<text class="query-txt">查询</text>
</view>
</view>
</view>
<!-- 主要表格区域 -->
<view class="table-card border-shadow">
<view class="table-container">
<view class="table-header-row">
<view class="th" style="width: 100px;">ID</view>
<view class="th" style="width: 150px;">优惠券名称</view>
<view class="th" style="width: 180px;">领取人</view>
<view class="th" style="width: 100px;">面值</view>
<view class="th" style="width: 120px;">最低消费额</view>
<view class="th" style="width: 180px;">开始使用时间</view>
<view class="th" style="width: 180px;">结束使用时间</view>
<view class="th" style="width: 120px;">获取方式</view>
<view class="th" style="width: 100px;">是否可用</view>
<view class="th" style="flex: 1; min-width: 100px;">状态</view>
</view>
<view class="table-body">
<view v-for="item in recordList" :key="item.id" class="table-row">
<view class="td" style="width: 100px;"><text class="td-txt">{{ item.id }}</text></view>
<view class="td" style="width: 150px;"><text class="td-txt">{{ item.couponName }}</text></view>
<view class="td" style="width: 180px;"><text class="td-txt">{{ item.username }}</text></view>
<view class="td" style="width: 100px;"><text class="td-txt price-txt">{{ item.value.toFixed(2) }}</text></view>
<view class="td" style="width: 120px;"><text class="td-txt price-txt">{{ item.minSpend.toFixed(2) }}</text></view>
<view class="td" style="width: 180px;"><text class="td-txt time-txt">{{ item.startTime }}</text></view>
<view class="td" style="width: 180px;"><text class="td-txt time-txt">{{ item.endTime }}</text></view>
<view class="td" style="width: 120px;"><text class="td-txt">{{ item.getType }}</text></view>
<view class="td" style="width: 100px;">
<text v-if="item.isValid" class="status-ic-success">✓</text>
<text v-else class="status-ic-fail">×</text>
</view>
<view class="td" style="flex: 1; min-width: 100px;"><text :class="['td-txt', item.status === '已使用' ? 'status-used' : '']">{{ item.status }}</text></view>
</view>
</view>
</view>
<!-- 分页 -->
<CommonPagination
v-if="total > 0"
:total="total"
:loading="false"
:currentPage="currentPage"
:pageSize="pageSize"
:pageSizeOptionLabels="pageSizeOptionLabels"
:pageSizeIndex="pageSizeIndex"
:visiblePages="visiblePages"
:totalPage="totalPage"
:jumpPageInput="jumpPageInput"
@page-size-change="handlePageSizeChange"
@page-change="handlePageChange"
@update:jumpPageInput="(val : string) => { jumpPageInput = val }"
@jump-page="handleJumpPage"
/>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, computed } from 'vue'
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
interface CouponRecord {
id: number
couponName: string
username: string
value: number
minSpend: number
startTime: string
endTime: string
getType: string
isValid: boolean
status: string
}
const filter = reactive({
username: '',
couponName: ''
})
const recordList = ref<CouponRecord[]>([
{ id: 217732, couponName: '满10减7', username: '嘻嘻', value: 7.00, minSpend: 0.00, startTime: '2026-02-03 17:23', endTime: '2026-02-13 17:23', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217731, couponName: '满10减7', username: '1岁上班22岁退休', value: 7.00, minSpend: 0.00, startTime: '2026-02-03 17:20', endTime: '2026-02-13 17:20', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217730, couponName: '店庆券', username: '136****0434', value: 100.00, minSpend: 1000.00, startTime: '2026-02-03 17:13', endTime: '2026-02-13 17:13', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217729, couponName: '优惠券', username: '187****2801', value: 100.00, minSpend: 599.00, startTime: '2026-02-03 16:36', endTime: '2026-03-05 16:36', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217728, couponName: '会员优惠券', username: '彭祖Dean', value: 29.90, minSpend: 0.00, startTime: '2026-02-03 16:06', endTime: '2026-08-22 16:06', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217727, couponName: '会员优惠券', username: '彭祖Dean', value: 200.00, minSpend: 0.00, startTime: '2026-02-03 16:06', endTime: '2026-08-22 16:06', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217726, couponName: '满10减7', username: '181****6929', value: 7.00, minSpend: 0.00, startTime: '2026-02-03 15:56', endTime: '2026-02-13 15:56', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217725, couponName: '优惠券', username: '181****3601', value: 100.00, minSpend: 599.00, startTime: '2026-02-03 15:51', endTime: '2026-03-05 15:51', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217724, couponName: '商品券', username: '陌年微凉TL', value: 1.00, minSpend: 0.00, startTime: '2026-02-03 15:17', endTime: '2026-08-22 15:17', getType: '手动领取', isValid: true, status: '未使用' },
{ id: 217723, couponName: '限时优惠', username: '陌年微凉TL', value: 20.00, minSpend: 199.00, startTime: '2026-02-03 15:17', endTime: '2026-02-08 15:17', getType: '手动领取', isValid: false, status: '已使用' }
])
const handleQuery = () => { console.log('Querying redemption records...') }
// 分页适配状态
const total = ref(16)
const currentPage = ref(1)
const pageSize = ref(15)
let jumpPageInput = ''
const pageSizeOptions = [10, 15, 20, 30, 50]
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
const pageSizeIndex = computed(() => {
const idx = pageSizeOptions.indexOf(pageSize.value)
return idx >= 0 ? idx : 0
})
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
const visiblePages = computed(() => {
const t = totalPage.value
const cur = currentPage.value
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
return [1, -1, cur - 1, cur, cur + 1, -1, t]
})
const handlePageChange = (p: number) => { currentPage.value = p }
const handlePageSizeChange = (e: any) => {
const idx = Number(e.detail.value)
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
currentPage.value = 1
}
const handleJumpPage = () => {
const p = parseInt(jumpPageInput)
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
}
</script>
<style scoped lang="scss">
.admin-marketing-coupon-user {
padding: 0;
background-color: transparent;
min-height: auto;
}
.border-shadow {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
.content-body {
display: flex;
flex-direction: column;
gap: 20px;
}
/* 过滤栏 */
.filter-card { padding: 24px; }
.filter-row { display: flex; flex-direction: row; align-items: center; flex-wrap: wrap; gap: 32px; }
.filter-item { display: flex; flex-direction: row; align-items: center; gap: 12px; }
.label-txt { font-size: 14px; color: #606266; }
.select-mock {
width: 180px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 12px;
cursor: pointer;
}
.select-val { font-size: 14px; color: #c0c4cc; }
.arrow-down { font-size: 10px; color: #c0c4cc; }
.search-input {
width: 180px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 0 12px;
font-size: 14px;
}
.input-wide { width: 240px; }
.btn-query {
background-color: #2d8cf0;
padding: 0 20px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
cursor: pointer;
}
.query-txt { color: #fff; font-size: 14px; }
/* 表格区域 */
.table-card { padding-top: 24px; }
.table-container { padding: 0 24px 24px; }
.table-header-row { display: flex; flex-direction: row; background-color: #f8f8f9; border-bottom: 1px solid #e8eaec; }
.th { padding: 12px 10px; font-size: 14px; color: #515a6e; font-weight: bold; }
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #e8eaec; }
.table-row:hover { background-color: #ebf7ff; }
.td { padding: 12px 10px; display: flex; align-items: center; }
.td-txt { font-size: 14px; color: #515a6e; }
.price-txt { color: #515a6e; }
.time-txt { color: #515a6e; }
.status-ic-success { color: #2d8cf0; font-weight: bold; font-size: 16px; margin-left: 10px; }
.status-ic-fail { color: #ed4014; font-weight: bold; font-size: 16px; margin-left: 10px; }
.status-used { color: #999; }
/* 分页区域已迁至 CommonPagination 组件 */
</style>