Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
易企天创
zentaoatf
提交
343aabe8
Z
zentaoatf
项目概览
易企天创
/
zentaoatf
9 个月 前同步成功
通知
11
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
3
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Z
zentaoatf
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
3
Issue
3
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
343aabe8
编写于
5月 25, 2023
作者:
aaronchen2k2k
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
filter products in selection
上级
9804d773
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
218 addition
and
169 deletion
+218
-169
ui/src/components/DropdownMenu.vue
ui/src/components/DropdownMenu.vue
+216
-169
ui/src/views/site/SiteNav.vue
ui/src/views/site/SiteNav.vue
+2
-0
未找到文件。
ui/src/components/DropdownMenu.vue
浏览文件 @
343aabe8
<
template
>
<div
class=
"dropdown-menu"
:class=
"menuClass ?? 'layer rounded'"
:style=
"menuFinalStyle"
@
click=
"_handleClickMenu"
ref=
"menuRef"
class=
"dropdown-menu"
:class=
"menuClass ?? 'layer rounded'"
:style=
"menuFinalStyle"
@
click=
"_handleClickMenu"
ref=
"menuRef"
>
<template
v-if=
"state.show"
>
<input
type=
"text"
class=
"keywords"
v-if=
"filter"
v-model=
"keywords"
@
input=
"onKeywordsChanged"
@
click.stop
/>
<List
:items=
"items
"
:replaceFields=
"replaceFields"
:checkedKey=
"checkedKey"
:activeKey=
"activeKey"
:keyName=
"keyName"
:class=
"listClass"
:compact=
"listCompact"
:divider=
"listDivider"
@
click=
"emit('click', $event)"
:items=
"itemsToShow
"
:replaceFields=
"replaceFields"
:checkedKey=
"checkedKey"
:activeKey=
"activeKey"
:keyName=
"keyName"
:class=
"listClass"
:compact=
"listCompact"
:divider=
"listDivider"
@
click=
"emit('click', $event)"
/>
<slot
/>
<slot/>
</
template
>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
withDefaults
,
defineProps
,
ref
,
reactive
,
onMounted
,
onUnmounted
,
computed
,
defineEmits
}
from
'
vue
'
;
import
{
useWindowSize
,
onClickOutside
}
from
'
@vueuse/core
'
import
{
computed
,
defineEmits
,
defineProps
,
onMounted
,
onUnmounted
,
reactive
,
ref
,
withDefaults
}
from
'
vue
'
;
import
{
onClickOutside
,
useWindowSize
}
from
'
@vueuse/core
'
import
List
from
'
./List.vue
'
;
import
{
ListItemKey
,
ListItemProps
}
from
'
./ListItem.vue
'
;
export
type
DropdownMenuPosition
=
'
bottom
'
|
'
left
'
|
'
right
'
|
'
top
'
|
'
bottom-left
'
|
'
bottom-right
'
|
'
top-left
'
|
'
top-right
'
|
'
left-top
'
|
'
left-bottom
'
|
'
right-top
'
|
'
right-bottom
'
|
{
left
:
number
,
top
:
number
}
|
((
toggleElement
:
HTMLElement
)
=>
{
left
:
number
,
top
:
number
});
export
type
DropdownMenuPosition
=
'
bottom
'
|
'
left
'
|
'
right
'
|
'
top
'
|
'
bottom-left
'
|
'
bottom-right
'
|
'
top-left
'
|
'
top-right
'
|
'
left-top
'
|
'
left-bottom
'
|
'
right-top
'
|
'
right-bottom
'
|
{
left
:
number
,
top
:
number
}
|
((
toggleElement
:
HTMLElement
)
=>
{
left
:
number
,
top
:
number
});
const
props
=
withDefaults
(
defineProps
<
{
toggle
?:
object
|
string
,
triggerEvent
?:
string
,
position
?:
DropdownMenuPosition
,
items
?:
ListItemProps
[]
|
Record
<
string
,
any
>
[],
keyName
?:
string
,
checkedKey
?:
ListItemKey
,
activeKey
?:
ListItemKey
,
replaceFields
?:
Record
<
string
,
string
>
,
listClass
?:
string
,
listCompact
?:
boolean
,
listDivider
?:
boolean
,
defaultShow
?:
boolean
,
showOnHover
?:
boolean
,
hideOnClickAway
?:
boolean
,
hideOnClickMenu
?:
boolean
,
menuClass
?:
string
,
limitInWindow
?:
boolean
,
menuStyle
?:
object
toggle
?:
object
|
string
,
triggerEvent
?:
string
,
position
?:
DropdownMenuPosition
,
items
?:
ListItemProps
[]
|
Record
<
string
,
any
>
[],
keyName
?:
string
,
checkedKey
?:
ListItemKey
,
activeKey
?:
ListItemKey
,
replaceFields
?:
Record
<
string
,
string
>
,
listClass
?:
string
,
listCompact
?:
boolean
,
listDivider
?:
boolean
,
defaultShow
?:
boolean
,
showOnHover
?:
boolean
,
hideOnClickAway
?:
boolean
,
hideOnClickMenu
?:
boolean
,
menuClass
?:
string
,
limitInWindow
?:
boolean
,
menuStyle
?:
object
filter
?:
boolean
}
>
(),
{
hideOnClickAway
:
true
,
hideOnClickMenu
:
true
});
const
menuRef
=
ref
<
HTMLElement
>
();
...
...
@@ -57,166 +78,178 @@ const cleanUpRef = ref();
const
state
=
reactive
({
show
:
!!
props
.
defaultShow
,
showed
:
false
});
const
showTimerRef
=
ref
<
number
>
(
0
);
const
keywords
=
ref
(
''
)
function
_toggle
(
show
?:
boolean
)
{
if
(
show
===
undefined
)
{
show
=
!
state
.
show
;
}
if
(
state
.
show
===
show
)
{
return
;
}
if
(
showTimerRef
.
value
)
{
clearTimeout
(
showTimerRef
.
value
);
showTimerRef
.
value
=
0
;
}
state
.
show
=
show
;
state
.
showed
=
false
;
if
(
show
)
{
showTimerRef
.
value
=
setTimeout
(()
=>
{
state
.
showed
=
true
;
showTimerRef
.
value
=
0
;
},
100
);
}
if
(
show
===
undefined
)
{
show
=
!
state
.
show
;
}
if
(
state
.
show
===
show
)
{
return
;
}
if
(
showTimerRef
.
value
)
{
clearTimeout
(
showTimerRef
.
value
);
showTimerRef
.
value
=
0
;
}
state
.
show
=
show
;
state
.
showed
=
false
;
if
(
show
)
{
showTimerRef
.
value
=
setTimeout
(()
=>
{
state
.
showed
=
true
;
showTimerRef
.
value
=
0
;
},
100
);
}
}
function
_handleClickMenu
(
event
:
MouseEvent
)
{
if
(
!
props
.
hideOnClickMenu
||
event
.
target
&&
event
.
target
instanceof
HTMLElement
&&
event
.
target
.
closest
(
'
.not-hide-menu
'
))
{
return
;
}
if
(
state
.
showed
)
{
_toggle
(
false
);
}
if
(
!
props
.
hideOnClickMenu
||
event
.
target
&&
event
.
target
instanceof
HTMLElement
&&
event
.
target
.
closest
(
'
.not-hide-menu
'
))
{
return
;
}
if
(
state
.
showed
)
{
_toggle
(
false
);
}
}
const
emit
=
defineEmits
<
{(
type
:
'
click
'
,
event
:
{
originalEvent
:
Event
,
key
:
ListItemKey
,
item
:
ListItemProps
|
Record
<
string
,
any
>
})
:
void
}
>
();
const
itemsToShow
=
computed
(()
=>
{
let
arr
=
props
.
items
?.
filter
((
item
)
=>
{
return
!
keywords
.
value
||
item
.
name
.
indexOf
(
keywords
.
value
)
>
-
1
;
})
return
arr
})
const
onKeywordsChanged
=
()
=>
{
console
.
log
(
'
onKeywordsChanged
'
)
}
const
emit
=
defineEmits
<
{
(
type
:
'
click
'
,
event
:
{
originalEvent
:
Event
,
key
:
ListItemKey
,
item
:
ListItemProps
|
Record
<
string
,
any
>
}):
void
}
>
();
onClickOutside
(
menuRef
,
_event
=>
{
if
(
props
.
hideOnClickAway
&&
state
.
showed
)
{
_toggle
(
false
);
}
if
(
props
.
hideOnClickAway
&&
state
.
showed
)
{
_toggle
(
false
);
}
});
function
getToggleElement
()
{
const
{
toggle
}
=
props
;
if
(
!
toggle
)
{
if
(
menuRef
.
value
)
{
return
menuRef
.
value
.
closest
(
'
.dropdown
'
)?.
querySelector
(
'
.dropdown-toggle
'
)
as
HTMLElement
||
undefined
;
}
return
undefined
;
}
if
(
toggle
instanceof
HTMLElement
)
{
return
toggle
;
}
if
(
typeof
toggle
===
'
string
'
)
{
return
document
.
querySelector
(
toggle
)
as
HTMLElement
||
undefined
;
const
{
toggle
}
=
props
;
if
(
!
toggle
)
{
if
(
menuRef
.
value
)
{
return
menuRef
.
value
.
closest
(
'
.dropdown
'
)?.
querySelector
(
'
.dropdown-toggle
'
)
as
HTMLElement
||
undefined
;
}
return
undefined
;
}
if
(
toggle
instanceof
HTMLElement
)
{
return
toggle
;
}
if
(
typeof
toggle
===
'
string
'
)
{
return
document
.
querySelector
(
toggle
)
as
HTMLElement
||
undefined
;
}
return
undefined
;
}
const
windowSize
=
useWindowSize
();
const
menuFinalStyle
=
computed
(()
=>
{
if
(
!
state
.
show
)
{
return
{
display
:
'
none
'
};
}
const
style
:
Record
<
string
,
any
>
=
{
display
:
'
block
'
,
opacity
:
1
,
top
:
'
0px
'
,
left
:
'
0px
'
,
};
const
element
=
getToggleElement
();
if
(
!
element
||
!
menuRef
.
value
)
{
return
style
;
}
if
(
!
state
.
showed
)
{
style
.
opacity
=
0
;
return
style
;
}
const
{
position
=
'
bottom-left
'
}
=
props
;
const
bounding
=
element
.
getBoundingClientRect
();
const
menuBounding
=
menuRef
.
value
.
getBoundingClientRect
();
if
(
typeof
position
===
'
function
'
)
{
Object
.
assign
(
style
,
position
(
element
));
}
else
if
(
typeof
position
===
'
object
'
)
{
Object
.
assign
(
style
,
position
);
}
else
if
(
position
===
'
bottom
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
Math
.
round
(
bounding
.
left
+
(
bounding
.
width
/
2
)
-
(
menuBounding
.
width
/
2
));
}
else
if
(
position
===
'
bottom-left
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
bounding
.
left
;
}
else
if
(
position
===
'
bottom-right
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
bounding
.
right
-
menuBounding
.
width
;
}
else
if
(
position
===
'
top
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
left
+
(
bounding
.
width
/
2
)
-
(
menuBounding
.
width
/
2
);
}
else
if
(
position
===
'
top-left
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
left
;
}
else
if
(
position
===
'
top-right
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
right
-
menuBounding
.
width
;
}
else
if
(
position
===
'
left
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
top
+
(
bounding
.
height
/
2
)
-
(
menuBounding
.
height
/
2
);
}
else
if
(
position
===
'
left-top
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
top
;
}
else
if
(
position
===
'
left-bottom
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
bottom
-
menuBounding
.
height
;
}
else
if
(
position
===
'
right
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
}
else
if
(
position
===
'
right-top
'
)
{
style
.
left
=
bounding
.
right
;
style
.
top
=
bounding
.
top
;
}
else
if
(
position
===
'
right-bottom
'
)
{
style
.
left
=
bounding
.
right
;
style
.
top
=
bounding
.
bottom
-
menuBounding
.
height
;
}
if
(
!
state
.
show
)
{
return
{
display
:
'
none
'
};
}
const
style
:
Record
<
string
,
any
>
=
{
display
:
'
block
'
,
opacity
:
1
,
top
:
'
0px
'
,
left
:
'
0px
'
,
};
const
element
=
getToggleElement
();
if
(
!
element
||
!
menuRef
.
value
)
{
return
style
;
}
if
(
!
state
.
showed
)
{
style
.
opacity
=
0
;
return
style
;
}
const
{
position
=
'
bottom-left
'
}
=
props
;
const
bounding
=
element
.
getBoundingClientRect
();
const
menuBounding
=
menuRef
.
value
.
getBoundingClientRect
();
if
(
typeof
position
===
'
function
'
)
{
Object
.
assign
(
style
,
position
(
element
));
}
else
if
(
typeof
position
===
'
object
'
)
{
Object
.
assign
(
style
,
position
);
}
else
if
(
position
===
'
bottom
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
Math
.
round
(
bounding
.
left
+
(
bounding
.
width
/
2
)
-
(
menuBounding
.
width
/
2
));
}
else
if
(
position
===
'
bottom-left
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
bounding
.
left
;
}
else
if
(
position
===
'
bottom-right
'
)
{
style
.
top
=
bounding
.
bottom
;
style
.
left
=
bounding
.
right
-
menuBounding
.
width
;
}
else
if
(
position
===
'
top
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
left
+
(
bounding
.
width
/
2
)
-
(
menuBounding
.
width
/
2
);
}
else
if
(
position
===
'
top-left
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
left
;
}
else
if
(
position
===
'
top-right
'
)
{
style
.
top
=
bounding
.
top
-
menuBounding
.
height
;
style
.
left
=
bounding
.
right
-
menuBounding
.
width
;
}
else
if
(
position
===
'
left
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
top
+
(
bounding
.
height
/
2
)
-
(
menuBounding
.
height
/
2
);
}
else
if
(
position
===
'
left-top
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
top
;
}
else
if
(
position
===
'
left-bottom
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
style
.
top
=
bounding
.
bottom
-
menuBounding
.
height
;
}
else
if
(
position
===
'
right
'
)
{
style
.
left
=
bounding
.
left
-
menuBounding
.
width
;
}
else
if
(
position
===
'
right-top
'
)
{
style
.
left
=
bounding
.
right
;
style
.
top
=
bounding
.
top
;
}
else
if
(
position
===
'
right-bottom
'
)
{
style
.
left
=
bounding
.
right
;
style
.
top
=
bounding
.
bottom
-
menuBounding
.
height
;
}
if
(
props
.
limitInWindow
!==
false
)
{
style
.
left
=
Math
.
min
(
windowSize
.
width
.
value
-
menuBounding
.
width
,
style
.
left
);
style
.
top
=
Math
.
min
(
windowSize
.
height
.
value
-
menuBounding
.
height
,
style
.
top
);
}
style
.
maxHeight
=
`
${
Math
.
round
(
windowSize
.
height
.
value
-
style
.
top
-
10
)}
px`
;
style
.
maxWidth
=
`
${
Math
.
round
(
windowSize
.
width
.
value
-
style
.
left
-
10
)}
px`
;
style
.
left
=
`
${
Math
.
round
(
style
.
left
)}
px`
;
style
.
top
=
`
${
Math
.
round
(
style
.
top
)}
px`
;
style
.
overflow
=
'
auto
'
;
if
(
props
.
menuStyle
)
{
Object
.
assign
(
style
,
props
.
menuStyle
);
}
if
(
props
.
limitInWindow
!==
false
)
{
style
.
left
=
Math
.
min
(
windowSize
.
width
.
value
-
menuBounding
.
width
,
style
.
left
);
style
.
top
=
Math
.
min
(
windowSize
.
height
.
value
-
menuBounding
.
height
,
style
.
top
);
}
style
.
maxHeight
=
`
${
Math
.
round
(
windowSize
.
height
.
value
-
style
.
top
-
10
)}
px`
;
style
.
maxWidth
=
`
${
Math
.
round
(
windowSize
.
width
.
value
-
style
.
left
-
10
)}
px`
;
style
.
left
=
`
${
Math
.
round
(
style
.
left
)}
px`
;
style
.
top
=
`
${
Math
.
round
(
style
.
top
)}
px`
;
style
.
overflow
=
'
auto
'
;
return
style
;
if
(
props
.
menuStyle
)
{
Object
.
assign
(
style
,
props
.
menuStyle
);
}
return
style
;
});
onMounted
(()
=>
{
const
toggleElement
=
getToggleElement
();
if
(
!
toggleElement
)
{
return
;
}
const
toggleElement
=
getToggleElement
();
if
(
!
toggleElement
)
{
return
;
}
const
triggerEvent
=
props
.
triggerEvent
??
'
click
'
;
const
handler
=
(
_event
)
=>
{
if
(
state
.
showed
)
{
_toggle
(
false
);
}
else
if
(
!
state
.
show
)
{
_toggle
(
true
);
}
};
toggleElement
.
addEventListener
(
triggerEvent
,
handler
,
false
);
cleanUpRef
.
value
=
()
=>
{
toggleElement
.
removeEventListener
(
triggerEvent
,
handler
,
false
);
};
const
triggerEvent
=
props
.
triggerEvent
??
'
click
'
;
const
handler
=
(
_event
)
=>
{
if
(
state
.
showed
)
{
_toggle
(
false
);
}
else
if
(
!
state
.
show
)
{
_toggle
(
true
);
}
};
toggleElement
.
addEventListener
(
triggerEvent
,
handler
,
false
);
cleanUpRef
.
value
=
()
=>
{
toggleElement
.
removeEventListener
(
triggerEvent
,
handler
,
false
);
};
});
onUnmounted
(()
=>
{
if
(
cleanUpRef
.
value
)
{
cleanUpRef
.
value
();
}
if
(
cleanUpRef
.
value
)
{
cleanUpRef
.
value
();
}
})
</
script
>
...
...
@@ -228,11 +261,25 @@ onUnmounted(() => {
padding-top
:
var
(
--space-sm
);
padding-bottom
:
var
(
--space-sm
);
}
.dropdown-menu
:deep
(
.list-item
)
{
padding-left
:
var
(
--space-lg
);
padding-right
:
var
(
--space-lg
);
}
.dropdown-menu
:deep
(
.list-item.has-checkmark
)
{
padding-right
:
var
(
--space-sm
);
}
.dropdown-menu
.keywords
{
margin
:
3px
10px
;
padding
:
0
5px
;
height
:
22px
;
outline
:
0
;
}
.dropdown-menu
.keywords
input
{
}
</
style
>
ui/src/views/site/SiteNav.vue
浏览文件 @
343aabe8
...
...
@@ -35,6 +35,7 @@
<DropdownMenu
v-if=
"products.length > 0"
:filter=
"true"
toggle=
"#productMenuToggle"
class=
"scrollbar-y scrollbar-hover"
:items=
"products"
...
...
@@ -43,6 +44,7 @@
@
click=
"selectProduct"
:replaceFields=
"replaceFields"
/>
<SitesModal
:show=
"showSitesModal"
@
cancel=
"sitesModalClose"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录