diff --git a/basic-info.css b/basic-info.css
index d0900ac..b748f8e 100644
--- a/basic-info.css
+++ b/basic-info.css
@@ -1075,3 +1075,239 @@ body.modal-open {
.back-home-btn:active {
transform: translateY(0);
}
+
+/* ==================== 授权流程样式 ==================== */
+.auth-flow-container {
+ max-width: 800px;
+ margin: 0 auto;
+ padding: 16px;
+ min-height: 100vh;
+}
+
+/* 授权进度区域 */
+.auth-progress-section {
+ background: #fff;
+ border-radius: 12px;
+ padding: 16px;
+ margin-bottom: 16px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+}
+
+.auth-progress-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+ padding-bottom: 12px;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.auth-progress-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+}
+
+.auth-progress-count {
+ font-size: 14px;
+ color: #666;
+}
+
+.auth-progress-list {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.auth-progress-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 12px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ transition: all 0.3s ease;
+}
+
+.auth-progress-item.active {
+ background: #e8f0ff;
+ border: 1px solid #3474fe;
+}
+
+.auth-progress-item.completed {
+ background: #f0fff4;
+}
+
+.auth-progress-item.completed .auth-progress-icon {
+ color: #19be6b;
+}
+
+.auth-progress-item.completed .auth-progress-status {
+ color: #19be6b;
+}
+
+.auth-progress-item.failed {
+ background: #fff5f5;
+}
+
+.auth-progress-item.failed .auth-progress-icon {
+ color: #ff4444;
+}
+
+.auth-progress-item.failed .auth-progress-status {
+ color: #ff4444;
+}
+
+.auth-progress-item.timeout {
+ background: #fffbe6;
+}
+
+.auth-progress-item.timeout .auth-progress-icon {
+ color: #faad14;
+}
+
+.auth-progress-item.timeout .auth-progress-status {
+ color: #faad14;
+}
+
+.auth-progress-icon {
+ font-size: 18px;
+ width: 24px;
+ text-align: center;
+ color: #999;
+}
+
+.auth-progress-item.active .auth-progress-icon {
+ color: #3474fe;
+ animation: pulse 1.5s ease-in-out infinite;
+}
+
+@keyframes pulse {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+.auth-progress-name {
+ flex: 1;
+ font-size: 14px;
+ color: #333;
+ font-weight: 500;
+}
+
+.auth-progress-status {
+ font-size: 12px;
+ color: #999;
+}
+
+.auth-progress-item.active .auth-progress-status {
+ color: #3474fe;
+}
+
+/* iframe 区域 */
+.auth-iframe-section {
+ background: #fff;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+}
+
+.auth-iframe-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 14px 16px;
+ background: linear-gradient(135deg, #3474fe 0%, #5b8def 100%);
+ color: #fff;
+}
+
+.auth-iframe-title {
+ font-size: 16px;
+ font-weight: 600;
+}
+
+.auth-iframe-hint {
+ font-size: 12px;
+ opacity: 0.9;
+}
+
+.auth-iframe {
+ width: 100%;
+ height: calc(100vh - 350px);
+ min-height: 400px;
+ border: none;
+ display: block;
+}
+
+/* 授权完成区域 */
+.auth-complete-section {
+ background: #fff;
+ border-radius: 12px;
+ padding: 40px 20px;
+ text-align: center;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+}
+
+.auth-complete-icon {
+ width: 72px;
+ height: 72px;
+ line-height: 72px;
+ margin: 0 auto 20px;
+ background: linear-gradient(135deg, #19be6b 0%, #47d88a 100%);
+ color: #fff;
+ font-size: 36px;
+ border-radius: 50%;
+ box-shadow: 0 4px 12px rgba(25, 190, 107, 0.3);
+}
+
+.auth-complete-title {
+ font-size: 22px;
+ font-weight: 600;
+ color: #333;
+ margin-bottom: 8px;
+}
+
+.auth-complete-desc {
+ font-size: 14px;
+ color: #666;
+ margin-bottom: 24px;
+}
+
+.auth-countdown {
+ font-size: 14px;
+ color: #999;
+ margin-bottom: 20px;
+}
+
+.auth-countdown #countdownSeconds {
+ font-size: 24px;
+ font-weight: 600;
+ color: #3474fe;
+ margin: 0 4px;
+}
+
+.auth-redirect-btn {
+ display: inline-block;
+ padding: 14px 48px;
+ background: linear-gradient(135deg, #3474fe 0%, #5b8def 100%);
+ color: #fff;
+ font-size: 16px;
+ font-weight: 500;
+ border: none;
+ border-radius: 24px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ box-shadow: 0 4px 12px rgba(52, 116, 254, 0.3);
+}
+
+.auth-redirect-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 16px rgba(52, 116, 254, 0.4);
+}
+
+.auth-redirect-btn:active {
+ transform: translateY(0);
+}
diff --git a/src/js/config/api.config.js b/src/js/config/api.config.js
index 1e68620..d29f5df 100644
--- a/src/js/config/api.config.js
+++ b/src/js/config/api.config.js
@@ -27,6 +27,9 @@ export const API_CONFIG = {
SUBMIT_DRAFT_FORM: '/partnerh5/save_draft',
GET_DRAFT_FORM: '/partnerh5/get_draft',
+ // 授权状态查询接口
+ CHECK_AUTH_STATUS: '/partnerh5/check_auth_status',
+
// 区域数据接口
AREA_LIST: '/partnerh5/area_list',
},
diff --git a/src/js/pages/basic-info.page.js b/src/js/pages/basic-info.page.js
index a8174aa..74ad084 100644
--- a/src/js/pages/basic-info.page.js
+++ b/src/js/pages/basic-info.page.js
@@ -9,6 +9,7 @@ import { DraftManager, FormIdGenerator, UserCache } from '../core/index.js';
import { ASSET_CONFIG, BASIC_INFO_CONFIG, PROVINCE_CITY_DATA, CACHE_CONFIG } from '../config/index.js';
import { showToast } from '../ui/toast.js';
import { AreaService } from '../services/area.service.js';
+import { AuthFlowService, AUTH_STATUS } from '../services/index.js';
export class BasicInfoPage {
constructor() {
@@ -655,85 +656,242 @@ export class BasicInfoPage {
}
/**
- * 显示提交成功页面
- * @param {Object} data - 返回数据 { formdataid, h5Urls }
+ * 显示提交成功页面(授权流程)
+ * @param {Object} data - 返回数据 { formdataid, h5Urls, redirectUrl }
*/
showSubmitSuccessDialog(data) {
- const h5Urls = data.h5Urls;
- const urlEntries = Object.entries(h5Urls);
+ const { formdataid, h5Urls, redirectUrl } = data;
- // 隐藏表单内容
- document.getElementById('assetList').style.display = 'none';
- document.getElementById('basicInfoSection').style.display = 'none';
- this.elements.submitBtn.style.display = 'none';
+ // 隐藏表单相关的所有内容
+ const topCard = document.querySelector('.top-card');
+ const assetSection = document.querySelector('.asset-section');
+ const basicInfoSection = document.getElementById('basicInfoSection');
+ const bottomSection = document.getElementById('bottomSection');
- // 创建成功提示区域
- const successContainer = document.createElement('div');
- successContainer.className = 'submit-success-container';
- successContainer.innerHTML = `
-
+ if (topCard) topCard.style.display = 'none';
+ if (assetSection) assetSection.style.display = 'none';
+ if (basicInfoSection) basicInfoSection.style.display = 'none';
+ if (bottomSection) bottomSection.style.display = 'none';
- ${urlEntries.length > 0 ? `
-
- ${urlEntries.map(([name, url], index) => `
-
-
-
+ // 创建授权流程容器
+ const authContainer = document.createElement('div');
+ authContainer.className = 'auth-flow-container';
+ authContainer.id = 'authFlowContainer';
+
+ // 如果没有 h5Urls,显示成功提示
+ if (!h5Urls || h5Urls.length === 0) {
+ authContainer.innerHTML = `
+
+
✓
+
信息提交成功
+
您的申请已提交成功!
+ ${redirectUrl ? `
+
+ 5 秒后自动跳转...
+
+
+ ` : `
+
+ `}
+
+ `;
+
+ const mainContainer = document.querySelector('.container') || document.body;
+ mainContainer.insertBefore(authContainer, mainContainer.firstChild);
+
+ // 如果有 redirectUrl,启动倒计时
+ if (redirectUrl) {
+ this.startFinalCountdown(redirectUrl);
+ }
+ return;
+ }
+
+ // 有 h5Urls,显示授权流程界面
+ authContainer.innerHTML = `
+
+
+
+ ${h5Urls.map((item, index) => `
+
+ ○
+ ${item.apiname}
+ 等待中
`).join('')}
-
- ${urlEntries.length > 1 ? `
-
- ${urlEntries.map(([name, url], index) => `
-
- `).join('')}
-
- ` : ''}
- ` : `
-
-
您的申请已提交成功!
-
我们会尽快处理您的申请。
+
+
+
- `}
-
-
`;
- // 插入到页面顶部
const mainContainer = document.querySelector('.container') || document.body;
- mainContainer.insertBefore(successContainer, mainContainer.firstChild);
+ mainContainer.insertBefore(authContainer, mainContainer.firstChild);
- // 绑定 Tab 切换事件
- if (urlEntries.length > 1) {
- const tabs = successContainer.querySelectorAll('.product-tab');
- const iframes = successContainer.querySelectorAll('.iframe-wrapper');
+ // 启动授权流程
+ this.runAuthFlow(formdataid, h5Urls, redirectUrl);
+ }
- tabs.forEach(tab => {
- tab.addEventListener('click', () => {
- const index = parseInt(tab.dataset.index);
+ /**
+ * 执行授权流程
+ * @param {number} formdataid - 表单数据ID
+ * @param {Array} h5Urls - H5 URL 列表
+ * @param {string} redirectUrl - 最终跳转 URL
+ */
+ async runAuthFlow(formdataid, h5Urls, redirectUrl) {
+ const iframe = document.getElementById('authIframe');
+ const currentIndexEl = document.getElementById('currentIndex');
+ const currentProductNameEl = document.getElementById('currentProductName');
- // 更新 Tab 状态
- tabs.forEach(t => t.classList.remove('active'));
- tab.classList.add('active');
+ await AuthFlowService.startAuthFlow(formdataid, h5Urls, {
+ // 开始处理某个产品
+ onStart: (item, index) => {
+ console.log('[BasicInfoPage] 开始处理:', item.apiname);
+
+ // 更新进度显示
+ if (currentIndexEl) {
+ currentIndexEl.textContent = index + 1;
+ }
+ if (currentProductNameEl) {
+ currentProductNameEl.textContent = item.apiname;
+ }
- // 更新 iframe 显示
- iframes.forEach(iframe => iframe.classList.remove('active'));
- iframes[index].classList.add('active');
+ // 更新进度列表状态
+ const iconEl = document.getElementById(`icon-${item.apicode}`);
+ const statusEl = document.getElementById(`status-${item.apicode}`);
+ if (iconEl) iconEl.textContent = '●';
+ if (statusEl) statusEl.textContent = '授权中...';
+
+ // 高亮当前项
+ document.querySelectorAll('.auth-progress-item').forEach(el => {
+ el.classList.remove('active');
});
+ const currentItem = document.querySelector(`.auth-progress-item[data-apicode="${item.apicode}"]`);
+ if (currentItem) {
+ currentItem.classList.add('active');
+ }
+ },
+
+ // iframe 切换
+ onIframeChange: (url) => {
+ console.log('[BasicInfoPage] iframe 切换到:', url);
+ if (iframe && url) {
+ iframe.src = url;
+ }
+ },
+
+ // 状态更新
+ onProgress: (item, index, status) => {
+ console.log('[BasicInfoPage] 状态更新:', item.apiname, status);
+ },
+
+ // 单个完成
+ onComplete: (item, index, result) => {
+ console.log('[BasicInfoPage] 完成:', item.apiname, result);
+
+ const iconEl = document.getElementById(`icon-${item.apicode}`);
+ const statusEl = document.getElementById(`status-${item.apicode}`);
+ const progressItem = document.querySelector(`.auth-progress-item[data-apicode="${item.apicode}"]`);
+
+ if (result.timeout) {
+ // 超时
+ if (iconEl) iconEl.textContent = '○';
+ if (statusEl) statusEl.textContent = '已超时';
+ if (progressItem) progressItem.classList.add('timeout');
+ } else if (result.status === AUTH_STATUS.APPLY_FAIL) {
+ // 失败
+ if (iconEl) iconEl.textContent = '✗';
+ if (statusEl) statusEl.textContent = '失败';
+ if (progressItem) progressItem.classList.add('failed');
+ } else {
+ // 成功
+ if (iconEl) iconEl.textContent = '✓';
+ if (statusEl) statusEl.textContent = '已完成';
+ if (progressItem) progressItem.classList.add('completed');
+ }
+ },
+
+ // 全部完成
+ onAllComplete: () => {
+ console.log('[BasicInfoPage] 全部授权完成');
+ this.showAuthComplete(redirectUrl);
+ }
+ });
+ }
+
+ /**
+ * 显示授权完成界面
+ * @param {string} redirectUrl - 跳转 URL
+ */
+ showAuthComplete(redirectUrl) {
+ const container = document.getElementById('authFlowContainer');
+ if (!container) return;
+
+ // 隐藏 iframe 区域,显示完成提示
+ const iframeSection = container.querySelector('.auth-iframe-section');
+ if (iframeSection) {
+ iframeSection.style.display = 'none';
+ }
+
+ // 创建完成提示
+ const completeSection = document.createElement('div');
+ completeSection.className = 'auth-complete-section';
+ completeSection.innerHTML = `
+
✓
+
全部授权完成
+
您的申请已全部提交成功!
+ ${redirectUrl ? `
+
+ 5 秒后自动跳转...
+
+
+ ` : `
+
+ `}
+ `;
+
+ container.appendChild(completeSection);
+
+ // 启动倒计时
+ if (redirectUrl) {
+ this.startFinalCountdown(redirectUrl);
+ }
+ }
+
+ /**
+ * 启动最终倒计时
+ * @param {string} redirectUrl - 跳转 URL
+ */
+ startFinalCountdown(redirectUrl) {
+ const countdownEl = document.getElementById('countdownSeconds');
+ const redirectBtn = document.getElementById('redirectNowBtn');
+
+ // 立即跳转按钮
+ if (redirectBtn) {
+ redirectBtn.addEventListener('click', () => {
+ AuthFlowService.redirect(redirectUrl);
});
}
+
+ // 启动倒计时
+ AuthFlowService.startCountdown(
+ AuthFlowService.COUNTDOWN_SECONDS,
+ (remaining) => {
+ if (countdownEl) {
+ countdownEl.textContent = remaining;
+ }
+ },
+ () => {
+ AuthFlowService.redirect(redirectUrl);
+ }
+ );
}
/**
diff --git a/src/js/services/auth-flow.service.js b/src/js/services/auth-flow.service.js
new file mode 100644
index 0000000..656a949
--- /dev/null
+++ b/src/js/services/auth-flow.service.js
@@ -0,0 +1,220 @@
+/**
+ * 授权流程服务
+ * 处理多个 H5 授权页面的逐个加载、轮询检测、超时控制和最终跳转
+ */
+
+import { ApiClient } from '../core/api.js';
+import { API_CONFIG } from '../config/index.js';
+
+// 授权状态常量
+const AUTH_STATUS = {
+ WAITING: 1, // 等待授权
+ CALLBACK: 2, // 已回调
+ APPLY_OK: 3, // 进件成功
+ APPLY_FAIL: 4 // 进件失败
+};
+
+export class AuthFlowService {
+ // 配置常量
+ static POLL_INTERVAL = 3000; // 轮询间隔:3秒
+ static POLL_TIMEOUT = 10 * 60 * 1000; // 超时时间:10分钟
+ static COUNTDOWN_SECONDS = 5; // 倒计时:5秒
+
+ /**
+ * 检查单个 API 的授权状态
+ * @param {number} formdataid - 表单数据ID
+ * @param {string} apicode - API编码
+ * @returns {Promise