|
|
@@ -0,0 +1,726 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>微信扫码登录 - 官方实现</title>
|
|
|
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
|
+ <style>
|
|
|
+ * {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ body {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ color: #333;
|
|
|
+ line-height: 1.6;
|
|
|
+ min-height: 100vh;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 900px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ header {
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 40px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ h1 {
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ font-size: 2.5rem;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .subtitle {
|
|
|
+ color: #7f8c8d;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ max-width: 600px;
|
|
|
+ margin: 0 auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-wrapper {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ width: 100%;
|
|
|
+ gap: 30px;
|
|
|
+ margin-bottom: 40px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-section {
|
|
|
+ flex: 1;
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
|
|
+ padding: 40px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info-section {
|
|
|
+ flex: 1;
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
|
|
+ padding: 40px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ font-size: 1.5rem;
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 25px;
|
|
|
+ padding-bottom: 15px;
|
|
|
+ border-bottom: 2px solid #f0f2f5;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ #login_container {
|
|
|
+ width: 100%;
|
|
|
+ min-height: 320px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ border-radius: 12px;
|
|
|
+ background-color: #f8fafc;
|
|
|
+ margin-bottom: 25px;
|
|
|
+ border: 1px solid #eaeaea;
|
|
|
+ }
|
|
|
+
|
|
|
+ .qrcode-loading {
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .qrcode-loading i {
|
|
|
+ font-size: 3rem;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ color: #07c160;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-indicator {
|
|
|
+ margin-top: 20px;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 10px;
|
|
|
+ background-color: #f8fafc;
|
|
|
+ border-left: 4px solid #07c160;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-title {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-desc {
|
|
|
+ color: #666;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .steps-container {
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ border-bottom: 1px solid #f0f2f5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ padding-bottom: 0;
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-number {
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background-color: #07c160;
|
|
|
+ color: white;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-right: 15px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-content h4 {
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-content p {
|
|
|
+ color: #666;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-section {
|
|
|
+ margin-top: 30px;
|
|
|
+ background-color: #f8fafc;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-title {
|
|
|
+ font-size: 1.1rem;
|
|
|
+ color: #2c3e50;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-item {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-item label {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #555;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-item input {
|
|
|
+ padding: 10px 12px;
|
|
|
+ border-radius: 6px;
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ transition: border-color 0.3s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-item input:focus {
|
|
|
+ outline: none;
|
|
|
+ border-color: #07c160;
|
|
|
+ box-shadow: 0 0 0 2px rgba(7, 193, 96, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .config-hint {
|
|
|
+ color: #888;
|
|
|
+ font-size: 0.85rem;
|
|
|
+ margin-top: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .buttons-container {
|
|
|
+ display: flex;
|
|
|
+ gap: 15px;
|
|
|
+ margin-top: 25px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ padding: 12px 24px;
|
|
|
+ border-radius: 8px;
|
|
|
+ border: none;
|
|
|
+ font-size: 1rem;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-primary {
|
|
|
+ background-color: #07c160;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-primary:hover {
|
|
|
+ background-color: #06ad56;
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 5px 15px rgba(7, 193, 96, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-secondary {
|
|
|
+ background-color: #f0f2f5;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-secondary:hover {
|
|
|
+ background-color: #e4e6e9;
|
|
|
+ transform: translateY(-2px);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-refresh {
|
|
|
+ background-color: #1677ff;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-refresh:hover {
|
|
|
+ background-color: #0d66d9;
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 5px 15px rgba(22, 119, 255, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn:disabled {
|
|
|
+ opacity: 0.6;
|
|
|
+ cursor: not-allowed;
|
|
|
+ transform: none !important;
|
|
|
+ box-shadow: none !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .note-box {
|
|
|
+ margin-top: 25px;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 10px;
|
|
|
+ background-color: #fff9e6;
|
|
|
+ border-left: 4px solid #ffc107;
|
|
|
+ }
|
|
|
+
|
|
|
+ .note-title {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #e6a700;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .note-content {
|
|
|
+ color: #8a6d3b;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer {
|
|
|
+ margin-top: 40px;
|
|
|
+ text-align: center;
|
|
|
+ color: #95a5a6;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ width: 100%;
|
|
|
+ max-width: 900px;
|
|
|
+ padding-top: 20px;
|
|
|
+ border-top: 1px solid #eee;
|
|
|
+ }
|
|
|
+
|
|
|
+ .wechat-qrcode {
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .wechat-qrcode img {
|
|
|
+ max-width: 200px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 768px) {
|
|
|
+ .content-wrapper {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ h1 {
|
|
|
+ font-size: 2rem;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-section, .info-section {
|
|
|
+ padding: 30px 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .buttons-container {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 480px) {
|
|
|
+ .section-title {
|
|
|
+ font-size: 1.3rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ #login_container {
|
|
|
+ min-height: 280px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <div class="container">
|
|
|
+ <header>
|
|
|
+ <h1>
|
|
|
+ <i class="fab fa-weixin"></i>
|
|
|
+ 微信官方扫码登录
|
|
|
+ </h1>
|
|
|
+ <p class="subtitle">
|
|
|
+ 本页面使用微信官方提供的JS SDK实现扫码登录功能。请按照下方步骤配置参数并体验微信扫码登录流程。
|
|
|
+ </p>
|
|
|
+ </header>
|
|
|
+
|
|
|
+ <div class="content-wrapper">
|
|
|
+ <div class="login-section">
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-qrcode"></i>
|
|
|
+ 微信扫码登录
|
|
|
+ </h2>
|
|
|
+
|
|
|
+ <!-- 微信登录二维码容器 -->
|
|
|
+ <div id="login_container">
|
|
|
+ <div class="qrcode-loading">
|
|
|
+ <i class="fas fa-spinner fa-spin"></i>
|
|
|
+ <p>正在加载微信登录二维码...</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="status-indicator">
|
|
|
+ <div class="status-title">
|
|
|
+ <i class="fas fa-info-circle"></i>
|
|
|
+ 状态监控
|
|
|
+ </div>
|
|
|
+ <p class="status-desc" id="statusText">等待二维码加载完成</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="buttons-container">
|
|
|
+ <button class="btn btn-refresh" id="refreshBtn">
|
|
|
+ <i class="fas fa-sync-alt"></i>
|
|
|
+ 刷新二维码
|
|
|
+ </button>
|
|
|
+ <button class="btn btn-secondary" id="testBtn">
|
|
|
+ <i class="fas fa-mobile-alt"></i>
|
|
|
+ 模拟扫码测试
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="note-box">
|
|
|
+ <div class="note-title">
|
|
|
+ <i class="fas fa-exclamation-triangle"></i>
|
|
|
+ 重要提示
|
|
|
+ </div>
|
|
|
+ <div class="note-content">
|
|
|
+ 此演示使用了测试参数,在实际生产环境中需要:
|
|
|
+ 1. 在微信开放平台注册应用获取真实appid
|
|
|
+ 2. 配置有效的redirect_uri(授权回调地址)
|
|
|
+ 3. 部署在备案的域名下(微信要求HTTPS)
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="info-section">
|
|
|
+ <h2 class="section-title">
|
|
|
+ <i class="fas fa-cogs"></i>
|
|
|
+ 配置说明
|
|
|
+ </h2>
|
|
|
+
|
|
|
+ <div class="steps-container">
|
|
|
+ <div class="step">
|
|
|
+ <div class="step-number">1</div>
|
|
|
+ <div class="step-content">
|
|
|
+ <h4>获取AppID</h4>
|
|
|
+ <p>访问微信开放平台,注册并创建网站应用,获取AppID和AppSecret</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="step">
|
|
|
+ <div class="step-number">2</div>
|
|
|
+ <div class="step-content">
|
|
|
+ <h4>配置回调地址</h4>
|
|
|
+ <p>在微信开放平台配置授权回调域名,必须与redirect_uri域名一致</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="step">
|
|
|
+ <div class="step-number">3</div>
|
|
|
+ <div class="step-content">
|
|
|
+ <h4>部署代码</h4>
|
|
|
+ <p>将配置好参数的代码部署到已备案的域名(必须支持HTTPS)</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-section">
|
|
|
+ <h3 class="config-title">
|
|
|
+ <i class="fas fa-sliders-h"></i>
|
|
|
+ 参数配置
|
|
|
+ </h3>
|
|
|
+
|
|
|
+ <div class="config-item">
|
|
|
+ <label for="appid">AppID</label>
|
|
|
+ <input type="text" id="appid" placeholder="请输入微信开放平台AppID" value="wxbdc5610cc59c1631">
|
|
|
+ <div class="config-hint">此处为测试AppID,实际使用时请替换为自己的AppID</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-item">
|
|
|
+ <label for="redirect_uri">Redirect URI</label>
|
|
|
+ <input type="text" id="redirect_uri" placeholder="请输入授权回调地址" value="https://open.weixin.qq.com/connect/qrconnect">
|
|
|
+ <div class="config-hint">用户授权后微信会跳转到此地址,需与开放平台配置一致</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="config-item">
|
|
|
+ <label for="scope">Scope</label>
|
|
|
+ <input type="text" id="scope" placeholder="请输入授权作用域" value="snsapi_login">
|
|
|
+ <div class="config-hint">应用授权作用域,snsapi_login为微信登录专用</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="buttons-container">
|
|
|
+ <button class="btn btn-primary" id="applyConfigBtn">
|
|
|
+ <i class="fas fa-check-circle"></i>
|
|
|
+ 应用配置
|
|
|
+ </button>
|
|
|
+ <button class="btn btn-secondary" id="resetConfigBtn">
|
|
|
+ <i class="fas fa-undo"></i>
|
|
|
+ 重置配置
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="wechat-qrcode">
|
|
|
+ <p>使用微信扫描体验</p>
|
|
|
+ <img src="https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png" alt="微信扫码">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <footer class="footer">
|
|
|
+ <p>本页面使用微信官方JS SDK实现扫码登录功能 | 请遵循微信开放平台相关规范</p>
|
|
|
+ <p>© 2023 微信扫码登录演示 | 仅用于学习和演示目的</p>
|
|
|
+ </footer>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 微信官方JS SDK -->
|
|
|
+ <script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ // 微信登录对象
|
|
|
+ let wxLoginObj = null;
|
|
|
+
|
|
|
+ // 默认配置参数
|
|
|
+ const defaultConfig = {
|
|
|
+ self_redirect: true,
|
|
|
+ id: "login_container",
|
|
|
+ appid: "wxbdc5610cc59c1631", // 微信提供的测试AppID:wxbdc5610cc59c1631
|
|
|
+ scope: "snsapi_login",
|
|
|
+ redirect_uri: encodeURIComponent("https://passport.yhd.com/wechat/callback.do"),
|
|
|
+ state: "STATE", // 可以自定义的参数,用于防止CSRF攻击
|
|
|
+ style: "black", // 二维码样式:black黑色,white白色
|
|
|
+ href: "" // 自定义样式链接,可以为空
|
|
|
+ };
|
|
|
+
|
|
|
+ // DOM元素
|
|
|
+ const loginContainer = document.getElementById('login_container');
|
|
|
+ const statusText = document.getElementById('statusText');
|
|
|
+ const refreshBtn = document.getElementById('refreshBtn');
|
|
|
+ const testBtn = document.getElementById('testBtn');
|
|
|
+ const applyConfigBtn = document.getElementById('applyConfigBtn');
|
|
|
+ const resetConfigBtn = document.getElementById('resetConfigBtn');
|
|
|
+ const appidInput = document.getElementById('appid');
|
|
|
+ const redirectUriInput = document.getElementById('redirect_uri');
|
|
|
+ const scopeInput = document.getElementById('scope');
|
|
|
+
|
|
|
+ // 初始化函数
|
|
|
+ function initWeChatLogin(config) {
|
|
|
+ // 清除现有二维码
|
|
|
+ loginContainer.innerHTML = '<div class="qrcode-loading"><i class="fas fa-spinner fa-spin"></i><p>正在加载微信登录二维码...</p></div>';
|
|
|
+ statusText.textContent = "正在初始化微信登录...";
|
|
|
+
|
|
|
+ // 销毁之前的实例
|
|
|
+ if (wxLoginObj) {
|
|
|
+ // 微信官方SDK没有提供销毁方法,我们只能替换容器内容
|
|
|
+ loginContainer.innerHTML = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建微信登录实例
|
|
|
+ try {
|
|
|
+ wxLoginObj = new WxLogin({
|
|
|
+ self_redirect: config.self_redirect,
|
|
|
+ id: config.id,
|
|
|
+ appid: config.appid,
|
|
|
+ scope: config.scope,
|
|
|
+ redirect_uri: config.redirect_uri,
|
|
|
+ state: config.state,
|
|
|
+ style: config.style,
|
|
|
+ href: config.href,
|
|
|
+ onReady: function(isReady) {
|
|
|
+ console.log("微信登录二维码加载状态:", isReady);
|
|
|
+ if (isReady) {
|
|
|
+ statusText.textContent = "二维码已就绪,请使用微信扫描";
|
|
|
+ refreshBtn.disabled = false;
|
|
|
+ } else {
|
|
|
+ statusText.textContent = "二维码加载失败,请检查配置";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 监听二维码状态变化(模拟)
|
|
|
+ setTimeout(() => {
|
|
|
+ statusText.textContent = "二维码已加载完成,请使用微信扫描";
|
|
|
+ }, 1000);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error("微信登录初始化失败:", error);
|
|
|
+ statusText.textContent = "微信登录初始化失败: " + error.message;
|
|
|
+ loginContainer.innerHTML = `<div class="qrcode-loading" style="color:#f44336;">
|
|
|
+ <i class="fas fa-exclamation-triangle"></i>
|
|
|
+ <p>微信登录初始化失败</p>
|
|
|
+ <p style="font-size:0.8rem; margin-top:10px;">${error.message}</p>
|
|
|
+ </div>`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 刷新二维码
|
|
|
+ function refreshQRCode() {
|
|
|
+ // 获取当前配置
|
|
|
+ const currentConfig = {
|
|
|
+ ...defaultConfig,
|
|
|
+ appid: appidInput.value.trim() || defaultConfig.appid,
|
|
|
+ scope: scopeInput.value.trim() || defaultConfig.scope,
|
|
|
+ redirect_uri: encodeURIComponent(redirectUriInput.value.trim() || defaultConfig.redirect_uri)
|
|
|
+ };
|
|
|
+
|
|
|
+ // 重新初始化
|
|
|
+ initWeChatLogin(currentConfig);
|
|
|
+
|
|
|
+ // 禁用按钮避免重复点击
|
|
|
+ refreshBtn.disabled = true;
|
|
|
+ refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 刷新中...';
|
|
|
+
|
|
|
+ // 3秒后启用按钮
|
|
|
+ setTimeout(() => {
|
|
|
+ refreshBtn.disabled = false;
|
|
|
+ refreshBtn.innerHTML = '<i class="fas fa-sync-alt"></i> 刷新二维码';
|
|
|
+ }, 30000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟扫码测试
|
|
|
+ function simulateScanTest() {
|
|
|
+ statusText.textContent = "已模拟扫描,请在手机上确认登录";
|
|
|
+ testBtn.disabled = true;
|
|
|
+ testBtn.innerHTML = '<i class="fas fa-check-circle"></i> 已模拟扫码';
|
|
|
+
|
|
|
+ // 5秒后重置
|
|
|
+ setTimeout(() => {
|
|
|
+ statusText.textContent = "二维码已就绪,请使用微信扫描";
|
|
|
+ testBtn.disabled = false;
|
|
|
+ testBtn.innerHTML = '<i class="fas fa-mobile-alt"></i> 模拟扫码测试';
|
|
|
+ }, 5000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应用配置
|
|
|
+ function applyConfig() {
|
|
|
+ // 验证配置
|
|
|
+ const appid = appidInput.value.trim();
|
|
|
+ const redirectUri = redirectUriInput.value.trim();
|
|
|
+
|
|
|
+ if (!appid) {
|
|
|
+ alert("请填写AppID");
|
|
|
+ appidInput.focus();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!redirectUri) {
|
|
|
+ alert("请填写Redirect URI");
|
|
|
+ redirectUriInput.focus();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应用配置并刷新二维码
|
|
|
+ applyConfigBtn.disabled = true;
|
|
|
+ applyConfigBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 应用中...';
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ refreshQRCode();
|
|
|
+ applyConfigBtn.disabled = false;
|
|
|
+ applyConfigBtn.innerHTML = '<i class="fas fa-check-circle"></i> 应用配置';
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置配置
|
|
|
+ function resetConfig() {
|
|
|
+ appidInput.value = defaultConfig.appid;
|
|
|
+ redirectUriInput.value = decodeURIComponent(defaultConfig.redirect_uri);
|
|
|
+ scopeInput.value = defaultConfig.scope;
|
|
|
+
|
|
|
+ // 应用重置的配置
|
|
|
+ applyConfig();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 页面加载完成后初始化
|
|
|
+ document.addEventListener('DOMContentLoaded', function() {
|
|
|
+ // 初始化微信登录
|
|
|
+ initWeChatLogin(defaultConfig);
|
|
|
+
|
|
|
+ // 设置输入框默认值
|
|
|
+ appidInput.value = defaultConfig.appid;
|
|
|
+ redirectUriInput.value = decodeURIComponent(defaultConfig.redirect_uri);
|
|
|
+ scopeInput.value = defaultConfig.scope;
|
|
|
+
|
|
|
+ // 绑定按钮事件
|
|
|
+ refreshBtn.addEventListener('click', refreshQRCode);
|
|
|
+ testBtn.addEventListener('click', simulateScanTest);
|
|
|
+ applyConfigBtn.addEventListener('click', applyConfig);
|
|
|
+ resetConfigBtn.addEventListener('click', resetConfig);
|
|
|
+
|
|
|
+ // 监听输入框变化
|
|
|
+ appidInput.addEventListener('input', function() {
|
|
|
+ applyConfigBtn.disabled = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ redirectUriInput.addEventListener('input', function() {
|
|
|
+ applyConfigBtn.disabled = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ scopeInput.addEventListener('input', function() {
|
|
|
+ applyConfigBtn.disabled = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加键盘快捷键
|
|
|
+ document.addEventListener('keydown', function(e) {
|
|
|
+ // Ctrl+R 刷新二维码
|
|
|
+ if (e.ctrlKey && e.key === 'r') {
|
|
|
+ e.preventDefault();
|
|
|
+ if (!refreshBtn.disabled) refreshQRCode();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Enter 在输入框时应用配置
|
|
|
+ if (e.key === 'Enter' && document.activeElement.tagName === 'INPUT') {
|
|
|
+ applyConfig();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 页面可见性变化时刷新二维码
|
|
|
+ document.addEventListener('visibilitychange', function() {
|
|
|
+ if (!document.hidden && wxLoginObj) {
|
|
|
+ // 页面从后台切换回来时刷新二维码
|
|
|
+ setTimeout(refreshQRCode, 500);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|