240 lines
8.6 KiB
TypeScript
240 lines
8.6 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
||
import { screenAdaptationService } from '../services/screenAdaptationService';
|
||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||
|
||
interface ScreenAdaptationSettingsProps {
|
||
onClose?: () => void;
|
||
}
|
||
|
||
/**
|
||
* 屏幕适配设置组件
|
||
* 允许用户自定义窗口适配参数
|
||
*/
|
||
export const ScreenAdaptationSettings: React.FC<ScreenAdaptationSettingsProps> = ({
|
||
onClose
|
||
}) => {
|
||
const [config, setConfig] = useState(screenAdaptationService.getConfig());
|
||
const [screenInfo, setScreenInfo] = useState<{
|
||
width: number;
|
||
height: number;
|
||
type: string;
|
||
} | null>(null);
|
||
const [currentSize, setCurrentSize] = useState<{
|
||
width: number;
|
||
height: number;
|
||
} | null>(null);
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
useEffect(() => {
|
||
loadScreenInfo();
|
||
loadCurrentSize();
|
||
}, []);
|
||
|
||
const loadScreenInfo = async () => {
|
||
try {
|
||
const { type } = await screenAdaptationService.getScreenTypeConfig();
|
||
// 模拟获取屏幕信息
|
||
const info = {
|
||
width: (globalThis as any).screen?.availWidth || 1920,
|
||
height: (globalThis as any).screen?.availHeight || 1080,
|
||
type: type
|
||
};
|
||
setScreenInfo(info);
|
||
} catch (error) {
|
||
console.error('获取屏幕信息失败:', error);
|
||
}
|
||
};
|
||
|
||
const loadCurrentSize = async () => {
|
||
try {
|
||
const window = getCurrentWindow();
|
||
const size = await window.innerSize();
|
||
setCurrentSize({
|
||
width: size.width,
|
||
height: size.height
|
||
});
|
||
} catch (error) {
|
||
console.error('获取当前窗口尺寸失败:', error);
|
||
}
|
||
};
|
||
|
||
const handleConfigChange = (key: string, value: number) => {
|
||
const newConfig = { ...config, [key]: value };
|
||
setConfig(newConfig);
|
||
screenAdaptationService.updateConfig(newConfig);
|
||
};
|
||
|
||
const handleApplyAdaptation = async () => {
|
||
setLoading(true);
|
||
try {
|
||
await screenAdaptationService.applyScreenAdaptation();
|
||
await loadCurrentSize();
|
||
} catch (error) {
|
||
console.error('应用屏幕适配失败:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleSmartAdaptation = async () => {
|
||
setLoading(true);
|
||
try {
|
||
await screenAdaptationService.applySmartAdaptation();
|
||
setConfig(screenAdaptationService.getConfig());
|
||
await loadCurrentSize();
|
||
} catch (error) {
|
||
console.error('智能适配失败:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const previewSize = screenInfo ? {
|
||
width: Math.floor(screenInfo.width * config.defaultWidthRatio),
|
||
height: Math.floor(screenInfo.height * config.defaultHeightRatio)
|
||
} : null;
|
||
|
||
return (
|
||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||
<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||
<div className="p-6">
|
||
<div className="flex justify-between items-center mb-6">
|
||
<h2 className="text-xl font-semibold text-gray-900">屏幕适配设置</h2>
|
||
{onClose && (
|
||
<button
|
||
onClick={onClose}
|
||
className="text-gray-400 hover:text-gray-600 transition-colors"
|
||
>
|
||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||
</svg>
|
||
</button>
|
||
)}
|
||
</div>
|
||
|
||
{/* 屏幕信息 */}
|
||
{screenInfo && (
|
||
<div className="mb-6 p-4 bg-blue-50 rounded-lg">
|
||
<h3 className="text-sm font-medium text-blue-900 mb-2">屏幕信息</h3>
|
||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||
<div>
|
||
<span className="text-blue-700">屏幕尺寸:</span>
|
||
<span className="ml-2 font-mono">{screenInfo.width} × {screenInfo.height}</span>
|
||
</div>
|
||
<div>
|
||
<span className="text-blue-700">屏幕类型:</span>
|
||
<span className="ml-2 capitalize">{screenInfo.type}</span>
|
||
</div>
|
||
{currentSize && (
|
||
<div>
|
||
<span className="text-blue-700">当前窗口:</span>
|
||
<span className="ml-2 font-mono">{currentSize.width} × {currentSize.height}</span>
|
||
</div>
|
||
)}
|
||
{previewSize && (
|
||
<div>
|
||
<span className="text-blue-700">预览尺寸:</span>
|
||
<span className="ml-2 font-mono">{previewSize.width} × {previewSize.height}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 配置选项 */}
|
||
<div className="space-y-6">
|
||
<div>
|
||
<h3 className="text-lg font-medium text-gray-900 mb-4">窗口尺寸配置</h3>
|
||
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
默认宽度比例 ({Math.round(config.defaultWidthRatio * 100)}%)
|
||
</label>
|
||
<input
|
||
type="range"
|
||
min="0.5"
|
||
max="1"
|
||
step="0.05"
|
||
value={config.defaultWidthRatio}
|
||
onChange={(e) => handleConfigChange('defaultWidthRatio', parseFloat(e.target.value))}
|
||
className="w-full"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
默认高度比例 ({Math.round(config.defaultHeightRatio * 100)}%)
|
||
</label>
|
||
<input
|
||
type="range"
|
||
min="0.5"
|
||
max="1"
|
||
step="0.05"
|
||
value={config.defaultHeightRatio}
|
||
onChange={(e) => handleConfigChange('defaultHeightRatio', parseFloat(e.target.value))}
|
||
className="w-full"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
最小宽度 (px)
|
||
</label>
|
||
<input
|
||
type="number"
|
||
min="600"
|
||
max="1200"
|
||
value={config.minWidth}
|
||
onChange={(e) => handleConfigChange('minWidth', parseInt(e.target.value))}
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
最小高度 (px)
|
||
</label>
|
||
<input
|
||
type="number"
|
||
min="400"
|
||
max="900"
|
||
value={config.minHeight}
|
||
onChange={(e) => handleConfigChange('minHeight', parseInt(e.target.value))}
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 操作按钮 */}
|
||
<div className="flex space-x-4 pt-4 border-t border-gray-200">
|
||
<button
|
||
onClick={handleSmartAdaptation}
|
||
disabled={loading}
|
||
className="flex-1 bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||
>
|
||
{loading ? '应用中...' : '智能适配'}
|
||
</button>
|
||
|
||
<button
|
||
onClick={handleApplyAdaptation}
|
||
disabled={loading}
|
||
className="flex-1 bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||
>
|
||
{loading ? '应用中...' : '应用设置'}
|
||
</button>
|
||
</div>
|
||
|
||
<div className="text-xs text-gray-500 space-y-1">
|
||
<p>• <strong>智能适配</strong>:根据屏幕类型自动选择最佳配置</p>
|
||
<p>• <strong>应用设置</strong>:使用当前自定义配置</p>
|
||
<p>• 设置会在应用重启后保持</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|