Skip to content

Commit 1abff21

Browse files
YunaiVgitee-org
authored andcommitted
!347 商城装修
Merge pull request !347 from 疯狂的世界/dev
2 parents 26a0827 + 80355f3 commit 1abff21

File tree

14 files changed

+702
-139
lines changed

14 files changed

+702
-139
lines changed

src/components/AppLinkInput/AppLinkSelectDialog.vue

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@
2929
:key="appLinkIndex"
3030
:content="appLink.path"
3131
placement="bottom"
32+
:show-after="300"
3233
>
3334
<el-button
3435
class="m-b-8px m-r-8px m-l-0px!"
35-
:type="isSameLink(appLink.path, activeAppLink) ? 'primary' : 'default'"
36+
:type="isSameLink(appLink.path, activeAppLink.path) ? 'primary' : 'default'"
3637
@click="handleAppLinkSelected(appLink)"
3738
>
3839
{{ appLink.name }}
@@ -63,7 +64,7 @@
6364
</Dialog>
6465
</template>
6566
<script lang="ts" setup>
66-
import { APP_LINK_GROUP_LIST, APP_LINK_TYPE_ENUM } from './data'
67+
import { APP_LINK_GROUP_LIST, APP_LINK_TYPE_ENUM, AppLink } from './data'
6768
import { ButtonInstance, ScrollbarInstance } from 'element-plus'
6869
import { split } from 'lodash-es'
6970
import ProductCategorySelect from '@/views/mall/product/category/components/ProductCategorySelect.vue'
@@ -74,17 +75,23 @@ defineOptions({ name: 'AppLinkSelectDialog' })
7475
// 选中的分组,默认选中第一个
7576
const activeGroup = ref(APP_LINK_GROUP_LIST[0].name)
7677
// 选中的 APP 链接
77-
const activeAppLink = ref('')
78+
const activeAppLink = ref({} as AppLink)
7879
7980
/** 打开弹窗 */
8081
const dialogVisible = ref(false)
8182
const open = (link: string) => {
82-
activeAppLink.value = link
83+
activeAppLink.value.path = link
8384
dialogVisible.value = true
8485
8586
// 滚动到当前的链接
8687
const group = APP_LINK_GROUP_LIST.find((group) =>
87-
group.links.some((linkItem) => isSameLink(linkItem.path, link))
88+
group.links.some((linkItem) => {
89+
const sameLink = isSameLink(linkItem.path, link)
90+
if (sameLink) {
91+
activeAppLink.value = { ...linkItem, path: link }
92+
}
93+
return sameLink
94+
})
8895
)
8996
if (group) {
9097
// 使用 nextTick 的原因:可能 Dom 还没生成,导致滚动失败
@@ -94,17 +101,17 @@ const open = (link: string) => {
94101
defineExpose({ open })
95102
96103
// 处理 APP 链接选中
97-
const handleAppLinkSelected = (appLink: any) => {
98-
if (!isSameLink(appLink.path, activeAppLink.value)) {
99-
activeAppLink.value = appLink.path
104+
const handleAppLinkSelected = (appLink: AppLink) => {
105+
if (!isSameLink(appLink.path, activeAppLink.value.path)) {
106+
activeAppLink.value = appLink
100107
}
101108
switch (appLink.type) {
102109
case APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST:
103110
detailSelectDialog.value.visible = true
104111
detailSelectDialog.value.type = appLink.type
105112
// 返显
106113
detailSelectDialog.value.id =
107-
getUrlNumberValue('id', 'http://127.0.0.1' + activeAppLink.value) || undefined
114+
getUrlNumberValue('id', 'http://127.0.0.1' + activeAppLink.value.path) || undefined
108115
break
109116
default:
110117
break
@@ -114,10 +121,12 @@ const handleAppLinkSelected = (appLink: any) => {
114121
// 处理绑定值更新
115122
const emit = defineEmits<{
116123
change: [link: string]
124+
appLinkChange: [appLink: AppLink]
117125
}>()
118126
const handleSubmit = () => {
119127
dialogVisible.value = false
120-
emit('change', activeAppLink.value)
128+
emit('change', activeAppLink.value.path)
129+
emit('appLinkChange', activeAppLink.value)
121130
}
122131
123132
// 分组标题引用列表
@@ -127,7 +136,7 @@ const groupTitleRefs = ref<HTMLInputElement[]>([])
127136
* @param scrollTop 滚动条的位置
128137
*/
129138
const handleScroll = ({ scrollTop }: { scrollTop: number }) => {
130-
const titleEl = groupTitleRefs.value.find((titleEl) => {
139+
const titleEl = groupTitleRefs.value.find((titleEl: HTMLInputElement) => {
131140
// 获取标题的位置信息
132141
const { offsetHeight, offsetTop } = titleEl
133142
// 判断标题是否在可视范围内
@@ -146,7 +155,7 @@ const linkScrollbar = ref<ScrollbarInstance>()
146155
// 处理分组选中
147156
const handleGroupSelected = (group: string) => {
148157
activeGroup.value = group
149-
const titleRef = groupTitleRefs.value.find((item) => item.textContent === group)
158+
const titleRef = groupTitleRefs.value.find((item: HTMLInputElement) => item.textContent === group)
150159
if (titleRef) {
151160
// 滚动分组标题
152161
linkScrollbar.value?.setScrollTop(titleRef.offsetTop)
@@ -160,8 +169,8 @@ const groupBtnRefs = ref<ButtonInstance[]>([])
160169
// 自动滚动分组按钮,确保分组按钮保持在可视区域内
161170
const scrollToGroupBtn = (group: string) => {
162171
const groupBtn = groupBtnRefs.value
163-
.map((btn) => btn['ref'])
164-
.find((ref) => ref.textContent === group)
172+
.map((btn: ButtonInstance) => btn['ref'])
173+
.find((ref: Node) => ref.textContent === group)
165174
if (groupBtn) {
166175
groupScrollbar.value?.setScrollTop(groupBtn.offsetTop)
167176
}
@@ -184,11 +193,11 @@ const detailSelectDialog = ref<{
184193
})
185194
// 处理详情选择
186195
const handleProductCategorySelected = (id: number) => {
187-
const url = new URL(activeAppLink.value, 'http://127.0.0.1')
196+
const url = new URL(activeAppLink.value.path, 'http://127.0.0.1')
188197
// 修改 id 参数
189198
url.searchParams.set('id', `${id}`)
190199
// 排除域名
191-
activeAppLink.value = `${url.pathname}${url.search}`
200+
activeAppLink.value.path = `${url.pathname}${url.search}`
192201
// 关闭对话框
193202
detailSelectDialog.value.visible = false
194203
// 重置 id

src/components/AppLinkInput/data.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
// APP 链接分组
2+
export interface AppLinkGroup {
3+
// 分组名称
4+
name: string
5+
// 链接列表
6+
links: AppLink[]
7+
}
8+
// APP 链接
9+
export interface AppLink {
10+
// 链接名称
11+
name: string
12+
// 链接地址
13+
path: string
14+
// 链接的类型
15+
type?: APP_LINK_TYPE_ENUM
16+
}
17+
118
// APP 链接类型(需要特殊处理,例如商品详情)
219
export const enum APP_LINK_TYPE_ENUM {
320
// 拼团活动
@@ -243,4 +260,4 @@ export const APP_LINK_GROUP_LIST = [
243260
}
244261
]
245262
}
246-
]
263+
] as AppLinkGroup[]

src/components/AppLinkInput/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const emit = defineEmits<{
3737
'update:modelValue': [link: string]
3838
}>()
3939
watch(
40-
() => appLink,
40+
() => appLink.value,
4141
() => emit('update:modelValue', appLink.value)
4242
)
4343
</script>
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { HotZoneItemProperty } from '@/components/DiyEditor/components/mobile/HotZone/config'
2+
import { StyleValue } from 'vue'
3+
4+
// 热区的最小宽高
5+
export const HOT_ZONE_MIN_SIZE = 100
6+
7+
// 控制的类型
8+
export enum CONTROL_TYPE_ENUM {
9+
LEFT,
10+
TOP,
11+
WIDTH,
12+
HEIGHT
13+
}
14+
15+
// 定义热区的控制点
16+
export interface ControlDot {
17+
position: string
18+
types: CONTROL_TYPE_ENUM[]
19+
style: StyleValue
20+
}
21+
22+
// 热区的8个控制点
23+
export const CONTROL_DOT_LIST = [
24+
{
25+
position: '左上角',
26+
types: [
27+
CONTROL_TYPE_ENUM.LEFT,
28+
CONTROL_TYPE_ENUM.TOP,
29+
CONTROL_TYPE_ENUM.WIDTH,
30+
CONTROL_TYPE_ENUM.HEIGHT
31+
],
32+
style: { left: '-5px', top: '-5px', cursor: 'nwse-resize' }
33+
},
34+
{
35+
position: '上方中间',
36+
types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.HEIGHT],
37+
style: { left: '50%', top: '-5px', cursor: 'n-resize', transform: 'translateX(-50%)' }
38+
},
39+
{
40+
position: '右上角',
41+
types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
42+
style: { right: '-5px', top: '-5px', cursor: 'nesw-resize' }
43+
},
44+
{
45+
position: '右侧中间',
46+
types: [CONTROL_TYPE_ENUM.WIDTH],
47+
style: { right: '-5px', top: '50%', cursor: 'e-resize', transform: 'translateX(-50%)' }
48+
},
49+
{
50+
position: '右下角',
51+
types: [CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
52+
style: { right: '-5px', bottom: '-5px', cursor: 'nwse-resize' }
53+
},
54+
{
55+
position: '下方中间',
56+
types: [CONTROL_TYPE_ENUM.HEIGHT],
57+
style: { left: '50%', bottom: '-5px', cursor: 's-resize', transform: 'translateX(-50%)' }
58+
},
59+
{
60+
position: '左下角',
61+
types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT],
62+
style: { left: '-5px', bottom: '-5px', cursor: 'nesw-resize' }
63+
},
64+
{
65+
position: '左侧中间',
66+
types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH],
67+
style: { left: '-5px', top: '50%', cursor: 'w-resize', transform: 'translateX(-50%)' }
68+
}
69+
] as ControlDot[]
70+
71+
//region 热区的缩放
72+
// 热区的缩放比例
73+
export const HOT_ZONE_SCALE_RATE = 2
74+
// 缩小:缩回适合手机屏幕的大小
75+
export const zoomOut = (list?: HotZoneItemProperty[]) => {
76+
return (
77+
list?.map((hotZone) => ({
78+
...hotZone,
79+
left: (hotZone.left /= HOT_ZONE_SCALE_RATE),
80+
top: (hotZone.top /= HOT_ZONE_SCALE_RATE),
81+
width: (hotZone.width /= HOT_ZONE_SCALE_RATE),
82+
height: (hotZone.height /= HOT_ZONE_SCALE_RATE)
83+
})) || []
84+
)
85+
}
86+
// 放大:作用是为了方便在电脑屏幕上编辑
87+
export const zoomIn = (list?: HotZoneItemProperty[]) => {
88+
return (
89+
list?.map((hotZone) => ({
90+
...hotZone,
91+
left: (hotZone.left *= HOT_ZONE_SCALE_RATE),
92+
top: (hotZone.top *= HOT_ZONE_SCALE_RATE),
93+
width: (hotZone.width *= HOT_ZONE_SCALE_RATE),
94+
height: (hotZone.height *= HOT_ZONE_SCALE_RATE)
95+
})) || []
96+
)
97+
}
98+
//endregion
99+
100+
/**
101+
* 封装热区拖拽
102+
*
103+
* 注:为什么不使用vueuse的useDraggable。在本场景下,其使用方式比较复杂
104+
* @param hotZone 热区
105+
* @param downEvent 鼠标按下事件
106+
* @param callback 回调函数
107+
*/
108+
export const useDraggable = (
109+
hotZone: HotZoneItemProperty,
110+
downEvent: MouseEvent,
111+
callback: (
112+
left: number,
113+
top: number,
114+
width: number,
115+
height: number,
116+
moveWidth: number,
117+
moveHeight: number
118+
) => void
119+
) => {
120+
// 阻止事件冒泡
121+
downEvent.stopPropagation()
122+
123+
// 移动前的鼠标坐标
124+
const { clientX: startX, clientY: startY } = downEvent
125+
// 移动前的热区坐标、大小
126+
const { left, top, width, height } = hotZone
127+
128+
// 监听鼠标移动
129+
document.onmousemove = (e) => {
130+
// 移动宽度
131+
const moveWidth = e.clientX - startX
132+
// 移动高度
133+
const moveHeight = e.clientY - startY
134+
// 移动回调
135+
callback(left, top, width, height, moveWidth, moveHeight)
136+
}
137+
138+
// 松开鼠标后,结束拖拽
139+
document.onmouseup = () => {
140+
document.onmousemove = null
141+
document.onmouseup = null
142+
}
143+
}

0 commit comments

Comments
 (0)