feat(用户界面): 添加客服功能并优化格口选择界面
- 新增微信客服功能入口及处理逻辑 - 添加不同尺寸格口的SVG图标资源 - 重构格口类型选择为卡片式布局,增加视觉反馈 - 简化取件流程,取消自动清空格口步骤 - 调整页面按钮布局,优化用户体验
This commit is contained in:
parent
8239ed657f
commit
364cba07b9
|
|
@ -216,32 +216,41 @@ async function handleRetrieveFlow() {
|
|||
password: String(password)
|
||||
})
|
||||
|
||||
// 4. 成功提示并询问是否清空
|
||||
// 4. 成功提示
|
||||
uni.showToast({
|
||||
title: '格口已打开',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 注释掉清空格口部分,打开格口即显示打开成功结束流程
|
||||
/*
|
||||
// 成功提示并询问是否清空
|
||||
await message.alert({
|
||||
title: '格口已打开',
|
||||
msg: '柜子已开,请取物品!如不再使用柜子请点击 “清空” 。',
|
||||
msg: '柜子已开,请取物品!如不再使用柜子请点击 "清空" 。',
|
||||
confirmButtonText: '清空',
|
||||
closeOnClickModal: false
|
||||
})
|
||||
|
||||
// 5. 确认清空弹窗
|
||||
// 确认清空弹窗
|
||||
await message.confirm({
|
||||
title: '确认清空',
|
||||
msg: '清空后密码将不能再次使用,确认清空?',
|
||||
closeOnClickModal: false
|
||||
})
|
||||
|
||||
// 6. 重置格口状态
|
||||
// 重置格口状态
|
||||
await resetByPassword({
|
||||
shopId: props.shopId,
|
||||
password: String(password)
|
||||
})
|
||||
|
||||
// 7. 重置成功提示
|
||||
// 重置成功提示
|
||||
uni.showToast({
|
||||
title: '格口已清空',
|
||||
icon: 'success'
|
||||
})
|
||||
*/
|
||||
} catch (error) {
|
||||
// 错误处理
|
||||
// 用户取消操作(message.prompt/confirm/alert 返回 'cancel' 字符串或包含 cancel 的错误)
|
||||
|
|
@ -265,6 +274,42 @@ async function handleRetrieveFlow() {
|
|||
}
|
||||
}
|
||||
|
||||
// 格口类型图标映射(需验证图标名称可用性)
|
||||
const CELL_TYPE_ICON_MAP = {
|
||||
1: 'box', // 小格
|
||||
2: 'archive', // 中格
|
||||
3: 'package', // 大格
|
||||
4: 'cube' // 超大格
|
||||
} as const
|
||||
|
||||
function getCellImg(type: number): string {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return '/static/svg/small-cell.svg'
|
||||
case 2:
|
||||
return '/static/svg/medium-cell.svg'
|
||||
case 3:
|
||||
return '/static/svg/large-cell.svg'
|
||||
case 4:
|
||||
return '/static/svg/extra-large-cell.svg'
|
||||
default:
|
||||
return '/static/svg/small-cell.svg'
|
||||
}
|
||||
}
|
||||
|
||||
// 处理格口类型选择
|
||||
function handleCellTypeSelect(stat: { type: number; count: number }) {
|
||||
if (stat.count === 0) {
|
||||
uni.showToast({
|
||||
title: '该类型格口暂不可用',
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
})
|
||||
return
|
||||
}
|
||||
selectedCellType.value = stat.type
|
||||
}
|
||||
|
||||
// 生命周期钩子
|
||||
onMounted(() => {
|
||||
if (props.autoLoad !== false) {
|
||||
|
|
@ -310,16 +355,28 @@ onMounted(() => {
|
|||
|
||||
<!-- 格口类型选择区域 -->
|
||||
<view v-else class="cell-type-selection">
|
||||
<wd-radio-group v-model="selectedCellType" shape="button" size="large" inline>
|
||||
<wd-radio
|
||||
v-for="stat in cellTypeStats"
|
||||
:key="stat.type"
|
||||
:value="stat.type"
|
||||
:disabled="stat.count === 0"
|
||||
<view class="cell-type-grid">
|
||||
<view
|
||||
v-for="stat in cellTypeStats"
|
||||
:key="stat.type"
|
||||
class="cell-type-card"
|
||||
:class="{
|
||||
'cell-type-card--selected': selectedCellType === stat.type,
|
||||
'cell-type-card--disabled': stat.count === 0
|
||||
}"
|
||||
@click="handleCellTypeSelect(stat)"
|
||||
>
|
||||
{{ stat.name }} ({{ stat.count }})
|
||||
</wd-radio>
|
||||
</wd-radio-group>
|
||||
<view class="cell-type-icon">
|
||||
<image :src="getCellImg(stat.type)" class="product-image">
|
||||
</image>
|
||||
</view>
|
||||
<text class="cell-type-name">{{ stat.name }}</text>
|
||||
<text class="cell-type-count">剩余{{ stat.count }}个可用</text>
|
||||
<!-- <view v-if="selectedCellType === stat.type" class="cell-type-selected-indicator">
|
||||
<wd-icon name="check" size="16px" color="#fff" />
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
|
|
@ -384,8 +441,83 @@ onMounted(() => {
|
|||
.cell-type-selection {
|
||||
margin-bottom: 48rpx;
|
||||
|
||||
.wd-radio {
|
||||
margin-bottom: 16rpx;
|
||||
.cell-type-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16rpx;
|
||||
|
||||
.cell-type-card {
|
||||
position: relative;
|
||||
padding: 32rpx 24rpx;
|
||||
background: #fff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active:not(.cell-type-card--disabled) {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
&--selected {
|
||||
border-color: #2979ff;
|
||||
background: rgba(41, 121, 255, 0.04);
|
||||
box-shadow: 0 4rpx 16rpx rgba(41, 121, 255, 0.15);
|
||||
|
||||
.cell-type-name {
|
||||
color: #2979ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cell-type-count {
|
||||
color: #2979ff;
|
||||
}
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background: #f9f9f9;
|
||||
border-color: #f0f0f0;
|
||||
opacity: 0.6;
|
||||
|
||||
.cell-type-name,
|
||||
.cell-type-count {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-type-icon {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.cell-type-name {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.cell-type-count {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cell-type-selected-indicator {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: #2979ff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2rpx 8rpx rgba(41, 121, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -424,5 +556,11 @@ onMounted(() => {
|
|||
/* 保留空白,自动换行 */
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -9,7 +9,7 @@ import { generateDynamicCode, getWxUserByOpenid } from '@/api/users'
|
|||
import { DynamicCodeResponse } from '@/api/users/types'
|
||||
import { bindWxMpUserByOpenid } from '@/api/ab98'
|
||||
import { BindWxMpUserByOpenidCommand } from '@/api/ab98/types'
|
||||
import { useToast } from 'wot-design-uni'
|
||||
import { useToast, useMessage } from 'wot-design-uni'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
|
|
@ -43,6 +43,7 @@ const showProfileSetupButton = computed(() => {
|
|||
const dynamicCodeActionSheet = ref<boolean>(false)
|
||||
const dynamicCodeData = ref<DynamicCodeResponse | null>(null)
|
||||
const toast = useToast()
|
||||
const message = useMessage()
|
||||
|
||||
// 汇邦云登录相关
|
||||
const hbLoginPopupVisible = ref<boolean>(false)
|
||||
|
|
@ -111,6 +112,32 @@ const navigateToPage = (pagePath: string, options: { type?: 'navigateTo' | 'swit
|
|||
}
|
||||
}
|
||||
|
||||
const openWxService = async () => {
|
||||
try {
|
||||
// 确认是否转到客服
|
||||
await message.confirm({
|
||||
title: '客服咨询',
|
||||
msg: '确认离开小程序,前往客服中心?',
|
||||
closeOnClickModal: false
|
||||
})
|
||||
|
||||
wx.openCustomerServiceChat({
|
||||
extInfo: {
|
||||
url: 'https://work.weixin.qq.com/kfid/kfce354fbeb3c58be22',
|
||||
},
|
||||
corpId: 'ww25c80308cbccc46a',
|
||||
});
|
||||
} catch (error) {
|
||||
// 用户取消操作
|
||||
if (error === 'cancel' || (error as any)?.message?.includes?.('cancel')) {
|
||||
return
|
||||
}
|
||||
|
||||
console.error('打开客服失败:', error)
|
||||
toast.show('打开客服失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
wxStore.refreshBalance();
|
||||
});
|
||||
|
|
@ -246,32 +273,35 @@ const handleHbLoginSubmit = async () => {
|
|||
<wd-icon name="star" size="20px" color="#fff"></wd-icon>
|
||||
<text>我的柜子</text>
|
||||
</view>
|
||||
<view class="button-item" @click="openWxService()">
|
||||
<wd-icon name="user-talk" size="20px" color="#fff"></wd-icon>
|
||||
<text>系统客服</text>
|
||||
</view>
|
||||
<view v-if="!wxUserDTO?.ab98UserId" class="button-item" @click="handleGenerateDynamicCode">
|
||||
<wd-icon name="qrcode" size="20px" color="#fff"></wd-icon>
|
||||
<text>动态码</text>
|
||||
</view>
|
||||
<view v-else class="button-placeholder"></view>
|
||||
<view v-if="!wxUserDTO?.ab98UserId" class="button-item" @click="hbLoginPopupVisible = true">
|
||||
<wd-icon name="login" size="20px" color="#fff"></wd-icon>
|
||||
<text>绑定汇邦云</text>
|
||||
</view>
|
||||
<view v-else class="button-placeholder"></view>
|
||||
<!-- <view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/cabinet/index')">
|
||||
<wd-icon name="tools" size="20px" color="#fff"></wd-icon>
|
||||
<text>柜机管理</text>
|
||||
</view> -->
|
||||
</view>
|
||||
<!-- <view class="button-row">
|
||||
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approval/list/index')">
|
||||
<view class="button-row">
|
||||
<view v-if="!wxUserDTO?.ab98UserId" class="button-item" @click="hbLoginPopupVisible = true">
|
||||
<wd-icon name="login" size="20px" color="#fff"></wd-icon>
|
||||
<text>绑定汇邦云</text>
|
||||
</view>
|
||||
<!-- <view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approval/list/index')">
|
||||
<wd-icon name="secured" size="20px" color="#fff"></wd-icon>
|
||||
<text>审批中心</text>
|
||||
</view>
|
||||
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approvalAsset/list/index')">
|
||||
<wd-icon name="edit-1" size="20px" color="#fff"></wd-icon>
|
||||
<text>耗材核销</text>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="button-placeholder"></view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 动态码弹窗 -->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<path fill="currentColor"
|
||||
d="M200 24H56a12 12 0 0 0-12 12v184a12 12 0 0 0 12 12h144a12 12 0 0 0 12-12V36a12 12 0 0 0-12-12m4 196a4 4 0 0 1-4 4H56a4 4 0 0 1-4-4V36a4 4 0 0 1 4-4h144a4 4 0 0 1 4 4v184Zm-64-92a4 4 0 0 1-4 4h-16a4 4 0 0 1 0-8h16a4 4 0 0 1 4 4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<path fill="currentColor"
|
||||
d="M200 48H56a12 12 0 0 0-12 12v136a12 12 0 0 0 12 12h144a12 12 0 0 0 12-12V60a12 12 0 0 0-12-12m4 148a4 4 0 0 1-4 4H56a4 4 0 0 1-4-4V60a4 4 0 0 1 4-4h144a4 4 0 0 1 4 4v136Zm-64-68a4 4 0 0 1-4 4h-16a4 4 0 0 1 0-8h16a4 4 0 0 1 4 4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<path fill="currentColor"
|
||||
d="M200 72H56a12 12 0 0 0-12 12v88a12 12 0 0 0 12 12h144a12 12 0 0 0 12-12V84a12 12 0 0 0-12-12m4 100a4 4 0 0 1-4 4H56a4 4 0 0 1-4-4V84a4 4 0 0 1 4-4h144a4 4 0 0 1 4 4v88Zm-64-44a4 4 0 0 1-4 4h-16a4 4 0 0 1 0-8h16a4 4 0 0 1 4 4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 365 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<path fill="currentColor"
|
||||
d="M200 96H56a12 12 0 0 0-12 12v40a12 12 0 0 0 12 12h144a12 12 0 0 0 12-12v-40a12 12 0 0 0-12-12m4 52a4 4 0 0 1-4 4H56a4 4 0 0 1-4-4v-40a4 4 0 0 1 4-4h144a4 4 0 0 1 4 4v40Zm-64-20a4 4 0 0 1-4 4h-16a4 4 0 0 1 0-8h16a4 4 0 0 1 4 4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 366 B |
Loading…
Reference in New Issue