添加 CLAUDE.md 用于 Claude Code 项目导航,包含架构说明和开发规范。 更新 AI 创作客户端至 V4.0,新增后端对接示例项目。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
114 lines
4.7 KiB
HTML
114 lines
4.7 KiB
HTML
<!DOCTYPE html>
|
||
<html><head><meta charset="utf-8"><title>iframe嵌入测试</title>
|
||
<style>
|
||
body { margin: 0; font-family: sans-serif; }
|
||
.bar { background: #7C3AED; color: white; padding: 10px 20px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
||
.bar button { background: white; color: #7C3AED; border: none; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 13px; }
|
||
.bar button:hover { background: #f0f0f0; }
|
||
.bar .label { font-size: 12px; opacity: 0.8; }
|
||
#status { font-size: 12px; margin-left: auto; }
|
||
iframe { width: 100%; height: calc(100vh - 46px); border: none; }
|
||
#log { position: fixed; bottom: 0; right: 0; width: 450px; max-height: 220px; overflow-y: auto; background: rgba(0,0,0,0.9); color: #0f0; font-size: 11px; padding: 8px; font-family: monospace; z-index: 999; border-radius: 8px 0 0 0; }
|
||
</style></head>
|
||
<body>
|
||
<div class="bar">
|
||
<span class="label">企业iframe测试:</span>
|
||
<button onclick="loadPage('')">新建创作</button>
|
||
<button onclick="loadPage('/edit-info/2041081353944043520')">编目(status=3)</button>
|
||
<button onclick="loadPage('/dubbing/2040041094040915968')">配音(status=4)</button>
|
||
<button onclick="expireToken()">模拟token过期</button>
|
||
<span id="status">等待加载...</span>
|
||
</div>
|
||
<iframe id="leai" allow="camera;microphone"></iframe>
|
||
<div id="log"></div>
|
||
|
||
<script>
|
||
const H5 = 'http://localhost:3001';
|
||
const API = 'http://localhost:8080';
|
||
const ORG_ID = 'LESINGLE888888888';
|
||
const APP_SECRET = 'leai_test_secret_2026_abc123xyz';
|
||
const PHONE = '18911223344';
|
||
let currentToken = '';
|
||
|
||
function log(msg) {
|
||
const t = new Date().toLocaleTimeString();
|
||
document.getElementById('log').innerHTML = '<div>[' + t + '] ' + msg + '</div>' + document.getElementById('log').innerHTML;
|
||
}
|
||
|
||
// 换取token(模拟企业后端)
|
||
async function getToken() {
|
||
const res = await fetch(API + '/api/v1/auth/session', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ orgId: ORG_ID, appSecret: APP_SECRET, phone: PHONE })
|
||
});
|
||
const data = await res.json();
|
||
currentToken = data.data.sessionToken;
|
||
log('Token获取: ' + currentToken.substring(0, 20) + '...');
|
||
return currentToken;
|
||
}
|
||
|
||
// 加载iframe页面
|
||
async function loadPage(path) {
|
||
const token = await getToken();
|
||
const url = H5 + path + '?token=' + token + '&orgId=' + ORG_ID + '&phone=' + PHONE + '&embed=1';
|
||
document.getElementById('leai').src = url;
|
||
document.getElementById('status').textContent = '加载: ' + (path || '新建创作');
|
||
log('iframe.src = ' + path + '?token=...');
|
||
}
|
||
|
||
// 模拟token过期(删除Redis中的token)
|
||
async function expireToken() {
|
||
if (!currentToken) { log('还没有token'); return; }
|
||
try {
|
||
// 直接调一个需要认证的接口,用一个假token触发过期
|
||
// 实际是通过Redis DEL,但这里我们通过修改store中的token来模拟
|
||
document.getElementById('leai').contentWindow.postMessage({
|
||
source: 'test', type: 'SIMULATE_EXPIRE'
|
||
}, '*');
|
||
log('已发送模拟过期指令(需手动redis-cli DEL session:token:' + currentToken + ')');
|
||
document.getElementById('status').textContent = '已模拟过期';
|
||
} catch(e) { log('模拟过期失败: ' + e); }
|
||
}
|
||
|
||
// 监听H5的postMessage
|
||
window.addEventListener('message', function(event) {
|
||
var msg = event.data;
|
||
if (!msg || msg.source !== 'leai-creation') return;
|
||
log('<b>收到: ' + msg.type + '</b> ' + JSON.stringify(msg.payload || {}));
|
||
|
||
switch (msg.type) {
|
||
case 'READY':
|
||
document.getElementById('status').textContent = 'H5已就绪';
|
||
break;
|
||
case 'TOKEN_EXPIRED':
|
||
document.getElementById('status').textContent = '刷新Token...';
|
||
log('★ Token过期! 正在刷新...');
|
||
getToken().then(function(newToken) {
|
||
document.getElementById('leai').contentWindow.postMessage({
|
||
source: 'leai-creation', version: 1, type: 'TOKEN_REFRESHED',
|
||
payload: { messageId: msg.payload.messageId, token: newToken, orgId: ORG_ID, phone: PHONE }
|
||
}, '*');
|
||
document.getElementById('status').textContent = 'Token已刷新';
|
||
log('★ Token刷新成功,已回传');
|
||
}).catch(function(e) { log('Token刷新失败: ' + e); });
|
||
break;
|
||
case 'WORK_CREATED':
|
||
document.getElementById('status').textContent = '创作中: ' + msg.payload.workId;
|
||
break;
|
||
case 'WORK_COMPLETED':
|
||
document.getElementById('status').textContent = '完成: ' + msg.payload.workId;
|
||
log('★★★ 创作完成! workId=' + msg.payload.workId);
|
||
break;
|
||
case 'CREATION_ERROR':
|
||
document.getElementById('status').textContent = '失败';
|
||
log('创作失败: ' + msg.payload.message);
|
||
break;
|
||
}
|
||
});
|
||
|
||
// 初始加载新建创作
|
||
loadPage('');
|
||
</script>
|
||
</body></html>
|