sc
This commit is contained in:
@@ -45,3 +45,12 @@ export const getVipType = async id => {
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 查询充值记录
|
||||
export const getRechargeRecord = async params => {
|
||||
return await request({
|
||||
url: '/applet/xunjia/pay/page',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</view>
|
||||
<view class="header-title">会员订单管理</view>
|
||||
<view class="header-right" @click="exportOrders">
|
||||
<view class="export-btn">导出</view>
|
||||
<!-- <view class="export-btn">导出</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -15,16 +15,14 @@
|
||||
<view class="filter-section">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">状态</view>
|
||||
<view class="filter-label">订单号</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
:range="statusOptions"
|
||||
:value="statusIndex"
|
||||
@change="onStatusChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ statusOptions[statusIndex] }}</view>
|
||||
</picker>
|
||||
<input
|
||||
v-model="searchParams.payNo"
|
||||
class="search-input"
|
||||
placeholder="请输入订单号"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
@@ -32,21 +30,22 @@
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
:range="memberTypeOptions"
|
||||
:range-key="'memberName'"
|
||||
:value="memberTypeIndex"
|
||||
@change="onMemberTypeChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ memberTypeOptions[memberTypeIndex] }}</view>
|
||||
<view class="picker-text">{{ memberTypeOptions[memberTypeIndex]?.memberName || '全部类型' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">搜索</view>
|
||||
<view class="filter-label">手机号</view>
|
||||
<view class="filter-control">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
v-model="searchParams.phone"
|
||||
class="search-input"
|
||||
placeholder="请输入订单号或学员姓名"
|
||||
placeholder="请输入手机号"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
@@ -64,42 +63,46 @@
|
||||
class="order-item"
|
||||
>
|
||||
<view class="order-header">
|
||||
<view class="order-code">{{ order.code }}</view>
|
||||
<view class="order-status" :class="order.statusClass">{{ order.status }}</view>
|
||||
<view class="order-code" @click="copyOrderId(order.payId)">订单号:{{ order.payId }} <text class="copy-icon">📋</text></view>
|
||||
<view class="distributor-name">{{ order.distributionName || '无分销员' }}</view>
|
||||
</view>
|
||||
<view class="order-body">
|
||||
<view class="order-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">学员姓名:</view>
|
||||
<view class="info-value">{{ order.studentName }}</view>
|
||||
<view class="info-label">用户姓名:</view>
|
||||
<view class="info-value">{{ order.userName }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">手机号:</view>
|
||||
<view class="info-value">{{ order.phone }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">会员类型:</view>
|
||||
<view class="info-value">{{ order.memberType }}</view>
|
||||
<view class="info-value">{{ order.memberName }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">科目:</view>
|
||||
<view class="info-value">{{ order.subjects }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">车型:</view>
|
||||
<view class="info-value">{{ order.carName }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">订单金额:</view>
|
||||
<view class="info-value price">{{ order.amount }}</view>
|
||||
<view class="info-value price">{{ order.money }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">下单时间:</view>
|
||||
<view class="info-value">{{ order.createTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-footer">
|
||||
<view class="order-actions">
|
||||
<view v-if="order.status === '待处理'" class="action-btn process-btn" @click="processOrder(order.id)">
|
||||
处理
|
||||
</view>
|
||||
<view class="action-btn detail-btn" @click="viewOrderDetail(order.id)">
|
||||
详情
|
||||
</view>
|
||||
<view class="action-btn refund-btn" @click="refundOrder(order.id)">
|
||||
退款
|
||||
<view class="info-label">支付时间:</view>
|
||||
<view class="info-value">{{ order.payTime }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">会员到期时间:</view>
|
||||
<view class="info-value">{{ order.memberEndTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -137,59 +140,23 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
import { getRechargeRecord, getVipTypeList } from "@/api/member"
|
||||
|
||||
// 筛选条件
|
||||
const statusOptions = ['全部状态', '待处理', '已完成', '已退款', '异常']
|
||||
const statusIndex = ref(0)
|
||||
|
||||
const memberTypeOptions = ['全部类型', '月度会员', '季度会员', '年度会员']
|
||||
const memberTypeOptions = ref([
|
||||
{ memberId: '', memberName: '全部类型' }
|
||||
])
|
||||
const memberTypeIndex = ref(0)
|
||||
|
||||
const searchKeyword = ref('')
|
||||
// 搜索参数
|
||||
const searchParams = ref({
|
||||
payNo: '', // 订单号
|
||||
memberId: '', // 会员类型ID
|
||||
phone: '' // 手机号
|
||||
})
|
||||
|
||||
// 订单列表数据
|
||||
const orderList = ref([
|
||||
{
|
||||
id: 1,
|
||||
code: 'MO20260129001',
|
||||
studentName: '张三',
|
||||
memberType: '年度会员',
|
||||
amount: '¥299.90',
|
||||
createTime: '2026-01-29 15:30:00',
|
||||
status: '待处理',
|
||||
statusClass: 'status-pending'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
code: 'MO20260129002',
|
||||
studentName: '李四',
|
||||
memberType: '月度会员',
|
||||
amount: '¥39.90',
|
||||
createTime: '2026-01-29 14:20:00',
|
||||
status: '已完成',
|
||||
statusClass: 'status-completed'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
code: 'MO20260129003',
|
||||
studentName: '王五',
|
||||
memberType: '季度会员',
|
||||
amount: '¥99.90',
|
||||
createTime: '2026-01-29 13:10:00',
|
||||
status: '异常',
|
||||
statusClass: 'status-exception'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
code: 'MO20260129004',
|
||||
studentName: '赵六',
|
||||
memberType: '年度会员',
|
||||
amount: '¥299.90',
|
||||
createTime: '2026-01-29 12:00:00',
|
||||
status: '已退款',
|
||||
statusClass: 'status-refunded'
|
||||
}
|
||||
])
|
||||
const orderList = ref([])
|
||||
|
||||
// 分页信息
|
||||
const currentPage = ref(1)
|
||||
@@ -202,10 +169,51 @@
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取订单列表
|
||||
// loadOrderList()
|
||||
// 加载订单列表
|
||||
loadOrderList()
|
||||
// 加载会员类型列表
|
||||
loadVipTypeList()
|
||||
})
|
||||
|
||||
// 加载会员类型列表
|
||||
function loadVipTypeList() {
|
||||
uni.showLoading({ title: '加载中...' })
|
||||
|
||||
getVipTypeList().then(res => {
|
||||
uni.hideLoading()
|
||||
if (res.code == '0000') {
|
||||
// 保留默认的"全部类型"选项,添加从接口获取的会员类型
|
||||
const vipTypes = res.data.list || []
|
||||
memberTypeOptions.value = [
|
||||
{ memberId: '', memberName: '全部类型' },
|
||||
...vipTypes
|
||||
]
|
||||
}
|
||||
}).catch(err => {
|
||||
uni.hideLoading()
|
||||
console.error('加载会员类型失败:', err)
|
||||
})
|
||||
}
|
||||
|
||||
// 加载订单列表
|
||||
function loadOrderList() {
|
||||
uni.showLoading({ title: '加载中...' })
|
||||
|
||||
getRechargeRecord({
|
||||
pageNo: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
payNo: searchParams.value.payNo,
|
||||
memberId: searchParams.value.memberId,
|
||||
phone: searchParams.value.phone
|
||||
}).then(res => {
|
||||
uni.hideLoading()
|
||||
if (res.code == '0000') {
|
||||
orderList.value = res.data.list || []
|
||||
totalOrders.value = res.data.total || 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
@@ -234,79 +242,27 @@
|
||||
})
|
||||
}
|
||||
|
||||
// 状态变更
|
||||
function onStatusChange(e) {
|
||||
const value = e.detail.value
|
||||
statusIndex.value = value
|
||||
// 实际项目中应根据状态筛选订单
|
||||
// filterOrderList()
|
||||
}
|
||||
|
||||
// 会员类型变更
|
||||
function onMemberTypeChange(e) {
|
||||
const value = e.detail.value
|
||||
memberTypeIndex.value = value
|
||||
// 实际项目中应根据会员类型筛选订单
|
||||
// filterOrderList()
|
||||
// 根据选择的会员类型设置memberId
|
||||
const selectedType = memberTypeOptions.value[value]
|
||||
if (selectedType) {
|
||||
searchParams.value.memberId = selectedType.memberId || ''
|
||||
}
|
||||
// 重新加载订单列表
|
||||
loadOrderList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch() {
|
||||
// 实际项目中应根据关键词搜索订单
|
||||
// searchOrderList()
|
||||
// 重置页码
|
||||
currentPage.value = 1
|
||||
// 重新加载订单列表
|
||||
loadOrderList()
|
||||
}
|
||||
|
||||
// 处理订单
|
||||
function processOrder(id) {
|
||||
uni.showModal({
|
||||
title: '处理订单',
|
||||
content: '确定要处理该订单吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应调用接口处理订单
|
||||
const order = orderList.value.find(item => item.id === id)
|
||||
if (order) {
|
||||
order.status = '已完成'
|
||||
order.statusClass = 'status-completed'
|
||||
}
|
||||
uni.showToast({
|
||||
title: '订单处理成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 查看订单详情
|
||||
function viewOrderDetail(id) {
|
||||
uni.showToast({
|
||||
title: '查看订单详情功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
// 退款订单
|
||||
function refundOrder(id) {
|
||||
uni.showModal({
|
||||
title: '退款订单',
|
||||
content: '确定要退款该订单吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应调用接口退款订单
|
||||
const order = orderList.value.find(item => item.id === id)
|
||||
if (order) {
|
||||
order.status = '已退款'
|
||||
order.statusClass = 'status-refunded'
|
||||
}
|
||||
uni.showToast({
|
||||
title: '订单退款成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转到指定页码
|
||||
function goToPage(page) {
|
||||
@@ -314,8 +270,21 @@
|
||||
return
|
||||
}
|
||||
currentPage.value = page
|
||||
// 实际项目中应加载指定页码的订单
|
||||
// loadOrderPage(page)
|
||||
// 加载指定页码的订单
|
||||
loadOrderList()
|
||||
}
|
||||
|
||||
// 复制订单号
|
||||
function copyOrderId(payId) {
|
||||
uni.setClipboardData({
|
||||
data: payId,
|
||||
success: function() {
|
||||
uni.showToast({ title: '订单号已复制', icon: 'success' })
|
||||
},
|
||||
fail: function() {
|
||||
uni.showToast({ title: '复制失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -434,15 +403,16 @@
|
||||
/* 订单列表 */
|
||||
.order-list-section {
|
||||
flex: 1;
|
||||
padding: 0 16rpx;
|
||||
padding: 0 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
margin-bottom: 28rpx;
|
||||
padding-left: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
@@ -450,121 +420,109 @@
|
||||
.order-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
padding: 28rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.order-item:hover {
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-2rpx);
|
||||
}
|
||||
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
border-bottom: 1rpx solid #e0e0e0;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.order-code {
|
||||
font-size: 24rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
word-break: break-all;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
.order-code:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 12rpx;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
color: #e6a23c;
|
||||
background-color: rgba(230, 162, 60, 0.1);
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
color: #67c23a;
|
||||
background-color: rgba(103, 194, 58, 0.1);
|
||||
}
|
||||
|
||||
.status-exception {
|
||||
color: #f56c6c;
|
||||
background-color: rgba(245, 108, 108, 0.1);
|
||||
}
|
||||
|
||||
.status-refunded {
|
||||
color: #909399;
|
||||
background-color: rgba(144, 147, 153, 0.1);
|
||||
.distributor-name {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
background-color: #f5f7fa;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
white-space: nowrap;
|
||||
max-width: 200rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.order-body {
|
||||
margin-bottom: 16rpx;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.order-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300rpx, 1fr));
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
font-size: 20rpx;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #606266;
|
||||
width: 120rpx;
|
||||
color: #909399;
|
||||
font-size: 24rpx;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #303133;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-value.price {
|
||||
color: #f56c6c;
|
||||
font-weight: 600;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.order-footer {
|
||||
border-top: 1rpx solid #e0e0e0;
|
||||
padding-top: 16rpx;
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 750rpx) {
|
||||
.order-info {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
padding: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 16rpx;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.process-btn {
|
||||
background-color: #ecf5ff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.detail-btn {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.refund-btn {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
@@ -621,85 +579,6 @@
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* 平板响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.member-order-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin: 0 32rpx 24rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.order-list-section {
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin: 0 32rpx 32rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 36rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.picker-text,
|
||||
.search-input {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.filter-control {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.order-code {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.order-status {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 160rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 18rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
}
|
||||
|
||||
.page-info {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.page-btn {
|
||||
font-size: 22rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
}
|
||||
|
||||
.export-btn {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 大屏设备响应式 */
|
||||
@media screen and (min-width: 1024px) {
|
||||
.member-order-container {
|
||||
|
||||
Reference in New Issue
Block a user