Explorar el Código

feat 个人中心,生涯成熟度

sys5923812@126.com hace 1 mes
padre
commit
7b09b55354

+ 206 - 88
src/views/xjc-integratedmachine/components/xjc_keyboard.vue

@@ -5,10 +5,9 @@
 </template>
 
 <script setup>
-    import { ref, onMounted, watch, nextTick } from 'vue'
+    import { ref, onMounted, watch, nextTick, onUnmounted } from 'vue'
     import Keyboard from 'simple-keyboard'
     import 'simple-keyboard/build/css/index.css'
-    import chineseLayout from 'simple-keyboard-layouts/build/layouts/chinese'
 
     const props = defineProps({
         keyboardClass: {
@@ -28,6 +27,7 @@
     const currentLayout = ref('default')
     const isChineseMode = ref(false)
     const isShiftOn = ref(false)
+    const chineseLayoutModule = ref(null)
 
     const displayOptions = {
         '{bksp}': '⌫',
@@ -58,46 +58,147 @@
         ]
     }
 
-    const chineseLayoutConfig = {
-        ...englishLayout,
-        layoutCandidates: chineseLayout.layoutCandidates
+    // 安全的中文布局配置
+    const getChineseLayoutConfig = () => {
+        if (!chineseLayoutModule.value) return englishLayout
+
+        try {
+            // 确保 layoutCandidates 存在且是有效的函数/对象
+            const layoutCandidates = chineseLayoutModule.value.layoutCandidates
+            if (!layoutCandidates) return englishLayout
+
+            return {
+                ...englishLayout,
+                layoutCandidates: typeof layoutCandidates === 'function' ?
+                    layoutCandidates : () => ([])
+            }
+        } catch (error) {
+            console.warn('Chinese layout configuration error:', error)
+            return englishLayout
+        }
     }
 
-    onMounted(() => {
+    // 加载中文布局
+    const loadChineseLayout = async () => {
+        try {
+            const module = await import('simple-keyboard-layouts/build/layouts/chinese')
+            chineseLayoutModule.value = module.default || module
+        } catch (error) {
+            console.warn('Failed to load Chinese layout:', error)
+            chineseLayoutModule.value = null
+        }
+    }
+
+    onMounted(async () => {
+        await loadChineseLayout()
         initializeKeyboard()
     })
 
     function initializeKeyboard() {
-        keyboard.value = new Keyboard(keyboardEl.value, {
-            onChange: input => {
-                emit('onChange', input)
-            },
-            onKeyPress: button => {
-                handleKeyPress(button)
-            },
-            layout: isChineseMode.value ? chineseLayoutConfig : englishLayout,
-            layoutName: currentLayout.value,
-            display: displayOptions,
-            buttonTheme: [
-                {
-                    class: 'hg-function-btn',
-                    buttons: '{bksp} {lock} {enter} {tab} {shift} {clear} {close}'
+        if (!keyboardEl.value) return
+
+        try {
+            // 使用安全的配置
+            const layout = isChineseMode.value ? getChineseLayoutConfig() : englishLayout
+
+            keyboard.value = new Keyboard(keyboardEl.value, {
+                onChange: input => {
+                    emit('onChange', input)
                 },
-                {
-                    class: 'hg-mode-btn',
-                    buttons: '{change}'
+                onKeyPress: button => {
+                    handleKeyPress(button)
                 },
-                {
-                    class: 'hg-space-btn',
-                    buttons: '{space}'
+                layout: layout,
+                layoutName: currentLayout.value,
+                display: displayOptions,
+                buttonTheme: [
+                    {
+                        class: 'hg-function-btn',
+                        buttons: '{bksp} {lock} {enter} {tab} {shift} {clear} {close}'
+                    },
+                    {
+                        class: 'hg-mode-btn',
+                        buttons: '{change}'
+                    },
+                    {
+                        class: 'hg-space-btn',
+                        buttons: '{space}'
+                    }
+                ],
+                mergeDisplay: true,
+                // 关键修复:只在中文模式且布局可用时启用候选词
+                enableLayoutCandidates: isChineseMode.value && !!chineseLayoutModule.value,
+                useMouseEvents: true,
+                physicalKeyboardHighlight: false,
+                syncInstanceInputs: true,
+                preventMouseDownDefault: true,
+                stopMouseDownPropagation: true
+            })
+
+            // 覆盖库中可能出错的方法
+            patchKeyboardMethods()
+
+        } catch (error) {
+            console.error('Keyboard initialization failed:', error)
+            initializeFallbackKeyboard()
+        }
+    }
+
+    // 修复库内部方法
+    function patchKeyboardMethods() {
+        if (!keyboard.value) return
+
+        // 保存原始方法
+        const originalSetInput = keyboard.value.setInput
+        const originalClearInput = keyboard.value.clearInput
+
+        // 重写 setInput 方法,添加错误处理
+        keyboard.value.setInput = function(input) {
+            try {
+                originalSetInput.call(this, input)
+            } catch (error) {
+                console.warn('setInput error:', error)
+                // 尝试安全的设置方式
+                try {
+                    if (this.input && typeof this.input === 'string') {
+                        this.input = input || ''
+                    }
+                } catch (e) {
+                    console.error('Failed to set input:', e)
                 }
-            ],
-            mergeDisplay: true,
-            enableLayoutCandidates: true,
-            useMouseEvents: true,
-            physicalKeyboardHighlight: true,
-            syncInstanceInputs: true
-        })
+            }
+        }
+
+        // 重写 clearInput 方法
+        keyboard.value.clearInput = function() {
+            try {
+                originalClearInput.call(this)
+            } catch (error) {
+                console.warn('clearInput error:', error)
+                try {
+                    if (this.input && typeof this.input === 'string') {
+                        this.input = ''
+                    }
+                } catch (e) {
+                    console.error('Failed to clear input:', e)
+                }
+            }
+        }
+    }
+
+    function initializeFallbackKeyboard() {
+        try {
+            keyboard.value = new Keyboard(keyboardEl.value, {
+                onChange: input => emit('onChange', input),
+                onKeyPress: button => handleKeyPress(button),
+                layout: englishLayout,
+                display: displayOptions,
+                mergeDisplay: true,
+                enableLayoutCandidates: false // 完全禁用候选词
+            })
+        } catch (error) {
+            console.error('Fallback keyboard also failed:', error)
+        }
     }
 
     function handleKeyPress(button) {
@@ -112,7 +213,7 @@
                 break
             case '{clear}':
                 emit('onChange', '')
-                keyboard.value?.clearInput()
+                safeClearInput()
                 break
             case '{shift}':
             case '{lock}':
@@ -121,25 +222,49 @@
         }
     }
 
+    function safeClearInput() {
+        if (!keyboard.value) return
+
+        try {
+            // 直接设置输入为空,避免调用可能出错的方法
+            keyboard.value.input = ''
+            emit('onChange', '')
+        } catch (error) {
+            console.warn('Error clearing input:', error)
+        }
+    }
+
     async function toggleChineseMode() {
-        isChineseMode.value = !isChineseMode.value
+        // 检查中文布局是否可用
+        if (!chineseLayoutModule.value) {
+            console.warn('Chinese layout not available')
+            return
+        }
 
-        // 更新按钮显示文本
+        isChineseMode.value = !isChineseMode.value
         displayOptions['{change}'] = isChineseMode.value ? '英/中' : '中/英'
 
         await nextTick()
 
-        keyboard.value.setOptions({
-            layout: isChineseMode.value ? chineseLayoutConfig : englishLayout,
-            layoutCandidates: isChineseMode.value ? chineseLayout.layoutCandidates : null,
-            display: displayOptions
-        })
-
-        // 强制刷新候选词显示
-        if (isChineseMode.value && keyboard.value.input) {
-            const currentInput = keyboard.value.input
-            keyboard.value.setInput(currentInput + ' ')
-            keyboard.value.setInput(currentInput)
+        if (!keyboard.value) return
+
+        try {
+            keyboard.value.setOptions({
+                layout: isChineseMode.value ? getChineseLayoutConfig() : englishLayout,
+                enableLayoutCandidates: isChineseMode.value,
+                display: displayOptions
+            })
+
+        } catch (error) {
+            console.error('Failed to toggle Chinese mode:', error)
+            // 出错时回退到英文模式
+            isChineseMode.value = false
+            displayOptions['{change}'] = '中/英'
+            keyboard.value.setOptions({
+                layout: englishLayout,
+                enableLayoutCandidates: false,
+                display: displayOptions
+            })
         }
     }
 
@@ -147,20 +272,46 @@
         isShiftOn.value = !isShiftOn.value
         currentLayout.value = isShiftOn.value ? 'shift' : 'default'
 
-        keyboard.value.setOptions({
-            layoutName: currentLayout.value
-        })
+        if (keyboard.value) {
+            try {
+                keyboard.value.setOptions({
+                    layoutName: currentLayout.value
+                })
+            } catch (error) {
+                console.warn('Error toggling shift:', error)
+            }
+        }
     }
 
     watch(() => props.input, (newVal) => {
         if (keyboard.value && newVal !== keyboard.value.input) {
-            keyboard.value.setInput(newVal)
+            try {
+                keyboard.value.setInput(newVal)
+            } catch (error) {
+                console.warn('Error setting input from props:', error)
+            }
+        }
+    })
+
+    onUnmounted(() => {
+        if (keyboard.value) {
+            try {
+                keyboard.value.destroy()
+            } catch (error) {
+                console.warn('Error destroying keyboard:', error)
+            }
         }
     })
 
     defineExpose({
         setInput: (input) => {
-            if (keyboard.value) keyboard.value.setInput(input)
+            if (keyboard.value) {
+                try {
+                    keyboard.value.setInput(input)
+                } catch (error) {
+                    console.warn('Error setting input:', error)
+                }
+            }
         }
     })
 </script>
@@ -196,6 +347,9 @@
         display: flex;
         align-items: center;
         justify-content: center;
+        -webkit-user-select: none;
+        user-select: none;
+        touch-action: manipulation;
     }
 
     :deep(.hg-function-btn) {
@@ -211,40 +365,4 @@
         flex-grow: 1;
         max-width: none !important;
     }
-
-    :deep(.hg-candidate-box) {
-        position: absolute;
-        bottom: calc(100% + 5px);
-        left: 0;
-        width: 100%;
-        background: white;
-        border: 1px solid #ddd;
-        border-radius: 5px;
-        padding: 5px;
-        box-shadow: 0 2px 5px rgba(0,0,0,0.1);
-    }
-
-    :deep(.hg-candidate-box-list) {
-        display: flex;
-        flex-wrap: wrap;
-        justify-content: center;
-        gap: 5px;
-    }
-
-    :deep(.hg-candidate-box-list-item) {
-        padding: 8px 12px;
-        cursor: pointer;
-        border-radius: 3px;
-        background: #f5f5f5;
-        transition: all 0.2s;
-    }
-
-    :deep(.hg-candidate-box-list-item:hover) {
-        background: #e0e0e0;
-    }
-
-    :deep(.hg-candidate-box-list-item.active) {
-        background: #4a8cff;
-        color: white;
-    }
 </style>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 402 - 342
src/views/xjc-integratedmachine/plan/develop_career_plan1.vue