From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/components/AppLinkInput/AppLinkSelectDialog.vue | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 211 insertions(+), 0 deletions(-)
diff --git a/src/components/AppLinkInput/AppLinkSelectDialog.vue b/src/components/AppLinkInput/AppLinkSelectDialog.vue
new file mode 100644
index 0000000..5211f74
--- /dev/null
+++ b/src/components/AppLinkInput/AppLinkSelectDialog.vue
@@ -0,0 +1,211 @@
+<template>
+ <Dialog v-model="dialogVisible" title="閫夋嫨閾炬帴" width="65%">
+ <div class="h-500px flex gap-8px">
+ <!-- 宸︿晶鍒嗙粍鍒楄〃 -->
+ <el-scrollbar wrap-class="h-full" ref="groupScrollbar" view-class="flex flex-col">
+ <el-button
+ v-for="(group, groupIndex) in APP_LINK_GROUP_LIST"
+ :key="groupIndex"
+ :class="[
+ 'm-r-16px m-l-0px! justify-start! w-90px',
+ { active: activeGroup === group.name }
+ ]"
+ ref="groupBtnRefs"
+ :text="activeGroup !== group.name"
+ :type="activeGroup === group.name ? 'primary' : 'default'"
+ @click="handleGroupSelected(group.name)"
+ >
+ {{ group.name }}
+ </el-button>
+ </el-scrollbar>
+ <!-- 鍙充晶閾炬帴鍒楄〃 -->
+ <el-scrollbar class="h-full flex-1" @scroll="handleScroll" ref="linkScrollbar">
+ <div v-for="(group, groupIndex) in APP_LINK_GROUP_LIST" :key="groupIndex">
+ <!-- 鍒嗙粍鏍囬 -->
+ <div class="font-bold" ref="groupTitleRefs">{{ group.name }}</div>
+ <!-- 閾炬帴鍒楄〃 -->
+ <el-tooltip
+ v-for="(appLink, appLinkIndex) in group.links"
+ :key="appLinkIndex"
+ :content="appLink.path"
+ placement="bottom"
+ :show-after="300"
+ >
+ <el-button
+ class="m-b-8px m-r-8px m-l-0px!"
+ :type="isSameLink(appLink.path, activeAppLink.path) ? 'primary' : 'default'"
+ @click="handleAppLinkSelected(appLink)"
+ >
+ {{ appLink.name }}
+ </el-button>
+ </el-tooltip>
+ </div>
+ </el-scrollbar>
+ </div>
+ <!-- 搴曢儴瀵硅瘽妗嗘搷浣滄寜閽� -->
+ <template #footer>
+ <el-button type="primary" @click="handleSubmit">纭� 瀹�</el-button>
+ <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+ </template>
+ </Dialog>
+ <Dialog v-model="detailSelectDialog.visible" title="" width="50%">
+ <el-form class="min-h-200px">
+ <el-form-item
+ label="閫夋嫨鍒嗙被"
+ v-if="detailSelectDialog.type === APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST"
+ >
+ <ProductCategorySelect
+ v-model="detailSelectDialog.id"
+ :parent-id="0"
+ @update:model-value="handleProductCategorySelected"
+ />
+ </el-form-item>
+ </el-form>
+ </Dialog>
+</template>
+<script lang="ts" setup>
+import { APP_LINK_GROUP_LIST, APP_LINK_TYPE_ENUM, AppLink } from './data'
+import { ButtonInstance, ScrollbarInstance } from 'element-plus'
+import { split } from 'lodash-es'
+import ProductCategorySelect from '@/views/mall/product/category/components/ProductCategorySelect.vue'
+import { getUrlNumberValue } from '@/utils'
+
+// APP 閾炬帴閫夋嫨寮规
+defineOptions({ name: 'AppLinkSelectDialog' })
+// 閫変腑鐨勫垎缁勶紝榛樿閫変腑绗竴涓�
+const activeGroup = ref(APP_LINK_GROUP_LIST[0].name)
+// 閫変腑鐨� APP 閾炬帴
+const activeAppLink = ref({} as AppLink)
+
+/** 鎵撳紑寮圭獥 */
+const dialogVisible = ref(false)
+const open = (link: string) => {
+ // 杩涘叆椤甸潰鏃跺厛閲嶇疆 activeAppLink
+ activeAppLink.value = { name: '', path: '' }
+ dialogVisible.value = true
+
+ // 婊氬姩鍒板綋鍓嶇殑閾炬帴
+ const group = APP_LINK_GROUP_LIST.find((group) =>
+ group.links.some((linkItem) => {
+ const sameLink = isSameLink(linkItem.path, link)
+ if (sameLink) {
+ activeAppLink.value = { ...linkItem, path: link }
+ }
+ return sameLink
+ })
+ )
+ if (group) {
+ // 浣跨敤 nextTick 鐨勫師鍥狅細鍙兘 Dom 杩樻病鐢熸垚锛屽鑷存粴鍔ㄥけ璐�
+ nextTick(() => handleGroupSelected(group.name))
+ }
+}
+defineExpose({ open })
+
+// 澶勭悊 APP 閾炬帴閫変腑
+const handleAppLinkSelected = (appLink: AppLink) => {
+ // 鍙湁涓嶅悓閾炬帴鏃舵墠鏇存柊锛堥伩鍏嶉噸澶嶈Е鍙戯級
+ if (!isSameLink(appLink.path, activeAppLink.value.path)) {
+ // 濡傛灉鏂伴摼鎺ョ殑 path 涓虹┖锛屽垯娌跨敤褰撳墠 activeAppLink 鐨� path
+ const path = appLink.path || activeAppLink.value.path
+ activeAppLink.value = { ...appLink, path: path }
+ }
+ switch (appLink.type) {
+ case APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST:
+ detailSelectDialog.value.visible = true
+ detailSelectDialog.value.type = appLink.type
+ // 杩旀樉
+ detailSelectDialog.value.id =
+ getUrlNumberValue('id', 'http://127.0.0.1' + activeAppLink.value.path) || undefined
+ break
+ default:
+ break
+ }
+}
+
+// 澶勭悊缁戝畾鍊兼洿鏂�
+const emit = defineEmits<{
+ change: [link: string]
+ appLinkChange: [appLink: AppLink]
+}>()
+const handleSubmit = () => {
+ dialogVisible.value = false
+ emit('change', activeAppLink.value.path)
+ emit('appLinkChange', activeAppLink.value)
+}
+
+// 鍒嗙粍鏍囬寮曠敤鍒楄〃
+const groupTitleRefs = ref<HTMLInputElement[]>([])
+/**
+ * 澶勭悊鍙充晶閾炬帴鍒楄〃婊氬姩
+ * @param scrollTop 婊氬姩鏉$殑浣嶇疆
+ */
+const handleScroll = ({ scrollTop }: { scrollTop: number }) => {
+ const titleEl = groupTitleRefs.value.find((titleEl: HTMLInputElement) => {
+ // 鑾峰彇鏍囬鐨勪綅缃俊鎭�
+ const { offsetHeight, offsetTop } = titleEl
+ // 鍒ゆ柇鏍囬鏄惁鍦ㄥ彲瑙嗚寖鍥村唴
+ return scrollTop >= offsetTop && scrollTop < offsetTop + offsetHeight
+ })
+ // 鍙渶澶勭悊涓�娆�
+ if (titleEl && activeGroup.value !== titleEl.textContent) {
+ activeGroup.value = titleEl.textContent || ''
+ // 鍚屾宸︿晶鐨勬粴鍔ㄦ潯浣嶇疆
+ scrollToGroupBtn(activeGroup.value)
+ }
+}
+
+// 鍙充晶婊氬姩鏉�
+const linkScrollbar = ref<ScrollbarInstance>()
+// 澶勭悊鍒嗙粍閫変腑
+const handleGroupSelected = (group: string) => {
+ activeGroup.value = group
+ const titleRef = groupTitleRefs.value.find((item: HTMLInputElement) => item.textContent === group)
+ if (titleRef) {
+ // 婊氬姩鍒嗙粍鏍囬
+ linkScrollbar.value?.setScrollTop(titleRef.offsetTop)
+ }
+}
+
+// 鍒嗙粍婊氬姩鏉�
+const groupScrollbar = ref<ScrollbarInstance>()
+// 鍒嗙粍寮曠敤鍒楄〃
+const groupBtnRefs = ref<ButtonInstance[]>([])
+// 鑷姩婊氬姩鍒嗙粍鎸夐挳锛岀‘淇濆垎缁勬寜閽繚鎸佸湪鍙鍖哄煙鍐�
+const scrollToGroupBtn = (group: string) => {
+ const groupBtn = groupBtnRefs.value
+ .map((btn: ButtonInstance) => btn['ref'])
+ .find((ref: HTMLButtonElement) => ref.textContent === group)
+ if (groupBtn) {
+ groupScrollbar.value?.setScrollTop(groupBtn.offsetTop)
+ }
+}
+
+// 鏄惁涓虹浉鍚岀殑閾炬帴锛堜笉姣旇緝鍙傛暟锛屽彧姣旇緝閾炬帴锛�
+const isSameLink = (link1: string, link2: string) => {
+ return split(link1, '?', 1)[0] === split(link2, '?', 1)[0]
+}
+
+// 璇︽儏閫夋嫨瀵硅瘽妗�
+const detailSelectDialog = ref<{
+ visible: boolean
+ id?: number
+ type?: APP_LINK_TYPE_ENUM
+}>({
+ visible: false,
+ id: undefined,
+ type: undefined
+})
+// 澶勭悊璇︽儏閫夋嫨
+const handleProductCategorySelected = (id: number) => {
+ const url = new URL(activeAppLink.value.path, 'http://127.0.0.1')
+ // 淇敼 id 鍙傛暟
+ url.searchParams.set('id', `${id}`)
+ // 鎺掗櫎鍩熷悕
+ activeAppLink.value.path = `${url.pathname}${url.search}`
+ // 鍏抽棴瀵硅瘽妗�
+ detailSelectDialog.value.visible = false
+ // 閲嶇疆 id
+ detailSelectDialog.value.id = undefined
+}
+</script>
+<style lang="scss" scoped></style>
--
Gitblit v1.8.0