fix: 订单查询改为先搜客户再查该客户的订单
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Agent
2026-03-28 03:28:57 +00:00
parent 848423faa3
commit 430a5422ee

View File

@@ -6,23 +6,47 @@
<text class="search-icon">🔍</text> <text class="search-icon">🔍</text>
<input <input
class="search-input" class="search-input"
v-model="customerName" v-model="keyword"
placeholder="输入客户姓名" placeholder="输入客户姓名搜索"
placeholder-class="placeholder" placeholder-class="placeholder"
@confirm="searchOrders" @input="searchCustomers"
/> />
</view> </view>
<button class="search-btn" @click="searchOrders">查询</button>
</view> </view>
<!-- 搜索结果 --> <!-- 搜索结果列表 -->
<scroll-view scroll-y class="result-section"> <scroll-view scroll-y class="result-section">
<view v-if="loading" class="loading">加载中...</view> <view v-if="loading" class="loading">加载中...</view>
<view v-else-if="orders.length === 0 && searched" class="empty"> <view v-else-if="customers.length === 0 && keyword" class="empty">
<text class="empty-icon">📋</text> <text class="empty-icon">👤</text>
<text class="empty-text">未找到相关订单</text> <text class="empty-text">未找到相关客户</text>
</view> </view>
<view v-else-if="orders.length > 0" class="order-list"> <view v-else-if="customers.length > 0" class="customer-list">
<view
v-for="customer in customers"
:key="customer.customerId"
class="customer-card"
@click="selectCustomer(customer)"
>
<view class="customer-info">
<text class="customer-name">{{ customer.name }}</text>
<text class="customer-phone">{{ customer.phone || '' }}</text>
</view>
<text class="arrow"></text>
</view>
</view>
<view v-else-if="selectedCustomer" class="selected-info">
<text>已选择: {{ selectedCustomer.name }}</text>
<text class="clear-btn" @click="clearSelection">清除</text>
</view>
</scroll-view>
<!-- 已选客户的订单列表 -->
<view class="orders-section" v-if="selectedCustomer && orders.length > 0">
<view class="orders-header">
<text class="orders-title">{{ selectedCustomer.name }} 的订单</text>
</view>
<scroll-view scroll-y class="orders-list">
<view <view
v-for="order in orders" v-for="order in orders"
:key="order.orderId" :key="order.orderId"
@@ -36,61 +60,78 @@
</text> </text>
</view> </view>
<view class="card-body"> <view class="card-body">
<text class="customer-name">👤 {{ order.customerName || '散客' }}</text>
<text class="order-amount">实付: ¥{{ order.actualAmount }}</text> <text class="order-amount">实付: ¥{{ order.actualAmount }}</text>
<text class="order-time">{{ formatTime(order.createdAt) }}</text> <text class="order-time">{{ formatTime(order.createdAt) }}</text>
</view> </view>
</view> </view>
</view>
<view v-else class="hint">
<text>请输入客户姓名进行查询</text>
</view>
</scroll-view> </scroll-view>
</view> </view>
</view>
</template> </template>
<script> <script>
import orderApi from '@/api/order' import orderApi from '@/api/order'
import customerApi from '@/api/customer'
export default { export default {
data() { data() {
return { return {
customerName: '', keyword: '',
customers: [],
selectedCustomer: null,
orders: [], orders: [],
loading: false, loading: false
searched: false
} }
}, },
methods: { methods: {
async searchOrders() { async searchCustomers() {
if (!this.customerName.trim()) { if (!this.keyword.trim()) {
uni.showToast({ title: '请输入客户姓名', icon: 'none' }) this.customers = []
return return
} }
this.loading = true this.loading = true
this.searched = true try {
const res = await customerApi.getCustomers({
keyword: this.keyword.trim(),
page: 1,
pageSize: 20
})
this.customers = res.records || []
} catch (e) {
console.error(e)
} finally {
this.loading = false
}
},
async selectCustomer(customer) {
this.selectedCustomer = customer
this.keyword = ''
this.customers = []
this.loadOrders()
},
clearSelection() {
this.selectedCustomer = null
this.orders = [] this.orders = []
},
async loadOrders() {
if (!this.selectedCustomer) return
try { try {
const res = await orderApi.getOrders({ const res = await orderApi.getOrders({
customerName: this.customerName.trim(), customerId: this.selectedCustomer.customerId,
page: 1, page: 1,
pageSize: 50 pageSize: 50
}) })
this.orders = res.records || [] this.orders = res.records || []
} catch (e) { } catch (e) {
uni.showToast({ title: '查询失败', icon: 'none' }) console.error(e)
} finally {
this.loading = false
} }
}, },
getStatusClass(status) { getStatusClass(status) {
const map = { const map = {
1: 'status-success', 1: 'status-success',
2: 'status-cancel', 2: 'status-cancel'
3: 'status-refunding',
4: 'status-refunded'
} }
return map[status] || '' return map[status] || ''
}, },
@@ -98,9 +139,7 @@ export default {
const map = { const map = {
0: '未完成', 0: '未完成',
1: '已完成', 1: '已完成',
2: '已取消', 2: '已取消'
3: '退款中',
4: '已退款'
} }
return map[status] || '未知' return map[status] || '未知'
}, },
@@ -111,7 +150,7 @@ export default {
viewDetail(order) { viewDetail(order) {
uni.showModal({ uni.showModal({
title: '订单详情', title: '订单详情',
content: `订单号: ${order.orderNo}\n客户: ${order.customerName || '散客'}\n原价: ¥${order.totalAmount}\n优惠: ¥${order.discountAmount}\n实付: ¥${order.actualAmount}\n状态: ${this.getStatusText(order.status)}`, content: `订单号: ${order.orderNo}\n原价: ¥${order.totalAmount}\n优惠: ¥${order.discountAmount}\n实付: ¥${order.actualAmount}\n状态: ${this.getStatusText(order.status)}`,
showCancel: false showCancel: false
}) })
} }
@@ -128,12 +167,9 @@ export default {
.search-section { .search-section {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 30rpx; padding: 30rpx;
display: flex;
align-items: center;
} }
.search-bar { .search-bar {
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
@@ -157,74 +193,116 @@ export default {
color: #999; color: #999;
} }
.search-btn {
margin-left: 20rpx;
background: #fff;
color: #667eea;
font-size: 28rpx;
padding: 16rpx 32rpx;
border-radius: 40rpx;
border: none;
}
.result-section { .result-section {
height: calc(100vh - 180rpx); height: 400rpx;
padding: 20rpx; padding: 20rpx;
} }
.loading, .hint { .loading, .empty {
text-align: center; text-align: center;
color: #999; color: #999;
padding: 60rpx; padding: 60rpx;
} }
.empty {
display: flex;
flex-direction: column;
align-items: center;
padding: 100rpx;
}
.empty-icon { .empty-icon {
font-size: 80rpx; font-size: 60rpx;
margin-bottom: 20rpx; display: block;
}
.empty-text {
color: #999;
font-size: 28rpx;
}
.order-list {
display: flex;
flex-direction: column;
}
.order-card {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx; margin-bottom: 16rpx;
} }
.order-no { .selected-info {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
background: #e6f7ff;
border-radius: 12rpx;
margin: 20rpx;
color: #1890ff;
}
.clear-btn {
color: #ff4d4f;
font-size: 26rpx;
}
.customer-list {
display: flex;
flex-direction: column;
}
.customer-card {
display: flex;
justify-content: space-between;
align-items: center;
background: #fff;
padding: 24rpx;
margin-bottom: 16rpx;
border-radius: 12rpx;
}
.customer-info {
display: flex;
flex-direction: column;
}
.customer-name {
font-size: 28rpx; font-size: 28rpx;
font-weight: bold; font-weight: bold;
color: #333; color: #333;
} }
.order-status { .customer-phone {
font-size: 24rpx; font-size: 24rpx;
padding: 4rpx 16rpx; color: #999;
border-radius: 20rpx; margin-top: 8rpx;
}
.arrow {
font-size: 36rpx;
color: #ccc;
}
.orders-section {
background: #fff;
padding: 20rpx;
margin-top: 20rpx;
}
.orders-header {
margin-bottom: 20rpx;
}
.orders-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.orders-list {
height: 500rpx;
}
.order-card {
padding: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.card-header {
display: flex;
justify-content: space-between;
margin-bottom: 12rpx;
}
.order-no {
font-size: 26rpx;
color: #333;
}
.order-status {
font-size: 22rpx;
padding: 4rpx 12rpx;
border-radius: 16rpx;
} }
.status-success { .status-success {
@@ -239,17 +317,11 @@ export default {
.card-body { .card-body {
display: flex; display: flex;
flex-direction: column; justify-content: space-between;
gap: 8rpx;
}
.customer-name {
font-size: 26rpx;
color: #666;
} }
.order-amount { .order-amount {
font-size: 30rpx; font-size: 28rpx;
font-weight: bold; font-weight: bold;
color: #ff4d4f; color: #ff4d4f;
} }