205 lines
7.1 KiB
JavaScript
205 lines
7.1 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* 验证双向跳转脚本逻辑(与 index.html / qiming config 内联脚本一致)
|
||
* 用法: node scripts/verify-redirect-logic.mjs
|
||
*/
|
||
|
||
const agentDetailPathMobile = '/pages/agent-detail/agent-detail';
|
||
const chatTempPathMobile = '/pages/chat-temp/chat-temp';
|
||
const newAgentDetailPathMobile = '/subpackages' + agentDetailPathMobile;
|
||
const newChatTempPathMobile = '/subpackages' + chatTempPathMobile;
|
||
|
||
// 应用详情页路径
|
||
const appDetailsPathMobile = '/subpackages/pages/app-details/app-details';
|
||
|
||
function runRedirectLogic(protocol, host, href, hash, userAgent) {
|
||
const baseUrl = protocol + '//' + host;
|
||
const isMobile = /Android|iPhone|iPad|iPod|Mobile|Tablet/i.test(userAgent);
|
||
let replaceUrl = null;
|
||
|
||
const location = {
|
||
get protocol() { return protocol; },
|
||
get host() { return host; },
|
||
get href() { return href; },
|
||
get hash() { return hash; },
|
||
replace(url) { replaceUrl = url; },
|
||
};
|
||
|
||
// 兼容分包前的页面
|
||
if (isMobile && href.includes('/m/#/pages/')) {
|
||
let mHash = hash;
|
||
if (hash.indexOf(agentDetailPathMobile) !== -1) {
|
||
mHash = mHash.replace(agentDetailPathMobile, newAgentDetailPathMobile);
|
||
replaceUrl = baseUrl + '/m/' + mHash;
|
||
return replaceUrl;
|
||
}
|
||
if (hash.indexOf(chatTempPathMobile) !== -1) {
|
||
mHash = mHash.replace(chatTempPathMobile, newChatTempPathMobile);
|
||
replaceUrl = baseUrl + '/m/' + mHash;
|
||
return replaceUrl;
|
||
}
|
||
}
|
||
|
||
// PC 端访问 M 页面 => 跳转 PC
|
||
if (!isMobile && href.includes('/m/')) {
|
||
// 智能体详情页
|
||
if (hash && hash.indexOf(agentDetailPathMobile) !== -1) {
|
||
const matchId = hash.match(new RegExp('[?&]id=([^&#]+)'));
|
||
const matchConversationId = hash.match(new RegExp('[?&]conversationId=([^&#]+)'));
|
||
if (matchId && matchId[1]) {
|
||
const agentId = matchId[1];
|
||
if (matchConversationId && matchConversationId[1]) {
|
||
const conversationId = matchConversationId[1];
|
||
replaceUrl = baseUrl + '/home/chat/' + conversationId + '/' + agentId;
|
||
} else {
|
||
replaceUrl = baseUrl + '/agent/' + agentId;
|
||
}
|
||
return replaceUrl;
|
||
}
|
||
}
|
||
|
||
// 应用详情页
|
||
if (hash && hash.indexOf(appDetailsPathMobile) !== -1) {
|
||
const matchId = hash.match(new RegExp('[?&]id=([^&#]+)'));
|
||
const matchConversationId = hash.match(new RegExp('[?&]conversationId=([^&#]+)'));
|
||
|
||
if (matchId && matchId[1]) {
|
||
const agentId = matchId[1];
|
||
if (matchConversationId && matchConversationId[1]) {
|
||
const conversationId = matchConversationId[1];
|
||
replaceUrl = baseUrl + '/app/chat/' + agentId + '/' + conversationId;
|
||
} else {
|
||
replaceUrl = baseUrl + '/app/' + agentId;
|
||
}
|
||
return replaceUrl;
|
||
}
|
||
}
|
||
|
||
|
||
// 临时会话页
|
||
if (hash && hash.indexOf(chatTempPathMobile) !== -1) {
|
||
const matchChatTemp = hash.match(new RegExp('[?&]chatKey=([^&#]+)'));
|
||
if (matchChatTemp && matchChatTemp[1]) {
|
||
replaceUrl = baseUrl + '/chat-temp/' + matchChatTemp[1];
|
||
return replaceUrl;
|
||
}
|
||
}
|
||
replaceUrl = baseUrl + '/';
|
||
return replaceUrl;
|
||
}
|
||
|
||
// 移动端访问 PC 页面 => 跳转 M
|
||
if (isMobile && !href.includes('/m/')) {
|
||
// 智能体详情页
|
||
const matchAgent = href.match(new RegExp('/agent/([^/?#]+)'));
|
||
if (matchAgent) {
|
||
replaceUrl = baseUrl + '/m/#' + newAgentDetailPathMobile + '?id=' + matchAgent[1];
|
||
return replaceUrl;
|
||
}
|
||
|
||
// 应用会话页 (这里必须要放在应用详情页匹配之前,否则会匹配到应用详情页)
|
||
const matchAppChat = href.match(new RegExp('app/chat/([^/]+)/([^/]+)'));
|
||
if (matchAppChat) {
|
||
const agentId = matchAppChat[1];
|
||
const conversationId = matchAppChat[2];
|
||
replaceUrl = baseUrl + '/m/#' + appDetailsPathMobile + '?id=' + agentId + '&conversationId=' + conversationId;
|
||
return replaceUrl;
|
||
}
|
||
|
||
// 应用详情页
|
||
const matchAppDetails = href.match(new RegExp('/app/([^/?#]+)'));
|
||
if (matchAppDetails) {
|
||
replaceUrl = baseUrl + '/m/#' + appDetailsPathMobile + '?id=' + matchAppDetails[1];
|
||
return replaceUrl;
|
||
}
|
||
|
||
// 临时会话页
|
||
const matchChatTemp = href.match(new RegExp('/chat-temp/([^/?#]+)'));
|
||
if (matchChatTemp) {
|
||
replaceUrl = baseUrl + '/m/#' + newChatTempPathMobile + '?chatKey=' + matchChatTemp[1];
|
||
return replaceUrl;
|
||
}
|
||
const matchHomeChat = href.match(new RegExp('home/chat/([^/]+)/([^/]+)'));
|
||
if (matchHomeChat) {
|
||
const conversationId = matchHomeChat[1];
|
||
const agentId = matchHomeChat[2];
|
||
replaceUrl = baseUrl + '/m/#' + newAgentDetailPathMobile + '?id=' + agentId + '&conversationId=' + conversationId;
|
||
return replaceUrl;
|
||
}
|
||
replaceUrl = baseUrl + '/m/';
|
||
return replaceUrl;
|
||
}
|
||
|
||
return replaceUrl;
|
||
}
|
||
|
||
const base = 'https://testagent.xspaceagi.com';
|
||
|
||
const cases = [
|
||
{
|
||
name: '移动端打开 H5 会话详情 /home/chat/1534879/1602 → M 端会话页',
|
||
protocol: 'https:',
|
||
host: 'testagent.xspaceagi.com',
|
||
href: base + '/home/chat/1534879/1602',
|
||
hash: '',
|
||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15',
|
||
expect: base + '/m/#/subpackages/pages/agent-detail/agent-detail?id=1602&conversationId=1534879',
|
||
},
|
||
{
|
||
name: 'PC 打开 M 端会话链接(带 conversationId)→ /home/chat/conversationId/agentId',
|
||
protocol: 'https:',
|
||
host: 'testagent.xspaceagi.com',
|
||
href: base + '/m/#/subpackages/pages/agent-detail/agent-detail?id=1602&conversationId=1534879',
|
||
hash: '#/subpackages/pages/agent-detail/agent-detail?id=1602&conversationId=1534879',
|
||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0',
|
||
expect: base + '/home/chat/1534879/1602',
|
||
},
|
||
{
|
||
name: 'PC 打开 M 端仅智能体(无 conversationId)→ /agent/agentId',
|
||
protocol: 'https:',
|
||
host: 'testagent.xspaceagi.com',
|
||
href: base + '/m/#/subpackages/pages/agent-detail/agent-detail?id=1602',
|
||
hash: '#/subpackages/pages/agent-detail/agent-detail?id=1602',
|
||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0',
|
||
expect: base + '/agent/1602',
|
||
},
|
||
{
|
||
name: '移动端打开 /agent/1602 → M 端智能体详情(无会话)',
|
||
protocol: 'https:',
|
||
host: 'testagent.xspaceagi.com',
|
||
href: base + '/agent/1602',
|
||
hash: '',
|
||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)',
|
||
expect: base + '/m/#/subpackages/pages/agent-detail/agent-detail?id=1602',
|
||
},
|
||
{
|
||
name: '移动端打开未知 PC 路径 → /m/ 首页',
|
||
protocol: 'https:',
|
||
host: 'testagent.xspaceagi.com',
|
||
href: base + '/other',
|
||
hash: '',
|
||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)',
|
||
expect: base + '/m/',
|
||
},
|
||
];
|
||
|
||
let passed = 0;
|
||
let failed = 0;
|
||
|
||
for (const c of cases) {
|
||
const got = runRedirectLogic(c.protocol, c.host, c.href, c.hash, c.userAgent);
|
||
const ok = got === c.expect;
|
||
if (ok) {
|
||
passed++;
|
||
console.log('✓', c.name);
|
||
} else {
|
||
failed++;
|
||
console.log('✗', c.name);
|
||
console.log(' 期望:', c.expect);
|
||
console.log(' 实际:', got);
|
||
}
|
||
}
|
||
|
||
console.log('\n' + passed + ' 通过, ' + failed + ' 失败');
|
||
process.exit(failed > 0 ? 1 : 0);
|