|
|
@@ -1,6 +1,7 @@
|
|
|
<route lang="json5" type="page">
|
|
|
{
|
|
|
layout: 'default',
|
|
|
+ needLogin: true,
|
|
|
style: {
|
|
|
navigationBarTitleText: '%myOrders.title%',
|
|
|
navigationBarBackgroundColor: '#fff',
|
|
|
@@ -13,10 +14,13 @@
|
|
|
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
|
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
|
import useZPaging from 'z-paging/components/z-paging/js/hooks/useZPaging.js'
|
|
|
-import { orderList, orderStatusEnum } from '@/api/order'
|
|
|
+import { getConfigByCode } from '@/api/common'
|
|
|
+import { orderList, orderStatusEnum, recycleOrder, userCanRecycleNum } from '@/api/order'
|
|
|
+import { DialogBox } from '@/components/DialogBox'
|
|
|
import { t } from '@/locale'
|
|
|
import { formatNumber } from '@/utils'
|
|
|
import { toPage } from '@/utils/page'
|
|
|
+import { toast } from '@/utils/toast'
|
|
|
|
|
|
defineOptions({
|
|
|
name: 'MyOrders', // 我的订单
|
|
|
@@ -27,6 +31,7 @@ const paging = ref(null)
|
|
|
// 类似mixins,如果是页面滚动务必要写这一行,并传入当前ref绑定的paging,注意此处是paging,而非paging.value
|
|
|
useZPaging(paging)
|
|
|
const isPageLoading = ref(true) // 页面加载状态
|
|
|
+const systemInfo = ref(uni.getSystemInfoSync()) // 获取系统信息
|
|
|
const tab = ref<number>(0)
|
|
|
const tabList = ref<any>([
|
|
|
{
|
|
|
@@ -50,6 +55,41 @@ const tabList = ref<any>([
|
|
|
value: 4,
|
|
|
},
|
|
|
])
|
|
|
+
|
|
|
+// 搜索结果
|
|
|
+const dataList = ref<any[]>([])
|
|
|
+
|
|
|
+const maxSelectCount = ref<number>(0) // 最大可选订单数量
|
|
|
+const selectedOrders = ref<string[]>([]) // 已选中的订单ID列表
|
|
|
+
|
|
|
+const recycleProportion = ref<string>('')
|
|
|
+const recycleRate = ref<number>(0)
|
|
|
+
|
|
|
+async function getRecycleProportion() {
|
|
|
+ try {
|
|
|
+ const res = await getConfigByCode({ code: 'recycle_proportion' })
|
|
|
+ if (res.code === '200' && res.data?.valueInfo) {
|
|
|
+ let rate = Number(res.data.valueInfo) || 0
|
|
|
+ if (rate > 1)
|
|
|
+ rate = rate / 100
|
|
|
+ recycleRate.value = rate
|
|
|
+ recycleProportion.value = String(rate * 100)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch {
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function getUserCanRecycleNum() {
|
|
|
+ try {
|
|
|
+ const res = await userCanRecycleNum()
|
|
|
+ if (res.code === '200') {
|
|
|
+ maxSelectCount.value = Number(res.data) || 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch {
|
|
|
+ }
|
|
|
+}
|
|
|
const orderStatusEnumData = ref<any>([])
|
|
|
async function getOrderStatus() {
|
|
|
try {
|
|
|
@@ -63,8 +103,91 @@ async function getOrderStatus() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 搜索结果
|
|
|
-const dataList = ref<any[]>([])
|
|
|
+// 判断订单是否已选中
|
|
|
+function isOrderSelected(orderId: string) {
|
|
|
+ return selectedOrders.value.includes(orderId)
|
|
|
+}
|
|
|
+
|
|
|
+// 判断订单是否可以勾选(未选中且未达到上限,或已选中)
|
|
|
+function canSelectOrder(orderId: string) {
|
|
|
+ return isOrderSelected(orderId) || selectedOrders.value.length < maxSelectCount.value
|
|
|
+}
|
|
|
+
|
|
|
+// 切换订单选中状态
|
|
|
+function toggleOrderSelection(orderId: string) {
|
|
|
+ const index = selectedOrders.value.indexOf(orderId)
|
|
|
+ if (index > -1) {
|
|
|
+ // 已选中,取消选中
|
|
|
+ selectedOrders.value.splice(index, 1)
|
|
|
+ }
|
|
|
+ else if (selectedOrders.value.length < maxSelectCount.value) {
|
|
|
+ // 未选中且未达到上限,添加选中
|
|
|
+ selectedOrders.value.push(orderId)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 切换tab时清空选中状态
|
|
|
+function handleTabChange() {
|
|
|
+ selectedOrders.value = []
|
|
|
+ getUserCanRecycleNum()
|
|
|
+ queryList(1, 20)
|
|
|
+}
|
|
|
+
|
|
|
+// 计算选中订单的总金额
|
|
|
+const totalAmount = computed(() => {
|
|
|
+ if (selectedOrders.value.length === 0)
|
|
|
+ return 0
|
|
|
+ return dataList.value
|
|
|
+ .filter(item => selectedOrders.value.includes(item.orderId))
|
|
|
+ .reduce((sum, item) => {
|
|
|
+ const price = Number(item?.orderInfoVO?.[0]?.price) || 0
|
|
|
+ const quantity = Number(item?.orderInfoVO?.[0]?.payNum) || 0
|
|
|
+ return sum + (price * quantity)
|
|
|
+ }, 0)
|
|
|
+})
|
|
|
+
|
|
|
+const recycleAmount = computed(() => {
|
|
|
+ return totalAmount.value * recycleRate.value
|
|
|
+})
|
|
|
+
|
|
|
+// 弹框状态
|
|
|
+const showRecycleDialog = ref(false)
|
|
|
+
|
|
|
+// 点击 Recycle Order 按钮,显示二次确认弹框
|
|
|
+function handleRecycleOrder() {
|
|
|
+ showRecycleDialog.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 确认回收订单
|
|
|
+async function confirmRecycle() {
|
|
|
+ try {
|
|
|
+ if (selectedOrders.value.length === 0) {
|
|
|
+ toast.info(t('myOrders.selectTip', [maxSelectCount.value]))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.showLoading({
|
|
|
+ title: t('common.loading'),
|
|
|
+ mask: true,
|
|
|
+ })
|
|
|
+
|
|
|
+ const res = await recycleOrder({ orderNos: selectedOrders.value })
|
|
|
+ if (res.code === '200') {
|
|
|
+ toast.success(t('myOrders.recycleSuccess'))
|
|
|
+ }
|
|
|
+ selectedOrders.value = []
|
|
|
+ // 刷新列表
|
|
|
+ paging.value?.reload()
|
|
|
+ getUserCanRecycleNum()
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ console.error('回收订单失败:', error)
|
|
|
+ toast.error(t('myOrders.recycleFailed'))
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ uni.hideLoading()
|
|
|
+ }
|
|
|
+}
|
|
|
async function queryList(pageNo: number, pageSize: number) {
|
|
|
// 此处请求仅为演示,请替换为自己项目中的请求
|
|
|
try {
|
|
|
@@ -79,6 +202,9 @@ async function queryList(pageNo: number, pageSize: number) {
|
|
|
type: tab.value, // 根据tab的值来查询不同状态的订单
|
|
|
})
|
|
|
paging.value.complete(res.data.list)
|
|
|
+ if (pageNo === 1) {
|
|
|
+ getUserCanRecycleNum()
|
|
|
+ }
|
|
|
}
|
|
|
catch {
|
|
|
paging.value.complete(false)
|
|
|
@@ -92,6 +218,8 @@ async function queryList(pageNo: number, pageSize: number) {
|
|
|
}
|
|
|
onLoad((options) => {
|
|
|
getOrderStatus()
|
|
|
+ getUserCanRecycleNum()
|
|
|
+ getRecycleProportion()
|
|
|
|
|
|
// 处理页面参数,如果有type参数则切换到对应的tab
|
|
|
if (options) {
|
|
|
@@ -109,7 +237,7 @@ onLoad((options) => {
|
|
|
<template>
|
|
|
<z-paging ref="paging" v-model="dataList" use-page-scroll @query="queryList">
|
|
|
<template #top>
|
|
|
- <wd-tabs v-model="tab" :auto-line-width="true" custom-class="bg-transparent!" slidable="always" @click="() => queryList(1, 20)">
|
|
|
+ <wd-tabs v-model="tab" :auto-line-width="true" custom-class="bg-transparent!" slidable="always" @click="handleTabChange">
|
|
|
<wd-tab v-for="tabItem in tabList" :key="tabItem.value" :title="t(tabItem.label)" :name="tabItem.value" />
|
|
|
</wd-tabs>
|
|
|
</template>
|
|
|
@@ -149,12 +277,26 @@ onLoad((options) => {
|
|
|
|
|
|
<!-- 实际内容 -->
|
|
|
<template v-else>
|
|
|
+ <!-- Success tab 选择提示 -->
|
|
|
+ <view v-if="tab === 2" class="pt-24rpx text-center font-bold">
|
|
|
+ {{ t('myOrders.selectTip', [maxSelectCount]) }}
|
|
|
+ </view>
|
|
|
<view class="pt-24rpx">
|
|
|
<wd-card v-for="item in dataList" :key="item.orderId" type="rectangle" custom-class="px-24rpx! py-6rpx!" custom-content-class="py-18rpx!" custom-title-class="py-18rpx!" @click="toPage({ url: '/pages/myOrders/orderDetail', params: { orderNo: item?.orderId } })">
|
|
|
<template #title>
|
|
|
<view class="flex items-center justify-between">
|
|
|
- <view class="text-28rpx text-#000">
|
|
|
- {{ t('myOrders.order.id') }}:{{ item.orderId }}
|
|
|
+ <view class="flex items-center text-28rpx text-#000">
|
|
|
+ <!-- 仅在 success tab (tab=2) 时显示勾选框 -->
|
|
|
+ <wd-checkbox
|
|
|
+ v-if="tab === 2"
|
|
|
+ :model-value="isOrderSelected(item.orderId)"
|
|
|
+ :disabled="!canSelectOrder(item.orderId)"
|
|
|
+ custom-class="mr-16rpx"
|
|
|
+ @click.stop="toggleOrderSelection(item.orderId)"
|
|
|
+ />
|
|
|
+ <view>
|
|
|
+ {{ t('myOrders.order.id') }}:{{ item.orderId }}
|
|
|
+ </view>
|
|
|
</view>
|
|
|
<wd-text size="26rpx" type="primary" :text="orderStatusEnumData.find((i:any) => i.code === item.status)?.name" />
|
|
|
</view>
|
|
|
@@ -189,7 +331,61 @@ onLoad((options) => {
|
|
|
</wd-card>
|
|
|
</view>
|
|
|
</template>
|
|
|
+
|
|
|
+ <!-- 底部提交信息块 -->
|
|
|
+ <template #bottom>
|
|
|
+ <view
|
|
|
+ v-if="tab === 2 && selectedOrders.length > 0"
|
|
|
+ class="flex items-center justify-end bg-white px-24rpx pt-30rpx shadow-[0_-2rpx_8rpx_0_rgba(0,0,0,0.1)]"
|
|
|
+ :style="{ paddingBottom: `${systemInfo.safeAreaInsets?.bottom + 30 || 30}rpx` }"
|
|
|
+ >
|
|
|
+ <view>
|
|
|
+ <text>
|
|
|
+ {{ $t('myOrders.total') }}:
|
|
|
+ </text>
|
|
|
+ <text class="text-[var(--wot-color-theme)]">
|
|
|
+ ৳{{ formatNumber(recycleAmount) }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <wd-button
|
|
|
+ custom-class="ml-16rpx! min-w-260rpx! bg-[var(--wot-color-theme)]"
|
|
|
+ @click="handleRecycleOrder"
|
|
|
+ >
|
|
|
+ {{ $t('myOrders.recycleOrder') }}
|
|
|
+ </wd-button>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
</z-paging>
|
|
|
+
|
|
|
+ <!-- 回收订单确认弹框 -->
|
|
|
+ <DialogBox
|
|
|
+ v-model:show="showRecycleDialog"
|
|
|
+ :show-cancel="false"
|
|
|
+ :confirm-text="$t('myOrders.dialog.confirm')"
|
|
|
+ @confirm="confirmRecycle"
|
|
|
+ >
|
|
|
+ <view class="text-left">
|
|
|
+ <view class="pb-24rpx text-center text-32rpx font-bold">
|
|
|
+ {{ $t('myOrders.dialog.title') }}
|
|
|
+ </view>
|
|
|
+ <view class="pb-24rpx text-24rpx font-bold">
|
|
|
+ {{ $t('myOrders.dialog.notesTitle') }}
|
|
|
+ </view>
|
|
|
+ <view class="pb-32rpx text-24rpx text-#666">
|
|
|
+ <view class="space-y-16rpx">
|
|
|
+ <view>{{ $t('myOrders.dialog.note1') }}</view>
|
|
|
+ <view>{{ $t('myOrders.dialog.note2', [recycleProportion]) }}</view>
|
|
|
+ <view>{{ $t('myOrders.dialog.note3') }}</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="mb-44rpx text-center">
|
|
|
+ <text>{{ $t('myOrders.dialog.priceLabel') }}: </text>
|
|
|
+ <text class="text-[var(--wot-color-theme)]">
|
|
|
+ ৳{{ formatNumber(recycleAmount) }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </DialogBox>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss" scoped>
|