mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 优化选择面板、查找面板交互,添加查找忽略大小写开关(#231)
This commit is contained in:
parent
6aa6acaafa
commit
3450843878
@ -18,6 +18,8 @@ interface SearchTableResult {
|
|||||||
|
|
||||||
type SearchResult = SearchTextResult | SearchTableResult
|
type SearchResult = SearchTextResult | SearchTableResult
|
||||||
|
|
||||||
|
type Modifiers = 'g' | 'gi'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const mainStore = useMainStore()
|
const mainStore = useMainStore()
|
||||||
const slidesStore = useSlidesStore()
|
const slidesStore = useSlidesStore()
|
||||||
@ -29,9 +31,11 @@ export default () => {
|
|||||||
const searchResults = ref<SearchResult[]>([])
|
const searchResults = ref<SearchResult[]>([])
|
||||||
const searchIndex = ref(-1)
|
const searchIndex = ref(-1)
|
||||||
|
|
||||||
|
const modifiers = ref<Modifiers>('g')
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
const textList: SearchResult[] = []
|
const textList: SearchResult[] = []
|
||||||
const matchRegex = new RegExp(searchWord.value, 'g')
|
const matchRegex = new RegExp(searchWord.value, modifiers.value)
|
||||||
const textRegex = /(<([^>]+)>)/g
|
const textRegex = /(<([^>]+)>)/g
|
||||||
|
|
||||||
for (const slide of slides.value) {
|
for (const slide of slides.value) {
|
||||||
@ -116,7 +120,7 @@ export default () => {
|
|||||||
type TextInfoList = ReturnType<typeof getTextInfoList>
|
type TextInfoList = ReturnType<typeof getTextInfoList>
|
||||||
|
|
||||||
const getMatchList = (content: string, keyword: string) => {
|
const getMatchList = (content: string, keyword: string) => {
|
||||||
const reg = new RegExp(keyword, 'g')
|
const reg = new RegExp(keyword, modifiers.value)
|
||||||
const matchList = []
|
const matchList = []
|
||||||
let match = reg.exec(content)
|
let match = reg.exec(content)
|
||||||
while (match) {
|
while (match) {
|
||||||
@ -154,7 +158,7 @@ export default () => {
|
|||||||
|
|
||||||
const highlightTableText = (nodes: NodeListOf<Element>, index: number) => {
|
const highlightTableText = (nodes: NodeListOf<Element>, index: number) => {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
node.innerHTML = node.innerHTML.replace(new RegExp(searchWord.value, 'g'), () => {
|
node.innerHTML = node.innerHTML.replace(new RegExp(searchWord.value, modifiers.value), () => {
|
||||||
return `<mark data-index=${index++}>${searchWord.value}</mark>`
|
return `<mark data-index=${index++}>${searchWord.value}</mark>`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -394,12 +398,14 @@ export default () => {
|
|||||||
searchIndex.value = -1
|
searchIndex.value = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(searchWord, () => {
|
const reset = () => {
|
||||||
searchIndex.value = -1
|
searchIndex.value = -1
|
||||||
searchResults.value = []
|
searchResults.value = []
|
||||||
|
|
||||||
if (!searchWord.value) clearMarks()
|
if (!searchWord.value) clearMarks()
|
||||||
})
|
}
|
||||||
|
|
||||||
|
watch(searchWord, reset)
|
||||||
|
|
||||||
watch(slideIndex, () => {
|
watch(slideIndex, () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -418,14 +424,21 @@ export default () => {
|
|||||||
|
|
||||||
onBeforeUnmount(clearMarks)
|
onBeforeUnmount(clearMarks)
|
||||||
|
|
||||||
|
const toggleModifiers = () => {
|
||||||
|
modifiers.value = modifiers.value === 'g' ? 'gi' : 'g'
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
searchWord,
|
searchWord,
|
||||||
replaceWord,
|
replaceWord,
|
||||||
searchResults,
|
searchResults,
|
||||||
searchIndex,
|
searchIndex,
|
||||||
|
modifiers,
|
||||||
searchNext,
|
searchNext,
|
||||||
searchPrev,
|
searchPrev,
|
||||||
replace,
|
replace,
|
||||||
replaceAll,
|
replaceAll,
|
||||||
|
toggleModifiers,
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,8 +4,8 @@
|
|||||||
<IconBack class="handler-item" :class="{ 'disable': !canUndo }" v-tooltip="'撤销'" @click="undo()" />
|
<IconBack class="handler-item" :class="{ 'disable': !canUndo }" v-tooltip="'撤销'" @click="undo()" />
|
||||||
<IconNext class="handler-item" :class="{ 'disable': !canRedo }" v-tooltip="'重做'" @click="redo()" />
|
<IconNext class="handler-item" :class="{ 'disable': !canRedo }" v-tooltip="'重做'" @click="redo()" />
|
||||||
<Divider type="vertical" style="height: 20px;" />
|
<Divider type="vertical" style="height: 20px;" />
|
||||||
<IconMoveOne class="handler-item" v-tooltip="'选择窗格'" @click="openSelectPanel()" />
|
<IconMoveOne class="handler-item" :class="{ 'active': showSelectPanel }" v-tooltip="'选择窗格'" @click="toggleSelectPanel()" />
|
||||||
<IconSearch class="handler-item" v-tooltip="'查找/替换'" @click="openSraechPanel()" />
|
<IconSearch class="handler-item" :class="{ 'active': showSearchPanel }" v-tooltip="'查找/替换'" @click="toggleSraechPanel()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="add-element-handler">
|
<div class="add-element-handler">
|
||||||
@ -116,7 +116,7 @@ import Popover from '@/components/Popover.vue'
|
|||||||
import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
|
import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
|
||||||
|
|
||||||
const mainStore = useMainStore()
|
const mainStore = useMainStore()
|
||||||
const { creatingElement, creatingCustomShape } = storeToRefs(mainStore)
|
const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel } = storeToRefs(mainStore)
|
||||||
const { canUndo, canRedo } = storeToRefs(useSnapshotStore())
|
const { canUndo, canRedo } = storeToRefs(useSnapshotStore())
|
||||||
|
|
||||||
const { redo, undo } = useHistorySnapshot()
|
const { redo, undo } = useHistorySnapshot()
|
||||||
@ -191,13 +191,13 @@ const drawLine = (line: LinePoolItem) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打开选择面板
|
// 打开选择面板
|
||||||
const openSelectPanel = () => {
|
const toggleSelectPanel = () => {
|
||||||
mainStore.setSelectPanelState(true)
|
mainStore.setSelectPanelState(!showSelectPanel.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开搜索替换面板
|
// 打开搜索替换面板
|
||||||
const openSraechPanel = () => {
|
const toggleSraechPanel = () => {
|
||||||
mainStore.setSearchPanelState(true)
|
mainStore.setSearchPanelState(!showSearchPanel.value)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -289,6 +289,7 @@ const openSraechPanel = () => {
|
|||||||
.handler-item {
|
.handler-item {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
|
|
||||||
|
&.active,
|
||||||
&:not(.disable):hover {
|
&:not(.disable):hover {
|
||||||
background-color: #f1f1f1;
|
background-color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<MoveablePanel
|
<MoveablePanel
|
||||||
class="search-panel"
|
class="search-panel"
|
||||||
:width="300"
|
:width="330"
|
||||||
:height="0"
|
:height="0"
|
||||||
:left="-270"
|
:left="-270"
|
||||||
:top="90"
|
:top="90"
|
||||||
@ -17,8 +17,14 @@
|
|||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span class="count">{{searchIndex + 1}}/{{searchResults.length}}</span>
|
<span class="count">{{searchIndex + 1}}/{{searchResults.length}}</span>
|
||||||
<Divider type="vertical" />
|
<Divider type="vertical" />
|
||||||
<IconLeft class="next-btn left" @click="searchPrev()" />
|
<span class="ignore-case"
|
||||||
<IconRight class="next-btn right" @click="searchNext()" />
|
:class="{ 'active': modifiers === 'g' }"
|
||||||
|
v-tooltip="'忽略大小写'"
|
||||||
|
@click="toggleModifiers()"
|
||||||
|
>Aa</span>
|
||||||
|
<Divider type="vertical" />
|
||||||
|
<IconLeft class="next-btn left" @click="searchPrev()" v-tooltip="'上一个'" />
|
||||||
|
<IconRight class="next-btn right" @click="searchNext()" v-tooltip="'下一个'" />
|
||||||
</template>
|
</template>
|
||||||
</Input>
|
</Input>
|
||||||
<Input class="input" v-model:value="replaceWord" placeholder="输入替换内容" @enter="replace()" v-if="type === 'replace'"></Input>
|
<Input class="input" v-model:value="replaceWord" placeholder="输入替换内容" @enter="replace()" v-if="type === 'replace'"></Input>
|
||||||
@ -53,10 +59,12 @@ const {
|
|||||||
replaceWord,
|
replaceWord,
|
||||||
searchResults,
|
searchResults,
|
||||||
searchIndex,
|
searchIndex,
|
||||||
|
modifiers,
|
||||||
searchNext,
|
searchNext,
|
||||||
searchPrev,
|
searchPrev,
|
||||||
replace,
|
replace,
|
||||||
replaceAll,
|
replaceAll,
|
||||||
|
toggleModifiers,
|
||||||
} = useSearch()
|
} = useSearch()
|
||||||
|
|
||||||
const type = ref<TypeKey>('search')
|
const type = ref<TypeKey>('search')
|
||||||
@ -98,6 +106,15 @@ watch(type, () => {
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.ignore-case {
|
||||||
|
font-size: 12px;
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $themeColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
.next-btn {
|
.next-btn {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user