fix(dealer/customer): 修复客户添加表单手机号字段绑定错误- 修正了客户添加表单中手机号字段的绑定逻辑,确保使用表单值而非用户信息中的电话号码
- 在客户添加表单中新增了报备人(userId)字段的选择项 - 移除了二维码登录相关API和类型定义文件 - 移除了统一扫码处理组件及相关的Hook实现 - 优化了首页Header组件的登录状态显示逻辑- 移除了用户卡片组件中的冗余扫码功能 - 更新了门店核销页面的配置和实现,移除了扫码相关功能- 移除了多个文档文件,包括配置说明、登录状态更新测试指南、运行时错误解决方案和TypeScript修复说明
This commit is contained in:
@@ -1,197 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
import type { ApiResult } from '@/api';
|
||||
import type {
|
||||
QrLoginGenerateResponse,
|
||||
QrLoginStatusResponse,
|
||||
QrLoginConfirmRequest,
|
||||
ScanResultParsed,
|
||||
ScanResultType
|
||||
} from './model';
|
||||
|
||||
/**
|
||||
* 生成扫码登录token
|
||||
*/
|
||||
export async function generateQrLoginToken() {
|
||||
const res = await request.post<ApiResult<QrLoginGenerateResponse>>(
|
||||
'/api/qr-login/generate'
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查扫码登录状态
|
||||
*/
|
||||
export async function checkQrLoginStatus(token: string) {
|
||||
const res = await request.get<ApiResult<QrLoginStatusResponse>>(
|
||||
`/api/qr-login/status/${token}`
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认扫码登录
|
||||
*/
|
||||
export async function confirmQrLogin(data: QrLoginConfirmRequest) {
|
||||
const res = await request.post<ApiResult<QrLoginStatusResponse>>(
|
||||
'/api/qr-login/confirm',
|
||||
data
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序扫码登录确认
|
||||
*/
|
||||
export async function wechatMiniProgramConfirm(data: QrLoginConfirmRequest) {
|
||||
const res = await request.post<ApiResult<QrLoginStatusResponse>>(
|
||||
'/api/qr-login/wechat-confirm',
|
||||
data
|
||||
);
|
||||
if (res.code === 0 && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码操作(更新状态为已扫码)
|
||||
*/
|
||||
export async function scanQrCode(token: string) {
|
||||
const res = await request.post<ApiResult<boolean>>(
|
||||
`/api/qr-login/scan/${token}`
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.data;
|
||||
}
|
||||
return Promise.reject(new Error(res.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否为有效的JSON
|
||||
*/
|
||||
export function isValidJSON(str: string): boolean {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析扫码结果,识别二维码类型
|
||||
*/
|
||||
export function parseScanResult(scanResult: string): ScanResultParsed {
|
||||
const rawContent = scanResult.trim();
|
||||
|
||||
try {
|
||||
// 1. 尝试解析JSON格式(礼品卡核销)
|
||||
if (isValidJSON(rawContent)) {
|
||||
const json = JSON.parse(rawContent);
|
||||
if (json.businessType === 'gift') {
|
||||
return {
|
||||
type: 'gift-verification',
|
||||
rawContent,
|
||||
data: json,
|
||||
requireAuth: true,
|
||||
requireAdmin: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 检查是否为二维码登录token格式
|
||||
// 假设二维码登录的格式为: qr-login:token 或者纯token(32位以上字符串)
|
||||
if (rawContent.startsWith('qr-login:')) {
|
||||
const token = rawContent.replace('qr-login:', '');
|
||||
return {
|
||||
type: 'qr-login',
|
||||
rawContent,
|
||||
data: { token },
|
||||
requireAuth: true
|
||||
};
|
||||
}
|
||||
|
||||
// 检查是否为纯token格式(32位以上的字母数字组合)
|
||||
if (/^[a-zA-Z0-9-]{32,}$/.test(rawContent)) {
|
||||
return {
|
||||
type: 'qr-login',
|
||||
rawContent,
|
||||
data: { token: rawContent },
|
||||
requireAuth: true
|
||||
};
|
||||
}
|
||||
|
||||
// 3. 检查是否为礼品卡兑换码(6位字母数字组合)
|
||||
if (/^[A-Z0-9]{6}$/.test(rawContent)) {
|
||||
return {
|
||||
type: 'gift-redeem',
|
||||
rawContent,
|
||||
data: { code: rawContent },
|
||||
requireAuth: false
|
||||
};
|
||||
}
|
||||
|
||||
// 4. 检查是否为车辆查询码
|
||||
if (rawContent.startsWith('vehicle-') || rawContent.startsWith('car-')) {
|
||||
return {
|
||||
type: 'vehicle-query' as ScanResultType,
|
||||
rawContent,
|
||||
data: { vehicleId: rawContent },
|
||||
requireAuth: false
|
||||
};
|
||||
}
|
||||
|
||||
// 5. 检查URL格式的二维码
|
||||
if (rawContent.startsWith('http://') || rawContent.startsWith('https://')) {
|
||||
const url = new URL(rawContent);
|
||||
|
||||
// 检查是否包含二维码登录相关参数
|
||||
if (url.searchParams.has('qr-login-token') || url.pathname.includes('/qr-login/')) {
|
||||
const token = url.searchParams.get('qr-login-token') || url.pathname.split('/').pop();
|
||||
return {
|
||||
type: 'qr-login',
|
||||
rawContent,
|
||||
data: { token },
|
||||
requireAuth: true
|
||||
};
|
||||
}
|
||||
|
||||
// 检查是否为礼品卡相关URL
|
||||
if (url.pathname.includes('/gift/') || url.searchParams.has('gift-code')) {
|
||||
const code = url.searchParams.get('gift-code') || url.pathname.split('/').pop();
|
||||
return {
|
||||
type: 'gift-redeem',
|
||||
rawContent,
|
||||
data: { code },
|
||||
requireAuth: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 默认返回未知类型
|
||||
return {
|
||||
type: 'unknown',
|
||||
rawContent,
|
||||
data: { content: rawContent },
|
||||
requireAuth: false
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('解析扫码结果失败:', error);
|
||||
return {
|
||||
type: 'unknown',
|
||||
rawContent,
|
||||
data: { content: rawContent, error: error.message },
|
||||
requireAuth: false
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* 二维码登录相关类型定义
|
||||
*/
|
||||
|
||||
/**
|
||||
* 二维码登录生成响应
|
||||
*/
|
||||
export interface QrLoginGenerateResponse {
|
||||
/** 扫码登录token */
|
||||
token: string;
|
||||
/** 二维码内容 */
|
||||
qrCode: string;
|
||||
/** 过期时间(秒) */
|
||||
expiresIn: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二维码登录状态响应
|
||||
*/
|
||||
export interface QrLoginStatusResponse {
|
||||
/** 登录状态: pending-等待扫码, scanned-已扫码, confirmed-已确认, expired-已过期, cancelled-已取消 */
|
||||
status: 'pending' | 'scanned' | 'confirmed' | 'expired' | 'cancelled';
|
||||
/** 状态描述 */
|
||||
message?: string;
|
||||
/** 登录成功时返回的用户信息 */
|
||||
user?: any;
|
||||
/** 登录成功时返回的访问令牌 */
|
||||
accessToken?: string;
|
||||
/** 剩余过期时间(秒) */
|
||||
remainingTime?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二维码登录确认请求
|
||||
*/
|
||||
export interface QrLoginConfirmRequest {
|
||||
/** 扫码登录token */
|
||||
token: string;
|
||||
/** 用户ID */
|
||||
userId?: number;
|
||||
/** 登录平台: web-网页端, app-移动应用, miniprogram-微信小程序 */
|
||||
platform?: string;
|
||||
/** 微信小程序相关信息 */
|
||||
wechatInfo?: WechatMiniProgramInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序信息
|
||||
*/
|
||||
export interface WechatMiniProgramInfo {
|
||||
/** 微信openid */
|
||||
openid?: string;
|
||||
/** 微信unionid */
|
||||
unionid?: string;
|
||||
/** 微信昵称 */
|
||||
nickname?: string;
|
||||
/** 微信头像 */
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码结果类型
|
||||
*/
|
||||
export type ScanResultType =
|
||||
| 'qr-login' // 二维码登录
|
||||
| 'gift-verification' // 礼品卡核销
|
||||
| 'gift-redeem' // 礼品卡兑换
|
||||
| 'vehicle-query' // 车辆查询
|
||||
| 'unknown'; // 未知类型
|
||||
|
||||
/**
|
||||
* 扫码结果解析
|
||||
*/
|
||||
export interface ScanResultParsed {
|
||||
/** 扫码结果类型 */
|
||||
type: ScanResultType;
|
||||
/** 原始扫码内容 */
|
||||
rawContent: string;
|
||||
/** 解析后的数据 */
|
||||
data: any;
|
||||
/** 是否需要权限验证 */
|
||||
requireAuth?: boolean;
|
||||
/** 是否需要管理员权限 */
|
||||
requireAdmin?: boolean;
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@nutui/nutui-react-taro';
|
||||
import { View } from '@tarojs/components';
|
||||
import { Scan } from '@nutui/icons-react-taro';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useUnifiedQRScan, ScanType, type UnifiedScanResult } from '@/hooks/useUnifiedQRScan';
|
||||
@@ -29,15 +27,11 @@ export interface UnifiedQRButtonProps {
|
||||
* 支持登录和核销两种类型的二维码扫描
|
||||
*/
|
||||
const UnifiedQRButton: React.FC<UnifiedQRButtonProps> = ({
|
||||
type = 'success',
|
||||
size = 'small',
|
||||
text = '',
|
||||
showIcon = true,
|
||||
onSuccess,
|
||||
onError,
|
||||
usePageMode = false
|
||||
}) => {
|
||||
const { startScan, isLoading, canScan, state, result } = useUnifiedQRScan();
|
||||
const { startScan, canScan, result } = useUnifiedQRScan();
|
||||
console.log(result,'useUnifiedQRScan>>result')
|
||||
// 处理点击事件
|
||||
const handleClick = async () => {
|
||||
@@ -83,43 +77,8 @@ const UnifiedQRButton: React.FC<UnifiedQRButtonProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const disabled = !canScan() || isLoading;
|
||||
|
||||
// 根据当前状态动态显示文本
|
||||
const getButtonText = () => {
|
||||
if (isLoading) {
|
||||
switch (state) {
|
||||
case 'scanning':
|
||||
return '扫码中...';
|
||||
case 'processing':
|
||||
return '处理中...';
|
||||
default:
|
||||
return '扫码中...';
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled && !canScan()) {
|
||||
return '请先登录';
|
||||
}
|
||||
|
||||
return text;
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
type={type}
|
||||
size={size}
|
||||
loading={isLoading}
|
||||
disabled={disabled}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<View className="flex items-center justify-center text-white">
|
||||
{showIcon && !isLoading && (
|
||||
<Scan />
|
||||
)}
|
||||
{getButtonText()}
|
||||
</View>
|
||||
</Button>
|
||||
<Scan className={'text-white'} onClick={handleClick} />
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
import React from 'react';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { parseScanResult, wechatMiniProgramConfirm, scanQrCode } from '@/api/qrLogin';
|
||||
import type { ScanResultParsed } from '@/api/qrLogin/model';
|
||||
import navTo from '@/utils/common';
|
||||
import { useUser } from '@/hooks/useUser';
|
||||
|
||||
/**
|
||||
* 统一扫码处理组件
|
||||
*/
|
||||
export interface UniversalScannerProps {
|
||||
/** 扫码成功回调 */
|
||||
onScanSuccess?: (result: ScanResultParsed) => void;
|
||||
/** 扫码失败回调 */
|
||||
onScanError?: (error: string) => void;
|
||||
/** 是否显示处理结果提示 */
|
||||
showToast?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一扫码处理Hook
|
||||
*/
|
||||
export function useUniversalScanner(props: UniversalScannerProps = {}) {
|
||||
const {
|
||||
onScanSuccess,
|
||||
onScanError,
|
||||
showToast = true
|
||||
} = props;
|
||||
|
||||
const { user, isLoggedIn, isAdmin } = useUser();
|
||||
|
||||
/**
|
||||
* 启动扫码
|
||||
*/
|
||||
const startScan = () => {
|
||||
Taro.scanCode({
|
||||
onlyFromCamera: true,
|
||||
scanType: ['qrCode', 'barCode'],
|
||||
success: (res) => {
|
||||
handleScanResult(res.result);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('扫码失败:', err);
|
||||
const errorMsg = '扫码失败,请重试';
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
onScanError?.(errorMsg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理扫码结果
|
||||
*/
|
||||
const handleScanResult = async (scanResult: string) => {
|
||||
try {
|
||||
console.log('扫码结果:', scanResult);
|
||||
|
||||
// 解析扫码结果
|
||||
const parsed = parseScanResult(scanResult);
|
||||
console.log('解析结果:', parsed);
|
||||
|
||||
// 权限检查
|
||||
if (parsed.requireAuth && !isLoggedIn) {
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: '请先登录',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
onScanError?.('请先登录');
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed.requireAdmin && !isAdmin()) {
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: '仅管理员可使用此功能',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
onScanError?.('权限不足');
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据类型处理
|
||||
await handleByType(parsed);
|
||||
|
||||
// 回调
|
||||
onScanSuccess?.(parsed);
|
||||
|
||||
} catch (error) {
|
||||
console.error('处理扫码结果失败:', error);
|
||||
const errorMsg = error instanceof Error ? error.message : '处理扫码结果失败';
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
onScanError?.(errorMsg);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据类型处理扫码结果
|
||||
*/
|
||||
const handleByType = async (parsed: ScanResultParsed) => {
|
||||
switch (parsed.type) {
|
||||
case 'qr-login':
|
||||
await handleQrLogin(parsed);
|
||||
break;
|
||||
|
||||
case 'gift-verification':
|
||||
handleGiftVerification(parsed);
|
||||
break;
|
||||
|
||||
case 'gift-redeem':
|
||||
handleGiftRedeem(parsed);
|
||||
break;
|
||||
|
||||
case 'vehicle-query':
|
||||
handleVehicleQuery(parsed);
|
||||
break;
|
||||
|
||||
case 'unknown':
|
||||
handleUnknownType(parsed);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`未支持的扫码类型: ${parsed.type}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理二维码登录
|
||||
*/
|
||||
const handleQrLogin = async (parsed: ScanResultParsed) => {
|
||||
const { token } = parsed.data;
|
||||
|
||||
try {
|
||||
if (showToast) {
|
||||
Taro.showLoading({ title: '正在处理登录...' });
|
||||
}
|
||||
|
||||
// 1. 先调用扫码接口,更新状态为已扫码
|
||||
await scanQrCode(token);
|
||||
|
||||
// 2. 确认登录
|
||||
const confirmData = {
|
||||
token,
|
||||
userId: user?.userId,
|
||||
platform: 'miniprogram',
|
||||
wechatInfo: {
|
||||
openid: user?.openid,
|
||||
nickname: user?.nickname || user?.realName,
|
||||
avatar: user?.avatar
|
||||
}
|
||||
};
|
||||
|
||||
const result = await wechatMiniProgramConfirm(confirmData);
|
||||
|
||||
if (result.status === 'confirmed') {
|
||||
if (showToast) {
|
||||
Taro.hideLoading();
|
||||
Taro.showToast({
|
||||
title: '后台管理登录确认成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
|
||||
// 显示成功提示弹窗
|
||||
Taro.showModal({
|
||||
title: '登录成功',
|
||||
content: '您已成功确认后台管理系统登录,请在电脑端查看登录状态。',
|
||||
showCancel: false,
|
||||
confirmText: '知道了'
|
||||
});
|
||||
|
||||
} else {
|
||||
throw new Error(result.message || '登录确认失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (showToast) {
|
||||
Taro.hideLoading();
|
||||
}
|
||||
|
||||
// 根据错误类型显示不同的提示
|
||||
let errorMessage = '登录确认失败';
|
||||
const errorMsg = error instanceof Error ? error.message : '';
|
||||
if (errorMsg?.includes('过期')) {
|
||||
errorMessage = '二维码已过期,请重新生成';
|
||||
} else if (errorMsg?.includes('无效')) {
|
||||
errorMessage = '无效的登录二维码';
|
||||
} else if (errorMsg) {
|
||||
errorMessage = errorMsg;
|
||||
}
|
||||
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: errorMessage,
|
||||
icon: 'error',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理礼品卡核销
|
||||
*/
|
||||
const handleGiftVerification = (parsed: ScanResultParsed) => {
|
||||
// 跳转到核销页面,并传递扫码数据
|
||||
const encryptedData = encodeURIComponent(JSON.stringify(parsed.data));
|
||||
navTo(`/user/store/verification?scanData=${encryptedData}`, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理礼品卡兑换
|
||||
*/
|
||||
const handleGiftRedeem = (parsed: ScanResultParsed) => {
|
||||
const { code } = parsed.data;
|
||||
navTo(`/user/gift/redeem?code=${encodeURIComponent(code)}`, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理车辆查询
|
||||
*/
|
||||
const handleVehicleQuery = (parsed: ScanResultParsed) => {
|
||||
const { vehicleId } = parsed.data;
|
||||
navTo(`/hjm/query?id=${vehicleId}`, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理未知类型
|
||||
*/
|
||||
const handleUnknownType = (parsed: ScanResultParsed) => {
|
||||
// 显示选择弹窗,让用户选择如何处理
|
||||
Taro.showActionSheet({
|
||||
itemList: [
|
||||
'复制内容',
|
||||
'作为礼品卡兑换码',
|
||||
'作为车辆查询码',
|
||||
'取消'
|
||||
],
|
||||
success: (res) => {
|
||||
const { tapIndex } = res;
|
||||
switch (tapIndex) {
|
||||
case 0:
|
||||
// 复制内容
|
||||
Taro.setClipboardData({
|
||||
data: parsed.rawContent,
|
||||
success: () => {
|
||||
if (showToast) {
|
||||
Taro.showToast({
|
||||
title: '已复制到剪贴板',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// 作为礼品卡兑换码
|
||||
navTo(`/user/gift/redeem?code=${encodeURIComponent(parsed.rawContent)}`, true);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// 作为车辆查询码
|
||||
navTo(`/hjm/query?id=${parsed.rawContent}`, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
startScan,
|
||||
handleScanResult
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一扫码处理组件(如果需要作为组件使用)
|
||||
*/
|
||||
const UniversalScanner: React.FC<UniversalScannerProps> = (props) => {
|
||||
const { startScan } = useUniversalScanner(props);
|
||||
console.log(startScan,'startScan333')
|
||||
// 这个组件主要提供Hook,不渲染UI
|
||||
// 如果需要可以返回一个扫码按钮
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default UniversalScanner;
|
||||
@@ -204,7 +204,7 @@ const AddShopDealerApply = () => {
|
||||
...values,
|
||||
type: 4,
|
||||
realName: values.realName || user?.nickname,
|
||||
mobile: user?.phone,
|
||||
mobile: values.mobile,
|
||||
refereeId: 33534,
|
||||
applyStatus: isEditMode ? 20 : 10,
|
||||
auditTime: undefined,
|
||||
@@ -338,6 +338,9 @@ const AddShopDealerApply = () => {
|
||||
{/*</Form.Item>*/}
|
||||
</>
|
||||
)}
|
||||
<Form.Item name="userId" label="报备人" initialValue={FormData?.userId} required>
|
||||
选择
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
|
||||
|
||||
@@ -222,32 +222,7 @@ const Header = (props: any) => {
|
||||
onBackClick={() => {
|
||||
}}
|
||||
left={
|
||||
isLoggedIn ? (
|
||||
<View style={{display: 'flex', alignItems: 'center', gap: '8px'}}
|
||||
onClick={() => navTo(`/user/profile/profile`, true)}>
|
||||
<Avatar
|
||||
size="22"
|
||||
src={getWebsiteLogo()}
|
||||
/>
|
||||
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
||||
<TriangleDown className={'text-white'} size={9}/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={{display: 'flex', alignItems: 'center'}}>
|
||||
<Space>
|
||||
<Avatar
|
||||
size="22"
|
||||
src={getWebsiteLogo()}
|
||||
/>
|
||||
<Text style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
||||
<TriangleDown size={9} className={'text-white'}/>
|
||||
</Space>
|
||||
</View>
|
||||
)}
|
||||
right={
|
||||
<Space style={{
|
||||
marginRight: '100px'
|
||||
}}>
|
||||
<Space>
|
||||
{/*统一扫码入口 - 支持登录和核销*/}
|
||||
<UnifiedQRButton
|
||||
size="small"
|
||||
@@ -269,6 +244,20 @@ const Header = (props: any) => {
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
{isLoggedIn ? (
|
||||
<Space onClick={() => navTo(`/user/profile/profile`, true)}>
|
||||
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
||||
</Space>
|
||||
) : (
|
||||
<View style={{display: 'flex', alignItems: 'center'}}>
|
||||
<Avatar
|
||||
size="22"
|
||||
src={getWebsiteLogo()}
|
||||
/>
|
||||
<Text className={'text-xs'} style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
||||
<TriangleDown size={9} className={'text-white'}/>
|
||||
</View>
|
||||
)}
|
||||
</NavBar>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ import navTo from "@/utils/common";
|
||||
import {TenantId} from "@/config/app";
|
||||
import {useUser} from "@/hooks/useUser";
|
||||
import {useUserData} from "@/hooks/useUserData";
|
||||
import {useUniversalScanner} from "@/components/UniversalScanner";
|
||||
|
||||
function UserCard() {
|
||||
const {
|
||||
@@ -23,17 +22,6 @@ function UserCard() {
|
||||
} = useUser();
|
||||
const {data} = useUserData();
|
||||
|
||||
// 统一扫码处理
|
||||
const { startScan } = useUniversalScanner({
|
||||
onScanSuccess: (result) => {
|
||||
console.log('扫码成功:', result);
|
||||
},
|
||||
onScanError: (error) => {
|
||||
console.error('扫码失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(startScan, 'startScan')
|
||||
useEffect(() => {
|
||||
// Taro.getSetting:获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
|
||||
Taro.getSetting({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default definePageConfig({
|
||||
export default {
|
||||
navigationBarTitleText: '门店核销',
|
||||
navigationBarTextStyle: 'black'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import React, {useState} from 'react'
|
||||
import {View, Text, Image} from '@tarojs/components'
|
||||
import {Button, Input} from '@nutui/nutui-react-taro'
|
||||
import {Scan, Search} from '@nutui/icons-react-taro'
|
||||
@@ -8,7 +8,6 @@ import {getShopGiftByCode, updateShopGift, decryptQrData} from "@/api/shop/shopG
|
||||
import {useUser} from "@/hooks/useUser";
|
||||
import type {ShopGift} from "@/api/shop/shopGift/model";
|
||||
import {isValidJSON} from "@/utils/jsonUtils";
|
||||
import {useUniversalScanner} from "@/components/UniversalScanner";
|
||||
|
||||
const StoreVerification: React.FC = () => {
|
||||
const {
|
||||
@@ -19,55 +18,8 @@ const StoreVerification: React.FC = () => {
|
||||
const [giftInfo, setGiftInfo] = useState<ShopGift | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// 统一扫码处理(仅用于管理员权限检查后的扫码)
|
||||
const { startScan } = useUniversalScanner({
|
||||
onScanSuccess: (result) => {
|
||||
console.log('管理员扫码成功:', result);
|
||||
},
|
||||
onScanError: (error) => {
|
||||
console.error('管理员扫码失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(startScan,'startScan222')
|
||||
|
||||
// 页面加载时检查是否有传递的扫码数据
|
||||
useEffect(() => {
|
||||
const handlePageLoad = async () => {
|
||||
try {
|
||||
// 获取页面参数
|
||||
const instance = Taro.getCurrentInstance();
|
||||
const params = instance.router?.params;
|
||||
|
||||
if (params?.scanData) {
|
||||
// 解析传递过来的扫码数据
|
||||
const scanData = JSON.parse(decodeURIComponent(params.scanData));
|
||||
console.log('接收到扫码数据:', scanData);
|
||||
|
||||
if (scanData.businessType === 'gift') {
|
||||
setLoading(true);
|
||||
await handleDecryptAndVerify(scanData.token, scanData.data);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理页面参数失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
handlePageLoad();
|
||||
}, []);
|
||||
|
||||
// 扫码功能(保留原有的直接扫码功能,用于管理员在此页面的直接操作)
|
||||
// 扫码功能
|
||||
const handleScan = () => {
|
||||
// 检查管理员权限
|
||||
if (!isAdmin()) {
|
||||
Taro.showToast({
|
||||
title: '仅管理员可使用核销功能',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Taro.scanCode({
|
||||
success: (res) => {
|
||||
if (res.result) {
|
||||
|
||||
Reference in New Issue
Block a user