更新项目配置和添加小程序模块

- 修改 ArticleController.java
- 更新 application.yml 配置
- 更新 frontend/.env.production 环境配置
- 添加 single_uniapp22miao 小程序模块
- 添加 logs 目录
This commit is contained in:
panchengyong
2026-03-13 13:27:13 +08:00
parent 5432904bcb
commit 786bf78282
360 changed files with 571027 additions and 4 deletions

View File

@@ -0,0 +1,605 @@
<template>
<view class="order-list-page">
<!-- 买卖方切换 -->
<view class="role-tabs">
<view class="role-tab" :class="{ 'active': userRole === 0 }" @click="switchRole(0)">买方</view>
<view class="role-tab" :class="{ 'active': userRole === 1 }" @click="switchRole(1)">卖方</view>
</view>
<!-- 状态Tab切换 -->
<view class="status-tabs">
<view v-for="(tab, index) in statusTabs" :key="index" class="status-tab" :class="{ 'active': currentTab === index }" @click="switchTab(index)">
{{ tab }}
</view>
</view>
<!-- 订单列表 -->
<scroll-view scroll-y class="scroll-view" @scrolltolower="loadMore">
<view class="order-list">
<!-- 订单列表项 -->
<view v-for="(order, index) in orderList" :key="order.id" class="order-item" @click="viewOrderDetail(order)">
<!-- 订单头部 -->
<view class="order-header">
<view class="order-no">订单编号{{ order.order_no }}</view>
<view class="order-status">待支付</view>
</view>
<!-- 商品信息 -->
<view class="goods-info">
<image :src="order.goods_image || order.image" class="goods-image"></image>
<view class="goods-detail">
<view class="goods-name">{{ order.goods_name || order.name }}</view>
<view class="goods-price">商品价格¥{{ order.price }}</view>
<!-- 卖家信息 -->
<view class="user-info">
<view class="user-label">卖家</view>
<view class="user-name">{{ order.seller_name || order.seller }}</view>
</view>
<view class="user-phone">卖家电话{{ order.seller_phone || order.seller_tel }}</view>
<!-- 买家信息 -->
<view class="user-info">
<view class="user-label">买家</view>
<view class="user-name">{{ order.buyer_name || order.buyer }}</view>
</view>
<view class="user-phone">买家电话{{ order.buyer_phone || order.buyer_tel }}</view>
</view>
</view>
<!-- 订单时间 -->
<view class="order-time">
<view class="time-item">下单时间{{ formatTime(order.created_at) }}</view>
<view class="time-item">抢单时间{{ formatTime(order.created_at) }}</view>
</view>
<!-- 操作按钮 -->
<view class="order-actions">
<button class="action-btn cancel" @click.stop="cancelOrder(order, index)">取消</button>
<button class="action-btn primary" @click.stop="payOrder(order)">去支付</button>
</view>
</view>
<!-- 加载更多 -->
<view class="load-more" v-if="orderList.length > 0">
<text v-if="loading">加载中...</text>
<text v-else-if="noMore">没有更多了</text>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="orderList.length === 0 && !loading">
<text class="icon">📦</text>
<text class="text">暂无订单</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { getOrderList, cancelOrder, payOrder } from '@/api/miao.js';
export default {
data() {
return {
userRole: 0, // 0: 买方, 1: 卖方
statusTabs: ['寄卖中/交易中', '已完成'],
// 注意当前type参数定义为1:寄卖中/交易中2:已完成
currentTab: 0,
// 新增参数用于直接从URL获取
cate: 1, // 1: 买方, 2: 卖方
type: 1, // 1: 仓库, 2: 交易中, 3: 已完成
orderList: [],
page: 1,
limit: 20,
loading: false,
noMore: false
}
},
onLoad(options) {
// 从URL参数中获取cate和type
if (options.cate) {
this.cate = parseInt(options.cate);
// 根据cate设置用户角色1=买方2=卖方
this.userRole = this.cate === 2 ? 1 : 0;
}
if (options.type) {
this.type = parseInt(options.type);
// 根据type设置当前标签页1=寄卖中/交易中2=已完成
this.currentTab = this.type - 1;
}
// 兼容旧参数格式
if (options.userRole) {
this.userRole = parseInt(options.userRole);
this.cate = this.userRole === 1 ? 2 : 1;
}
if (options.tab) {
this.currentTab = parseInt(options.tab);
// 转换旧tab为新type参数格式
this.type = this.currentTab === 0 ? 1 : 2; // 仓库和交易中合并为1
}
this.loadOrderList();
},
methods: {
// 切换买卖方
switchRole(role) {
if (this.userRole === role) return;
this.userRole = role;
// 同步更新cate参数
this.cate = role === 1 ? 2 : 1;
this.page = 1;
this.noMore = false;
this.orderList = [];
this.loadOrderList();
},
// 切换Tab
switchTab(index) {
if (this.currentTab === index) return;
this.currentTab = index;
// 同步更新type参数1=寄卖中/交易中2=已完成
this.type = index + 1;
this.page = 1;
this.noMore = false;
this.orderList = [];
this.loadOrderList();
},
// 格式化时间
formatTime(time) {
if (!time) return '';
const date = new Date(time);
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}`;
},
// 加载订单列表
async loadOrderList() {
if (this.loading || this.noMore) return;
this.loading = true;
try {
// 直接使用data中的cate和type参数
const res = await getOrderList({
page: this.page,
limit: this.limit,
cate: this.cate,
type: this.type
});
if (res.code === 0) {
const list = res.data.list || [];
// 处理数据,确保字段一致性
const processedList = list.map(item => ({
...item,
// 确保有必要的字段
id: item.id || item.order_id || '',
order_no: item.order_no || item.order_id || '',
goods_image: item.goods_image || item.image || '',
goods_name: item.goods_name || item.name || '商品',
price: item.price || item.goods_price || '0.00',
created_at: item.created_at || item.create_time || new Date().toISOString(),
seller_name: item.seller_name || item.seller || '未知',
seller_phone: item.seller_phone || item.seller_tel || '',
buyer_name: item.buyer_name || item.buyer || '未知',
buyer_phone: item.buyer_phone || item.buyer_tel || ''
}));
if (processedList.length < this.limit) {
this.noMore = true;
}
this.orderList = this.page === 1 ? processedList : [...this.orderList, ...processedList];
}
} catch (error) {
console.error('加载订单失败:', error);
uni.showToast({
title: error.msg || '加载失败,请重试',
icon: 'none'
});
} finally {
this.loading = false;
}
},
// 加载更多
loadMore() {
if (!this.loading && !this.noMore) {
this.page++;
this.loadOrderList();
}
},
// 确认收货和确认发货功能暂时隐藏,根据参考图不显示这些按钮
// 确认收货功能已移除
// 确认发货功能已移除
// 转卖功能已移除
// 查看订单详情
viewOrderDetail(order) {
uni.navigateTo({
url: `/pages/sub-pages/rushing-order/detail?id=${order.id}`
});
},
// 取消订单
cancelOrder(order, index) {
uni.showModal({
title: '提示',
content: '确定要取消该订单吗?',
success: async (res) => {
if (res.confirm) {
try {
const result = await cancelOrder({
id: order.id
});
if (result.code === 0) {
this.orderList[index].status = 3;
uni.showToast({
title: '订单已取消',
icon: 'success'
});
}
} catch (error) {
uni.showToast({
title: error.msg || '取消失败',
icon: 'none'
});
}
}
}
});
},
// 支付订单
payOrder(order) {
uni.navigateTo({
url: `/pages/sub-pages/rushing-order/detail?id=${order.id}&pay=1`
});
},
// 确认收货
confirmOrder(order, index) {
// 由于方法命名冲突这里改为使用导入的confirmOrder接口
const confirmOrderApi = async () => {
try {
const result = await this.$http.post('/api/order/confirm', {
id: order.id
});
if (result.code === 0) {
this.orderList[index].status = 2;
uni.showToast({
title: '确认成功',
icon: 'success'
});
}
} catch (error) {
uni.showToast({
title: error.msg || '确认失败',
icon: 'none'
});
}
};
uni.showModal({
title: '提示',
content: '确认收到货物了吗?',
success: async (res) => {
if (res.confirm) {
await confirmOrderApi();
}
}
});
},
// 确认发货
deliverOrder(order, index) {
uni.showModal({
title: '提示',
content: '确认已发货了吗?',
success: async (res) => {
if (res.confirm) {
try {
const result = await this.$http.post('/api/order/deliver', {
id: order.id
});
if (result.code === 0) {
this.orderList.splice(index, 1);
uni.showToast({
title: '发货成功',
icon: 'success'
});
}
} catch (error) {
uni.showToast({
title: error.msg || '操作失败',
icon: 'none'
});
}
}
}
});
},
// 转卖订单
resellOrder(order) {
uni.showModal({
title: '提示',
content: '确定要将该订单转卖吗?',
success: async (res) => {
if (res.confirm) {
try {
const result = await this.$http.post('/api/order/resell', {
id: order.id
});
if (result.code === 0) {
uni.showToast({
title: '转卖成功',
icon: 'success'
});
// 刷新列表
this.page = 1;
this.noMore = false;
this.orderList = [];
this.loadOrderList();
}
} catch (error) {
uni.showToast({
title: error.msg || '转卖失败',
icon: 'none'
});
}
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.order-list-page {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #f5f5f5;
}
/* 买卖方切换 */
.role-tabs {
display: flex;
background-color: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
.role-tab {
flex: 1;
height: 70rpx;
line-height: 70rpx;
text-align: center;
font-size: 32rpx;
color: #333;
border-radius: 35rpx;
background-color: #f5f5f5;
margin: 0 10rpx;
transition: all 0.3s;
&.active {
background-color: #ff6666;
color: #fff;
font-weight: bold;
}
}
}
/* 状态Tab切换 */
.status-tabs {
display: flex;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.status-tab {
flex: 1;
height: 90rpx;
line-height: 90rpx;
text-align: center;
font-size: 28rpx;
color: #666;
position: relative;
&.active {
color: #ff6666;
font-weight: bold;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background-color: #ff6666;
border-radius: 2rpx;
}
}
}
}
.scroll-view {
flex: 1;
}
.order-list {
padding: 20rpx 30rpx;
}
.order-item {
background-color: #fff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.order-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
padding-bottom: 20rpx;
border-bottom: 1px solid #f5f5f5;
.order-no {
font-size: 28rpx;
color: #333;
}
.order-status {
font-size: 28rpx;
color: #ff6666;
font-weight: bold;
}
}
.goods-info {
display: flex;
margin-bottom: 30rpx;
.goods-image {
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
margin-right: 25rpx;
background-color: #f5f5f5;
}
.goods-detail {
flex: 1;
display: flex;
flex-direction: column;
.goods-name {
font-size: 32rpx;
color: #333;
line-height: 1.4;
margin-bottom: 20rpx;
}
.goods-price {
font-size: 36rpx;
color: #ff6666;
font-weight: bold;
margin-bottom: 20rpx;
}
.user-info {
display: flex;
align-items: center;
margin-bottom: 10rpx;
.user-label {
background-color: #ff6666;
color: #fff;
padding: 4rpx 20rpx;
border-radius: 15rpx;
font-size: 22rpx;
margin-right: 15rpx;
}
.user-name {
font-size: 28rpx;
color: #333;
}
}
.user-phone {
font-size: 26rpx;
color: #666;
margin-bottom: 10rpx;
}
}
}
.order-time {
margin-bottom: 30rpx;
.time-item {
font-size: 26rpx;
color: #999;
margin-bottom: 8rpx;
}
}
.order-actions {
display: flex;
justify-content: flex-end;
gap: 20rpx;
.action-btn {
height: 70rpx;
line-height: 70rpx;
padding: 0 40rpx;
border-radius: 35rpx;
border: none;
font-size: 28rpx;
&.cancel {
background-color: #f5f5f5;
color: #666;
}
&.primary {
background-color: #ff6666;
color: #fff;
font-weight: bold;
}
}
}
}
.load-more {
padding: 30rpx;
text-align: center;
font-size: 26rpx;
color: #999;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 200rpx 0;
.icon {
font-size: 120rpx;
margin-bottom: 20rpx;
}
.text {
font-size: 28rpx;
color: #999;
}
}
</style>