feat(user): 新增收货地址管理及售后申请页面
- 新增地址类型定义,增强前端地址数据结构 - 新增地址编辑页面,支持地址智能识别和定位选点功能 - 地址编辑支持省市区选择及默认地址设置 - 新增地址列表页面,支持地址展示、删除、编辑和选择功能 - 实现售后申请页面,支持选择售后类型和退款原因 - 售后申请支持商品选择、退款金额计算和凭证上传 - 新增售后详情页面,支持售后状态展示及申请取消 - 优化页面加载和用户交互体验,增加错误提示和权限处理
This commit is contained in:
177
src_bak/passport/unified-qr/index.tsx
Normal file
177
src_bak/passport/unified-qr/index.tsx
Normal file
@@ -0,0 +1,177 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { Card, Button, Tag } from '@nutui/nutui-react-taro'
|
||||
import { Scan, Success, Failure, ArrowLeft } from '@nutui/icons-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { confirmWechatQRLogin, parseQRContent } from '@/api/passport/qr-login'
|
||||
|
||||
enum ScanType {
|
||||
LOGIN = 'login',
|
||||
UNKNOWN = 'unknown',
|
||||
}
|
||||
|
||||
interface ScanRecord {
|
||||
id: number
|
||||
time: string
|
||||
success: boolean
|
||||
type: ScanType
|
||||
message: string
|
||||
raw?: string
|
||||
}
|
||||
|
||||
const UnifiedQRPage: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [lastRecord, setLastRecord] = useState<ScanRecord | null>(null)
|
||||
const [scanHistory, setScanHistory] = useState<ScanRecord[]>([])
|
||||
|
||||
const pushHistory = (record: ScanRecord) => {
|
||||
setLastRecord(record)
|
||||
setScanHistory((prev) => [record, ...prev.slice(0, 4)])
|
||||
}
|
||||
|
||||
const handleGoBack = () => {
|
||||
Taro.navigateBack()
|
||||
}
|
||||
|
||||
const buildRecord = (success: boolean, type: ScanType, message: string, raw?: string): ScanRecord => ({
|
||||
id: Date.now(),
|
||||
time: new Date().toLocaleString(),
|
||||
success,
|
||||
type,
|
||||
message,
|
||||
raw,
|
||||
})
|
||||
|
||||
const handleLoginScan = async (raw: string) => {
|
||||
const token = parseQRContent(raw)
|
||||
const userId = Number(Taro.getStorageSync('UserId') || 0)
|
||||
|
||||
if (!token) {
|
||||
throw new Error('未识别到可登录的二维码内容')
|
||||
}
|
||||
if (!userId) {
|
||||
throw new Error('请先登录小程序账号后再扫码')
|
||||
}
|
||||
|
||||
const result = await confirmWechatQRLogin(token, userId)
|
||||
if (result?.status !== 'confirmed') {
|
||||
throw new Error(result?.message || '二维码登录确认失败')
|
||||
}
|
||||
|
||||
return '登录确认成功'
|
||||
}
|
||||
|
||||
const handleStartScan = async () => {
|
||||
if (loading) return
|
||||
|
||||
try {
|
||||
setLoading(true)
|
||||
const res = await Taro.scanCode({ scanType: ['qrCode'] })
|
||||
const raw = (res.result || '').trim()
|
||||
|
||||
if (!raw) {
|
||||
throw new Error('扫码结果为空')
|
||||
}
|
||||
|
||||
const token = parseQRContent(raw)
|
||||
if (token) {
|
||||
const message = await handleLoginScan(raw)
|
||||
pushHistory(buildRecord(true, ScanType.LOGIN, message, raw))
|
||||
Taro.showToast({ title: message, icon: 'success' })
|
||||
return
|
||||
}
|
||||
|
||||
const unsupportedMessage = '当前版本仅支持登录二维码,核销能力待补充'
|
||||
pushHistory(buildRecord(false, ScanType.UNKNOWN, unsupportedMessage, raw))
|
||||
Taro.showToast({ title: unsupportedMessage, icon: 'none' })
|
||||
} catch (error: any) {
|
||||
const message =
|
||||
error?.errMsg?.includes('cancel')
|
||||
? '已取消扫码'
|
||||
: error?.message || '扫码失败'
|
||||
|
||||
pushHistory(buildRecord(false, ScanType.UNKNOWN, message))
|
||||
if (message !== '已取消扫码') {
|
||||
Taro.showToast({ title: message, icon: 'none' })
|
||||
}
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const getTypeTag = (type: ScanType) => {
|
||||
if (type === ScanType.LOGIN) {
|
||||
return <Tag type='success'>登录</Tag>
|
||||
}
|
||||
return <Tag type='primary'>其他</Tag>
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='unified-qr-page min-h-screen bg-gray-50'>
|
||||
<View className='bg-white px-4 py-3 border-b border-gray-100 flex items-center'>
|
||||
<ArrowLeft className='text-gray-600 mr-3' size='20' onClick={handleGoBack} />
|
||||
<View className='flex-1'>
|
||||
<Text className='text-lg font-bold'>统一扫码</Text>
|
||||
<Text className='text-sm text-gray-600 block'>先恢复登录扫码,后续再补齐核销流程</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Card className='m-4'>
|
||||
<View className='text-center py-6'>
|
||||
<Scan className='text-blue-500 mx-auto mb-4' size='48' />
|
||||
<Text className='text-lg font-medium text-gray-800 mb-2 block'>扫码入口</Text>
|
||||
<Text className='text-gray-600 mb-6 block'>当前可识别网页登录二维码,其他码先给出明确提示</Text>
|
||||
<Button
|
||||
type='primary'
|
||||
size='large'
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
onClick={handleStartScan}
|
||||
className='w-full'
|
||||
>
|
||||
{loading ? '扫码中...' : '开始扫码'}
|
||||
</Button>
|
||||
</View>
|
||||
</Card>
|
||||
|
||||
{lastRecord && (
|
||||
<Card className='mx-4 mb-4'>
|
||||
<View className='flex items-start'>
|
||||
<View className='mr-3 mt-1'>
|
||||
{lastRecord.success ? (
|
||||
<Success className='text-green-500' size='18' />
|
||||
) : (
|
||||
<Failure className='text-red-500' size='18' />
|
||||
)}
|
||||
</View>
|
||||
<View className='flex-1'>
|
||||
<View className='flex items-center justify-between mb-2'>
|
||||
<Text className='font-medium'>最近一次结果</Text>
|
||||
{getTypeTag(lastRecord.type)}
|
||||
</View>
|
||||
<Text className='text-sm text-gray-800 block mb-1'>{lastRecord.message}</Text>
|
||||
<Text className='text-xs text-gray-500 block'>{lastRecord.time}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{scanHistory.length > 0 && (
|
||||
<Card className='mx-4 mb-4'>
|
||||
<Text className='font-medium block mb-3'>扫码记录</Text>
|
||||
{scanHistory.map((item) => (
|
||||
<View key={item.id} className='py-2 border-b border-gray-100' style={item === scanHistory[scanHistory.length - 1] ? { borderBottom: 'none' } : undefined}>
|
||||
<View className='flex items-center justify-between mb-1'>
|
||||
<Text className='text-sm text-gray-800'>{item.message}</Text>
|
||||
{getTypeTag(item.type)}
|
||||
</View>
|
||||
<Text className='text-xs text-gray-500 block'>{item.time}</Text>
|
||||
</View>
|
||||
))}
|
||||
</Card>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default UnifiedQRPage
|
||||
Reference in New Issue
Block a user