diff --git a/src/utils/systemInfo.js b/src/utils/systemInfo.js
new file mode 100644
index 00000000..fe1fe00a
--- /dev/null
+++ b/src/utils/systemInfo.js
@@ -0,0 +1,475 @@
+// 浏览器信息检测
+class SystemInfo {
+ constructor() {
+ this.info = {
+ browser: this.getBrowserInfo(),
+ os: this.getOSInfo(),
+ hardware: this.getHardwareInfo(),
+ webgl: this.getWebGLInfo()
+ };
+ }
+
+ // 获取浏览器信息
+ getBrowserInfo() {
+ const ua = navigator.userAgent;
+ let browser = {
+ name: 'Unknown',
+ version: 'Unknown',
+ fullVersion: navigator.appVersion
+ };
+
+ // 检测浏览器类型
+ if (ua.includes('Firefox')) {
+ browser.name = 'Firefox';
+ browser.version = this.extractVersion(ua, 'Firefox');
+ } else if (ua.includes('Chrome') && !ua.includes('Edg') && !ua.includes('OPR')) {
+ browser.name = 'Chrome';
+ browser.version = this.extractVersion(ua, 'Chrome');
+ } else if (ua.includes('Safari') && !ua.includes('Chrome')) {
+ browser.name = 'Safari';
+ browser.version = this.extractVersion(ua, 'Version');
+ } else if (ua.includes('Edg')) {
+ browser.name = 'Edge';
+ browser.version = this.extractVersion(ua, 'Edg');
+ } else if (ua.includes('OPR') || ua.includes('Opera')) {
+ browser.name = 'Opera';
+ browser.version = this.extractVersion(ua, 'OPR') || this.extractVersion(ua, 'Opera');
+ } else if (ua.includes('Trident') || ua.includes('MSIE')) {
+ browser.name = 'Internet Explorer';
+ browser.version = this.extractVersion(ua, 'MSIE') || this.extractVersion(ua, 'rv:');
+ }
+
+ return browser;
+ }
+
+ // 提取版本号
+ extractVersion(userAgent, browserName) {
+ const match = userAgent.match(new RegExp(`${browserName}/([0-9]+(\\.[0-9]+)?)`));
+ return match ? match[1] : 'Unknown';
+ }
+
+ // 获取操作系统信息
+ getOSInfo() {
+ const ua = navigator.userAgent;
+ let os = {
+ name: 'Unknown',
+ version: 'Unknown',
+ architecture: this.getArchitecture()
+ };
+
+ if (ua.includes('Windows')) {
+ os.name = 'Windows';
+ if (ua.includes('Windows NT 10.0')) os.version = '10';
+ else if (ua.includes('Windows NT 6.3')) os.version = '8.1';
+ else if (ua.includes('Windows NT 6.2')) os.version = '8';
+ else if (ua.includes('Windows NT 6.1')) os.version = '7';
+ else if (ua.includes('Windows NT 6.0')) os.version = 'Vista';
+ else if (ua.includes('Windows NT 5.1')) os.version = 'XP';
+ } else if (ua.includes('Mac OS X')) {
+ os.name = 'macOS';
+ const match = ua.match(/Mac OS X (\d+[._]\d+)/);
+ if (match) os.version = match[1].replace('_', '.');
+ } else if (ua.includes('Linux')) {
+ os.name = 'Linux';
+ } else if (ua.includes('Android')) {
+ os.name = 'Android';
+ const match = ua.match(/Android ([0-9.]+)/);
+ if (match) os.version = match[1];
+ } else if (ua.includes('like Mac')) {
+ os.name = 'iOS';
+ const match = ua.match(/OS (\d+[_]\d+)/);
+ if (match) os.version = match[1].replace('_', '.');
+ }
+
+ return os;
+ }
+
+ // 获取系统架构
+ getArchitecture() {
+ if (navigator.userAgent.includes('x64') || navigator.userAgent.includes('x86_64')) {
+ return '64-bit';
+ } else if (navigator.userAgent.includes('x86') || navigator.userAgent.includes('i686')) {
+ return '32-bit';
+ } else if (navigator.userAgent.includes('ARM')) {
+ return 'ARM';
+ } else if (navigator.userAgent.includes('Win64')) {
+ return '64-bit';
+ }
+ return 'Unknown';
+ }
+
+ // 获取硬件信息
+ getHardwareInfo() {
+ return {
+ logicalCores: navigator.hardwareConcurrency || 'Unknown',
+ deviceMemory: navigator.deviceMemory ? `${navigator.deviceMemory} GB` : 'Unknown',
+ maxTouchPoints: navigator.maxTouchPoints || 0
+ };
+ }
+
+ // 获取WebGL和显卡信息
+ getWebGLInfo() {
+ const webglInfo = {
+ webgl1: this.getWebGLContextInfo('webgl'),
+ webgl2: this.getWebGLContextInfo('webgl2'),
+ supported: false,
+ renderer: 'Unknown',
+ vendor: 'Unknown',
+ version: 'Unknown',
+ shadingLanguage: 'Unknown',
+ extensions: []
+ };
+
+ const canvas = document.createElement('canvas');
+ let gl = null;
+
+ // 尝试获取WebGL2上下文
+ try {
+ gl = canvas.getContext('webgl2') || canvas.getContext('experimental-webgl2');
+ } catch (e) {
+ console.log('WebGL2 not supported:', e.message);
+ }
+
+ // 如果WebGL2不可用,尝试WebGL1
+ if (!gl) {
+ try {
+ gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
+ } catch (e) {
+ console.log('WebGL not supported:', e.message);
+ }
+ }
+
+ if (gl) {
+ webglInfo.supported = true;
+
+ // 获取显卡信息
+ const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
+ if (debugInfo) {
+ webglInfo.renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || 'Unknown';
+ webglInfo.vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || 'Unknown';
+ }
+
+ // 获取WebGL版本信息
+ webglInfo.version = gl.getParameter(gl.VERSION) || 'Unknown';
+ webglInfo.shadingLanguage = gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || 'Unknown';
+
+ // 获取支持的扩展
+ try {
+ webglInfo.extensions = gl.getSupportedExtensions() || [];
+ } catch (e) {
+ console.log('无法获取WebGL扩展:', e.message);
+ }
+
+ // 检查GPU性能级别
+ webglInfo.performance = this.getGPUPerformanceInfo(gl);
+
+ // 检查内存信息(如果支持)
+ webglInfo.memoryInfo = this.getGPUMemoryInfo(gl);
+
+ // 检查是否使用集成显卡
+ if (webglInfo.renderer) {
+ webglInfo.gpuType = this.detectGPUType(webglInfo.renderer);
+ }
+ }
+
+ return webglInfo;
+ }
+
+ // 获取WebGL上下文的具体信息
+ getWebGLContextInfo(contextType) {
+ const canvas = document.createElement('canvas');
+ let gl = null;
+
+ try {
+ gl = canvas.getContext(contextType) ||
+ canvas.getContext(`experimental-${contextType}`);
+ } catch (e) {
+ return { supported: false, error: e.message };
+ }
+
+ if (!gl) {
+ return { supported: false };
+ }
+
+ return {
+ supported: true,
+ context: gl
+ };
+ }
+
+ // 获取GPU性能信息
+ getGPUPerformanceInfo(gl) {
+ const info = { tier: 'unknown', features: [] };
+
+ // 检查是否支持高性能特性
+ try {
+ // 检查帧缓冲
+ if (gl.checkFramebufferStatus) {
+ info.features.push('framebuffer');
+ }
+
+ // 检查浮点纹理
+ const floatExt = gl.getExtension('OES_texture_float') ||
+ gl.getExtension('EXT_color_buffer_float');
+ if (floatExt) info.features.push('float_textures');
+
+ // 检查多重采样
+ const msaaExt = gl.getExtension('WEBGL_multisampled_render_to_texture');
+ if (msaaExt) info.features.push('msaa');
+
+ // 检查实例化渲染
+ const instancingExt = gl.getExtension('ANGLE_instanced_arrays') ||
+ gl.getExtension('WEBGL_draw_buffers');
+ if (instancingExt) info.features.push('instancing');
+
+ // 尝试检测性能级别(基于支持的扩展)
+ if (info.features.includes('float_textures') &&
+ info.features.includes('msaa') &&
+ info.features.includes('instancing')) {
+ info.tier = 'high';
+ } else if (info.features.length >= 2) {
+ info.tier = 'medium';
+ } else {
+ info.tier = 'low';
+ }
+ } catch (e) {
+ console.log('获取GPU性能信息失败:', e);
+ }
+
+ return info;
+ }
+
+ // 获取GPU内存信息
+ getGPUMemoryInfo(gl) {
+ const memoryInfo = { estimatedMemory: 'Unknown' };
+
+ // 尝试通过扩展获取内存信息
+ try {
+ // 检查是否支持内存信息扩展
+ const memoryExt = gl.getExtension('WEBGL_debug_renderer_info');
+ if (memoryExt) {
+ // 一些浏览器会通过UNMASKED_RENDERER_WEBGL暴露内存信息
+ const renderer = gl.getParameter(memoryExt.UNMASKED_RENDERER_WEBGL);
+ if (renderer) {
+ // 尝试从渲染器字符串中提取内存信息
+ const match = renderer.match(/(\d+)\s*MB|(\d+)\s*GB|VRAM\s*:\s*(\d+)/i);
+ if (match) {
+ memoryInfo.estimatedMemory = match[0];
+ }
+ }
+ }
+
+ // 通过创建大纹理测试内存
+ memoryInfo.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
+ memoryInfo.maxRenderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
+ } catch (e) {
+ // 静默失败
+ }
+
+ return memoryInfo;
+ }
+
+ // 检测GPU类型
+ detectGPUType(renderer) {
+ const r = renderer.toLowerCase();
+
+ if (r.includes('nvidia') || r.includes('geforce') || r.includes('gtx') || r.includes('rtx')) {
+ return { type: 'NVIDIA', discrete: true };
+ } else if (r.includes('amd') || r.includes('radeon') || r.includes('rx')) {
+ return { type: 'AMD', discrete: true };
+ } else if (r.includes('intel') || r.includes('hd graphics') || r.includes('iris') || r.includes('uhd')) {
+ return { type: 'Intel', discrete: false };
+ } else if (r.includes('apple') || r.includes('apple gpu') || r.includes('apple m')) {
+ return { type: 'Apple Silicon', discrete: false };
+ } else if (r.includes('mali') || r.includes('adreno') || r.includes('powervr')) {
+ return { type: 'Mobile GPU', discrete: false };
+ } else if (r.includes('microsoft') || r.includes('basic')) {
+ return { type: 'Software Renderer', discrete: false };
+ }
+
+ return { type: 'Unknown', discrete: false };
+ }
+
+ // 获取屏幕信息
+ getScreenInfo() {
+ return {
+ width: window.screen.width,
+ height: window.screen.height,
+ colorDepth: window.screen.colorDepth,
+ pixelDepth: window.screen.pixelDepth,
+ devicePixelRatio: window.devicePixelRatio || 1,
+ orientation: window.screen.orientation ? window.screen.orientation.type : 'unknown'
+ };
+ }
+
+ // 获取所有系统信息
+ getAllInfo() {
+ return {
+ ...this.info,
+ screen: this.getScreenInfo(),
+ userAgent: navigator.userAgent,
+ platform: navigator.platform,
+ language: navigator.language,
+ languages: navigator.languages,
+ cookiesEnabled: navigator.cookieEnabled,
+ online: navigator.onLine,
+ javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false,
+ pdfViewerEnabled: navigator.pdfViewerEnabled || false,
+ doNotTrack: navigator.doNotTrack || 'unknown',
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
+ dateTimeFormat: new Date().toString()
+ };
+ }
+
+ // 格式化输出
+ formatAsText() {
+ const info = this.getAllInfo();
+ let output = '========== 系统信息 ==========\n\n';
+
+ // 浏览器信息
+ output += '=== 浏览器信息 ===\n';
+ output += `浏览器: ${info.browser.name} ${info.browser.version}\n`;
+ output += `完整版本: ${info.browser.fullVersion}\n`;
+ output += `用户代理: ${info.userAgent}\n\n`;
+
+ // 操作系统信息
+ output += '=== 操作系统信息 ===\n';
+ output += `系统: ${info.os.name} ${info.os.version}\n`;
+ output += `架构: ${info.os.architecture}\n`;
+ output += `平台: ${info.platform}\n\n`;
+
+ // 硬件信息
+ output += '=== 硬件信息 ===\n';
+ output += `逻辑核心数: ${info.hardware.logicalCores}\n`;
+ output += `设备内存: ${info.hardware.deviceMemory}\n`;
+ output += `最大触摸点数: ${info.hardware.maxTouchPoints}\n\n`;
+
+ // 屏幕信息
+ output += '=== 屏幕信息 ===\n';
+ output += `分辨率: ${info.screen.width} × ${info.screen.height}\n`;
+ output += `设备像素比: ${info.screen.devicePixelRatio}\n`;
+ output += `颜色深度: ${info.screen.colorDepth} 位\n`;
+ output += `像素深度: ${info.screen.pixelDepth} 位\n`;
+ output += `方向: ${info.screen.orientation}\n\n`;
+
+ // WebGL信息
+ output += '=== WebGL 信息 ===\n';
+ output += `WebGL 支持: ${info.webgl.supported ? '是' : '否'}\n`;
+
+ if (info.webgl.supported) {
+ output += `WebGL 版本: ${info.webgl.version}\n`;
+ output += `显卡型号: ${info.webgl.renderer}\n`;
+ output += `显卡厂商: ${info.webgl.vendor}\n`;
+ output += `着色语言: ${info.webgl.shadingLanguage}\n`;
+
+ if (info.webgl.gpuType) {
+ output += `GPU 类型: ${info.webgl.gpuType.type}\n`;
+ output += `独立显卡: ${info.webgl.gpuType.discrete ? '是' : '否'}\n`;
+ }
+
+ output += `性能等级: ${info.webgl.performance.tier}\n`;
+ output += `支持特性: ${info.webgl.performance.features.join(', ')}\n`;
+
+ if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') {
+ output += `显存估计: ${info.webgl.memoryInfo.estimatedMemory}\n`;
+ }
+
+ if (info.webgl.memoryInfo.maxTextureSize) {
+ output += `最大纹理尺寸: ${info.webgl.memoryInfo.maxTextureSize}\n`;
+ }
+
+ output += `WebGL 扩展数: ${info.webgl.extensions.length}\n`;
+ }
+
+ // 其他信息
+ output += '\n=== 其他信息 ===\n';
+ output += `语言: ${info.language}\n`;
+ output += `支持语言: ${info.languages.join(', ')}\n`;
+ output += `时区: ${info.timezone}\n`;
+ output += `Cookie 支持: ${info.cookiesEnabled ? '是' : '否'}\n`;
+ output += `在线状态: ${info.online ? '在线' : '离线'}\n`;
+ output += `Java 支持: ${info.javaEnabled ? '是' : '否'}\n`;
+ output += `PDF 查看器: ${info.pdfViewerEnabled ? '支持' : '不支持'}\n`;
+ output += `Do Not Track: ${info.doNotTrack}\n`;
+ output += `当前时间: ${info.dateTimeFormat}\n`;
+
+ return output;
+ }
+
+ // 创建HTML显示
+ createInfoHTML() {
+ const info = this.getAllInfo();
+ let html = `
+
+
系统信息
+
+
+
🌐 浏览器信息
+
+ | 浏览器 | ${info.browser.name} ${info.browser.version} |
+ | 用户代理 | ${info.userAgent} |
+ | 平台 | ${info.platform} |
+
+
+
+
+
💻 操作系统
+
+ | 系统 | ${info.os.name} ${info.os.version} |
+ | 架构 | ${info.os.architecture} |
+ | 语言 | ${info.language} |
+ | 时区 | ${info.timezone} |
+
+
+
+
+
🖥️ 硬件信息
+
+ | CPU 核心数 | ${info.hardware.logicalCores} |
+ | 设备内存 | ${info.hardware.deviceMemory} |
+ | 屏幕分辨率 | ${info.screen.width} × ${info.screen.height} |
+ | 设备像素比 | ${info.screen.devicePixelRatio} |
+
+
+ `;
+
+ if (info.webgl.supported) {
+ html += `
+
+
🎮 WebGL & 显卡信息
+
+ | WebGL 支持 | ✅ 已支持 |
+ | WebGL 版本 | ${info.webgl.version} |
+ | 显卡型号 | ${info.webgl.renderer} |
+ | 显卡厂商 | ${info.webgl.vendor} |
+ | GPU 类型 | ${info.webgl.gpuType.type} ${info.webgl.gpuType.discrete ? '(独立显卡)' : '(集成显卡)'} |
+ | 着色语言 | ${info.webgl.shadingLanguage} |
+ | 性能等级 | ${info.webgl.performance.tier} |
+ | WebGL 扩展数 | ${info.webgl.extensions.length} 个 |
+ `;
+
+ if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') {
+ html += `| 显存估计 | ${info.webgl.memoryInfo.estimatedMemory} |
`;
+ }
+
+ html += `
`;
+ } else {
+ html += `
+
+
🎮 WebGL & 显卡信息
+
❌ WebGL 不支持
+
+ `;
+ }
+
+ html += `
`;
+
+ return html;
+ }
+}
+
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = SystemInfo;
+} else if (typeof window !== 'undefined') {
+ window.SystemInfo = SystemInfo;
+}
\ No newline at end of file
diff --git a/src/views/dictionary/template/browser/tip.vue b/src/views/dictionary/template/browser/tip.vue
index 5e380a6e..a88e10d1 100644
--- a/src/views/dictionary/template/browser/tip.vue
+++ b/src/views/dictionary/template/browser/tip.vue
@@ -6,12 +6,13 @@
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
index f76e71b5..e82995b7 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
@@ -498,6 +498,7 @@ import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils"
import readingChart from '@/components/readingChart'
+import SystemInfo from "@/utils/systemInfo";
const { visibility } = annotation
const { ViewportType, Events } = Enums
const renderingEngineId = 'myRenderingEngine'
@@ -3289,8 +3290,11 @@ export default {
}
const series = data ? data : this.$refs[`viewport-${this.activeViewportIndex}`][0].series
if (series.ImageIds.length <= 5) return this.$confirm(this.$t('trials:reading:confirm:smallNumberOfimage'))
+ if (series.ImageIds.length > 500) {
+ let res = await this.getSystemInfo()
+ if (!res) return false
+ }
this.isMPR = true
- console.log(series, 'series')
this.rows = 3
this.cols = 1
this.loading = true
@@ -3315,11 +3319,15 @@ export default {
if (!confirm) return false
this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].removeAllNoSaveAnnotation()
}
+ const { ct, pt } = data
+ if (ct.ImageIds.length > 400) {
+ let res = await this.getSystemInfo()
+ if (!res) return false
+ }
this.fusionVisible = false
this.isFusion = true
this.rows = 2
this.cols = 2
- const { ct, pt } = data
this.loading = true
this.loadingText = this.$t('trials:lugano:message:loadVolumes')
this.renderedTaskIds = []
@@ -3456,6 +3464,23 @@ export default {
this.uploadStatus = status
this[`${status}ImageVisible`] = true
},
+ getSystemInfo() {
+ return new Promise(async resolve => {
+ const systemInfo = new SystemInfo();
+ const allInfo = systemInfo.getAllInfo();
+ let deviceMemory = allInfo.hardware.deviceMemory; // 设备内存
+ let { width, height } = allInfo.screen; // 分辨率
+ let discrete = allInfo.webgl.gpuType.discrete; // 是否独立显卡
+ let estimatedMemory = allInfo.webgl.memoryInfo.estimatedMemory; // 显卡内存
+ if (parseFloat(deviceMemory) < 16 || width < 1920 || height < 1080 || !discrete || parseFloat(estimatedMemory) < 2) {
+ let res = await this.$confirm(this.$t('browser:tip:ReadingConfiguration'))
+ resolve(res)
+ } else {
+ resolve(true)
+ }
+
+ })
+ },
},
beforeDestroy() {
DicomEvent.$off('isCanActiveNoneDicomTool')