新增团餐管理
This commit is contained in:
Vendored
+2
-2
@@ -5,7 +5,7 @@ VITE_DELETE_CONSOLE=false
|
|||||||
|
|
||||||
#本地环境
|
#本地环境
|
||||||
#VITE_SERVER_BASEURL=http://liuyao.nat100.top/meiguowaimai
|
#VITE_SERVER_BASEURL=http://liuyao.nat100.top/meiguowaimai
|
||||||
VITE_SERVER_BASEURL=http://192.168.5.11:8080
|
#VITE_SERVER_BASEURL=http://192.168.5.11:8080
|
||||||
#VITE_SERVER_BASEURL=https://howhowfresh.com/prod-api
|
VITE_SERVER_BASEURL=https://howhowfresh.com/prod-api
|
||||||
#VITE_SERVER_BASEURL=http://192.168.1.8:8811
|
#VITE_SERVER_BASEURL=http://192.168.1.8:8811
|
||||||
#VITE_SERVER_BASEURL=http://mifengchuantou.natapp1.cc/meiguowaimai
|
#VITE_SERVER_BASEURL=http://mifengchuantou.natapp1.cc/meiguowaimai
|
||||||
|
|||||||
@@ -173,3 +173,19 @@ export enum MessageTypeEnum {
|
|||||||
/** 评论审核未通过 */
|
/** 评论审核未通过 */
|
||||||
COMMENT_REJECTED = 14,
|
COMMENT_REJECTED = 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 团餐预定状态 */
|
||||||
|
export enum GroupMealReservationStatus {
|
||||||
|
/** 待处理 */
|
||||||
|
PENDING = 1,
|
||||||
|
/** 已联系 */
|
||||||
|
CONTACTED = 2,
|
||||||
|
/** 已确认 */
|
||||||
|
CONFIRMED = 3,
|
||||||
|
/** 已拒绝 */
|
||||||
|
REJECTED = 4,
|
||||||
|
/** 已完成 */
|
||||||
|
COMPLETED = 5,
|
||||||
|
/** 用户取消 */
|
||||||
|
USER_CANCELLED = 6,
|
||||||
|
}
|
||||||
@@ -95,6 +95,7 @@
|
|||||||
"navbar-future-order": "Future Order",
|
"navbar-future-order": "Future Order",
|
||||||
"navbar-month-order": "This Month's Order",
|
"navbar-month-order": "This Month's Order",
|
||||||
"navbar-refund-order": "Refund order",
|
"navbar-refund-order": "Refund order",
|
||||||
|
"navbar-group-meal-reservation": "Group meal reservation",
|
||||||
"navbar-reservation": "Today's ordered dishes",
|
"navbar-reservation": "Today's ordered dishes",
|
||||||
"navbar-set-payment-password": "Set a payment password",
|
"navbar-set-payment-password": "Set a payment password",
|
||||||
"navbar-settings": "Settings",
|
"navbar-settings": "Settings",
|
||||||
@@ -108,6 +109,7 @@
|
|||||||
"card-title": "CHEFLINK stir fry machine",
|
"card-title": "CHEFLINK stir fry machine",
|
||||||
"commonTools": "Common tools",
|
"commonTools": "Common tools",
|
||||||
"coupons": "Coupons",
|
"coupons": "Coupons",
|
||||||
|
"groupMealReservation": "Group meals",
|
||||||
"createStore": "Create a store",
|
"createStore": "Create a store",
|
||||||
"dataStatistics": "Data statistics",
|
"dataStatistics": "Data statistics",
|
||||||
"futureOrders": "Booking order",
|
"futureOrders": "Booking order",
|
||||||
@@ -371,6 +373,34 @@
|
|||||||
"value": "Value"
|
"value": "Value"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"groupMealReservation": {
|
||||||
|
"tabs": {
|
||||||
|
"all": "All"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"pending": "Pending",
|
||||||
|
"contacted": "Contacted",
|
||||||
|
"confirmed": "Confirmed",
|
||||||
|
"rejected": "Rejected",
|
||||||
|
"completed": "Completed",
|
||||||
|
"userCancelled": "Cancelled by user"
|
||||||
|
},
|
||||||
|
"contactPhone": "Contact phone",
|
||||||
|
"peopleCount": "People count",
|
||||||
|
"perCapitaPrice": "Price per person",
|
||||||
|
"estimatedTotal": "Estimated total",
|
||||||
|
"expectedTime": "Expected time",
|
||||||
|
"scene": "Scene",
|
||||||
|
"remark": "User remark",
|
||||||
|
"handleRemark": "Handle remark",
|
||||||
|
"cancelReason": "Cancel reason",
|
||||||
|
"userNickName": "User nickname",
|
||||||
|
"detailTitle": "Group meal details",
|
||||||
|
"handleTitle": "Update status",
|
||||||
|
"handleRemarkPlaceholder": "Handle remark (optional)",
|
||||||
|
"confirmHandle": "Update status to \"{status}\"?",
|
||||||
|
"userCancelledTip": "Cancelled by user. View only."
|
||||||
|
},
|
||||||
"income": {
|
"income": {
|
||||||
"index": {
|
"index": {
|
||||||
"accountToReceive": "Account to receive:",
|
"accountToReceive": "Account to receive:",
|
||||||
|
|||||||
@@ -95,6 +95,7 @@
|
|||||||
"navbar-future-order": "未来订单",
|
"navbar-future-order": "未来订单",
|
||||||
"navbar-month-order": "本月订单",
|
"navbar-month-order": "本月订单",
|
||||||
"navbar-refund-order": "退款订单",
|
"navbar-refund-order": "退款订单",
|
||||||
|
"navbar-group-meal-reservation": "团餐预定",
|
||||||
"navbar-reservation": "今日预定菜品统计",
|
"navbar-reservation": "今日预定菜品统计",
|
||||||
"navbar-set-payment-password": "设置支付密码",
|
"navbar-set-payment-password": "设置支付密码",
|
||||||
"navbar-settings": "设置",
|
"navbar-settings": "设置",
|
||||||
@@ -106,6 +107,7 @@
|
|||||||
"bookDishesToday": "预订菜品",
|
"bookDishesToday": "预订菜品",
|
||||||
"commonTools": "常用工具",
|
"commonTools": "常用工具",
|
||||||
"coupons": "优惠券",
|
"coupons": "优惠券",
|
||||||
|
"groupMealReservation": "团餐预定",
|
||||||
"createStore": "创建店铺",
|
"createStore": "创建店铺",
|
||||||
"dataStatistics": "数据统计",
|
"dataStatistics": "数据统计",
|
||||||
"futureOrders": "预定单",
|
"futureOrders": "预定单",
|
||||||
@@ -371,6 +373,34 @@
|
|||||||
"value": "值"
|
"value": "值"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"groupMealReservation": {
|
||||||
|
"tabs": {
|
||||||
|
"all": "全部"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"pending": "待处理",
|
||||||
|
"contacted": "已联系",
|
||||||
|
"confirmed": "已确认",
|
||||||
|
"rejected": "已拒绝",
|
||||||
|
"completed": "已完成",
|
||||||
|
"userCancelled": "用户取消"
|
||||||
|
},
|
||||||
|
"contactPhone": "联系电话",
|
||||||
|
"peopleCount": "团餐人数",
|
||||||
|
"perCapitaPrice": "人均单价",
|
||||||
|
"estimatedTotal": "预计总价",
|
||||||
|
"expectedTime": "期望时间",
|
||||||
|
"scene": "场景",
|
||||||
|
"remark": "用户备注",
|
||||||
|
"handleRemark": "处理备注",
|
||||||
|
"cancelReason": "取消原因",
|
||||||
|
"userNickName": "用户昵称",
|
||||||
|
"detailTitle": "团餐预定详情",
|
||||||
|
"handleTitle": "处理状态",
|
||||||
|
"handleRemarkPlaceholder": "请输入处理备注(选填)",
|
||||||
|
"confirmHandle": "确认将状态更新为「{status}」?",
|
||||||
|
"userCancelledTip": "用户已取消,仅可查看详情"
|
||||||
|
},
|
||||||
"income": {
|
"income": {
|
||||||
"index": {
|
"index": {
|
||||||
"accountToReceive": "到账账户:",
|
"accountToReceive": "到账账户:",
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
"name" : "CHEFLINK Merchant",
|
"name" : "CHEFLINK Merchant",
|
||||||
"appid" : "__UNI__BB8E3C9",
|
"appid" : "__UNI__BB8E3C9",
|
||||||
"description" : "美国外卖商户端",
|
"description" : "美国外卖商户端",
|
||||||
"versionName" : "3.0.1",
|
"versionName" : "3.0.2",
|
||||||
"versionCode" : 301,
|
"versionCode" : 302,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import {
|
||||||
|
appGroupMealReservationMerchantIdGet,
|
||||||
|
appGroupMealReservationMerchantStatusPost,
|
||||||
|
type GroupMealReservationVo,
|
||||||
|
} from '@/service'
|
||||||
|
import {GroupMealReservationStatus} from '@/constant/enums'
|
||||||
|
import {
|
||||||
|
calcGroupMealTotal,
|
||||||
|
canMerchantHandleGroupMeal,
|
||||||
|
getGroupMealContactPhone,
|
||||||
|
} from '@/utils/groupMealReservation'
|
||||||
|
import {callPhone, formatTimestampWithMonthName} from '@/utils/utils'
|
||||||
|
import {useMessage} from 'wot-design-uni'
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const {t} = useI18n()
|
||||||
|
|
||||||
|
const reservationId = ref('')
|
||||||
|
const detail = ref<GroupMealReservationVo>()
|
||||||
|
const loading = ref(false)
|
||||||
|
const handleRemark = ref('')
|
||||||
|
|
||||||
|
const handleActions = computed(() => [
|
||||||
|
{status: GroupMealReservationStatus.CONTACTED, label: t('pages-user.groupMealReservation.status.contacted')},
|
||||||
|
{status: GroupMealReservationStatus.CONFIRMED, label: t('pages-user.groupMealReservation.status.confirmed')},
|
||||||
|
{status: GroupMealReservationStatus.REJECTED, label: t('pages-user.groupMealReservation.status.rejected')},
|
||||||
|
{status: GroupMealReservationStatus.COMPLETED, label: t('pages-user.groupMealReservation.status.completed')},
|
||||||
|
])
|
||||||
|
|
||||||
|
const canHandle = computed(() => canMerchantHandleGroupMeal(detail.value?.status))
|
||||||
|
|
||||||
|
function statusLabel(status?: number) {
|
||||||
|
const map: Record<number, string> = {
|
||||||
|
[GroupMealReservationStatus.PENDING]: t('pages-user.groupMealReservation.status.pending'),
|
||||||
|
[GroupMealReservationStatus.CONTACTED]: t('pages-user.groupMealReservation.status.contacted'),
|
||||||
|
[GroupMealReservationStatus.CONFIRMED]: t('pages-user.groupMealReservation.status.confirmed'),
|
||||||
|
[GroupMealReservationStatus.REJECTED]: t('pages-user.groupMealReservation.status.rejected'),
|
||||||
|
[GroupMealReservationStatus.COMPLETED]: t('pages-user.groupMealReservation.status.completed'),
|
||||||
|
[GroupMealReservationStatus.USER_CANCELLED]: t('pages-user.groupMealReservation.status.userCancelled'),
|
||||||
|
}
|
||||||
|
return status != null ? (map[status] || String(status)) : '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadDetail() {
|
||||||
|
if (!reservationId.value) return
|
||||||
|
loading.value = true
|
||||||
|
appGroupMealReservationMerchantIdGet({
|
||||||
|
params: {id: reservationId.value},
|
||||||
|
}).then((res: any) => {
|
||||||
|
detail.value = res.data
|
||||||
|
handleRemark.value = res.data?.handleRemark || ''
|
||||||
|
}).catch((err: any) => {
|
||||||
|
uni.showToast({
|
||||||
|
title: err?.msg || err?.message || t('common.prompt.request-failed-please-try-again-later'),
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeCall() {
|
||||||
|
callPhone(getGroupMealContactPhone(detail.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitStatus(status: 2 | 3 | 4 | 5) {
|
||||||
|
if (!detail.value?.id) return
|
||||||
|
message.confirm({
|
||||||
|
title: t('common.prompt.system-prompt'),
|
||||||
|
msg: t('pages-user.groupMealReservation.confirmHandle', {status: statusLabel(status)}),
|
||||||
|
confirmButtonText: t('common.yes'),
|
||||||
|
cancelButtonText: t('common.no'),
|
||||||
|
}).then(() => {
|
||||||
|
appGroupMealReservationMerchantStatusPost({
|
||||||
|
body: {
|
||||||
|
id: detail.value!.id!,
|
||||||
|
status,
|
||||||
|
handleRemark: handleRemark.value.trim() || undefined,
|
||||||
|
},
|
||||||
|
}).then((res: any) => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res?.msg || t('common.operation-success'),
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
loadDetail()
|
||||||
|
}).catch((err: any) => {
|
||||||
|
uni.showToast({
|
||||||
|
title: err?.msg || err?.message || t('common.prompt.request-incorrect'),
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleActionClick(status: number) {
|
||||||
|
submitStatus(status as 2 | 3 | 4 | 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options?.id) {
|
||||||
|
reservationId.value = options.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (reservationId.value) {
|
||||||
|
loadDetail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="min-h-100vh bg-#F6F6F6 pb-200rpx">
|
||||||
|
<navbar :title="t('pages-user.groupMealReservation.detailTitle')"/>
|
||||||
|
|
||||||
|
<view v-if="loading" class="px-30rpx pt-30rpx">
|
||||||
|
<view class="bg-white rounded-16rpx p-30rpx">
|
||||||
|
<view v-for="n in 6" :key="n" class="w-full h-28rpx skeleton-item mb-24rpx"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else-if="detail" class="px-30rpx pt-30rpx">
|
||||||
|
<view class="bg-white rounded-16rpx p-30rpx mb-24rpx">
|
||||||
|
<view class="flex-center-sb mb-28rpx">
|
||||||
|
<text class="text-36rpx text-#333 font-500">{{ detail.contactName || '-' }}</text>
|
||||||
|
<text class="text-26rpx text-#FF6106">{{ statusLabel(detail.status) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.contactPhone') }}</text>
|
||||||
|
<view class="flex items-center" @click="makeCall">
|
||||||
|
<text class="value text-#007AFF mr-12rpx">{{ getGroupMealContactPhone(detail) || '-' }}</text>
|
||||||
|
<image class="w-48rpx h-48rpx shrink-0" src="@img/chef/206.png"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.scene') }}</text>
|
||||||
|
<text class="value">{{ detail.scene || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.peopleCount') }}</text>
|
||||||
|
<text class="value">{{ detail.peopleCount || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.perCapitaPrice') }}</text>
|
||||||
|
<text class="value">${{ detail.perCapitaPrice ?? 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.estimatedTotal') }}</text>
|
||||||
|
<text class="value font-500">${{ calcGroupMealTotal(detail.peopleCount, detail.perCapitaPrice) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.expectedTime') }}</text>
|
||||||
|
<text class="value">
|
||||||
|
{{ detail.expectedTime ? formatTimestampWithMonthName(detail.expectedTime) : '-' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="detail.remark" class="info-row items-start">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.remark') }}</text>
|
||||||
|
<text class="value flex-1 text-right">{{ detail.remark }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="detail.handleRemark" class="info-row items-start">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.handleRemark') }}</text>
|
||||||
|
<text class="value flex-1 text-right">{{ detail.handleRemark }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="detail.cancelReason" class="info-row items-start">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.cancelReason') }}</text>
|
||||||
|
<text class="value flex-1 text-right">{{ detail.cancelReason }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="detail.user?.nickName" class="info-row">
|
||||||
|
<text class="label">{{ t('pages-user.groupMealReservation.userNickName') }}</text>
|
||||||
|
<text class="value">{{ detail.user.nickName }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="canHandle" class="bg-white rounded-16rpx p-30rpx">
|
||||||
|
<text class="text-32rpx text-#333 font-500 mb-24rpx block">
|
||||||
|
{{ t('pages-user.groupMealReservation.handleTitle') }}
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<view class="bg-#F6F6F6 rounded-16rpx px-24rpx py-20rpx mb-30rpx">
|
||||||
|
<wd-textarea
|
||||||
|
v-model="handleRemark"
|
||||||
|
:placeholder="t('pages-user.groupMealReservation.handleRemarkPlaceholder')"
|
||||||
|
auto-height
|
||||||
|
custom-class="!bg-#F6F6F6"
|
||||||
|
custom-textarea-container-class="!bg-#F6F6F6"
|
||||||
|
no-border
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="grid grid-cols-2 gap-20rpx">
|
||||||
|
<view
|
||||||
|
v-for="action in handleActions"
|
||||||
|
:key="action.status"
|
||||||
|
class="h-88rpx center rounded-16rpx bg-#F2F2F2 text-28rpx text-#333 font-500"
|
||||||
|
@click="handleActionClick(action.status)"
|
||||||
|
>
|
||||||
|
{{ action.label }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else-if="detail.status === GroupMealReservationStatus.USER_CANCELLED"
|
||||||
|
class="bg-white rounded-16rpx p-30rpx text-28rpx text-#999 center">
|
||||||
|
{{ t('pages-user.groupMealReservation.userCancelledTip') }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import {
|
||||||
|
appGroupMealReservationMerchantListPost,
|
||||||
|
type GroupMealReservationVo,
|
||||||
|
} from '@/service'
|
||||||
|
import {GroupMealReservationStatus} from '@/constant/enums'
|
||||||
|
import {calcGroupMealTotal, getGroupMealContactPhone} from '@/utils/groupMealReservation'
|
||||||
|
import {callPhone, formatTimestampWithMonthName} from '@/utils/utils'
|
||||||
|
import {useUserStore} from '@/store'
|
||||||
|
|
||||||
|
const {t} = useI18n()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const currentTab = ref(0)
|
||||||
|
const tabsList = computed(() => [
|
||||||
|
{title: t('pages-user.groupMealReservation.tabs.all'), status: undefined},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.pending'), status: GroupMealReservationStatus.PENDING},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.contacted'), status: GroupMealReservationStatus.CONTACTED},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.confirmed'), status: GroupMealReservationStatus.CONFIRMED},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.rejected'), status: GroupMealReservationStatus.REJECTED},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.completed'), status: GroupMealReservationStatus.COMPLETED},
|
||||||
|
{title: t('pages-user.groupMealReservation.status.userCancelled'), status: GroupMealReservationStatus.USER_CANCELLED},
|
||||||
|
])
|
||||||
|
|
||||||
|
function statusLabel(status?: number) {
|
||||||
|
const map: Record<number, string> = {
|
||||||
|
[GroupMealReservationStatus.PENDING]: t('pages-user.groupMealReservation.status.pending'),
|
||||||
|
[GroupMealReservationStatus.CONTACTED]: t('pages-user.groupMealReservation.status.contacted'),
|
||||||
|
[GroupMealReservationStatus.CONFIRMED]: t('pages-user.groupMealReservation.status.confirmed'),
|
||||||
|
[GroupMealReservationStatus.REJECTED]: t('pages-user.groupMealReservation.status.rejected'),
|
||||||
|
[GroupMealReservationStatus.COMPLETED]: t('pages-user.groupMealReservation.status.completed'),
|
||||||
|
[GroupMealReservationStatus.USER_CANCELLED]: t('pages-user.groupMealReservation.status.userCancelled'),
|
||||||
|
}
|
||||||
|
return status != null ? (map[status] || String(status)) : '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusClass(status?: number) {
|
||||||
|
if (status === GroupMealReservationStatus.PENDING) return 'text-#FF6106 bg-#FFF3EB'
|
||||||
|
if (status === GroupMealReservationStatus.CONTACTED) return 'text-#007AFF bg-#EAF3FF'
|
||||||
|
if (status === GroupMealReservationStatus.CONFIRMED) return 'text-#00A76D bg-#E8F8F2'
|
||||||
|
if (status === GroupMealReservationStatus.REJECTED) return 'text-#FF2828 bg-#FFECEC'
|
||||||
|
if (status === GroupMealReservationStatus.COMPLETED) return 'text-#333 bg-#F2F2F2'
|
||||||
|
if (status === GroupMealReservationStatus.USER_CANCELLED) return 'text-#999 bg-#F6F6F6'
|
||||||
|
return 'text-#666 bg-#F6F6F6'
|
||||||
|
}
|
||||||
|
|
||||||
|
const {paging, dataList, loading, queryList} = usePage<GroupMealReservationVo>((pageNum, pageSize) => {
|
||||||
|
const tab = tabsList.value[currentTab.value]
|
||||||
|
return appGroupMealReservationMerchantListPost({
|
||||||
|
params: {pageNum, pageSize},
|
||||||
|
body: tab?.status != null ? {status: tab.status} : {},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function tabsChange(e: { index: number }) {
|
||||||
|
currentTab.value = e.index
|
||||||
|
paging.value?.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
function goDetail(item: GroupMealReservationVo) {
|
||||||
|
if (!item.id) return
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages-user/pages/group-meal-reservation/detail?id=${item.id}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function dialPhone(item: GroupMealReservationVo) {
|
||||||
|
callPhone(getGroupMealContactPhone(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (!userStore.isLogin) return
|
||||||
|
nextTick(() => {
|
||||||
|
paging.value?.reload()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<z-paging ref="paging" v-model="dataList" :auto="false" @query="queryList">
|
||||||
|
<template #top>
|
||||||
|
<navbar :title="t('navbar-group-meal-reservation')"/>
|
||||||
|
<wd-tabs v-model="currentTab" :lineWidth="67" animated color="#14181B" inactiveColor="#666666" sticky
|
||||||
|
@change="tabsChange">
|
||||||
|
<wd-tab v-for="(item, index) in tabsList" :key="index" :title="item.title"/>
|
||||||
|
</wd-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<view v-show="loading" class="px-30rpx py-20rpx">
|
||||||
|
<view v-for="n in 4" :key="n" class="bg-white rounded-16rpx p-24rpx mb-20rpx">
|
||||||
|
<view class="w-200rpx h-28rpx skeleton-item mb-20rpx"/>
|
||||||
|
<view class="w-full h-24rpx skeleton-item mb-16rpx"/>
|
||||||
|
<view class="w-300rpx h-24rpx skeleton-item"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-show="!loading" class="px-30rpx py-20rpx">
|
||||||
|
<view
|
||||||
|
v-for="item in dataList"
|
||||||
|
:key="item.id"
|
||||||
|
class="bg-white rounded-16rpx p-24rpx mb-20rpx last:mb-0"
|
||||||
|
@click="goDetail(item)"
|
||||||
|
>
|
||||||
|
<view class="flex-center-sb mb-20rpx">
|
||||||
|
<text class="text-32rpx text-#333 font-500">{{ item.contactName || '-' }}</text>
|
||||||
|
<text :class="statusClass(item.status)" class="text-24rpx px-16rpx py-6rpx rounded-8rpx">
|
||||||
|
{{ statusLabel(item.status) }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-center-sb mb-16rpx">
|
||||||
|
<text class="text-28rpx text-#666">{{ t('pages-user.groupMealReservation.contactPhone') }}</text>
|
||||||
|
<view class="flex items-center" @click.stop="dialPhone(item)">
|
||||||
|
<text class="text-28rpx text-#007AFF mr-10rpx">{{ getGroupMealContactPhone(item) || '-' }}</text>
|
||||||
|
<image class="w-36rpx h-36rpx shrink-0" src="@img/chef/206.png"/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-center-sb mb-16rpx">
|
||||||
|
<text class="text-28rpx text-#666">{{ t('pages-user.groupMealReservation.peopleCount') }}</text>
|
||||||
|
<text class="text-28rpx text-#333">{{ item.peopleCount || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-center-sb mb-16rpx">
|
||||||
|
<text class="text-28rpx text-#666">{{ t('pages-user.groupMealReservation.perCapitaPrice') }}</text>
|
||||||
|
<text class="text-28rpx text-#333">${{ item.perCapitaPrice ?? 0 }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-center-sb mb-16rpx">
|
||||||
|
<text class="text-28rpx text-#666">{{ t('pages-user.groupMealReservation.estimatedTotal') }}</text>
|
||||||
|
<text class="text-28rpx text-#333 font-500">${{ calcGroupMealTotal(item.peopleCount, item.perCapitaPrice) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-center-sb">
|
||||||
|
<text class="text-28rpx text-#666">{{ t('pages-user.groupMealReservation.expectedTime') }}</text>
|
||||||
|
<text class="text-28rpx text-#333">
|
||||||
|
{{ item.expectedTime ? formatTimestampWithMonthName(item.expectedTime) : '-' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.wd-tabs__nav-item) {
|
||||||
|
font-size: 28rpx !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -99,6 +99,12 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/home-order/refund-order"
|
"path": "pages/home-order/refund-order"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/group-meal-reservation/index"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/group-meal-reservation/detail"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/store-management/index"
|
"path": "pages/store-management/index"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ function navigateTo(url: string) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (url === '/pages-user/pages/group-meal-reservation/index' && !userStore.currentMerchantToken) {
|
||||||
|
uni.showToast({
|
||||||
|
title: t('toast.pleaseSelectStore'),
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url,
|
url,
|
||||||
})
|
})
|
||||||
@@ -293,30 +300,40 @@ defineExpose({
|
|||||||
<view class="text-36rpx text-#333 font-bold lh-36rpx mb-48rpx tracking-[.04em]">
|
<view class="text-36rpx text-#333 font-bold lh-36rpx mb-48rpx tracking-[.04em]">
|
||||||
{{ t('pages.home.commonTools') }}
|
{{ t('pages.home.commonTools') }}
|
||||||
</view>
|
</view>
|
||||||
<view class="grid grid-cols-4">
|
<scroll-view :show-scrollbar="false" class="common-tools-scroll w-full" scroll-x>
|
||||||
<view class="flex flex-col items-center relative"
|
<view class="common-tools-row flex flex-nowrap">
|
||||||
|
<view class="common-tools-item flex flex-col items-center relative shrink-0"
|
||||||
@click="navigateTo('/pages-user/pages/home-order/refund-order')">
|
@click="navigateTo('/pages-user/pages/home-order/refund-order')">
|
||||||
<view
|
<view
|
||||||
v-if="storeInfo?.refundOrderNum && +storeInfo?.refundOrderNum > 0"
|
v-if="storeInfo?.refundOrderNum && +storeInfo?.refundOrderNum > 0"
|
||||||
class="absolute top--10rpx right-40rpx z-2 min-w-36rpx h-36rpx rounded-full bg-#FF1212 text-28rpx text-#fff center">
|
class="absolute top--10rpx right-8rpx z-2 min-w-36rpx h-36rpx rounded-full bg-#FF1212 text-28rpx text-#fff center">
|
||||||
{{ +storeInfo?.refundOrderNum > 99 ? '99+' : storeInfo?.refundOrderNum }}
|
{{ +storeInfo?.refundOrderNum > 99 ? '99+' : storeInfo?.refundOrderNum }}
|
||||||
</view>
|
</view>
|
||||||
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/101.png"></image>
|
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/101.png"></image>
|
||||||
<view class="text-24rpx text-#333 lh-20rpx">{{ t('pages.home.refundOrders') }}</view>
|
<view class="text-24rpx text-#333 lh-20rpx text-center px-8rpx">{{ t('pages.home.refundOrders') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col items-center" @click="navigateTo('/pages-user/pages/income/index')">
|
<view class="common-tools-item flex flex-col items-center shrink-0"
|
||||||
|
@click="navigateTo('/pages-user/pages/income/index')">
|
||||||
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/102.png"></image>
|
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/102.png"></image>
|
||||||
<view class="text-24rpx text-#333 lh-20rpx">{{ t('pages.home.myIncome') }}</view>
|
<view class="text-24rpx text-#333 lh-20rpx text-center px-8rpx">{{ t('pages.home.myIncome') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col items-center" @click="navigateTo('/pages-user/pages/recipe/index')">
|
<view class="common-tools-item flex flex-col items-center shrink-0"
|
||||||
|
@click="navigateTo('/pages-user/pages/recipe/index')">
|
||||||
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/103.png"></image>
|
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/103.png"></image>
|
||||||
<view class="text-24rpx text-#333 lh-20rpx">{{ t('pages.home.recipes') }}</view>
|
<view class="text-24rpx text-#333 lh-20rpx text-center px-8rpx">{{ t('pages.home.recipes') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col items-center" @click="navigateTo('/pages-user/pages/coupons/index')">
|
<view class="common-tools-item flex flex-col items-center shrink-0"
|
||||||
|
@click="navigateTo('/pages-user/pages/coupons/index')">
|
||||||
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/104.png"></image>
|
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/104.png"></image>
|
||||||
<view class="text-24rpx text-#333 lh-20rpx">{{ t('pages.home.coupons') }}</view>
|
<view class="text-24rpx text-#333 lh-20rpx text-center px-8rpx">{{ t('pages.home.coupons') }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="common-tools-item flex flex-col items-center shrink-0"
|
||||||
|
@click="navigateTo('/pages-user/pages/group-meal-reservation/index')">
|
||||||
|
<image class="w-52rpx h-52rpx mb-24rpx" src="@img/chef/9191.png"></image>
|
||||||
|
<view class="text-24rpx text-#333 lh-20rpx text-center px-8rpx">{{ t('pages.home.groupMealReservation') }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 订单列表 -->
|
<!-- 订单列表 -->
|
||||||
@@ -407,6 +424,21 @@ defineExpose({
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.common-tools-scroll {
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.common-tools-row {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.common-tools-item {
|
||||||
|
width: 20%;
|
||||||
|
min-width: 136rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.wd-tabs__nav-item) {
|
:deep(.wd-tabs__nav-item) {
|
||||||
font-size: 30rpx !important;
|
font-size: 30rpx !important;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
import request from '@/http/vue-query';
|
||||||
|
import type { CustomRequestOptions } from '@/http/types';
|
||||||
|
|
||||||
|
export type GroupMealReservationVo = {
|
||||||
|
id?: number;
|
||||||
|
merchantId?: number;
|
||||||
|
userId?: number;
|
||||||
|
peopleCount?: number;
|
||||||
|
perCapitaPrice?: number;
|
||||||
|
scene?: string;
|
||||||
|
contactName?: string;
|
||||||
|
contactPhone?: string;
|
||||||
|
expectedTime?: number;
|
||||||
|
status?: number;
|
||||||
|
handleRemark?: string;
|
||||||
|
cancelReason?: string;
|
||||||
|
remark?: string;
|
||||||
|
createTime?: number;
|
||||||
|
merchant?: {
|
||||||
|
merchantName?: string;
|
||||||
|
logo?: string;
|
||||||
|
merchantAddress?: string;
|
||||||
|
};
|
||||||
|
user?: {
|
||||||
|
nickName?: string;
|
||||||
|
surname?: string;
|
||||||
|
firstName?: string;
|
||||||
|
phone?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GroupMealReservationQueryBo = {
|
||||||
|
status?: number;
|
||||||
|
contactName?: string;
|
||||||
|
contactPhone?: string;
|
||||||
|
expectedBeginTime?: number;
|
||||||
|
expectedEndTime?: number;
|
||||||
|
createBeginTime?: number;
|
||||||
|
createEndTime?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GroupMealReservationStatusBo = {
|
||||||
|
id: number;
|
||||||
|
status: 2 | 3 | 4 | 5;
|
||||||
|
handleRemark?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 商户端团餐预定列表 POST /app/groupMealReservation/merchantList */
|
||||||
|
export async function appGroupMealReservationMerchantListPost({
|
||||||
|
params,
|
||||||
|
body,
|
||||||
|
options,
|
||||||
|
}: {
|
||||||
|
params: { pageNum: number; pageSize: number };
|
||||||
|
body?: GroupMealReservationQueryBo;
|
||||||
|
options?: CustomRequestOptions;
|
||||||
|
}) {
|
||||||
|
return request<any>('/app/groupMealReservation/merchantList', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
data: body || {},
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商户端团餐预定详情 GET /app/groupMealReservation/merchant/{id} */
|
||||||
|
export async function appGroupMealReservationMerchantIdGet({
|
||||||
|
params,
|
||||||
|
options,
|
||||||
|
}: {
|
||||||
|
params: { id: number | string };
|
||||||
|
options?: CustomRequestOptions;
|
||||||
|
}) {
|
||||||
|
return request<{ data?: GroupMealReservationVo }>(`/app/groupMealReservation/merchant/${params.id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商户端处理团餐预定状态 POST /app/groupMealReservation/merchant/status */
|
||||||
|
export async function appGroupMealReservationMerchantStatusPost({
|
||||||
|
body,
|
||||||
|
options,
|
||||||
|
}: {
|
||||||
|
body: GroupMealReservationStatusBo;
|
||||||
|
options?: CustomRequestOptions;
|
||||||
|
}) {
|
||||||
|
return request<{ code?: number; msg?: string }>('/app/groupMealReservation/merchant/status', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
data: body,
|
||||||
|
...(options || {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ export * from './merchantCart';
|
|||||||
export * from './coupon';
|
export * from './coupon';
|
||||||
export * from './search';
|
export * from './search';
|
||||||
export * from './merchantOrder';
|
export * from './merchantOrder';
|
||||||
|
export * from './groupMealReservation';
|
||||||
export * from './featuredMerchant';
|
export * from './featuredMerchant';
|
||||||
export * from './feedback';
|
export * from './feedback';
|
||||||
export * from './membershipConfig';
|
export * from './membershipConfig';
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
import {GroupMealReservationStatus} from '@/constant/enums'
|
||||||
|
|
||||||
|
export function calcGroupMealTotal(peopleCount?: number, perCapitaPrice?: number) {
|
||||||
|
const count = Number(peopleCount) || 0
|
||||||
|
const price = Number(perCapitaPrice) || 0
|
||||||
|
return (count * price).toFixed(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canMerchantHandleGroupMeal(status?: number) {
|
||||||
|
return status === GroupMealReservationStatus.PENDING || status === GroupMealReservationStatus.CONTACTED
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGroupMealContactPhone(item?: { contactPhone?: string; user?: { phone?: string } }) {
|
||||||
|
return (item?.contactPhone || item?.user?.phone || '').trim()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user