This commit is contained in:
2025-08-26 16:17:24 +08:00
commit e3d080e419
557 changed files with 70994 additions and 0 deletions

748
pages/code/code.vue Normal file
View File

@@ -0,0 +1,748 @@
<template>
<view class="page-container">
<!-- 页面标题 -->
<view class="page-title">订单列表</view>
<!-- 搜索区域 - 仅保留时间查询 -->
<view class="search-box">
<view class="search-item">
<text class="label">订单日期</text>
<view class="date-picker" @click="showDatePicker = true">
<text>{{ dateRangeText || '选择日期范围' }}</text>
<text class="arrow"></text>
</view>
</view>
<view class="search-buttons">
<button class="search-btn" @click="handleQuery">查询</button>
<button class="reset-btn" @click="resetQuery">重置</button>
</view>
</view>
<!-- 订单列表 -->
<view class="order-list">
<!-- 加载中 -->
<view class="loading" v-if="loading">
<view class="spinner"></view>
<text>加载中...</text>
</view>
<!-- 错误提示 -->
<view class="error" v-if="errorMsg">
<text>{{ errorMsg }}</text>
</view>
<!-- 空状态 -->
<view class="empty" v-if="!loading && !errorMsg && orderList.length === 0">
<text>该时间段内暂无订单数据</text>
</view>
<!-- 列表标题 -->
<view class="list-header" v-if="!loading && !errorMsg && orderList.length > 0">
<view class="header-item" style="width: 35%;">订单号</view>
<!-- <view class="header-item" style="width: 12%;">顾客姓名</view> -->
<!-- <view class="header-item" style="width: 8%;">桌号</view> -->
<view class="header-item" style="width: 15%;">订单类型</view>
<view class="header-item" style="width: 15%;">订单状态</view>
<view class="header-item" style="width: 15%;">应收金额</view>
<view class="header-item" style="width: 15%;">实收金额</view>
<!-- <view class="header-item" style="width: 15%;">支付方式</view> -->
</view>
<!-- 列表内容 -->
<view class="list-body" v-if="!loading && !errorMsg && orderList.length > 0">
<view class="order-item" v-for="(order, index) in orderList" :key="order.id || index">
<view class="order-cell" style="width: 35%;">{{ order.id || '-' }}</view>
<!-- <view class="order-cell" style="width: 12%;">{{ order.customerName || '-' }}</view> -->
<!-- <view class="order-cell" style="width: 8%;">{{ order.tableId || '-' }}</view> -->
<view class="order-cell" style="width: 15%;">
<view class="tag" :class="getTypeClass(order.orderType)">{{ getOrderType(order.orderType) }}</view>
</view>
<view class="order-cell" style="width: 15%;">
<view class="tag" :class="getStatusClass(order.orderStatus)">{{ getOrderStatus(order.orderStatus) }}</view>
</view>
<view class="order-cell" style="width: 15%;">¥{{ formatMoney(order.totalAmount) }}</view>
<view class="order-cell" style="width: 15%;">¥{{ formatMoney(order.actualReceivedAmount) }}</view>
<!-- <view class="order-cell" style="width: 15%;">{{ getPaymentMethod(order.paymentMethod) || '-' }}</view> -->
</view>
</view>
</view>
<!-- 分页 -->
<view class="pagination" v-if="!loading && !errorMsg && total > 0">
<view class="pagination-info">
<text> {{ total }} {{ queryParams.pageNum }}/{{ totalPages }} </text>
</view>
<view class="pagination-buttons">
<button
class="page-btn"
@click="prevPage"
:disabled="queryParams.pageNum <= 1"
>上一页</button>
<button
class="page-btn"
@click="nextPage"
:disabled="queryParams.pageNum >= totalPages"
>下一页</button>
</view>
</view>
<!-- 日期选择器弹窗 -->
<view class="picker-mask" v-if="showDatePicker" @click="showDatePicker = false"></view>
<view class="picker-popup" v-if="showDatePicker">
<view class="picker-title">
<text @click="showDatePicker = false">取消</text>
<text>选择日期范围</text>
<text @click="confirmDate">确定</text>
</view>
<picker-view
class="date-picker-view"
:value="datePickerValue"
@change="onDateChange"
>
<picker-view-column>
<view v-for="(year, index) in years" :key="index">{{ year }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(month, index) in months" :key="index">{{ month }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(day, index) in days" :key="index">{{ day }}</view>
</picker-view-column>
<picker-view-column>
<view></view>
</picker-view-column>
<picker-view-column>
<view v-for="(year, index) in years" :key="index">{{ year }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(month, index) in months" :key="index">{{ month }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(day, index) in days" :key="index">{{ day }}</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
<script>
import orderApi from '@/common/http/eatery/order.js'
export default {
data() {
return {
// 订单列表数据
orderList: [],
// 加载状态
loading: false,
// 错误信息
errorMsg: '',
// 总条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
startDate: '',
endDate: ''
},
// 支付方式列表
paymentMethods: [],
// 日期范围文本
dateRangeText: '',
// 日期选择器显示状态
showDatePicker: false,
// 日期选择器数据
years: [],
months: [],
days: [],
// 日期选择器值
datePickerValue: [],
// 开始日期和结束日期
startDateObj: null,
endDateObj: null,
// 订单类型映射
orderTypeMap: {
'1': '堂食',
'2': '外卖'
},
// 订单状态映射
orderStatusMap: {
'1': '待结算',
'2': '已结算',
'3': '已取消'
}
}
},
computed: {
// 总页数
totalPages() {
return Math.ceil(this.total / this.queryParams.pageSize)
}
},
onLoad() {
// 初始化日期数据
this.initDateData()
// 获取支付方式
this.getPaymentMethods()
// 默认加载最近7天数据
this.handleQuery()
},
methods: {
/**
* 初始化日期选择器数据
*/
initDateData() {
const now = new Date()
const year = now.getFullYear()
// 生成年份数据近3年
this.years = []
for (let i = year - 2; i <= year; i++) {
this.years.push(i)
}
// 生成月份数据
this.months = []
for (let i = 1; i <= 12; i++) {
this.months.push(i)
}
// 生成日期数据
this.days = []
for (let i = 1; i <= 31; i++) {
this.days.push(i)
}
// 设置默认日期最近7天
const start = new Date()
start.setDate(start.getDate() - 7)
this.startDateObj = start
this.endDateObj = now
// 设置日期选择器初始值
this.datePickerValue = [
this.years.indexOf(start.getFullYear()),
start.getMonth(),
start.getDate() - 1,
0, // 分隔符
this.years.indexOf(now.getFullYear()),
now.getMonth(),
now.getDate() - 1
]
// 更新日期文本
this.updateDateRangeText()
},
/**
* 更新日期范围文本
*/
updateDateRangeText() {
if (this.startDateObj && this.endDateObj) {
const formatDate = (date) => {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`
}
this.dateRangeText = `${formatDate(this.startDateObj)}${formatDate(this.endDateObj)}`
this.queryParams.startDate = formatDate(this.startDateObj)
this.queryParams.endDate = formatDate(this.endDateObj)
} else {
this.dateRangeText = ''
this.queryParams.startDate = ''
this.queryParams.endDate = ''
}
},
/**
* 日期选择变化
*/
onDateChange(e) {
const val = e.detail.value
// 解析开始日期
const startYear = this.years[val[0]]
const startMonth = this.months[val[1]]
const startDay = this.days[val[2]]
// 解析结束日期
const endYear = this.years[val[4]]
const endMonth = this.months[val[5]]
const endDay = this.days[val[6]]
// 更新日期对象
this.startDateObj = new Date(startYear, startMonth - 1, startDay)
this.endDateObj = new Date(endYear, endMonth - 1, endDay)
},
/**
* 确认日期选择
*/
confirmDate() {
// 确保开始日期不晚于结束日期
if (this.startDateObj > this.endDateObj) {
uni.showToast({ title: '开始日期不能晚于结束日期', icon: 'none' })
return
}
this.updateDateRangeText()
this.showDatePicker = false
},
/**
* 获取支付方式列表
*/
getPaymentMethods() {
orderApi.getPaymentMethods().then(res => {
if (res.data && Array.isArray(res.data)) {
this.paymentMethods = res.data.map(item => ({
value: item.dictValue,
text: item.dictLabel
}))
}
}).catch(err => {
console.error('获取支付方式失败:', err)
// 不阻断主流程,仅在控制台输出错误
})
},
/**
* 分页查询订单 - 修复数据不显示问题
*/
getOrderPage() {
// 重置错误信息
this.errorMsg = ''
// 显示加载状态
this.loading = true
// 检查日期参数是否完整
if (!this.queryParams.startDate || !this.queryParams.endDate) {
this.loading = false
this.errorMsg = '请选择完整的日期范围'
return
}
// 调用API查询数据
orderApi.getOrderPage(this.queryParams)
.then(res => {
// 确保返回数据格式正确
if (res && typeof res === 'object') {
// 适配不同的API返回格式
const data = res.data || res
this.orderList = Array.isArray(data.rows) ? data.rows : []
this.total = typeof data.total === 'number' ? data.total : 0
} else {
this.orderList = []
this.total = 0
this.errorMsg = '数据格式错误'
}
})
.catch(err => {
console.error('获取订单失败:', err)
this.orderList = []
this.total = 0
this.errorMsg = '获取订单失败,请重试'
})
.finally(() => {
// 无论成功失败都关闭加载状态
this.loading = false
})
},
/**
* 查询按钮触发
*/
handleQuery() {
this.queryParams.pageNum = 1
this.getOrderPage()
},
/**
* 重置查询条件
*/
resetQuery() {
// 重置为最近7天
const now = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
this.startDateObj = start
this.endDateObj = now
// 更新日期选择器值
this.datePickerValue = [
this.years.indexOf(start.getFullYear()),
start.getMonth(),
start.getDate() - 1,
0, // 分隔符
this.years.indexOf(now.getFullYear()),
now.getMonth(),
now.getDate() - 1
]
this.updateDateRangeText()
this.queryParams.pageNum = 1
this.getOrderPage()
},
/**
* 上一页
*/
prevPage() {
if (this.queryParams.pageNum > 1) {
this.queryParams.pageNum--
this.getOrderPage()
}
},
/**
* 下一页
*/
nextPage() {
if (this.queryParams.pageNum < this.totalPages) {
this.queryParams.pageNum++
this.getOrderPage()
}
},
/**
* 获取订单类型文本
*/
getOrderType(type) {
return this.orderTypeMap[type] || '未知'
},
/**
* 获取订单类型样式类
*/
getTypeClass(type) {
const classMap = {
'1': 'type-dining',
'2': 'type-takeout'
}
return classMap[type] || 'type-default'
},
/**
* 获取订单状态文本
*/
getOrderStatus(status) {
return this.orderStatusMap[status] || '未知'
},
/**
* 获取订单状态样式类
*/
getStatusClass(status) {
const classMap = {
'1': 'status-pending',
'2': 'status-settled',
'3': 'status-canceled'
}
return classMap[status] || 'status-default'
},
/**
* 获取支付方式文本
*/
getPaymentMethod(method) {
const methodItem = this.paymentMethods.find(item => item.value === method)
return methodItem ? methodItem.text : '未知'
},
/**
* 格式化金额
*/
formatMoney(amount) {
// 处理可能的null/undefined值
if (amount === null || amount === undefined) return '0.00'
// 转换为数字并保留两位小数
return parseFloat(amount).toFixed(2)
}
}
}
</script>
<style lang="scss" scoped>
.page-container {
padding: 20rpx;
background-color: #f5f7fa;
min-height: 100vh;
box-sizing: border-box;
font-size: 28rpx;
}
.page-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin: 30rpx 0;
color: #333;
}
.search-box {
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 20rpx;
}
.search-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.label {
width: 140rpx;
color: #666;
}
.date-picker {
flex: 1;
height: 70rpx;
border: 1px solid #eee;
border-radius: 8rpx;
padding: 0 15rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
}
.arrow {
color: #999;
font-size: 24rpx;
}
.search-buttons {
display: flex;
gap: 20rpx;
}
.search-btn {
flex: 1;
height: 70rpx;
line-height: 70rpx;
background-color: #03AE80;
color: #fff;
border-radius: 8rpx;
font-size: 28rpx;
border: none;
}
.reset-btn {
flex: 1;
height: 70rpx;
line-height: 70rpx;
background-color: #f5f5f5;
color: #666;
border-radius: 8rpx;
font-size: 28rpx;
border: 1px solid #eee;
}
.order-list {
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
overflow-x: auto;
}
.loading {
display: flex;
flex-direction: column;
align-items: center;
padding: 100rpx 0;
}
.spinner {
width: 50rpx;
height: 50rpx;
border: 5rpx solid #eee;
border-top-color: #03AE80;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20rpx;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.error {
text-align: center;
padding: 100rpx 0;
color: #ff3b30;
}
.empty {
text-align: center;
padding: 100rpx 0;
color: #999;
}
.list-header {
display: flex;
background-color: #f5f5f5;
border-radius: 8rpx 8rpx 0 0;
overflow: hidden;
font-weight: bold;
}
.header-item {
padding: 15rpx 10rpx;
text-align: center;
border-right: 1px solid #eee;
box-sizing: border-box;
}
.header-item:last-child {
border-right: none;
}
.list-body {
border: 1px solid #eee;
border-top: none;
border-radius: 0 0 8rpx 8rpx;
overflow: hidden;
}
.order-item {
display: flex;
border-bottom: 1px solid #eee;
}
.order-item:last-child {
border-bottom: none;
}
.order-cell {
padding: 15rpx 10rpx;
text-align: center;
border-right: 1px solid #eee;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.order-cell:last-child {
border-right: none;
}
.tag {
display: inline-block;
padding: 5rpx 10rpx;
border-radius: 4rpx;
font-size: 24rpx;
color: #fff;
}
.type-dining {
background-color: #007aff;
}
.type-takeout {
background-color: #4cd964;
}
.type-default {
background-color: #999;
}
.status-pending {
background-color: #ff9500;
}
.status-settled {
background-color: #4cd964;
}
.status-canceled {
background-color: #ff3b30;
}
.status-default {
background-color: #999;
}
.pagination {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
padding: 10rpx 0;
}
.pagination-info {
color: #666;
font-size: 26rpx;
}
.pagination-buttons {
display: flex;
gap: 15rpx;
}
.page-btn {
padding: 0 25rpx;
height: 60rpx;
line-height: 60rpx;
background-color: #f5f5f5;
color: #666;
border-radius: 8rpx;
font-size: 26rpx;
border: 1px solid #eee;
}
.page-btn:disabled {
opacity: 0.5;
}
.picker-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 998;
}
.picker-popup {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
z-index: 999;
}
.picker-title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #eee;
}
.picker-title text {
flex: 1;
text-align: center;
font-size: 30rpx;
}
.picker-title text:first-child,
.picker-title text:last-child {
color: #03AE80;
}
.date-picker-view {
width: 100%;
height: 400rpx;
}
</style>