fix: 修复路由缺少 name 和带有动态参数时菜单搜索功能异常问题

This commit is contained in:
pany 2023-08-15 13:36:54 +08:00
parent 5f0e91c5ec
commit 4a27131c6d
3 changed files with 47 additions and 20 deletions

View File

@ -28,7 +28,7 @@ const searchResultRef = ref<InstanceType<typeof SearchResult> | null>(null)
const keyword = ref<string>("") const keyword = ref<string>("")
const resultList = shallowRef<RouteRecordRaw[]>([]) const resultList = shallowRef<RouteRecordRaw[]>([])
const activeRouteName = ref<RouteRecordName>("") const activeRouteName = ref<RouteRecordName | undefined>(undefined)
/** 是否按下了上键或下键(用于解决和 mouseenter 事件的冲突) */ /** 是否按下了上键或下键(用于解决和 mouseenter 事件的冲突) */
const isPressUpOrDown = ref<boolean>(false) const isPressUpOrDown = ref<boolean>(false)
@ -54,7 +54,7 @@ const handleSearch = debounce(() => {
) )
// //
const length = resultList.value?.length const length = resultList.value?.length
activeRouteName.value = length > 0 ? resultList.value[0].name! : "" activeRouteName.value = length > 0 ? resultList.value[0].name : undefined
}, 500) }, 500)
/** 将树形菜单扁平化为一维数组,用于菜单搜索 */ /** 将树形菜单扁平化为一维数组,用于菜单搜索 */
@ -89,13 +89,22 @@ const handleUp = () => {
isPressUpOrDown.value = true isPressUpOrDown.value = true
const { length } = resultList.value const { length } = resultList.value
if (length === 0) return if (length === 0) return
// name
const index = resultList.value.findIndex((item) => item.name === activeRouteName.value) const index = resultList.value.findIndex((item) => item.name === activeRouteName.value)
//
if (index === 0) { if (index === 0) {
// const bottomName = resultList.value[length - 1].name
activeRouteName.value = resultList.value[length - 1].name! // bottomName 1 name
scrollTo(resultList.value.length - 1) if (activeRouteName.value === bottomName && length > 1) {
activeRouteName.value = resultList.value[length - 2].name
scrollTo(length - 2)
} else { } else {
activeRouteName.value = resultList.value[index - 1].name! //
activeRouteName.value = bottomName
scrollTo(length - 1)
}
} else {
activeRouteName.value = resultList.value[index - 1].name
scrollTo(index - 1) scrollTo(index - 1)
} }
} }
@ -105,13 +114,22 @@ const handleDown = () => {
isPressUpOrDown.value = true isPressUpOrDown.value = true
const { length } = resultList.value const { length } = resultList.value
if (length === 0) return if (length === 0) return
const index = resultList.value.findIndex((item) => item.name === activeRouteName.value) // name name
const index = resultList.value.map((item) => item.name).lastIndexOf(activeRouteName.value)
//
if (index === length - 1) { if (index === length - 1) {
// const topName = resultList.value[0].name
activeRouteName.value = resultList.value[0].name! // topName 1 name
scrollTo(0) if (activeRouteName.value === topName && length > 1) {
activeRouteName.value = resultList.value[1].name
scrollTo(1)
} else { } else {
activeRouteName.value = resultList.value[index + 1].name! //
activeRouteName.value = topName
scrollTo(0)
}
} else {
activeRouteName.value = resultList.value[index + 1].name
scrollTo(index + 1) scrollTo(index + 1)
} }
} }
@ -120,11 +138,17 @@ const handleDown = () => {
const handleEnter = () => { const handleEnter = () => {
const { length } = resultList.value const { length } = resultList.value
if (length === 0) return if (length === 0) return
if (!activeRouteName.value) { const name = activeRouteName.value
ElMessage.error("无法通过搜索功能进入该菜单,请为对应的路由设置唯一的 Name") if (!name) {
ElMessage.warning("无法通过搜索进入该菜单,请为对应的路由设置唯一的 Name")
return
}
try {
router.push({ name })
} catch {
ElMessage.error("该菜单有必填的动态参数,无法通过搜索进入")
return return
} }
router.push({ name: activeRouteName.value })
handleClose() handleClose()
} }

View File

@ -3,14 +3,14 @@ import { computed, getCurrentInstance, onBeforeMount, onBeforeUnmount, onMounted
import { type RouteRecordName, type RouteRecordRaw } from "vue-router" import { type RouteRecordName, type RouteRecordRaw } from "vue-router"
interface Props { interface Props {
modelValue: RouteRecordName modelValue: RouteRecordName | undefined
list: RouteRecordRaw[] list: RouteRecordRaw[]
isPressUpOrDown: boolean isPressUpOrDown: boolean
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<{ const emit = defineEmits<{
"update:modelValue": [RouteRecordName] "update:modelValue": [RouteRecordName | undefined]
}>() }>()
const instance = getCurrentInstance() const instance = getCurrentInstance()
@ -21,7 +21,7 @@ const activeRouteName = computed({
get() { get() {
return props.modelValue return props.modelValue
}, },
set(value: RouteRecordName) { set(value: RouteRecordName | undefined) {
emit("update:modelValue", value) emit("update:modelValue", value)
} }
}) })
@ -39,7 +39,7 @@ const itemStyle = (item: RouteRecordRaw) => {
const handleMouseenter = (item: RouteRecordRaw) => { const handleMouseenter = (item: RouteRecordRaw) => {
// mouseenter // mouseenter
if (props.isPressUpOrDown) return if (props.isPressUpOrDown) return
activeRouteName.value = item.name! activeRouteName.value = item.name
} }
/** 计算滚动可视区高度 */ /** 计算滚动可视区高度 */
@ -91,7 +91,7 @@ defineExpose({ getScrollTop })
<span class="result-item-title"> <span class="result-item-title">
{{ item.meta?.title }} {{ item.meta?.title }}
</span> </span>
<SvgIcon v-if="activeRouteName === item.name" name="keyboard-enter" /> <SvgIcon v-if="activeRouteName && activeRouteName === item.name" name="keyboard-enter" />
</div> </div>
</div> </div>
</template> </template>

View File

@ -4,7 +4,10 @@ import routeSettings from "@/config/route"
const Layouts = () => import("@/layouts/index.vue") const Layouts = () => import("@/layouts/index.vue")
/** 常驻路由 */ /**
*
* redirect/403/404/login Name
*/
export const constantRoutes: RouteRecordRaw[] = [ export const constantRoutes: RouteRecordRaw[] = [
{ {
path: "/redirect", path: "/redirect",