From e47e34825a69e042217c50843e4213c98de877bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com>
Date: Mon, 22 Sep 2025 15:44:44 +0800
Subject: [PATCH] =?UTF-8?q?```=20feat(passport):=20=E5=AE=9E=E7=8E=B0?=
=?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=89=AB=E7=A0=81=E5=8A=9F=E8=83=BD=E5=B9=B6?=
=?UTF-8?q?=E8=BF=81=E7=A7=BB=E4=BA=8C=E7=BB=B4=E7=A0=81=E7=99=BB=E5=BD=95?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
将原有的扫码登录和扫码核销功能合并为统一扫码功能,支持智能识别二维码类型,
自动执行相应操作。同时将二维码登录相关页面迁移到 /passport 路径下,优化用户体验与代码结构。
主要变更:
- 新增统一扫码 Hook (useUnifiedQRScan) 和按钮组件 (UnifiedQRButton)- 新增统一扫码页面 /passport/unified-qr/index
- 迁移二维码登录页面路径:/pages/qr-login → /passport/qr-login
- 更新管理员面板及用户卡片中的扫码入口为统一扫码- 移除旧的 QRLoginDemo 和 qr-test 测试页面- 补充统一扫码使用指南文档```
---
README_QR_LOGIN.md | 8 +-
docs/QR_LOGIN_INTEGRATION.md | 4 +-
docs/QR_LOGIN_USAGE.md | 6 +-
docs/UNIFIED_QR_SCAN_GUIDE.md | 212 +++++++++++
src/api/qr-login/index.ts | 30 +-
src/app.config.ts | 8 +-
src/components/AdminPanel.tsx | 19 +-
src/components/QRLoginButton.tsx | 2 +-
src/components/QRLoginDemo.tsx | 184 ----------
src/components/UnifiedQRButton.tsx | 126 +++++++
src/hooks/useUnifiedQRScan.ts | 332 ++++++++++++++++++
src/pages/qr-test/index.config.ts | 5 -
src/pages/qr-test/index.tsx | 33 --
src/pages/user/components/UserCard.tsx | 41 +--
.../qr-confirm/index.config.ts | 0
src/{pages => passport}/qr-confirm/index.tsx | 4 +-
.../qr-login/index.config.ts | 0
src/{pages => passport}/qr-login/index.tsx | 0
src/passport/unified-qr/index.config.ts | 4 +
src/passport/unified-qr/index.tsx | 320 +++++++++++++++++
20 files changed, 1036 insertions(+), 302 deletions(-)
create mode 100644 docs/UNIFIED_QR_SCAN_GUIDE.md
delete mode 100644 src/components/QRLoginDemo.tsx
create mode 100644 src/components/UnifiedQRButton.tsx
create mode 100644 src/hooks/useUnifiedQRScan.ts
delete mode 100644 src/pages/qr-test/index.config.ts
delete mode 100644 src/pages/qr-test/index.tsx
rename src/{pages => passport}/qr-confirm/index.config.ts (100%)
rename src/{pages => passport}/qr-confirm/index.tsx (98%)
rename src/{pages => passport}/qr-login/index.config.ts (100%)
rename src/{pages => passport}/qr-login/index.tsx (100%)
create mode 100644 src/passport/unified-qr/index.config.ts
create mode 100644 src/passport/unified-qr/index.tsx
diff --git a/README_QR_LOGIN.md b/README_QR_LOGIN.md
index f1f4ba1..e362af2 100644
--- a/README_QR_LOGIN.md
+++ b/README_QR_LOGIN.md
@@ -79,7 +79,7 @@ import QRScanModal from '@/components/QRScanModal';
import Taro from '@tarojs/taro';
Taro.navigateTo({
- url: '/pages/qr-login/index'
+ url: '/passport/qr-login/index'
});
```
@@ -93,18 +93,18 @@ Taro.navigateTo({
## 📱 页面说明
-### 1. 扫码登录页面 (`/pages/qr-login/index`)
+### 1. 扫码登录页面 (`/passport/qr-login/index`)
- 完整的扫码登录功能
- 用户信息显示
- 登录历史记录
- 使用说明和安全提示
-### 2. 登录确认页面 (`/pages/qr-confirm/index`)
+### 2. 登录确认页面 (`/passport/qr-confirm/index`)
- 处理二维码跳转确认
- 支持URL参数:`qrCodeKey` 或 `token`
- 用户确认界面
-### 3. 功能测试页面 (`/pages/qr-test/index`)
+### 3. 功能测试页面 (`/passport/qr-test/index`)
- 演示各种集成方式
- 功能测试和调试
diff --git a/docs/QR_LOGIN_INTEGRATION.md b/docs/QR_LOGIN_INTEGRATION.md
index ecfacf1..e0f186d 100644
--- a/docs/QR_LOGIN_INTEGRATION.md
+++ b/docs/QR_LOGIN_INTEGRATION.md
@@ -98,7 +98,7 @@ const {
```
### 4. 页面层
-文件:`src/pages/qr-login/index.tsx`
+文件:`src/passport/qr-login/index.tsx`
专门的扫码登录页面,提供完整的用户体验:
- 用户信息展示
@@ -155,7 +155,7 @@ import Taro from '@tarojs/taro';
const handleQRLogin = () => {
Taro.navigateTo({
- url: '/pages/qr-login/index'
+ url: '/passport/qr-login/index'
});
};
```
diff --git a/docs/QR_LOGIN_USAGE.md b/docs/QR_LOGIN_USAGE.md
index 81699bf..ab942ba 100644
--- a/docs/QR_LOGIN_USAGE.md
+++ b/docs/QR_LOGIN_USAGE.md
@@ -105,7 +105,7 @@ import QRLoginButton from '@/components/QRLoginButton';
// 或者自定义跳转
) : (
-
+
确认登录
diff --git a/src/pages/qr-login/index.config.ts b/src/passport/qr-login/index.config.ts
similarity index 100%
rename from src/pages/qr-login/index.config.ts
rename to src/passport/qr-login/index.config.ts
diff --git a/src/pages/qr-login/index.tsx b/src/passport/qr-login/index.tsx
similarity index 100%
rename from src/pages/qr-login/index.tsx
rename to src/passport/qr-login/index.tsx
diff --git a/src/passport/unified-qr/index.config.ts b/src/passport/unified-qr/index.config.ts
new file mode 100644
index 0000000..3a5a194
--- /dev/null
+++ b/src/passport/unified-qr/index.config.ts
@@ -0,0 +1,4 @@
+export default {
+ navigationBarTitleText: '统一扫码',
+ navigationBarTextStyle: 'black'
+}
\ No newline at end of file
diff --git a/src/passport/unified-qr/index.tsx b/src/passport/unified-qr/index.tsx
new file mode 100644
index 0000000..9e87c7f
--- /dev/null
+++ b/src/passport/unified-qr/index.tsx
@@ -0,0 +1,320 @@
+import React, { useState } from 'react';
+import { View, Text } from '@tarojs/components';
+import { Card, Button, Tag } from '@nutui/nutui-react-taro';
+import { Scan, Success, Failure, Tips, ArrowLeft } from '@nutui/icons-react-taro';
+import Taro from '@tarojs/taro';
+import { useUnifiedQRScan, ScanType, type UnifiedScanResult } from '@/hooks/useUnifiedQRScan';
+
+/**
+ * 统一扫码页面
+ * 支持登录和核销两种类型的二维码扫描
+ */
+const UnifiedQRPage: React.FC = () => {
+ const [scanHistory, setScanHistory] = useState([]);
+ const {
+ startScan,
+ isLoading,
+ canScan,
+ state,
+ result,
+ error,
+ scanType,
+ reset
+ } = useUnifiedQRScan();
+
+ // 处理扫码成功
+ const handleScanSuccess = (result: UnifiedScanResult) => {
+ console.log('扫码成功:', result);
+
+ // 添加到扫码历史
+ const newRecord = {
+ id: Date.now(),
+ time: new Date().toLocaleString(),
+ type: result.type,
+ data: result.data,
+ message: result.message,
+ success: true
+ };
+ setScanHistory(prev => [newRecord, ...prev.slice(0, 4)]); // 只保留最近5条记录
+
+ // 根据类型给出不同提示
+ if (result.type === ScanType.VERIFICATION) {
+ // 核销成功后询问是否继续扫码
+ setTimeout(() => {
+ Taro.showModal({
+ title: '核销成功',
+ content: '是否继续扫码核销其他礼品卡?',
+ success: (res) => {
+ if (res.confirm) {
+ handleStartScan();
+ }
+ }
+ });
+ }, 2000);
+ }
+ };
+
+ // 处理扫码失败
+ const handleScanError = (error: string) => {
+ console.error('扫码失败:', error);
+
+ // 添加到扫码历史
+ const newRecord = {
+ id: Date.now(),
+ time: new Date().toLocaleString(),
+ error,
+ success: false
+ };
+ setScanHistory(prev => [newRecord, ...prev.slice(0, 4)]); // 只保留最近5条记录
+ };
+
+ // 开始扫码
+ const handleStartScan = async () => {
+ try {
+ const scanResult = await startScan();
+ if (scanResult) {
+ handleScanSuccess(scanResult);
+ }
+ } catch (error: any) {
+ handleScanError(error.message || '扫码失败');
+ }
+ };
+
+ // 返回上一页
+ const handleGoBack = () => {
+ Taro.navigateBack();
+ };
+
+ // 获取状态图标
+ const getStatusIcon = (success: boolean, type?: ScanType) => {
+ console.log(type,'获取状态图标')
+ if (success) {
+ return ;
+ } else {
+ return ;
+ }
+ };
+
+ // 获取类型标签
+ const getTypeTag = (type: ScanType) => {
+ switch (type) {
+ case ScanType.LOGIN:
+ return 登录;
+ case ScanType.VERIFICATION:
+ return 核销;
+ default:
+ return 未知;
+ }
+ };
+
+ return (
+
+ {/* 页面头部 */}
+
+
+
+ 统一扫码
+
+ 支持登录和核销功能
+
+
+
+
+ {/* 主要扫码区域 */}
+
+
+ {/* 状态显示 */}
+ {state === 'idle' && (
+ <>
+
+
+ 智能扫码
+
+
+ 自动识别登录和核销二维码
+
+
+ {canScan() ? '开始扫码' : '请先登录'}
+
+ >
+ )}
+
+ {state === 'scanning' && (
+ <>
+
+
+ 扫码中...
+
+
+ 请对准二维码
+
+
+ 取消
+
+ >
+ )}
+
+ {state === 'processing' && (
+ <>
+
+
+
+
+ 处理中...
+
+
+ {scanType === ScanType.LOGIN ? '正在确认登录' :
+ scanType === ScanType.VERIFICATION ? '正在核销礼品卡' : '正在处理'}
+
+ >
+ )}
+
+ {state === 'success' && result && (
+ <>
+
+
+ {result.message}
+
+ {result.type === ScanType.VERIFICATION && result.data && (
+
+
+ 礼品卡:{result.data.goodsName || '未知商品'}
+
+
+ 面值:¥{result.data.faceValue}
+
+
+ )}
+
+
+ 继续扫码
+
+
+ 重置
+
+
+ >
+ )}
+
+ {state === 'error' && (
+ <>
+
+
+ 操作失败
+
+
+ {error || '未知错误'}
+
+
+
+ 重试
+
+
+ 重置
+
+
+ >
+ )}
+
+
+
+ {/* 扫码历史 */}
+ {scanHistory.length > 0 && (
+
+
+
+ 最近扫码记录
+
+
+ {scanHistory.map((record, index) => (
+
+
+ {getStatusIcon(record.success, record.type)}
+
+
+ {record.type && getTypeTag(record.type)}
+
+ {record.time}
+
+
+
+ {record.success ? record.message : record.error}
+
+ {record.success && record.type === ScanType.VERIFICATION && record.data && (
+
+ {record.data.goodsName} - ¥{record.data.faceValue}
+
+ )}
+
+
+
+ ))}
+
+
+ )}
+
+ {/* 功能说明 */}
+
+
+
+
+
+
+ 功能说明
+
+
+ • 登录二维码:自动确认网页端登录
+
+
+ • 核销二维码:门店核销用户礼品卡
+
+
+ • 系统会自动识别二维码类型并执行相应操作
+
+
+
+
+
+
+ );
+};
+
+export default UnifiedQRPage;