修复内容: 1. 修复Agent头像显示问题 - 使用真实图片替代emoji 2. 移除ResultPageV2自动跳转行为 3. 删除不符合需求的ResultPageV2组件 4. 修复undefined变量错误(currentTerminalData) 5. 添加缺失的getSimulationData导入 6. 优化ResultModal支持动态内容展示 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
516 lines
17 KiB
JavaScript
516 lines
17 KiB
JavaScript
// 移动端优化组件
|
||
(function() {
|
||
let isMobile = false;
|
||
let isTablet = false;
|
||
let currentOrientation = 'portrait';
|
||
|
||
// 检测设备类型
|
||
function detectDevice() {
|
||
const userAgent = navigator.userAgent.toLowerCase();
|
||
const screenWidth = window.innerWidth;
|
||
const screenHeight = window.innerHeight;
|
||
|
||
// 检测是否为移动设备
|
||
isMobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent) || screenWidth <= 768;
|
||
isTablet = /ipad|android(?!.*mobile)|tablet/i.test(userAgent) || (screenWidth > 768 && screenWidth <= 1024);
|
||
|
||
// 检测屏幕方向
|
||
currentOrientation = screenWidth > screenHeight ? 'landscape' : 'portrait';
|
||
|
||
// 添加设备类到body(确保body存在)
|
||
if (document.body) {
|
||
document.body.classList.remove('mobile', 'tablet', 'desktop', 'portrait', 'landscape');
|
||
document.body.classList.add(
|
||
isMobile ? 'mobile' : isTablet ? 'tablet' : 'desktop',
|
||
currentOrientation
|
||
);
|
||
}
|
||
|
||
return { isMobile, isTablet, currentOrientation };
|
||
}
|
||
|
||
// 添加移动端优化样式
|
||
function addMobileStyles() {
|
||
const style = document.createElement('style');
|
||
style.textContent = `
|
||
/* 移动端基础优化 */
|
||
* {
|
||
-webkit-tap-highlight-color: transparent;
|
||
-webkit-touch-callout: none;
|
||
-webkit-user-select: none;
|
||
-moz-user-select: none;
|
||
-ms-user-select: none;
|
||
user-select: none;
|
||
}
|
||
|
||
/* 允许文本选择 */
|
||
p, h1, h2, h3, h4, h5, h6, span, div, article, section {
|
||
-webkit-user-select: text;
|
||
-moz-user-select: text;
|
||
-ms-user-select: text;
|
||
user-select: text;
|
||
}
|
||
|
||
/* 移动端滚动优化 */
|
||
html {
|
||
-webkit-overflow-scrolling: touch;
|
||
scroll-behavior: smooth;
|
||
}
|
||
|
||
/* 移动端字体优化 */
|
||
body.mobile {
|
||
font-size: 16px; /* 防止iOS缩放 */
|
||
line-height: 1.6;
|
||
-webkit-text-size-adjust: 100%;
|
||
-moz-text-size-adjust: 100%;
|
||
-ms-text-size-adjust: 100%;
|
||
}
|
||
|
||
/* 移动端容器优化 */
|
||
.container {
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
body.mobile .container {
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
body.tablet .container {
|
||
padding-left: 2rem;
|
||
padding-right: 2rem;
|
||
}
|
||
|
||
/* 移动端导航优化 */
|
||
body.mobile #navbar {
|
||
padding: 0.75rem 1rem;
|
||
}
|
||
|
||
body.mobile .nav-container {
|
||
padding: 0.75rem 0;
|
||
}
|
||
|
||
/* 移动端按钮优化 */
|
||
body.mobile button,
|
||
body.mobile .btn {
|
||
min-height: 44px; /* iOS推荐的最小触摸目标 */
|
||
padding: 0.75rem 1.5rem;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* 移动端表单优化 */
|
||
body.mobile input,
|
||
body.mobile textarea,
|
||
body.mobile select {
|
||
min-height: 44px;
|
||
padding: 0.75rem;
|
||
font-size: 16px; /* 防止iOS缩放 */
|
||
border-radius: 8px;
|
||
}
|
||
|
||
/* 移动端卡片优化 */
|
||
body.mobile .card,
|
||
body.mobile .glass-card {
|
||
margin-bottom: 1rem;
|
||
padding: 1rem;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
/* 移动端文字优化 */
|
||
body.mobile h1 {
|
||
font-size: 2rem;
|
||
line-height: 1.2;
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
body.mobile h2 {
|
||
font-size: 1.75rem;
|
||
line-height: 1.3;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
body.mobile h3 {
|
||
font-size: 1.5rem;
|
||
line-height: 1.4;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
body.mobile p {
|
||
font-size: 1rem;
|
||
line-height: 1.6;
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
/* 移动端网格优化 */
|
||
body.mobile .grid {
|
||
grid-template-columns: 1fr;
|
||
gap: 1rem;
|
||
}
|
||
|
||
body.mobile .grid-cols-2,
|
||
body.mobile .grid-cols-3,
|
||
body.mobile .grid-cols-4,
|
||
body.mobile .md\\:grid-cols-2,
|
||
body.mobile .md\\:grid-cols-3,
|
||
body.mobile .lg\\:grid-cols-3 {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
/* 平板端网格优化 */
|
||
body.tablet .grid-cols-3,
|
||
body.tablet .lg\\:grid-cols-3 {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
/* 移动端间距优化 */
|
||
body.mobile .py-16 { padding-top: 3rem; padding-bottom: 3rem; }
|
||
body.mobile .py-12 { padding-top: 2rem; padding-bottom: 2rem; }
|
||
body.mobile .py-8 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
||
body.mobile .mb-12 { margin-bottom: 2rem; }
|
||
body.mobile .mb-8 { margin-bottom: 1.5rem; }
|
||
|
||
/* 移动端图片优化 */
|
||
body.mobile img {
|
||
max-width: 100%;
|
||
height: auto;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
/* 横屏优化 */
|
||
body.mobile.landscape {
|
||
/* 横屏时减少垂直间距 */
|
||
}
|
||
|
||
body.mobile.landscape .py-16 {
|
||
padding-top: 2rem;
|
||
padding-bottom: 2rem;
|
||
}
|
||
|
||
body.mobile.landscape h1 {
|
||
font-size: 1.75rem;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
/* 移动端返回顶部按钮优化 */
|
||
body.mobile #back-to-top {
|
||
bottom: 1.5rem;
|
||
right: 1.5rem;
|
||
}
|
||
|
||
body.mobile .back-to-top-btn {
|
||
width: 3rem;
|
||
height: 3rem;
|
||
}
|
||
|
||
/* 移动端页面加载器优化 */
|
||
body.mobile #page-loader .w-20 {
|
||
width: 4rem;
|
||
height: 4rem;
|
||
}
|
||
|
||
body.mobile #page-loader h1 {
|
||
font-size: 1.25rem;
|
||
}
|
||
|
||
body.mobile #page-loader .w-64 {
|
||
width: 16rem;
|
||
}
|
||
|
||
/* 防止页面缩放 */
|
||
@media screen and (max-width: 768px) {
|
||
html {
|
||
zoom: 1;
|
||
-ms-zoom: 1;
|
||
-webkit-zoom: 1;
|
||
-moz-zoom: 1;
|
||
}
|
||
}
|
||
|
||
/* 触摸设备特定优化 */
|
||
@media (hover: none) and (pointer: coarse) {
|
||
/* 移除hover效果,使用active效果 */
|
||
.hover\\:scale-110:hover {
|
||
transform: none;
|
||
}
|
||
|
||
.hover\\:scale-110:active {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.hover\\:shadow-xl:hover {
|
||
box-shadow: none;
|
||
}
|
||
|
||
.hover\\:shadow-xl:active {
|
||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
||
}
|
||
}
|
||
|
||
/* 安全区域适配(iPhone X等带刘海屏的设备) */
|
||
@supports (padding: max(0px)) {
|
||
body.mobile {
|
||
padding-left: max(1rem, env(safe-area-inset-left));
|
||
padding-right: max(1rem, env(safe-area-inset-right));
|
||
}
|
||
|
||
body.mobile #navbar {
|
||
padding-left: max(1rem, env(safe-area-inset-left));
|
||
padding-right: max(1rem, env(safe-area-inset-right));
|
||
padding-top: max(0.75rem, env(safe-area-inset-top));
|
||
}
|
||
|
||
body.mobile #back-to-top {
|
||
right: max(1.5rem, env(safe-area-inset-right));
|
||
bottom: max(1.5rem, env(safe-area-inset-bottom));
|
||
}
|
||
}
|
||
`;
|
||
document.head.appendChild(style);
|
||
}
|
||
|
||
// 优化图片加载
|
||
function optimizeImages() {
|
||
const images = document.querySelectorAll('img');
|
||
|
||
images.forEach(img => {
|
||
// 添加懒加载
|
||
if (!img.loading) {
|
||
img.loading = 'lazy';
|
||
}
|
||
|
||
// 添加错误处理
|
||
img.addEventListener('error', function() {
|
||
this.style.display = 'none';
|
||
});
|
||
|
||
// 移动端图片优化
|
||
if (isMobile) {
|
||
// 移动端使用较小的图片
|
||
const src = img.src;
|
||
if (src && !src.includes('placeholder')) {
|
||
// 这里可以添加图片压缩逻辑
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 优化触摸事件
|
||
function optimizeTouch() {
|
||
// 添加触摸反馈
|
||
document.addEventListener('touchstart', function(e) {
|
||
const target = e.target;
|
||
if (target.tagName === 'BUTTON' || target.classList.contains('btn') || target.tagName === 'A') {
|
||
target.style.opacity = '0.7';
|
||
}
|
||
}, { passive: true });
|
||
|
||
document.addEventListener('touchend', function(e) {
|
||
const target = e.target;
|
||
if (target.tagName === 'BUTTON' || target.classList.contains('btn') || target.tagName === 'A') {
|
||
setTimeout(() => {
|
||
target.style.opacity = '';
|
||
}, 150);
|
||
}
|
||
}, { passive: true });
|
||
|
||
// 防止双击缩放
|
||
let lastTouchEnd = 0;
|
||
document.addEventListener('touchend', function(event) {
|
||
const now = (new Date()).getTime();
|
||
if (now - lastTouchEnd <= 300) {
|
||
event.preventDefault();
|
||
}
|
||
lastTouchEnd = now;
|
||
}, false);
|
||
}
|
||
|
||
// 处理屏幕方向变化
|
||
function handleOrientationChange() {
|
||
// 延迟执行以确保尺寸更新
|
||
setTimeout(() => {
|
||
detectDevice();
|
||
|
||
// 重新计算布局
|
||
const event = new Event('resize');
|
||
window.dispatchEvent(event);
|
||
|
||
// 滚动到顶部(防止方向变化后位置错乱)
|
||
if (window.scrollY > 100) {
|
||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
}
|
||
}, 100);
|
||
}
|
||
|
||
// 优化键盘弹出时的布局
|
||
function handleKeyboard() {
|
||
if (!isMobile) return;
|
||
|
||
const originalHeight = window.innerHeight;
|
||
let keyboardOpen = false;
|
||
|
||
window.addEventListener('resize', function() {
|
||
const currentHeight = window.innerHeight;
|
||
const heightDifference = originalHeight - currentHeight;
|
||
|
||
// 键盘弹出(高度减少超过150px)
|
||
if (heightDifference > 150 && !keyboardOpen) {
|
||
keyboardOpen = true;
|
||
document.body.classList.add('keyboard-open');
|
||
|
||
// 隐藏导航栏(为输入框腾出空间)
|
||
const navbar = document.getElementById('navbar');
|
||
if (navbar) {
|
||
navbar.style.transform = 'translateY(-100%)';
|
||
}
|
||
|
||
// 隐藏返回顶部按钮
|
||
const backToTop = document.getElementById('back-to-top');
|
||
if (backToTop) {
|
||
backToTop.style.display = 'none';
|
||
}
|
||
}
|
||
// 键盘收起
|
||
else if (heightDifference <= 150 && keyboardOpen) {
|
||
keyboardOpen = false;
|
||
document.body.classList.remove('keyboard-open');
|
||
|
||
// 恢复导航栏
|
||
const navbar = document.getElementById('navbar');
|
||
if (navbar) {
|
||
navbar.style.transform = '';
|
||
}
|
||
|
||
// 恢复返回顶部按钮
|
||
const backToTop = document.getElementById('back-to-top');
|
||
if (backToTop) {
|
||
backToTop.style.display = '';
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 性能优化
|
||
function optimizePerformance() {
|
||
// 使用 Intersection Observer 优化动画
|
||
if ('IntersectionObserver' in window) {
|
||
const observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(entry => {
|
||
if (entry.isIntersecting) {
|
||
entry.target.classList.add('animate-visible');
|
||
}
|
||
});
|
||
}, {
|
||
threshold: 0.1,
|
||
rootMargin: '50px'
|
||
});
|
||
|
||
// 观察所有动画元素
|
||
document.querySelectorAll('[class*="animate-"]').forEach(el => {
|
||
if (!el.classList.contains('animate-visible')) {
|
||
observer.observe(el);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 移动端减少动画
|
||
if (isMobile) {
|
||
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||
if (mediaQuery.matches) {
|
||
document.body.classList.add('reduce-motion');
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加调试信息(开发环境)
|
||
function addDebugInfo() {
|
||
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
|
||
const debugInfo = document.createElement('div');
|
||
debugInfo.style.cssText = `
|
||
position: fixed;
|
||
top: 70px;
|
||
right: 10px;
|
||
background: rgba(0,0,0,0.8);
|
||
color: white;
|
||
padding: 8px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
z-index: 10000;
|
||
font-family: monospace;
|
||
`;
|
||
|
||
function updateDebugInfo() {
|
||
const { isMobile, isTablet, currentOrientation } = detectDevice();
|
||
debugInfo.innerHTML = `
|
||
${window.innerWidth}×${window.innerHeight}<br>
|
||
${isMobile ? 'Mobile' : isTablet ? 'Tablet' : 'Desktop'}<br>
|
||
${currentOrientation}
|
||
`;
|
||
}
|
||
|
||
updateDebugInfo();
|
||
document.body.appendChild(debugInfo);
|
||
|
||
window.addEventListener('resize', updateDebugInfo);
|
||
window.addEventListener('orientationchange', updateDebugInfo);
|
||
}
|
||
}
|
||
|
||
// 初始化移动端优化
|
||
function init() {
|
||
// 检测设备类型
|
||
detectDevice();
|
||
|
||
// 添加移动端样式
|
||
addMobileStyles();
|
||
|
||
// 优化触摸体验
|
||
optimizeTouch();
|
||
|
||
// 处理屏幕方向变化
|
||
window.addEventListener('orientationchange', handleOrientationChange);
|
||
window.addEventListener('resize', () => {
|
||
setTimeout(detectDevice, 100);
|
||
});
|
||
|
||
// 页面加载完成后的优化
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
setTimeout(() => {
|
||
optimizeImages();
|
||
handleKeyboard();
|
||
optimizePerformance();
|
||
addDebugInfo();
|
||
}, 500);
|
||
});
|
||
} else {
|
||
setTimeout(() => {
|
||
optimizeImages();
|
||
handleKeyboard();
|
||
optimizePerformance();
|
||
addDebugInfo();
|
||
}, 500);
|
||
}
|
||
|
||
// 监听页面加载完成事件
|
||
document.addEventListener('pageLoaded', () => {
|
||
setTimeout(() => {
|
||
optimizeImages();
|
||
optimizePerformance();
|
||
}, 100);
|
||
});
|
||
}
|
||
|
||
// 提供外部接口
|
||
window.MobileOptimize = {
|
||
detectDevice,
|
||
isMobile: () => isMobile,
|
||
isTablet: () => isTablet,
|
||
getCurrentOrientation: () => currentOrientation,
|
||
optimizeImages,
|
||
optimizePerformance
|
||
};
|
||
|
||
// 初始化
|
||
init();
|
||
})(); |