Browse Source

fix(R19): 顶部位置+禁聊+未读

dev
cursor 1 day ago
parent
commit
7f79ab6254
10 changed files with 92 additions and 46 deletions
  1. +18
    -8
      pages/chat/chat.vue
  2. +9
    -4
      pages/confirm/confirm.vue
  3. +8
    -3
      pages/index/index.vue
  4. +7
    -4
      pages/menu/menu.vue
  5. +11
    -6
      pages/orders/orders.vue
  6. +11
    -6
      pages/staff/board.vue
  7. +18
    -8
      pages/staff/chat.vue
  8. +8
    -5
      pages/staff/detail.vue
  9. +0
    -1
      uni.scss
  10. +2
    -1
      utils/constants.js

+ 18
- 8
pages/chat/chat.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-chat">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">💬 调酒师</text>
<text></text>
@ -33,14 +33,13 @@ export default {
const messages = ref([])
const inputText = ref('')
const scrollToId = ref('')
const statusBarHeight = ref(0)
let lastId = 0
async function loadMessages() {
try {
const res = await get(API.MESSAGE_LIST, { card_no: card.cardNo, since: lastId })
if (Array.isArray(res) && res.length > 0) {
const newMsgs = res.filter(m => m.senderType === 'staff')
if (newMsgs.length > 0) card.incrementUnread(newMsgs.length)
messages.value = [...messages.value, ...res]
lastId = res[res.length - 1].id
scrollToId.value = 'chat-bottom'
@ -48,6 +47,13 @@ export default {
} catch (e) {}
}
async function markRead() {
try {
await post(API.MESSAGE_READ, { card_no: card.cardNo })
card.clearUnread()
} catch (e) {}
}
async function sendMsg() {
const content = inputText.value.trim()
if (!content) return
@ -58,22 +64,26 @@ export default {
} catch (e) {}
}
function goBack() { card.clearUnread(); uni.navigateBack() }
function goBack() { uni.navigateBack() }
onMounted(() => { card.clearUnread(); loadMessages(); startPoll('chat', loadMessages, 5000) })
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
loadMessages(); markRead(); startPoll('chat', loadMessages, 5000)
})
onUnmounted(() => stopPoll('chat'))
return { messages, inputText, scrollToId, sendMsg, goBack }
return { messages, inputText, scrollToId, statusBarHeight, sendMsg, goBack }
}
}
</script>
<style scoped>
.page-chat{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.chat-list{flex:1;padding:16rpx 0}
.chat-list{flex:1;padding:16rpx 0;margin-top:100rpx}
.chat-input-bar{display:flex;align-items:center;padding:16rpx 24rpx;padding-bottom:calc(16rpx + var(--safe-b));background:var(--bg-card);border-top:1px solid var(--border);gap:16rpx}
.chat-input{flex:1;height:76rpx;background:var(--bg);border-radius:16rpx;padding:0 28rpx;font-size:28rpx;color:var(--text)}
.chat-send{width:104rpx;height:72rpx;border-radius:16rpx;background:var(--blue);color:#fff;border:none;font-size:26rpx;font-weight:700}


+ 9
- 4
pages/confirm/confirm.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-confirm">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">确认下单</text>
<text></text>
@ -56,6 +56,7 @@ export default {
const presets = ref([])
const note = ref('')
const submitting = ref(false)
const statusBarHeight = ref(0)
function goBack() { uni.navigateBack() }
@ -76,17 +77,21 @@ export default {
submitting.value = false
}
return { cart, presets, note, submitting, goBack, onSubmit }
return { cart, presets, note, submitting, statusBarHeight, goBack, onSubmit }
},
created() {
const systemInfo = uni.getSystemInfoSync()
this.statusBarHeight = systemInfo.statusBarHeight
}
}
</script>
<style scoped>
.page-confirm{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.confirm-body{flex:1;padding:0 28rpx}
.confirm-body{flex:1;padding:0 28rpx;margin-top:100rpx}
.section{padding:20rpx 0;border-bottom:1px solid var(--border)}
.section-title{font-size:28rpx;font-weight:700;color:var(--gold);display:block;margin-bottom:16rpx}
.confirm-item{display:flex;align-items:center;padding:16rpx 0;gap:16rpx}


+ 8
- 3
pages/index/index.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-index">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<view class="nav-left">
<text class="nav-logo">🍸</text>
<text class="nav-brand">纯瘾大</text>
@ -76,6 +76,7 @@ export default {
const generated = ref(false)
const inputNo = ref('')
const cardNo = ref('')
const statusBarHeight = ref(0)
let navTimer = null
function goMenu() {
@ -121,7 +122,11 @@ export default {
function goMyOrders() { uni.navigateTo({ url: '/pages/orders/orders' }) }
function goStaffLogin() { uni.navigateTo({ url: '/pages/staff/login' }) }
return { showModal, generated, inputNo, cardNo, onGenerate, onCheck, onMaskTap, goMyOrders, goStaffLogin }
return { showModal, generated, inputNo, cardNo, statusBarHeight, onGenerate, onCheck, onMaskTap, goMyOrders, goStaffLogin }
},
created() {
const systemInfo = uni.getSystemInfoSync()
this.statusBarHeight = systemInfo.statusBarHeight
}
}
</script>
@ -129,7 +134,7 @@ export default {
<style scoped>
.page-index{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-left{display:flex;align-items:center;gap:16rpx}
.nav-logo{font-size:44rpx}
.nav-brand{font-size:40rpx;font-weight:900;color:var(--gold);letter-spacing:4rpx}


+ 7
- 4
pages/menu/menu.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-menu">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<view class="nav-left">
<text class="nav-logo">🍸</text>
<text class="nav-brand">纯瘾大</text>
@ -87,6 +87,7 @@ export default {
const showCart = ref(false)
const bellPressed = ref(false)
const bellWaving = ref(false)
const statusBarHeight = ref(0)
async function loadCategories() {
try {
@ -128,24 +129,26 @@ export default {
function goMyOrders() { uni.navigateTo({ url: '/pages/orders/orders' }) }
onMounted(async () => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
await loadCategories()
await loadProducts('all')
})
return { card, cart, categories, activeCate, products, showCart, bellPressed, bellWaving, onCateChange, onAddToCart, onBellPress, onGoConfirm, goMyOrders }
return { card, cart, categories, activeCate, products, showCart, bellPressed, bellWaving, statusBarHeight, onCateChange, onAddToCart, onBellPress, onGoConfirm, goMyOrders }
}
}
</script>
<style scoped>
.page-menu{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-left{display:flex;align-items:center;gap:16rpx}
.nav-logo{font-size:44rpx}
.nav-brand{font-size:40rpx;font-weight:900;color:var(--gold);letter-spacing:4rpx}
.card-badge{background:linear-gradient(135deg,var(--gold-dark),var(--gold));color:#1A1A1A;padding:10rpx 24rpx;border-radius:28rpx;font-weight:800;font-size:26rpx;letter-spacing:6rpx;animation:card-appear-top .5s ease}
.my-btn{font-size:26rpx;color:var(--gold);font-weight:600}
.menu-scroll{flex:1}
.menu-scroll{flex:1;margin-top:100rpx}
.product-grid{padding:16rpx 20rpx}
.empty-state{display:flex;flex-direction:column;align-items:center;padding:120rpx 0}
.empty-icon{font-size:112rpx;opacity:.3}


+ 11
- 6
pages/orders/orders.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-orders">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">我的订单</text>
<text></text>
@ -11,7 +11,7 @@
<template #actions>
<view class="card-actions">
<button v-if="o.status===0" class="action-btn action-remind" @tap="onRemind(o.id)">🔔 催单</button>
<button v-if="o.status!==3" class="action-btn action-chat" @tap="onChat">
<button v-if="o.status!==3 && o.status!==2" class="action-btn action-chat" @tap="onChat">
💬 联系调酒师
<text v-if="card.unread > 0" class="unread-dot">{{ card.unread }}</text>
</button>
@ -41,6 +41,7 @@ export default {
setup() {
const card = useCardStore()
const orders = ref([])
const statusBarHeight = ref(0)
async function loadOrders() {
try {
@ -68,20 +69,24 @@ export default {
function goBack() { uni.navigateBack() }
function goMenu() { uni.navigateBack() }
onMounted(() => { loadOrders(); checkUnread(); startPoll('orders', loadOrders, 15000); startPoll('ordersUnread', checkUnread, 10000) })
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
loadOrders(); checkUnread(); startPoll('orders', loadOrders, 15000); startPoll('ordersUnread', checkUnread, 10000)
})
onUnmounted(() => { stopPoll('orders'); stopPoll('ordersUnread') })
return { card, orders, onRemind, onChat, goBack, goMenu }
return { card, orders, statusBarHeight, onRemind, onChat, goBack, goMenu }
}
}
</script>
<style scoped>
.page-orders{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.orders-body{flex:1;padding:20rpx}
.orders-body{flex:1;padding:20rpx;margin-top:100rpx}
.card-actions{display:flex;gap:16rpx;padding-top:16rpx}
.action-btn{padding:12rpx 28rpx;border-radius:24rpx;font-size:24rpx;font-weight:600;border:none;position:relative}
.action-remind{background:rgba(255,59,59,.15);color:var(--red)}


+ 11
- 6
pages/staff/board.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-staff-board">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<view class="nav-left">
<text class="nav-logo">🍸</text>
<text class="nav-brand">纯瘾大</text>
@ -24,7 +24,7 @@
<template #actions>
<view class="board-actions">
<button class="ba-btn ba-gold" @tap="onDetail(o)">📖 详情</button>
<button v-if="o.status!==3" class="ba-btn ba-blue" @tap="onChat(o)">💬 聊天</button>
<button v-if="o.status!==3 && o.status!==2" class="ba-btn ba-blue" @tap="onChat(o)">💬 聊天</button>
<button v-if="o.status===0" class="ba-btn ba-gold" @tap="onConfirm(o.id)"> 接单</button>
<button v-if="o.status===0" class="ba-btn ba-red" @tap="onCancel(o.id)"> 拒单</button>
<button v-if="o.status===1" class="ba-btn ba-gold" @tap="onDone(o.id)"> 结单</button>
@ -62,6 +62,7 @@ export default {
const recipeVisible = ref(false)
const recipeCardNo = ref('')
const recipeItems = ref([])
const statusBarHeight = ref(0)
async function loadOrders() {
try {
@ -94,22 +95,26 @@ export default {
function onChat(order) { uni.setStorageSync('chatCardNo', order.cardNo); uni.navigateTo({ url: '/pages/staff/chat' }) }
function onLogout() { staff.logout(); uni.redirectTo({ url: '/pages/staff/login' }) }
onMounted(() => { loadOrders(); loadCounts(); startPoll('board', () => { loadOrders(); loadCounts() }, 10000) })
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
loadOrders(); loadCounts(); startPoll('board', () => { loadOrders(); loadCounts() }, 10000)
})
onUnmounted(() => stopPoll('board'))
return { staff, tabs, activeTab, orders, counts, recipeVisible, recipeCardNo, recipeItems, switchTab, onConfirm, onCancel, onDone, onDetail, onRecipe, onChat, onLogout }
return { staff, tabs, activeTab, orders, counts, recipeVisible, recipeCardNo, recipeItems, statusBarHeight, switchTab, onConfirm, onCancel, onDone, onDetail, onRecipe, onChat, onLogout }
}
}
</script>
<style scoped>
.page-staff-board{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-left{display:flex;align-items:center;gap:16rpx}
.nav-logo{font-size:44rpx}
.nav-brand{font-size:32rpx;font-weight:900;color:var(--gold)}
.logout-btn{font-size:26rpx;color:var(--red)}
.staff-info{background:var(--bg-card);padding:16rpx 32rpx;font-size:24rpx;color:var(--text-dim);border-bottom:1px solid var(--border)}
.staff-info{background:var(--bg-card);padding:16rpx 32rpx;font-size:24rpx;color:var(--text-dim);border-bottom:1px solid var(--border);margin-top:100rpx}
.board-tabs{display:flex;border-bottom:1px solid var(--border);background:var(--bg);flex-shrink:0}
.board-tab{flex:1;padding:24rpx;text-align:center;font-size:26rpx;font-weight:600;color:var(--text-dim);border-bottom:4rpx solid transparent}
.board-tab.active{color:var(--gold);border-bottom-color:var(--gold)}


+ 18
- 8
pages/staff/chat.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-staff-chat">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">💬 客人对话</text>
<text></text>
@ -34,14 +34,13 @@ export default {
const messages = ref([])
const inputText = ref('')
const scrollToId = ref('')
const statusBarHeight = ref(0)
let lastId = 0
async function loadMessages() {
try {
const res = await get(API.MESSAGE_LIST, { card_no: cardNo.value, since: lastId })
if (Array.isArray(res) && res.length > 0) {
const newMsgs = res.filter(m => m.senderType === 'customer')
if (newMsgs.length > 0) staff.incrementUnread(newMsgs.length)
messages.value = [...messages.value, ...res]
lastId = res[res.length - 1].id
scrollToId.value = 'chat-bottom'
@ -49,6 +48,13 @@ export default {
} catch (e) {}
}
async function markRead() {
try {
await post(API.MESSAGE_READ, { card_no: cardNo.value, staff_id: staff.staffId })
staff.clearUnread()
} catch (e) {}
}
async function sendMsg() {
const content = inputText.value.trim()
if (!content) return
@ -59,22 +65,26 @@ export default {
} catch (e) {}
}
function goBack() { staff.clearUnread(); uni.navigateBack() }
function goBack() { uni.navigateBack() }
onMounted(() => { staff.clearUnread(); loadMessages(); startPoll('staffChat', loadMessages, 5000) })
onMounted(() => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight
loadMessages(); markRead(); startPoll('staffChat', loadMessages, 5000)
})
onUnmounted(() => stopPoll('staffChat'))
return { cardNo, messages, inputText, scrollToId, sendMsg, goBack }
return { cardNo, messages, inputText, scrollToId, statusBarHeight, sendMsg, goBack }
}
}
</script>
<style scoped>
.page-staff-chat{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.chat-list{flex:1;padding:16rpx 0}
.chat-list{flex:1;padding:16rpx 0;margin-top:100rpx}
.chat-input-bar{display:flex;align-items:center;padding:16rpx 24rpx;padding-bottom:calc(16rpx + var(--safe-b));background:var(--bg-card);border-top:1px solid var(--border);gap:16rpx}
.chat-input{flex:1;height:76rpx;background:var(--bg);border-radius:16rpx;padding:0 28rpx;font-size:28rpx;color:var(--text)}
.chat-send{width:104rpx;height:72rpx;border-radius:16rpx;background:var(--blue);color:#fff;border:none;font-size:26rpx;font-weight:700}


+ 8
- 5
pages/staff/detail.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page-staff-detail">
<view class="nav-bar">
<view class="nav-bar" :style="{ top: statusBarHeight + 'px' }">
<text class="nav-back" @tap="goBack"></text>
<text class="nav-title">订单详情</text>
<text></text>
@ -41,7 +41,7 @@
<view v-if="order" class="detail-actions">
<button v-if="order.status===0" class="da-btn da-confirm" @tap="onConfirm"> 接单</button>
<button v-if="order.status===1" class="da-btn da-done" @tap="onDone"> 结单</button>
<button v-if="order.status!==3" class="da-btn da-chat" @tap="onChat">💬 聊天</button>
<button v-if="order.status!==3 && order.status!==2" class="da-btn da-chat" @tap="onChat">💬 聊天</button>
</view>
</view>
</template>
@ -55,6 +55,7 @@ export default {
setup() {
const order = ref(null)
const orderId = ref(0)
const statusBarHeight = ref(0)
const statusLabel = computed(() => order.value ? ORDER_STATUS[order.value.status]?.label : '')
const statusColor = computed(() => order.value ? ORDER_STATUS[order.value.status]?.color : '')
@ -67,9 +68,11 @@ export default {
function onChat() { uni.setStorageSync('chatCardNo', order.value.cardNo); uni.navigateTo({ url: '/pages/staff/chat' }) }
function goBack() { uni.navigateBack() }
return { order, statusLabel, statusColor, orderId, loadDetail, onConfirm, onDone, onChat, goBack }
return { order, statusLabel, statusColor, statusBarHeight, orderId, loadDetail, onConfirm, onDone, onChat, goBack }
},
onLoad(options) {
const systemInfo = uni.getSystemInfoSync()
this.statusBarHeight = systemInfo.statusBarHeight
this.orderId = parseInt(options.id) || 0
this.loadDetail()
}
@ -78,10 +81,10 @@ export default {
<style scoped>
.page-staff-detail{min-height:100vh;display:flex;flex-direction:column;background:var(--bg);width:100%}
.nav-bar{height:100rpx;position:sticky;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);flex-shrink:0}
.nav-bar{height:100rpx;position:fixed;top:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:space-between;padding:0 28rpx;border-bottom:1px solid var(--border);width:100%}
.nav-back{font-size:36rpx;color:var(--text-dim)}
.nav-title{font-size:32rpx;font-weight:800;color:var(--gold)}
.detail-body{flex:1;padding:28rpx}
.detail-body{flex:1;padding:28rpx;margin-top:100rpx}
.detail-card{background:var(--bg-card);border-radius:var(--radius);padding:32rpx;margin-bottom:24rpx;border:1px solid var(--border)}
.detail-row{display:flex;justify-content:space-between;padding:10rpx 0;font-size:28rpx;color:var(--text)}
.section-title{font-size:28rpx;font-weight:700;color:var(--gold);display:block;margin-bottom:20rpx}


+ 0
- 1
uni.scss View File

@ -28,7 +28,6 @@ page {
font-size: 28rpx;
height: 100vh;
width: 100%;
padding-top: var(--status-bar-height, 0px);
}
// 动画


+ 2
- 1
utils/constants.js View File

@ -1,4 +1,4 @@
// 纯瘾大 · 全局常量
// 纯瘾大 · 全局常量
export const API = {
BASE: 'http://127.0.0.1:8080',
@ -12,6 +12,7 @@ export const API = {
ORDER_REMIND: '/api/order/remind',
MESSAGE_LIST: '/api/message/list',
MESSAGE_SEND: '/api/message/send',
MESSAGE_READ: '/api/message/read',
STAFF_LOGIN: '/api/staff/login',
STAFF_ORDERS: '/api/staff/orders',
STAFF_ORDER: '/api/staff/order',


Loading…
Cancel
Save