feat: 添加搜索框

This commit is contained in:
Baobhan Sith
2025-06-04 18:00:51 +08:00
parent b4442cd4b4
commit d3b21f376b
2 changed files with 56 additions and 7 deletions
@@ -6,12 +6,12 @@
import { ref, onMounted, onBeforeUnmount, watch, shallowRef, computed } from 'vue'; import { ref, onMounted, onBeforeUnmount, watch, shallowRef, computed } from 'vue';
import { EditorState, Compartment } from '@codemirror/state'; import { EditorState, Compartment } from '@codemirror/state';
import { useAppearanceStore } from '../stores/appearance.store'; import { useAppearanceStore } from '../stores/appearance.store';
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightActiveLine, drawSelection, dropCursor } from '@codemirror/view'; import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightActiveLine, drawSelection, dropCursor } from '@codemirror/view';
import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, bracketMatching, foldGutter, foldKeymap } from '@codemirror/language'; import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, bracketMatching, foldGutter, foldKeymap } from '@codemirror/language';
import { vscodeDark } from '@uiw/codemirror-theme-vscode'; import { vscodeDark } from '@uiw/codemirror-theme-vscode';
import { history, historyKeymap, defaultKeymap } from '@codemirror/commands'; import { history, historyKeymap, defaultKeymap } from '@codemirror/commands';
import { autocompletion, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'; import { autocompletion, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
import { highlightSelectionMatches } from '@codemirror/search'; import { highlightSelectionMatches, searchKeymap, openSearchPanel } from '@codemirror/search'; // + Import search functionalities
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@@ -121,11 +121,12 @@ const createEditorState = (doc: string, languageExtension: any) => {
} }
}), }),
keymap.of([ keymap.of([
...closeBracketsKeymap, ...closeBracketsKeymap,
...defaultKeymap, ...defaultKeymap,
...historyKeymap, ...historyKeymap,
...foldKeymap, ...foldKeymap,
{ key: "Mod-s", run: () => { emit('request-save'); return true; } } ...searchKeymap, // + Add search keymap
{ key: "Mod-s", run: () => { emit('request-save'); return true; } }
]), ]),
], ],
}); });
@@ -271,8 +272,15 @@ watch(() => appearanceStore.currentMobileEditorFontSize, (newSize) => {
} }
}); });
const openSearch = () => {
if (view.value) {
openSearchPanel(view.value);
}
};
defineExpose({ defineExpose({
focus: () => view.value?.focus(), focus: () => view.value?.focus(),
openSearch, // + Expose openSearch method
}); });
</script> </script>
@@ -94,6 +94,7 @@ const startHeightPx = ref(0);
const minWidth = 400; // 最小宽度 const minWidth = 400; // 最小宽度
const minHeight = 300; // 最小高度 const minHeight = 300; // 最小高度
const encodingSelectRef = ref<HTMLSelectElement | null>(null); // +++ Ref for the select element +++ const encodingSelectRef = ref<HTMLSelectElement | null>(null); // +++ Ref for the select element +++
const codeMirrorMobileEditorRef = ref<InstanceType<typeof CodeMirrorMobileEditor> | null>(null); // +++ Ref for CodeMirrorMobileEditor +++
// --- 计算属性,用于模板绑定 --- // --- 计算属性,用于模板绑定 ---
const popupStyle = computed(() => { const popupStyle = computed(() => {
@@ -422,6 +423,13 @@ const handleEditorScroll = ({ scrollTop, scrollLeft }: { scrollTop: number; scro
const handleEditorFontSizeUpdate = (newSize: number) => { const handleEditorFontSizeUpdate = (newSize: number) => {
appearanceStore.setEditorFontSize(newSize); appearanceStore.setEditorFontSize(newSize);
}; };
// +++ 打开搜索面板 +++
const handleOpenSearch = () => {
if (codeMirrorMobileEditorRef.value) {
codeMirrorMobileEditorRef.value.openSearch();
}
};
// 关闭弹窗 (保持不变) // 关闭弹窗 (保持不变)
const handleCloseContainer = () => { const handleCloseContainer = () => {
@@ -561,6 +569,17 @@ onBeforeUnmount(() => {
<button @click="handleSaveRequest" :disabled="currentTabIsSaving || currentTabIsLoading || !!currentTabLoadingError || !activeTab" class="save-btn"> <button @click="handleSaveRequest" :disabled="currentTabIsSaving || currentTabIsLoading || !!currentTabLoadingError || !activeTab" class="save-btn">
{{ t('fileManager.actions.save') }} {{ t('fileManager.actions.save') }}
</button> </button>
<!-- +++ 移动端搜索按钮 +++ -->
<button
v-if="props.isMobile && activeTab && !currentTabIsLoading"
@click="handleOpenSearch"
class="search-btn"
:title="t('fileManager.actions.search', 'Search')"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/>
</svg>
</button>
<button v-if="!props.isMobile" @click="handleCloseContainer" class="close-editor-btn" :title="t('fileManager.actions.closeEditor')"></button> <button v-if="!props.isMobile" @click="handleCloseContainer" class="close-editor-btn" :title="t('fileManager.actions.closeEditor')"></button>
</div> </div>
@@ -601,6 +620,7 @@ onBeforeUnmount(() => {
:language="currentTabLanguage" :language="currentTabLanguage"
class="editor-instance" class="editor-instance"
@request-save="handleSaveRequest" @request-save="handleSaveRequest"
ref="codeMirrorMobileEditorRef"
/> />
<!-- 如果容器可见但没有活动标签页 --> <!-- 如果容器可见但没有活动标签页 -->
<div v-else class="editor-placeholder">{{ t('fileManager.selectFileToEdit') }}</div> <div v-else class="editor-placeholder">{{ t('fileManager.selectFileToEdit') }}</div>
@@ -817,6 +837,27 @@ onBeforeUnmount(() => {
background-color: #45a049; background-color: #45a049;
} }
/* +++ 搜索按钮样式 +++ */
.search-btn {
background-color: #555; /* 与其他按钮风格类似 */
color: white;
border: none;
padding: 0.4rem 0.6rem; /* 调整内边距以适应图标 */
cursor: pointer;
border-radius: 3px;
font-size: 0.9em;
display: inline-flex; /* 使图标居中 */
align-items: center;
justify-content: center;
}
.search-btn:hover {
background-color: #666;
}
.search-btn svg {
pointer-events: none; /* 防止 SVG 捕获点击事件 */
}
.save-status { .save-status {
font-size: 0.9em; font-size: 0.9em;
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;