Files
qiming/qiming-mobile/scripts/verify-redirect-logic.mjs

205 lines
7.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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);