408 lines
7.9 KiB
Vue
408 lines
7.9 KiB
Vue
<template>
|
||
<view class="coupon-container u-font-28">
|
||
<!-- 搜索表单 -->
|
||
<view class="search-box">
|
||
<!-- 第一行:名称 + 状态 -->
|
||
<view class="search-row">
|
||
<view class="search-item " @click="openStatusPicker">
|
||
<view class="">
|
||
{{ statusTextMap[query.status] || '请选择' }}
|
||
</view>
|
||
<up-icon name="arrow-down"></up-icon>
|
||
</view>
|
||
<view class="search-item flex-1 u-p-l-30">
|
||
<up-search v-model="query.name" placeholder="优惠券名称"></up-search>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<!-- 第二行:日期 + 搜索按钮 -->
|
||
<view class="search-row mt-20">
|
||
<view class="search-item flex-1" @click="timeToggle">
|
||
<text class="">领取时间</text>
|
||
<view class="select-text">
|
||
{{ showDate || '请选择' }}
|
||
<view @click.stop="()=>{}">
|
||
<up-icon name="arrow-down" v-if="!showDate" @click="timeToggle"></up-icon>
|
||
<up-icon name="close" @click="resetDate" v-else></up-icon>
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
|
||
<my-date-pickerview @confirm="datePickerConfirm" mode="date" ref="datePicker"></my-date-pickerview>
|
||
|
||
<!-- 优惠券列表 -->
|
||
<view class="coupon-list">
|
||
<view class="coupon-card" v-for="item in tableData" :key="item.id">
|
||
<view class="card-header">
|
||
<view class="card-name">{{ item.name }}</view>
|
||
<view class="card-tag" :class="getStatusClass(item.status)">
|
||
{{ getStatusText(item.status) }}
|
||
</view>
|
||
</view>
|
||
|
||
<view class="card-row">
|
||
<text class="label-text">券ID</text>
|
||
<text class="value-text">{{ item.id }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="label-text">领取来源</text>
|
||
<text class="value-text">{{ item.source }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="label-text">领取时间</text>
|
||
<text class="value-text">{{ item.createTime }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="label-text">使用时间</text>
|
||
<text class="value-text">{{ item.useTime || '—' }}</text>
|
||
</view>
|
||
|
||
<view class="card-footer u-flex u-row-right">
|
||
<view style="width:200rpx;">
|
||
<u-button type="error" size="small" @click="handleInvalid(item)"
|
||
custom-style="border-radius: 6rpx;padding: 0 20rpx;height: 50rpx;line-height: 50rpx;">
|
||
失效
|
||
</u-button>
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view class="empty" v-if="tableData.length === 0 && !loading">
|
||
<text class="empty-text">暂无优惠券记录</text>
|
||
</view>
|
||
|
||
<!-- 加载更多 -->
|
||
<u-loadmore :status="loadStatus" @loadmore="getMoreList" v-if="tableData.length>0" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
reactive,
|
||
ref
|
||
} from 'vue';
|
||
import {
|
||
onLoad
|
||
} from '@dcloudio/uni-app';
|
||
import * as couponApi from '@/http/api/market/coupon.js';
|
||
const datePicker = ref(null)
|
||
/**
|
||
* 选择时间
|
||
*/
|
||
function timeToggle() {
|
||
datePicker.value.toggle()
|
||
}
|
||
|
||
/**
|
||
* 筛选时间确认
|
||
* @param {Object} e
|
||
*/
|
||
function datePickerConfirm(e) {
|
||
console.log(e);
|
||
if (e) {
|
||
let {
|
||
start,
|
||
end
|
||
} = e
|
||
start = start.split(' ')[0]
|
||
end = end.split(' ')[0]
|
||
query.date = [start, end]
|
||
showDate.value = start + '至' + end
|
||
query.page = 1;
|
||
console.log('query.date', query.date);
|
||
getList();
|
||
}
|
||
}
|
||
|
||
function resetDate() {
|
||
query.date = '';
|
||
showDate.value = '';
|
||
query.page = 1;
|
||
getList();
|
||
}
|
||
// 状态配置
|
||
const statusList = ref([{
|
||
label: '全部',
|
||
value: ''
|
||
},
|
||
{
|
||
label: '未使用',
|
||
value: 0
|
||
},
|
||
{
|
||
label: '已使用',
|
||
value: 1
|
||
},
|
||
{
|
||
label: '已过期',
|
||
value: 2
|
||
},
|
||
]);
|
||
const statusTextMap = {
|
||
'': '全部',
|
||
0: '未使用',
|
||
1: '已使用',
|
||
2: '已过期',
|
||
};
|
||
|
||
// 查询参数
|
||
const query = reactive({
|
||
status: '',
|
||
name: '',
|
||
date: '',
|
||
shopUserId: '',
|
||
page: 1,
|
||
size: 10,
|
||
});
|
||
|
||
// 页面状态
|
||
const tableData = ref([]);
|
||
const loading = ref(false);
|
||
const loadStatus = ref('loadmore');
|
||
const showDate = ref('');
|
||
|
||
// 页面加载
|
||
onLoad((opt) => {
|
||
query.shopUserId = opt.userId;
|
||
getList();
|
||
});
|
||
|
||
// 打开状态选择
|
||
function openStatusPicker() {
|
||
const arr = statusList.value.map(i => i.label);
|
||
uni.showActionSheet({
|
||
itemList: arr,
|
||
success: (res) => {
|
||
const item = statusList.value[res.tapIndex];
|
||
query.status = item.value;
|
||
// 状态改变 → 自动重置页数并搜索
|
||
query.page = 1;
|
||
getList();
|
||
},
|
||
});
|
||
}
|
||
|
||
|
||
// 获取列表
|
||
async function getList() {
|
||
try {
|
||
loading.value = true;
|
||
loadStatus.value = 'loadmore';
|
||
const res = await couponApi.getRecordByUser({
|
||
...query
|
||
});
|
||
tableData.value = res.records || [];
|
||
loadStatus.value = tableData.value.length >= res.totalRow ? 'nomore' : 'loadmore';
|
||
} catch (e) {
|
||
console.error(e);
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
|
||
// 加载更多
|
||
async function getMoreList() {
|
||
if (loadStatus.value === 'nomore') return;
|
||
query.page++;
|
||
try {
|
||
loadStatus.value = 'loading';
|
||
const res = await couponApi.getRecordByUser({
|
||
...query
|
||
});
|
||
tableData.value.push(...res.records);
|
||
loadStatus.value = tableData.value.length >= res.totalRow ? 'nomore' : 'loadmore';
|
||
} catch (e) {
|
||
loadStatus.value = 'loadmore';
|
||
}
|
||
}
|
||
|
||
// 搜索
|
||
function handleSearch() {
|
||
query.page = 1;
|
||
getList();
|
||
}
|
||
|
||
// 失效
|
||
async function handleInvalid(row) {
|
||
uni.showModal({
|
||
title: '确认失效',
|
||
content: '确定要将该优惠券置为失效吗?',
|
||
success: async (res) => {
|
||
if (!res.confirm) return;
|
||
const resApi = await couponApi.deleteRecord({
|
||
id: row.id
|
||
});
|
||
uni.showToast({
|
||
title: '操作成功',
|
||
icon: 'success'
|
||
});
|
||
getList();
|
||
},
|
||
});
|
||
}
|
||
|
||
// 状态文本 + 样式
|
||
function getStatusText(status) {
|
||
return statusTextMap[status] || '未知';
|
||
}
|
||
|
||
function getStatusClass(status) {
|
||
if (status === 0) return 'tag-unused';
|
||
if (status === 1) return 'tag-used';
|
||
if (status === 2) return 'tag-expire';
|
||
return 'tag-default';
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.coupon-container {
|
||
padding: 20rpx;
|
||
background: #f7f8fa;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 搜索区域 */
|
||
.search-box {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
.search-row {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.search-item {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.select-text {
|
||
font-size: 28rpx;
|
||
border: 1px solid #dedede;
|
||
border-radius: 16rpx;
|
||
padding: 10rpx 30rpx;
|
||
color: #333;
|
||
display: flex;
|
||
flex: 1;
|
||
margin-left: 20rpx;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.arrow {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.search-btn {
|
||
border-radius: 8rpx !important;
|
||
height: 70rpx !important;
|
||
line-height: 70rpx !important;
|
||
}
|
||
|
||
.flex-1 {
|
||
flex: 1;
|
||
}
|
||
|
||
.ml-20 {
|
||
margin-left: 20rpx;
|
||
}
|
||
|
||
.mt-20 {
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
/* 卡片 */
|
||
.coupon-card {
|
||
background: #fff;
|
||
border-radius: 20rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
|
||
.card-name {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #222;
|
||
}
|
||
|
||
.card-tag {
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 30rpx;
|
||
font-size: 24rpx;
|
||
|
||
&.tag-unused {
|
||
background: #fff5e6;
|
||
color: #ff7d00;
|
||
}
|
||
|
||
&.tag-used {
|
||
background: #f2f3f5;
|
||
color: #666;
|
||
}
|
||
|
||
&.tag-expire {
|
||
background: #f7f8fa;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.card-row {
|
||
display: flex;
|
||
margin-bottom: 16rpx;
|
||
|
||
.label-text {
|
||
width: 140rpx;
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.value-text {
|
||
flex: 1;
|
||
font-size: 26rpx;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
.card-footer {
|
||
text-align: right;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty {
|
||
padding: 100rpx 0;
|
||
text-align: center;
|
||
|
||
.empty-text {
|
||
color: #999;
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
</style> |