Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jxf111348
vue-vben-admin
提交
81baf1d5
V
vue-vben-admin
项目概览
jxf111348
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
81baf1d5
编写于
11月 27, 2020
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
perf: perf modal and drawer
上级
819127e8
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
572 addition
and
497 deletion
+572
-497
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+6
-0
src/components/Drawer/index.ts
src/components/Drawer/index.ts
+4
-2
src/components/Drawer/src/BasicDrawer.tsx
src/components/Drawer/src/BasicDrawer.tsx
+137
-120
src/components/Drawer/src/props.ts
src/components/Drawer/src/props.ts
+17
-55
src/components/Drawer/src/types.ts
src/components/Drawer/src/types.ts
+1
-1
src/components/Drawer/src/useDrawer.ts
src/components/Drawer/src/useDrawer.ts
+30
-16
src/components/Modal/index.ts
src/components/Modal/index.ts
+5
-2
src/components/Modal/src/BasicModal.tsx
src/components/Modal/src/BasicModal.tsx
+82
-83
src/components/Modal/src/Modal.tsx
src/components/Modal/src/Modal.tsx
+7
-94
src/components/Modal/src/ModalWrapper.tsx
src/components/Modal/src/ModalWrapper.tsx
+31
-46
src/components/Modal/src/index.less
src/components/Modal/src/index.less
+23
-3
src/components/Modal/src/props.ts
src/components/Modal/src/props.ts
+13
-41
src/components/Modal/src/provideModal.ts
src/components/Modal/src/provideModal.ts
+0
-11
src/components/Modal/src/types.ts
src/components/Modal/src/types.ts
+3
-0
src/components/Modal/src/useFullScreen.ts
src/components/Modal/src/useFullScreen.ts
+44
-0
src/components/Modal/src/useModal.ts
src/components/Modal/src/useModal.ts
+30
-9
src/components/Modal/src/useModalContext.ts
src/components/Modal/src/useModalContext.ts
+16
-0
src/components/Modal/src/useModalDrag.ts
src/components/Modal/src/useModalDrag.ts
+107
-0
src/components/Scrollbar/src/Scrollbar.tsx
src/components/Scrollbar/src/Scrollbar.tsx
+1
-1
src/components/Table/src/hooks/useTableScroll.ts
src/components/Table/src/hooks/useTableScroll.ts
+3
-4
src/components/Tree/src/BasicTree.tsx
src/components/Tree/src/BasicTree.tsx
+2
-3
src/components/Tree/src/useTree.ts
src/components/Tree/src/useTree.ts
+2
-2
src/components/Verify/src/DragVerify.tsx
src/components/Verify/src/DragVerify.tsx
+2
-1
src/hooks/setting/useRootSetting.ts
src/hooks/setting/useRootSetting.ts
+1
-1
src/utils/helper/vueHelper.ts
src/utils/helper/vueHelper.ts
+5
-2
未找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
81baf1d5
...
...
@@ -18,12 +18,18 @@
-
缓存可以配置是否加密,默认生产环境开启 Aes 加密
-
新增标签页拖拽排序
-
新增 LayoutFooter.默认显示,可以在配置内关闭
### ⚡ Performance Improvements
-
优化
`Modal`
组件全屏动画不流畅问题
### 🐛 Bug Fixes
-
修复 tree 文本超出挡住操作按钮问题
-
修复通过 useRedo 刷新页面参数丢失问题
-
修复表单校验先设置在校验及控制台错误信息问题
-
修复
`modal`
与
`drawer`
组件传递数组参数问题
### 🎫 Chores
...
...
src/components/Drawer/index.ts
浏览文件 @
81baf1d5
export
{
default
as
BasicDrawer
}
from
'
./src/BasicDrawer
'
;
import
BasicDrawerLib
from
'
./src/BasicDrawer
'
;
import
{
withInstall
}
from
'
../util
'
;
export
{
useDrawer
,
useDrawerInner
}
from
'
./src/useDrawer
'
;
export
*
from
'
./src/types
'
;
export
{
useDrawer
,
useDrawerInner
}
from
'
./src/useDrawer
'
;
export
const
BasicDrawer
=
withInstall
(
BasicDrawerLib
);
src/components/Drawer/src/BasicDrawer.tsx
浏览文件 @
81baf1d5
import
'
./index.less
'
;
import
type
{
DrawerInstance
,
DrawerProps
}
from
'
./types
'
;
import
type
{
CSSProperties
}
from
'
vue
'
;
import
{
defineComponent
,
ref
,
computed
,
watchEffect
,
watch
,
unref
,
nextTick
,
toRaw
}
from
'
vue
'
;
import
{
Drawer
,
Row
,
Col
,
Button
}
from
'
ant-design-vue
'
;
...
...
@@ -9,53 +10,96 @@ import { BasicTitle } from '/@/components/Basic';
import
{
FullLoading
}
from
'
/@/components/Loading/index
'
;
import
{
LeftOutlined
}
from
'
@ant-design/icons-vue
'
;
import
{
basicProps
}
from
'
./props
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
getSlot
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
isFunction
,
isNumber
}
from
'
/@/utils/is
'
;
import
{
buildUUID
}
from
'
/@/utils/uuid
'
;
import
{
deepMerge
}
from
'
/@/utils
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
tryTsxEmit
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
basicProps
}
from
'
./props
'
;
const
prefixCls
=
'
basic-drawer
'
;
export
default
defineComponent
({
//
inheritAttrs: false,
inheritAttrs
:
false
,
props
:
basicProps
,
emits
:
[
'
visible-change
'
,
'
ok
'
,
'
close
'
,
'
register
'
],
setup
(
props
,
{
slots
,
emit
,
attrs
})
{
const
scrollRef
=
ref
<
ElRef
>
(
null
);
const
visibleRef
=
ref
(
false
);
const
propsRef
=
ref
<
Partial
<
DrawerProps
>
|
null
>
(
null
);
const
propsRef
=
ref
<
Partial
<
Nullable
<
DrawerProps
>>
>
(
null
);
const
{
t
}
=
useI18n
(
'
component.drawer
'
);
const
getMergeProps
=
computed
(():
any
=>
{
return
deepMerge
(
toRaw
(
props
),
unref
(
propsRef
));
});
const
getProps
=
computed
(()
=>
{
const
opt
:
any
=
{
placement
:
'
right
'
,
...
attrs
,
...
props
,
...(
unref
(
propsRef
)
as
any
),
visible
:
unref
(
visibleRef
),
};
opt
.
title
=
undefined
;
const
getMergeProps
=
computed
(
():
DrawerProps
=>
{
return
deepMerge
(
toRaw
(
props
),
unref
(
propsRef
));
}
);
if
(
opt
.
isDetail
)
{
if
(
!
opt
.
width
)
{
opt
.
width
=
'
100%
'
;
}
opt
.
wrapClassName
=
opt
.
wrapClassName
?
`
${
opt
.
wrapClassName
}
${
prefixCls
}
__detail`
:
`
${
prefixCls
}
__detail`
;
if
(
!
opt
.
getContainer
)
{
opt
.
getContainer
=
'
.layout-content
'
;
const
getProps
=
computed
(
():
DrawerProps
=>
{
const
opt
=
{
placement
:
'
right
'
,
...
attrs
,
...
unref
(
getMergeProps
),
visible
:
unref
(
visibleRef
),
};
opt
.
title
=
undefined
;
const
{
isDetail
,
width
,
wrapClassName
,
getContainer
}
=
opt
;
if
(
isDetail
)
{
if
(
!
width
)
{
opt
.
width
=
'
100%
'
;
}
const
detailCls
=
`
${
prefixCls
}
__detail`
;
opt
.
wrapClassName
=
wrapClassName
?
`
${
wrapClassName
}
${
detailCls
}
`
:
detailCls
;
if
(
!
getContainer
)
{
// TODO type error?
opt
.
getContainer
=
'
.layout-content
'
as
any
;
}
}
return
opt
as
DrawerProps
;
}
return
opt
;
);
const
getBindValues
=
computed
(
():
DrawerProps
=>
{
return
{
...
attrs
,
...
unref
(
getProps
),
};
}
);
// Custom implementation of the bottom button,
const
getFooterHeight
=
computed
(()
=>
{
const
{
footerHeight
,
showFooter
}
=
unref
(
getProps
);
if
(
showFooter
&&
footerHeight
)
{
return
isNumber
(
footerHeight
)
?
`
${
footerHeight
}
px`
:
`
${
footerHeight
.
replace
(
'
px
'
,
''
)}
px`
;
}
return
`0px`
;
});
const
getScrollContentStyle
=
computed
(
():
CSSProperties
=>
{
const
footerHeight
=
unref
(
getFooterHeight
);
return
{
position
:
'
relative
'
,
height
:
`calc(100% -
${
footerHeight
}
)`
,
overflow
:
'
auto
'
,
padding
:
'
16px
'
,
paddingBottom
:
'
30px
'
,
};
}
);
const
getLoading
=
computed
(()
=>
{
return
{
hidden
:
!
unref
(
getProps
).
loading
,
};
});
watchEffect
(()
=>
{
...
...
@@ -74,22 +118,13 @@ export default defineComponent({
}
);
// Custom implementation of the bottom button,
const
getFooterHeight
=
computed
(()
=>
{
const
{
footerHeight
,
showFooter
}:
DrawerProps
=
unref
(
getProps
);
if
(
showFooter
&&
footerHeight
)
{
return
isNumber
(
footerHeight
)
?
`
${
footerHeight
}
px`
:
`
${
footerHeight
.
replace
(
'
px
'
,
''
)}
px`
;
}
return
`0px`
;
});
// Cancel event
async
function
onClose
(
e
:
any
)
{
async
function
onClose
(
e
:
ChangeEvent
)
{
const
{
closeFunc
}
=
unref
(
getProps
);
emit
(
'
close
'
,
e
);
if
(
closeFunc
&&
isFunction
(
closeFunc
))
{
const
res
=
await
closeFunc
();
res
&&
(
visibleRef
.
value
=
false
)
;
visibleRef
.
value
=
!
res
;
return
;
}
visibleRef
.
value
=
false
;
...
...
@@ -98,12 +133,16 @@ export default defineComponent({
function
setDrawerProps
(
props
:
Partial
<
DrawerProps
>
):
void
{
// Keep the last setDrawerProps
propsRef
.
value
=
deepMerge
(
unref
(
propsRef
)
||
{},
props
);
if
(
Reflect
.
has
(
props
,
'
visible
'
))
{
visibleRef
.
value
=
!!
props
.
visible
;
}
}
function
renderFooter
()
{
if
(
slots
?.
footer
)
{
return
getSlot
(
slots
,
'
footer
'
);
}
const
{
showCancelBtn
,
cancelButtonProps
,
...
...
@@ -114,65 +153,64 @@ export default defineComponent({
okButtonProps
,
confirmLoading
,
showFooter
,
}:
DrawerProps
=
unref
(
getProps
);
}
=
unref
(
getProps
);
if
(
!
showFooter
)
{
return
null
;
}
return
(
getSlot
(
slots
,
'
footer
'
)
||
(
showFooter
&&
(
<
div
class
=
{
`
${
prefixCls
}
__footer`
}
>
{
getSlot
(
slots
,
'
insertFooter
'
)
}
{
showCancelBtn
&&
(
<
Button
{
...
cancelButtonProps
}
onClick
=
{
onClose
}
class
=
"mr-2"
>
{
()
=>
cancelText
}
</
Button
>
)
}
{
getSlot
(
slots
,
'
centerFooter
'
)
}
{
showOkBtn
&&
(
<
Button
type
=
{
okType
}
onClick
=
{
()
=>
{
emit
(
'
ok
'
);
}
}
{
...
okButtonProps
}
loading
=
{
confirmLoading
}
>
{
()
=>
okText
}
</
Button
>
)
}
{
getSlot
(
slots
,
'
appendFooter
'
)
}
</
div
>
))
<
div
class
=
{
`
${
prefixCls
}
__footer`
}
>
{
getSlot
(
slots
,
'
insertFooter
'
)
}
{
showCancelBtn
&&
(
<
Button
{
...
cancelButtonProps
}
onClick
=
{
onClose
}
class
=
"mr-2"
>
{
()
=>
cancelText
}
</
Button
>
)
}
{
getSlot
(
slots
,
'
centerFooter
'
)
}
{
showOkBtn
&&
(
<
Button
type
=
{
okType
}
onClick
=
{
()
=>
{
emit
(
'
ok
'
);
}
}
{
...
okButtonProps
}
loading
=
{
confirmLoading
}
>
{
()
=>
okText
}
</
Button
>
)
}
{
getSlot
(
slots
,
'
appendFooter
'
)
}
</
div
>
);
}
function
renderHeader
()
{
if
(
slots
?.
title
)
{
return
getSlot
(
slots
,
'
title
'
);
}
const
{
title
}
=
unref
(
getMergeProps
);
return
props
.
isDetail
?
(
getSlot
(
slots
,
'
title
'
)
||
(
<
Row
type
=
"flex"
align
=
"middle"
class
=
{
`
${
prefixCls
}
__detail-header`
}
>
{
()
=>
(
<>
{
props
.
showDetailBack
&&
(
<
Button
size
=
"small"
type
=
"link"
onClick
=
{
onClose
}
>
{
()
=>
<
LeftOutlined
/>
}
</
Button
>
)
}
{
title
&&
(
<
Col
style
=
"flex:1"
class
=
{
[
`
${
prefixCls
}
__detail-title`
,
'
ellipsis
'
,
'
px-2
'
]
}
>
{
()
=>
title
}
</
Col
>
)
}
{
getSlot
(
slots
,
'
titleToolbar
'
)
}
</>
)
}
</
Row
>
)
)
:
(
<
BasicTitle
>
{
()
=>
title
||
getSlot
(
slots
,
'
title
'
)
}
</
BasicTitle
>
if
(
!
props
.
isDetail
)
{
return
<
BasicTitle
>
{
()
=>
title
||
getSlot
(
slots
,
'
title
'
)
}
</
BasicTitle
>;
}
return
(
<
Row
type
=
"flex"
align
=
"middle"
class
=
{
`
${
prefixCls
}
__detail-header`
}
>
{
()
=>
(
<>
{
props
.
showDetailBack
&&
(
<
Button
size
=
"small"
type
=
"link"
onClick
=
{
onClose
}
>
{
()
=>
<
LeftOutlined
/>
}
</
Button
>
)
}
{
title
&&
(
<
Col
style
=
"flex:1"
class
=
{
[
`
${
prefixCls
}
__detail-title`
,
'
ellipsis
'
,
'
px-2
'
]
}
>
{
()
=>
title
}
</
Col
>
)
}
{
getSlot
(
slots
,
'
titleToolbar
'
)
}
</>
)
}
</
Row
>
);
}
...
...
@@ -180,41 +218,20 @@ export default defineComponent({
setDrawerProps
:
setDrawerProps
,
};
const
uuid
=
buildUUID
();
emit
(
'
register
'
,
drawerInstance
,
uuid
);
tryTsxEmit
((
instance
)
=>
{
emit
(
'
register
'
,
drawerInstance
,
instance
.
uid
);
});
return
()
=>
{
const
footerHeight
=
unref
(
getFooterHeight
);
return
(
<
Drawer
class
=
{
prefixCls
}
onClose
=
{
onClose
}
{
...{
...
attrs
,
...
unref
(
getProps
),
}
}
>
<
Drawer
class
=
{
prefixCls
}
onClose
=
{
onClose
}
{
...
unref
(
getBindValues
)
}
>
{
{
title
:
()
=>
renderHeader
(),
default
:
()
=>
(
<>
<
div
ref
=
{
scrollRef
}
{
...
attrs
}
style
=
{
{
position
:
'
relative
'
,
height
:
`calc(100% -
${
footerHeight
}
)`
,
overflow
:
'
auto
'
,
padding
:
'
16px
'
,
paddingBottom
:
'
30px
'
,
}
}
>
<
FullLoading
absolute
tip
=
{
t
(
'
loadingText
'
)
}
class
=
{
[
!
unref
(
getProps
).
loading
?
'
hidden
'
:
''
]
}
/>
{
getSlot
(
slots
,
'
default
'
)
}
<
div
ref
=
{
scrollRef
}
style
=
{
unref
(
getScrollContentStyle
)
}
>
<
FullLoading
absolute
tip
=
{
t
(
'
loadingText
'
)
}
class
=
{
unref
(
getLoading
)
}
/>
{
getSlot
(
slots
)
}
</
div
>
{
renderFooter
()
}
</>
...
...
src/components/Drawer/src/props.ts
浏览文件 @
81baf1d5
import
type
{
PropType
}
from
'
vue
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
const
{
t
}
=
useI18n
(
'
component.drawer
'
);
export
const
footerProps
=
{
confirmLoading
:
Boolean
as
PropType
<
boolean
>
,
confirmLoading
:
propTypes
.
bool
,
/**
* @description: Show close button
*/
showCancelBtn
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
showCancelBtn
:
propTypes
.
bool
.
def
(
true
),
cancelButtonProps
:
Object
as
PropType
<
any
>
,
cancelText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
t
(
'
cancelText
'
),
},
cancelText
:
propTypes
.
string
.
def
(
t
(
'
cancelText
'
)),
/**
* @description: Show confirmation button
*/
showOkBtn
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
okButtonProps
:
Object
as
PropType
<
any
>
,
okText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
t
(
'
okText
'
),
},
okType
:
{
type
:
String
as
PropType
<
string
>
,
default
:
'
primary
'
,
},
showFooter
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
showOkBtn
:
propTypes
.
bool
.
def
(
true
),
okButtonProps
:
propTypes
.
any
,
okText
:
propTypes
.
string
.
def
(
t
(
'
okText
'
)),
okType
:
propTypes
.
string
.
def
(
'
primary
'
),
showFooter
:
propTypes
.
bool
,
footerHeight
:
{
type
:
[
String
,
Number
]
as
PropType
<
string
|
number
>
,
default
:
60
,
},
};
export
const
basicProps
=
{
isDetail
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
title
:
{
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
showDetailBack
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
visible
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
loading
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
maskClosable
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
isDetail
:
propTypes
.
bool
,
title
:
propTypes
.
string
.
def
(
''
),
showDetailBack
:
propTypes
.
bool
.
def
(
true
),
visible
:
propTypes
.
bool
,
loading
:
propTypes
.
bool
,
maskClosable
:
propTypes
.
bool
.
def
(
true
),
getContainer
:
{
type
:
[
Object
,
String
]
as
PropType
<
any
>
,
},
...
...
@@ -78,10 +43,7 @@ export const basicProps = {
type
:
[
Function
,
Object
]
as
PropType
<
any
>
,
default
:
null
,
},
triggerWindowResize
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
destroyOnClose
:
Boolean
as
PropType
<
boolean
>
,
triggerWindowResize
:
propTypes
.
bool
,
destroyOnClose
:
propTypes
.
bool
,
...
footerProps
,
};
src/components/Drawer/src/types.ts
浏览文件 @
81baf1d5
...
...
@@ -75,7 +75,7 @@ export interface DrawerProps extends DrawerFooterProps {
* @type ScrollContainerOptions
*/
scrollOptions
?:
ScrollContainerOptions
;
closeFunc
?:
()
=>
Promise
<
void
>
;
closeFunc
?:
()
=>
Promise
<
any
>
;
triggerWindowResize
?:
boolean
;
/**
* Whether a close (x) button is visible on top right of the Drawer dialog or not.
...
...
src/components/Drawer/src/useDrawer.ts
浏览文件 @
81baf1d5
...
...
@@ -6,12 +6,15 @@ import type {
UseDrawerInnerReturnType
,
}
from
'
./types
'
;
import
{
ref
,
getCurrentInstance
,
onUnmounted
,
unref
,
reactive
,
watchEffect
,
nextTick
}
from
'
vue
'
;
import
{
ref
,
getCurrentInstance
,
unref
,
reactive
,
watchEffect
,
nextTick
,
toRaw
}
from
'
vue
'
;
import
{
isProdMode
}
from
'
/@/utils/env
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
isEqual
}
from
'
lodash-es
'
;
const
dataTransferRef
=
reactive
<
any
>
({});
/**
* @description: Applicable to separate drawer and call outside
*/
...
...
@@ -19,21 +22,23 @@ export function useDrawer(): UseDrawerReturnType {
if
(
!
getCurrentInstance
())
{
throw
new
Error
(
'
Please put useDrawer function in the setup function!
'
);
}
const
drawerRef
=
ref
<
DrawerInstance
|
null
>
(
null
);
const
loadedRef
=
ref
<
boolean
|
null
>
(
false
);
const
loadedRef
=
ref
<
Nullable
<
boolean
>
>
(
false
);
const
uidRef
=
ref
<
string
>
(
''
);
function
getDrawer
(
drawerInstance
:
DrawerInstance
,
uuid
:
string
)
{
uidRef
.
value
=
uuid
;
function
register
(
drawerInstance
:
DrawerInstance
,
uuid
:
string
)
{
isProdMode
()
&&
o
nUnmounted
(()
=>
{
tryO
nUnmounted
(()
=>
{
drawerRef
.
value
=
null
;
loadedRef
.
value
=
null
;
dataTransferRef
[
unref
(
uidRef
)]
=
null
;
});
if
(
unref
(
loadedRef
)
&&
isProdMode
()
&&
drawerInstance
===
unref
(
drawerRef
))
{
return
;
}
uidRef
.
value
=
uuid
;
drawerRef
.
value
=
drawerInstance
;
loadedRef
.
value
=
true
;
}
...
...
@@ -55,37 +60,46 @@ export function useDrawer(): UseDrawerReturnType {
getInstance
().
setDrawerProps
({
visible
:
visible
,
});
if
(
data
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
openOnSet
?
{
...
data
,
__t__
:
Date
.
now
(),
}
:
data
;
if
(
!
data
)
return
;
if
(
openOnSet
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
null
;
dataTransferRef
[
unref
(
uidRef
)]
=
data
;
return
;
}
const
equal
=
isEqual
(
toRaw
(
dataTransferRef
[
unref
(
uidRef
)]),
data
);
if
(
!
equal
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
data
;
}
},
};
return
[
getDraw
er
,
methods
];
return
[
regist
er
,
methods
];
}
export
const
useDrawerInner
=
(
callbackFn
?:
Fn
):
UseDrawerInnerReturnType
=>
{
const
drawerInstanceRef
=
ref
<
DrawerInstance
|
null
>
(
null
);
const
drawerInstanceRef
=
ref
<
Nullable
<
DrawerInstance
>
>
(
null
);
const
currentInstall
=
getCurrentInstance
();
const
uidRef
=
ref
<
string
>
(
''
);
if
(
!
currentInstall
)
{
throw
new
Error
(
'
instance is undefined!
'
);
throw
new
Error
(
'
useDrawerInner
instance is undefined!
'
);
}
const
getInstance
=
()
=>
{
const
instance
=
unref
(
drawerInstanceRef
);
if
(
!
instance
)
{
throw
new
Error
(
'
instance is undefined!
'
);
throw
new
Error
(
'
useDrawerInner
instance is undefined!
'
);
}
return
instance
;
};
const
register
=
(
modalInstance
:
DrawerInstance
,
uuid
:
string
)
=>
{
isProdMode
()
&&
tryOnUnmounted
(()
=>
{
drawerInstanceRef
.
value
=
null
;
});
uidRef
.
value
=
uuid
;
drawerInstanceRef
.
value
=
modalInstance
;
currentInstall
.
emit
(
'
register
'
,
modalInstance
);
...
...
src/components/Modal/index.ts
浏览文件 @
81baf1d5
import
'
./src/index.less
'
;
export
{
default
as
BasicModal
}
from
'
./src/BasicModal
'
;
export
{
default
as
Modal
}
from
'
./src/Modal
'
;
import
BasicModalLib
from
'
./src/BasicModal
'
;
import
{
withInstall
}
from
'
../util
'
;
export
{
useModalContext
}
from
'
./src/useModalContext
'
;
export
{
useModal
,
useModalInner
}
from
'
./src/useModal
'
;
export
*
from
'
./src/types
'
;
export
const
BasicModal
=
withInstall
(
BasicModalLib
);
src/components/Modal/src/BasicModal.tsx
浏览文件 @
81baf1d5
import
type
{
ModalProps
,
ModalMethods
}
from
'
./types
'
;
import
{
defineComponent
,
computed
,
ref
,
watch
,
unref
,
watchEffect
}
from
'
vue
'
;
import
{
defineComponent
,
computed
,
ref
,
watch
,
unref
,
watchEffect
,
toRef
}
from
'
vue
'
;
import
Modal
from
'
./Modal
'
;
import
{
Button
}
from
'
/@/components/Button
'
;
...
...
@@ -11,10 +11,10 @@ import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-
import
{
getSlot
,
extendSlots
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
deepMerge
}
from
'
/@/utils
'
;
import
{
buildUUID
}
from
'
/@/utils/uuid
'
;
import
{
tryTsxEmit
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
basicProps
}
from
'
./props
'
;
// import { triggerWindowResize } from '@/utils/event/triggerWindowResizeEvent
';
import
{
useFullScreen
}
from
'
./useFullScreen
'
;
export
default
defineComponent
({
name
:
'
BasicModal
'
,
props
:
basicProps
,
...
...
@@ -26,31 +26,41 @@ export default defineComponent({
// modal Bottom and top height
const
extHeightRef
=
ref
(
0
);
// Unexpanded height of the popup
const
formerHeightRef
=
ref
(
0
);
const
fullScreenRef
=
ref
(
false
);
// Custom title component: get title
const
getMergeProps
=
computed
(()
=>
{
return
{
...
props
,
...(
unref
(
propsRef
)
as
any
),
};
const
getMergeProps
=
computed
(
():
ModalProps
=>
{
return
{
...
props
,
...(
unref
(
propsRef
)
as
any
),
};
}
);
const
{
handleFullScreen
,
getWrapClassName
,
fullScreenRef
}
=
useFullScreen
({
modalWrapperRef
,
extHeightRef
,
wrapClassName
:
toRef
(
getMergeProps
.
value
,
'
wrapClassName
'
),
});
// modal component does not need title
const
getProps
=
computed
(():
any
=>
{
const
opt
=
{
...
props
,
...((
unref
(
propsRef
)
||
{})
as
any
),
visible
:
unref
(
visibleRef
),
title
:
undefined
,
};
const
{
wrapClassName
=
''
}
=
opt
;
const
className
=
unref
(
fullScreenRef
)
?
`
${
wrapClassName
}
fullscreen-modal`
:
wrapClassName
;
return
{
...
opt
,
wrapClassName
:
className
,
};
const
getProps
=
computed
(
():
ModalProps
=>
{
const
opt
=
{
...
unref
(
getMergeProps
),
visible
:
unref
(
visibleRef
),
title
:
undefined
,
};
return
{
...
opt
,
wrapClassName
:
unref
(
getWrapClassName
),
};
}
);
const
getModalBindValue
=
computed
(():
any
=>
{
return
{
...
attrs
,
...
unref
(
getProps
)
};
});
watchEffect
(()
=>
{
...
...
@@ -80,7 +90,35 @@ export default defineComponent({
);
}
// 取消事件
async
function
handleCancel
(
e
:
Event
)
{
e
?.
stopPropagation
();
if
(
props
.
closeFunc
&&
isFunction
(
props
.
closeFunc
))
{
const
isClose
:
boolean
=
await
props
.
closeFunc
();
visibleRef
.
value
=
!
isClose
;
return
;
}
visibleRef
.
value
=
false
;
emit
(
'
cancel
'
);
}
/**
* @description: 设置modal参数
*/
function
setModalProps
(
props
:
Partial
<
ModalProps
>
):
void
{
// Keep the last setModalProps
propsRef
.
value
=
deepMerge
(
unref
(
propsRef
)
||
{},
props
);
if
(
!
Reflect
.
has
(
props
,
'
visible
'
))
return
;
visibleRef
.
value
=
!!
props
.
visible
;
}
function
renderContent
()
{
type
OmitWrapperType
=
Omit
<
ModalProps
,
'
fullScreen
'
|
'
modalFooterHeight
'
|
'
visible
'
|
'
loading
'
>
;
const
{
useWrapper
,
loading
,
wrapperProps
}
=
unref
(
getProps
);
if
(
!
useWrapper
)
return
getSlot
(
slots
);
...
...
@@ -93,7 +131,7 @@ export default defineComponent({
loading
=
{
loading
}
visible
=
{
unref
(
visibleRef
)
}
modalFooterHeight
=
{
showFooter
}
{
...
wrapperProps
}
{
...
((
wrapperProps
as
unknown
)
as
OmitWrapperType
)
}
onGetExtHeight
=
{
(
height
:
number
)
=>
{
extHeightRef
.
value
=
height
;
}
}
...
...
@@ -106,18 +144,6 @@ export default defineComponent({
);
}
// 取消事件
async
function
handleCancel
(
e
:
Event
)
{
e
&&
e
.
stopPropagation
();
if
(
props
.
closeFunc
&&
isFunction
(
props
.
closeFunc
))
{
const
isClose
:
boolean
=
await
props
.
closeFunc
();
visibleRef
.
value
=
!
isClose
;
return
;
}
visibleRef
.
value
=
false
;
emit
(
'
cancel
'
);
}
// 底部按钮自定义实现,
function
renderFooter
()
{
const
{
...
...
@@ -162,64 +188,37 @@ export default defineComponent({
*/
function
renderClose
()
{
const
{
canFullscreen
}
=
unref
(
getProps
);
if
(
!
canFullscreen
)
{
return
null
;
}
const
fullScreen
=
unref
(
fullScreenRef
)
?
(
<
FullscreenExitOutlined
role
=
"full"
onClick
=
{
handleFullScreen
}
/>
)
:
(
<
FullscreenOutlined
role
=
"close"
onClick
=
{
handleFullScreen
}
/>
);
const
cls
=
[
'
custom-close-icon
'
,
{
'
can-full
'
:
canFullscreen
,
},
];
return
(
<
div
class
=
"custom-close-icon"
>
{
unref
(
fullScreenRef
)
?
(
<
FullscreenExitOutlined
role
=
"full"
onClick
=
{
handleFullScreen
}
/>
)
:
(
<
FullscreenOutlined
role
=
"close"
onClick
=
{
handleFullScreen
}
/>
)
}
<
div
class
=
{
cls
}
>
{
canFullscreen
&&
fullScreen
}
<
CloseOutlined
onClick
=
{
handleCancel
}
/>
</
div
>
);
}
function
handleFullScreen
(
e
:
Event
)
{
e
&&
e
.
stopPropagation
();
fullScreenRef
.
value
=
!
unref
(
fullScreenRef
);
const
modalWrapper
=
unref
(
modalWrapperRef
);
if
(
!
modalWrapper
)
return
;
const
wrapperEl
=
modalWrapper
.
$el
as
HTMLElement
;
if
(
!
wrapperEl
)
return
;
const
modalWrapSpinEl
=
wrapperEl
.
querySelector
(
'
.ant-spin-nested-loading
'
)
as
HTMLElement
;
if
(
!
modalWrapSpinEl
)
return
;
if
(
!
unref
(
formerHeightRef
)
&&
unref
(
fullScreenRef
))
{
formerHeightRef
.
value
=
modalWrapSpinEl
.
offsetHeight
;
}
if
(
unref
(
fullScreenRef
))
{
modalWrapSpinEl
.
style
.
height
=
`
${
window
.
innerHeight
-
unref
(
extHeightRef
)}
px`
;
}
else
{
modalWrapSpinEl
.
style
.
height
=
`
${
unref
(
formerHeightRef
)}
px`
;
}
}
/**
* @description: 设置modal参数
*/
function
setModalProps
(
props
:
Partial
<
ModalProps
>
):
void
{
// Keep the last setModalProps
propsRef
.
value
=
deepMerge
(
unref
(
propsRef
)
||
{},
props
);
if
(
!
Reflect
.
has
(
props
,
'
visible
'
))
return
;
visibleRef
.
value
=
!!
props
.
visible
;
}
const
modalMethods
:
ModalMethods
=
{
setModalProps
,
};
const
uuid
=
buildUUID
();
emit
(
'
register
'
,
modalMethods
,
u
uid
);
tryTsxEmit
((
instance
)
=>
{
emit
(
'
register
'
,
modalMethods
,
instance
.
uid
);
});
return
()
=>
(
<
Modal
onCancel
=
{
handleCancel
}
{
...
{
...
attrs
,
...
props
,
...
unref
(
getProps
)
}
}
>
<
Modal
onCancel
=
{
handleCancel
}
{
...
unref
(
getModalBindValue
)
}
>
{
{
footer
:
()
=>
renderFooter
(),
closeIcon
:
()
=>
renderClose
(),
...
...
src/components/Modal/src/Modal.tsx
浏览文件 @
81baf1d5
import
{
Modal
}
from
'
ant-design-vue
'
;
import
{
defineComponent
,
watchEffect
}
from
'
vue
'
;
import
{
defineComponent
,
toRefs
}
from
'
vue
'
;
import
{
basicProps
}
from
'
./props
'
;
import
{
use
TimeoutFn
}
from
'
/@/hooks/core/useTimeout
'
;
import
{
use
ModalDragMove
}
from
'
./useModalDrag
'
;
import
{
extendSlots
}
from
'
/@/utils/helper/tsxHelper
'
;
export
default
defineComponent
({
...
...
@@ -9,99 +9,12 @@ export default defineComponent({
inheritAttrs
:
false
,
props
:
basicProps
,
setup
(
props
,
{
attrs
,
slots
})
{
const
getStyle
=
(
dom
:
any
,
attr
:
any
)
=>
{
return
getComputedStyle
(
dom
)[
attr
];
};
const
drag
=
(
wrap
:
any
)
=>
{
if
(
!
wrap
)
return
;
wrap
.
setAttribute
(
'
data-drag
'
,
props
.
draggable
);
const
dialogHeaderEl
=
wrap
.
querySelector
(
'
.ant-modal-header
'
);
const
dragDom
=
wrap
.
querySelector
(
'
.ant-modal
'
);
if
(
!
dialogHeaderEl
||
!
dragDom
||
!
props
.
draggable
)
return
;
dialogHeaderEl
.
style
.
cursor
=
'
move
'
;
dialogHeaderEl
.
onmousedown
=
(
e
:
any
)
=>
{
if
(
!
e
)
return
;
// 鼠标按下,计算当前元素距离可视区的距离
const
disX
=
e
.
clientX
;
const
disY
=
e
.
clientY
;
const
screenWidth
=
document
.
body
.
clientWidth
;
// body当前宽度
const
screenHeight
=
document
.
documentElement
.
clientHeight
;
// 可见区域高度(应为body高度,可某些环境下无法获取)
const
dragDomWidth
=
dragDom
.
offsetWidth
;
// 对话框宽度
const
dragDomheight
=
dragDom
.
offsetHeight
;
// 对话框高度
const
minDragDomLeft
=
dragDom
.
offsetLeft
;
const
maxDragDomLeft
=
screenWidth
-
dragDom
.
offsetLeft
-
dragDomWidth
;
const
minDragDomTop
=
dragDom
.
offsetTop
;
const
maxDragDomTop
=
screenHeight
-
dragDom
.
offsetTop
-
dragDomheight
;
// 获取到的值带px 正则匹配替换
const
domLeft
=
getStyle
(
dragDom
,
'
left
'
);
const
domTop
=
getStyle
(
dragDom
,
'
top
'
);
let
styL
=
+
domLeft
;
let
styT
=
+
domTop
;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if
(
domLeft
.
includes
(
'
%
'
))
{
styL
=
+
document
.
body
.
clientWidth
*
(
+
domLeft
.
replace
(
/%/g
,
''
)
/
100
);
styT
=
+
document
.
body
.
clientHeight
*
(
+
domTop
.
replace
(
/%/g
,
''
)
/
100
);
}
else
{
styL
=
+
domLeft
.
replace
(
/px/g
,
''
);
styT
=
+
domTop
.
replace
(
/px/g
,
''
);
}
document
.
onmousemove
=
function
(
e
)
{
// 通过事件委托,计算移动的距离
let
left
=
e
.
clientX
-
disX
;
let
top
=
e
.
clientY
-
disY
;
// 边界处理
if
(
-
left
>
minDragDomLeft
)
{
left
=
-
minDragDomLeft
;
}
else
if
(
left
>
maxDragDomLeft
)
{
left
=
maxDragDomLeft
;
}
if
(
-
top
>
minDragDomTop
)
{
top
=
-
minDragDomTop
;
}
else
if
(
top
>
maxDragDomTop
)
{
top
=
maxDragDomTop
;
}
// 移动当前元素
dragDom
.
style
.
cssText
+=
`;left:
${
left
+
styL
}
px;top:
${
top
+
styT
}
px;`
;
};
document
.
onmouseup
=
()
=>
{
document
.
onmousemove
=
null
;
document
.
onmouseup
=
null
;
};
};
};
const
handleDrag
=
()
=>
{
const
dragWraps
=
document
.
querySelectorAll
(
'
.ant-modal-wrap
'
);
for
(
const
wrap
of
dragWraps
as
any
)
{
if
(
!
wrap
)
continue
;
const
display
=
getStyle
(
wrap
,
'
display
'
);
const
draggable
=
wrap
.
getAttribute
(
'
data-drag
'
);
if
(
display
!==
'
none
'
)
{
// 拖拽位置
(
draggable
===
null
||
props
.
destroyOnClose
)
&&
drag
(
wrap
);
}
}
};
const
{
visible
,
draggable
,
destroyOnClose
}
=
toRefs
(
props
);
watchEffect
(()
=>
{
if
(
!
props
.
visible
)
{
return
;
}
useTimeoutFn
(()
=>
{
handleDrag
();
},
30
);
useModalDragMove
({
visible
,
destroyOnClose
,
draggable
,
});
return
()
=>
{
...
...
src/components/Modal/src/ModalWrapper.tsx
浏览文件 @
81baf1d5
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
ModalWrapperProps
}
from
'
./types
'
;
import
type
{
CSSProperties
}
from
'
vue
'
;
import
{
defineComponent
,
...
...
@@ -18,59 +18,44 @@ import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import
{
getSlot
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
useElResize
}
from
'
/@/hooks/event/useElResize
'
;
import
{
provideModal
}
from
'
./provideModal
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
createModalContext
}
from
'
./useModalContext
'
;
export
default
defineComponent
({
name
:
'
ModalWrapper
'
,
props
:
{
loading
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
modalHeaderHeight
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
50
,
},
modalFooterHeight
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
70
,
},
minHeight
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
200
,
},
footerOffset
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
0
,
},
visible
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
fullScreen
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
loading
:
propTypes
.
bool
,
modalHeaderHeight
:
propTypes
.
number
.
def
(
50
),
modalFooterHeight
:
propTypes
.
number
.
def
(
54
),
minHeight
:
propTypes
.
number
.
def
(
200
),
footerOffset
:
propTypes
.
number
.
def
(
0
),
visible
:
propTypes
.
bool
,
fullScreen
:
propTypes
.
bool
,
},
emits
:
[
'
heightChange
'
,
'
getExtHeight
'
],
setup
(
props
:
ModalWrapperProps
,
{
slots
,
emit
})
{
const
wrapperRef
=
ref
<
HTMLElement
|
null
>
(
null
);
const
wrapperRef
=
ref
<
ElRef
>
(
null
);
const
spinRef
=
ref
<
ComponentRef
>
(
null
);
const
realHeightRef
=
ref
(
0
);
// 重试次数
// let tryCount = 0;
let
stopElResizeFn
:
Fn
=
()
=>
{};
provideModal
(
setModalHeight
);
useWindowSizeFn
(
setModalHeight
);
const
wrapStyle
=
computed
(()
=>
{
return
{
minHeight
:
`
${
props
.
minHeight
}
px`
,
height
:
`
${
unref
(
realHeightRef
)}
px`
,
overflow
:
'
auto
'
,
};
createModalContext
({
redoModalHeight
:
setModalHeight
,
});
const
wrapStyle
=
computed
(
():
CSSProperties
=>
{
return
{
minHeight
:
`
${
props
.
minHeight
}
px`
,
height
:
`
${
unref
(
realHeightRef
)}
px`
,
overflow
:
'
auto
'
,
};
}
);
watchEffect
(()
=>
{
setModalHeight
();
});
...
...
@@ -92,8 +77,6 @@ export default defineComponent({
stopElResizeFn
&&
stopElResizeFn
();
});
useWindowSizeFn
(
setModalHeight
);
async
function
setModalHeight
()
{
// 解决在弹窗关闭的时候监听还存在,导致再次打开弹窗没有高度
// 加上这个,就必须在使用的时候传递父级的visible
...
...
@@ -107,9 +90,8 @@ export default defineComponent({
try
{
const
modalDom
=
bodyDom
.
parentElement
&&
bodyDom
.
parentElement
.
parentElement
;
if
(
!
modalDom
)
{
return
;
}
if
(
!
modalDom
)
return
;
const
modalRect
=
getComputedStyle
(
modalDom
).
top
;
const
modalTop
=
Number
.
parseInt
(
modalRect
);
let
maxHeight
=
...
...
@@ -135,11 +117,12 @@ export default defineComponent({
if
(
props
.
fullScreen
)
{
realHeightRef
.
value
=
window
.
innerHeight
-
props
.
modalFooterHeight
-
props
.
modalHeaderHeight
-
6
;
window
.
innerHeight
-
props
.
modalFooterHeight
-
props
.
modalHeaderHeight
;
}
else
{
realHeightRef
.
value
=
realHeight
>
maxHeight
?
maxHeight
:
realHeight
+
16
+
30
;
}
emit
(
'
heightChange
'
,
unref
(
realHeightRef
));
nextTick
(()
=>
{
const
el
=
spinEl
.
$el
;
if
(
el
)
{
...
...
@@ -154,8 +137,10 @@ export default defineComponent({
function
listenElResize
()
{
const
wrapper
=
unref
(
wrapperRef
);
if
(
!
wrapper
)
return
;
const
container
=
wrapper
.
querySelector
(
'
.ant-spin-container
'
);
if
(
!
container
)
return
;
const
[
start
,
stop
]
=
useElResize
(
container
,
()
=>
{
setModalHeight
();
});
...
...
src/components/Modal/src/index.less
浏览文件 @
81baf1d5
...
...
@@ -9,6 +9,11 @@
bottom: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100%;
&-content {
height: 100%;
}
}
}
...
...
@@ -35,8 +40,23 @@
height: 95%;
align-items: center;
> * {
margin-left: 12px;
> span {
margin-left: 48px;
font-size: 16px;
}
&.can-full {
> span {
margin-left: 12px;
}
}
&:not(.can-full) {
> span:nth-child(1) {
&:hover {
font-weight: 700;
}
}
}
& span:nth-child(1) {
...
...
@@ -76,7 +96,7 @@
}
&-footer {
padding: 10px 26px 26px 16px;
//
padding: 10px 26px 26px 16px;
button + button {
margin-left: 10px;
...
...
src/components/Modal/src/props.ts
浏览文件 @
81baf1d5
...
...
@@ -2,66 +2,38 @@ import type { PropType } from 'vue';
import
{
ButtonProps
}
from
'
ant-design-vue/es/button/buttonTypes
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
const
{
t
}
=
useI18n
(
'
component.modal
'
);
export
const
modalProps
=
{
visible
:
Boolean
as
PropType
<
boolean
>
,
visible
:
propTypes
.
bool
,
// open drag
draggable
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
centered
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
cancelText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
t
(
'
cancelText
'
),
},
okText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
t
(
'
okText
'
),
},
draggable
:
propTypes
.
bool
.
def
(
true
),
centered
:
propTypes
.
bool
,
cancelText
:
propTypes
.
string
.
def
(
t
(
'
cancelText
'
)),
okText
:
propTypes
.
string
.
def
(
t
(
'
okText
'
)),
closeFunc
:
Function
as
PropType
<
()
=>
Promise
<
boolean
>>
,
};
export
const
basicProps
=
Object
.
assign
({},
modalProps
,
{
// Can it be full screen
canFullscreen
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
canFullscreen
:
propTypes
.
bool
.
def
(
true
),
// After enabling the wrapper, the bottom can be increased in height
wrapperFooterOffset
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
0
,
},
wrapperFooterOffset
:
propTypes
.
number
.
def
(
0
),
// Warm reminder message
helpMessage
:
[
String
,
Array
]
as
PropType
<
string
|
string
[]
>
,
// Whether to setting wrapper
useWrapper
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
loading
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
useWrapper
:
propTypes
.
bool
.
def
(
true
),
loading
:
propTypes
.
bool
,
/**
* @description: Show close button
*/
showCancelBtn
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
showCancelBtn
:
propTypes
.
bool
.
def
(
true
),
/**
* @description: Show confirmation button
*/
showOkBtn
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
showOkBtn
:
propTypes
.
bool
.
def
(
true
),
wrapperProps
:
Object
as
PropType
<
any
>
,
...
...
src/components/Modal/src/provideModal.ts
已删除
100644 → 0
浏览文件 @
819127e8
import
{
provide
,
inject
}
from
'
vue
'
;
const
key
=
Symbol
(
'
basic-modal
'
);
export
function
provideModal
(
redoHeight
:
Fn
)
{
provide
(
key
,
redoHeight
);
}
export
function
injectModal
():
Fn
{
return
inject
(
key
,
()
=>
{})
as
Fn
;
}
src/components/Modal/src/types.ts
浏览文件 @
81baf1d5
...
...
@@ -8,9 +8,11 @@ export interface ModalMethods {
}
export
type
RegisterFn
=
(
modalMethods
:
ModalMethods
,
uuid
?:
string
)
=>
void
;
export
interface
ReturnMethods
extends
ModalMethods
{
openModal
:
<
T
=
any
>
(
props
?:
boolean
,
data
?:
T
,
openOnSet
?:
boolean
)
=>
void
;
}
export
type
UseModalReturnType
=
[
RegisterFn
,
ReturnMethods
];
export
interface
ReturnInnerMethods
extends
ModalMethods
{
...
...
@@ -18,6 +20,7 @@ export interface ReturnInnerMethods extends ModalMethods {
changeLoading
:
(
loading
:
boolean
)
=>
void
;
changeOkLoading
:
(
loading
:
boolean
)
=>
void
;
}
export
type
UseModalInnerReturnType
=
[
RegisterFn
,
ReturnInnerMethods
];
export
interface
ModalProps
{
...
...
src/components/Modal/src/useFullScreen.ts
0 → 100644
浏览文件 @
81baf1d5
import
{
computed
,
Ref
,
ref
,
unref
}
from
'
vue
'
;
export
interface
UseFullScreenContext
{
wrapClassName
:
Ref
<
string
|
undefined
>
;
modalWrapperRef
:
Ref
<
ComponentRef
>
;
extHeightRef
:
Ref
<
number
>
;
}
export
function
useFullScreen
(
context
:
UseFullScreenContext
)
{
const
formerHeightRef
=
ref
(
0
);
const
fullScreenRef
=
ref
(
false
);
const
getWrapClassName
=
computed
(()
=>
{
const
clsName
=
unref
(
context
.
wrapClassName
)
||
''
;
return
unref
(
fullScreenRef
)
?
`fullscreen-modal
${
clsName
}
`
:
unref
(
clsName
);
});
function
handleFullScreen
(
e
:
Event
)
{
e
&&
e
.
stopPropagation
();
fullScreenRef
.
value
=
!
unref
(
fullScreenRef
);
const
modalWrapper
=
unref
(
context
.
modalWrapperRef
);
if
(
!
modalWrapper
)
return
;
const
wrapperEl
=
modalWrapper
.
$el
as
HTMLElement
;
if
(
!
wrapperEl
)
return
;
const
modalWrapSpinEl
=
wrapperEl
.
querySelector
(
'
.ant-spin-nested-loading
'
)
as
HTMLElement
;
if
(
!
modalWrapSpinEl
)
return
;
if
(
!
unref
(
formerHeightRef
)
&&
unref
(
fullScreenRef
))
{
formerHeightRef
.
value
=
modalWrapSpinEl
.
offsetHeight
;
}
if
(
unref
(
fullScreenRef
))
{
modalWrapSpinEl
.
style
.
height
=
`
${
window
.
innerHeight
-
unref
(
context
.
extHeightRef
)}
px`
;
}
else
{
modalWrapSpinEl
.
style
.
height
=
`
${
unref
(
formerHeightRef
)}
px`
;
}
}
return
{
getWrapClassName
,
handleFullScreen
,
fullScreenRef
};
}
src/components/Modal/src/useModal.ts
浏览文件 @
81baf1d5
...
...
@@ -5,9 +5,21 @@ import type {
ReturnMethods
,
UseModalInnerReturnType
,
}
from
'
./types
'
;
import
{
ref
,
onUnmounted
,
unref
,
getCurrentInstance
,
reactive
,
watchEffect
,
nextTick
}
from
'
vue
'
;
import
{
ref
,
onUnmounted
,
unref
,
getCurrentInstance
,
reactive
,
watchEffect
,
nextTick
,
toRaw
,
}
from
'
vue
'
;
import
{
isProdMode
}
from
'
/@/utils/env
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
isEqual
}
from
'
lodash-es
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
const
dataTransferRef
=
reactive
<
any
>
({});
/**
...
...
@@ -20,6 +32,7 @@ export function useModal(): UseModalReturnType {
const
modalRef
=
ref
<
Nullable
<
ModalMethods
>>
(
null
);
const
loadedRef
=
ref
<
Nullable
<
boolean
>>
(
false
);
const
uidRef
=
ref
<
string
>
(
''
);
function
register
(
modalMethod
:
ModalMethods
,
uuid
:
string
)
{
uidRef
.
value
=
uuid
;
...
...
@@ -52,13 +65,16 @@ export function useModal(): UseModalReturnType {
visible
:
visible
,
});
if
(
data
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
openOnSet
?
{
...
data
,
__t__
:
Date
.
now
(),
}
:
data
;
if
(
!
data
)
return
;
if
(
openOnSet
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
null
;
dataTransferRef
[
unref
(
uidRef
)]
=
data
;
return
;
}
const
equal
=
isEqual
(
toRaw
(
dataTransferRef
[
unref
(
uidRef
)]),
data
);
if
(
!
equal
)
{
dataTransferRef
[
unref
(
uidRef
)]
=
data
;
}
},
};
...
...
@@ -66,7 +82,7 @@ export function useModal(): UseModalReturnType {
}
export
const
useModalInner
=
(
callbackFn
?:
Fn
):
UseModalInnerReturnType
=>
{
const
modalInstanceRef
=
ref
<
ModalMethods
|
null
>
(
null
);
const
modalInstanceRef
=
ref
<
Nullable
<
ModalMethods
>
>
(
null
);
const
currentInstall
=
getCurrentInstance
();
const
uidRef
=
ref
<
string
>
(
''
);
...
...
@@ -83,6 +99,11 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => {
};
const
register
=
(
modalInstance
:
ModalMethods
,
uuid
:
string
)
=>
{
isProdMode
()
&&
tryOnUnmounted
(()
=>
{
modalInstanceRef
.
value
=
null
;
});
uidRef
.
value
=
uuid
;
modalInstanceRef
.
value
=
modalInstance
;
currentInstall
.
emit
(
'
register
'
,
modalInstance
);
...
...
src/components/Modal/src/useModalContext.ts
0 → 100644
浏览文件 @
81baf1d5
import
{
InjectionKey
}
from
'
vue
'
;
import
{
createContext
,
useContext
}
from
'
/@/hooks/core/useContext
'
;
export
interface
ModalContextProps
{
redoModalHeight
:
()
=>
void
;
}
const
modalContextInjectKey
:
InjectionKey
<
ModalContextProps
>
=
Symbol
();
export
function
createModalContext
(
context
:
ModalContextProps
)
{
return
createContext
<
ModalContextProps
>
(
context
,
modalContextInjectKey
);
}
export
function
useModalContext
()
{
return
useContext
<
ModalContextProps
>
(
modalContextInjectKey
);
}
src/components/Modal/src/useModalDrag.ts
0 → 100644
浏览文件 @
81baf1d5
import
{
Ref
,
unref
,
watchEffect
}
from
'
vue
'
;
import
{
useTimeoutFn
}
from
'
/@/hooks/core/useTimeout
'
;
export
interface
UseModalDragMoveContext
{
draggable
:
Ref
<
boolean
>
;
destroyOnClose
:
Ref
<
boolean
|
undefined
>
|
undefined
;
visible
:
Ref
<
boolean
>
;
}
export
function
useModalDragMove
(
context
:
UseModalDragMoveContext
)
{
const
getStyle
=
(
dom
:
any
,
attr
:
any
)
=>
{
return
getComputedStyle
(
dom
)[
attr
];
};
const
drag
=
(
wrap
:
any
)
=>
{
if
(
!
wrap
)
return
;
wrap
.
setAttribute
(
'
data-drag
'
,
unref
(
context
.
draggable
));
const
dialogHeaderEl
=
wrap
.
querySelector
(
'
.ant-modal-header
'
);
const
dragDom
=
wrap
.
querySelector
(
'
.ant-modal
'
);
if
(
!
dialogHeaderEl
||
!
dragDom
||
!
unref
(
context
.
draggable
))
return
;
dialogHeaderEl
.
style
.
cursor
=
'
move
'
;
dialogHeaderEl
.
onmousedown
=
(
e
:
any
)
=>
{
if
(
!
e
)
return
;
// 鼠标按下,计算当前元素距离可视区的距离
const
disX
=
e
.
clientX
;
const
disY
=
e
.
clientY
;
const
screenWidth
=
document
.
body
.
clientWidth
;
// body当前宽度
const
screenHeight
=
document
.
documentElement
.
clientHeight
;
// 可见区域高度(应为body高度,可某些环境下无法获取)
const
dragDomWidth
=
dragDom
.
offsetWidth
;
// 对话框宽度
const
dragDomheight
=
dragDom
.
offsetHeight
;
// 对话框高度
const
minDragDomLeft
=
dragDom
.
offsetLeft
;
const
maxDragDomLeft
=
screenWidth
-
dragDom
.
offsetLeft
-
dragDomWidth
;
const
minDragDomTop
=
dragDom
.
offsetTop
;
const
maxDragDomTop
=
screenHeight
-
dragDom
.
offsetTop
-
dragDomheight
;
// 获取到的值带px 正则匹配替换
const
domLeft
=
getStyle
(
dragDom
,
'
left
'
);
const
domTop
=
getStyle
(
dragDom
,
'
top
'
);
let
styL
=
+
domLeft
;
let
styT
=
+
domTop
;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if
(
domLeft
.
includes
(
'
%
'
))
{
styL
=
+
document
.
body
.
clientWidth
*
(
+
domLeft
.
replace
(
/%/g
,
''
)
/
100
);
styT
=
+
document
.
body
.
clientHeight
*
(
+
domTop
.
replace
(
/%/g
,
''
)
/
100
);
}
else
{
styL
=
+
domLeft
.
replace
(
/px/g
,
''
);
styT
=
+
domTop
.
replace
(
/px/g
,
''
);
}
document
.
onmousemove
=
function
(
e
)
{
// 通过事件委托,计算移动的距离
let
left
=
e
.
clientX
-
disX
;
let
top
=
e
.
clientY
-
disY
;
// 边界处理
if
(
-
left
>
minDragDomLeft
)
{
left
=
-
minDragDomLeft
;
}
else
if
(
left
>
maxDragDomLeft
)
{
left
=
maxDragDomLeft
;
}
if
(
-
top
>
minDragDomTop
)
{
top
=
-
minDragDomTop
;
}
else
if
(
top
>
maxDragDomTop
)
{
top
=
maxDragDomTop
;
}
// 移动当前元素
dragDom
.
style
.
cssText
+=
`;left:
${
left
+
styL
}
px;top:
${
top
+
styT
}
px;`
;
};
document
.
onmouseup
=
()
=>
{
document
.
onmousemove
=
null
;
document
.
onmouseup
=
null
;
};
};
};
const
handleDrag
=
()
=>
{
const
dragWraps
=
document
.
querySelectorAll
(
'
.ant-modal-wrap
'
);
for
(
const
wrap
of
Array
.
from
(
dragWraps
))
{
if
(
!
wrap
)
continue
;
const
display
=
getStyle
(
wrap
,
'
display
'
);
const
draggable
=
wrap
.
getAttribute
(
'
data-drag
'
);
if
(
display
!==
'
none
'
)
{
// 拖拽位置
if
(
draggable
===
null
||
unref
(
context
.
destroyOnClose
))
{
drag
(
wrap
);
}
}
}
};
watchEffect
(()
=>
{
if
(
!
unref
(
context
.
visible
)
||
!
unref
(
context
.
draggable
))
{
return
;
}
useTimeoutFn
(()
=>
{
handleDrag
();
},
30
);
});
}
src/components/Scrollbar/src/Scrollbar.tsx
浏览文件 @
81baf1d5
...
...
@@ -65,7 +65,7 @@ export default defineComponent({
}
onMounted
(()
=>
{
tryTsxEmit
((
instance
)
=>
{
tryTsxEmit
<
any
>
((
instance
)
=>
{
instance
.
wrap
=
unref
(
wrapElRef
);
});
...
...
src/components/Table/src/hooks/useTableScroll.ts
浏览文件 @
81baf1d5
import
type
{
BasicTableProps
}
from
'
../types/table
'
;
import
{
computed
,
Ref
,
onMounted
,
unref
,
ref
,
nextTick
,
ComputedRef
,
watch
}
from
'
vue
'
;
import
{
injectModal
}
from
'
/@/components/Modal/src/provideModal
'
;
import
{
getViewportOffset
}
from
'
/@/utils/domUtils
'
;
import
{
isBoolean
}
from
'
/@/utils/is
'
;
import
{
useWindowSizeFn
}
from
'
/@/hooks/event/useWindowSizeFn
'
;
import
{
useProps
}
from
'
./useProps
'
;
import
{
useModalContext
}
from
'
/@/components/Modal
'
;
export
function
useTableScroll
(
refProps
:
ComputedRef
<
BasicTableProps
>
,
tableElRef
:
Ref
<
any
>
)
{
const
{
propsRef
}
=
useProps
(
refProps
);
const
tableHeightRef
:
Ref
<
number
|
null
>
=
ref
(
null
);
const
redoModalHeight
=
injectModal
();
const
modalFn
=
useModalContext
();
watch
(
()
=>
unref
(
propsRef
).
canResize
,
...
...
@@ -93,7 +92,7 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
tableHeightRef
.
value
=
tableHeightRef
.
value
!
>
maxHeight
!
?
(
maxHeight
as
number
)
:
tableHeightRef
.
value
;
// 解决表格放modal内的时候,modal自适应高度计算问题
redoModalHeight
&&
redoModalHeight
();
modalFn
?.
redoModalHeight
?.
();
},
16
);
}
...
...
src/components/Tree/src/BasicTree.tsx
浏览文件 @
81baf1d5
import
'
./index.less
'
;
import
type
{
ReplaceFields
,
TreeItem
,
Keys
,
CheckKeys
}
from
'
./types
'
;
import
type
{
ReplaceFields
,
TreeItem
,
Keys
,
CheckKeys
,
TreeActionType
}
from
'
./types
'
;
import
{
defineComponent
,
reactive
,
computed
,
unref
,
ref
,
watchEffect
,
CSSProperties
}
from
'
vue
'
;
import
{
Tree
}
from
'
ant-design-vue
'
;
...
...
@@ -124,7 +124,6 @@ export default defineComponent({
title
:
()
=>
(
<
span
class
=
{
`
${
prefixCls
}
-title`
}
>
<
span
class
=
{
`
${
prefixCls
}
__content`
}
style
=
{
unref
(
getContentStyle
)
}
>
{
'
'
}
{
titleField
&&
anyItem
[
titleField
]
}
</
span
>
<
span
class
=
{
`
${
prefixCls
}
__actions`
}
>
{
renderAction
(
item
)
}
</
span
>
...
...
@@ -183,7 +182,7 @@ export default defineComponent({
state
.
checkedKeys
=
props
.
checkedKeys
;
});
tryTsxEmit
((
currentInstance
)
=>
{
tryTsxEmit
<
TreeActionType
>
((
currentInstance
)
=>
{
currentInstance
.
setExpandedKeys
=
setExpandedKeys
;
currentInstance
.
getExpandedKeys
=
getExpandedKeys
;
currentInstance
.
setSelectedKeys
=
setSelectedKeys
;
...
...
src/components/Tree/src/useTree.ts
浏览文件 @
81baf1d5
...
...
@@ -10,7 +10,7 @@ export function useTree(
getReplaceFields
:
ComputedRef
<
ReplaceFields
>
)
{
// 更新节点
function
updateNodeByKey
(
key
:
string
,
node
:
TreeItem
,
list
:
TreeItem
[])
{
function
updateNodeByKey
(
key
:
string
,
node
:
TreeItem
,
list
?
:
TreeItem
[])
{
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
...
@@ -75,7 +75,7 @@ export function useTree(
}
// 删除节点
function
deleteNodeByKey
(
key
:
string
,
list
:
TreeItem
[])
{
function
deleteNodeByKey
(
key
:
string
,
list
?
:
TreeItem
[])
{
if
(
!
key
)
return
;
const
treeData
=
list
||
unref
(
treeDataRef
);
const
{
key
:
keyField
,
children
:
childrenField
}
=
unref
(
getReplaceFields
);
...
...
src/components/Verify/src/DragVerify.tsx
浏览文件 @
81baf1d5
...
...
@@ -6,6 +6,7 @@ import { getSlot } from '/@/utils/helper/tsxHelper';
import
'
./DragVerify.less
'
;
import
{
CheckOutlined
,
DoubleRightOutlined
}
from
'
@ant-design/icons-vue
'
;
import
{
tryTsxEmit
}
from
'
/@/utils/helper/vueHelper
'
;
import
type
{
DragVerifyActionType
}
from
'
./types
'
;
export
default
defineComponent
({
name
:
'
BaseDargVerify
'
,
props
:
basicProps
,
...
...
@@ -210,7 +211,7 @@ export default defineComponent({
contentEl
.
style
.
width
=
unref
(
getContentStyleRef
).
width
;
}
tryTsxEmit
((
instance
)
=>
{
tryTsxEmit
<
DragVerifyActionType
>
((
instance
)
=>
{
instance
.
resume
=
resume
;
});
...
...
src/hooks/setting/useRootSetting.ts
浏览文件 @
81baf1d5
...
...
@@ -46,7 +46,7 @@ export function useRootSetting() {
unref
(
getRootSetting
).
contentMode
===
ContentEnum
.
FULL
?
ContentEnum
.
FULL
:
ContentEnum
.
FIXED
);
function
setRootSetting
(
setting
:
RootSetting
)
{
function
setRootSetting
(
setting
:
Partial
<
RootSetting
>
)
{
appStore
.
commitProjectConfigState
(
setting
);
}
...
...
src/utils/helper/vueHelper.ts
浏览文件 @
81baf1d5
...
...
@@ -7,6 +7,7 @@ import {
onUnmounted
,
nextTick
,
reactive
,
ComponentInternalInstance
,
}
from
'
vue
'
;
export
function
explicitComputed
<
T
,
S
>
(
source
:
WatchSource
<
S
>
,
fn
:
()
=>
T
)
{
...
...
@@ -29,8 +30,10 @@ export function tryOnUnmounted(fn: () => Promise<void> | void) {
getCurrentInstance
()
&&
onUnmounted
(
fn
);
}
export
function
tryTsxEmit
(
fn
:
(
_instance
:
any
)
=>
Promise
<
void
>
|
void
)
{
const
instance
=
getCurrentInstance
();
export
function
tryTsxEmit
<
T
extends
any
=
ComponentInternalInstance
>
(
fn
:
(
_instance
:
T
)
=>
Promise
<
void
>
|
void
)
{
const
instance
=
getCurrentInstance
()
as
any
;
instance
&&
fn
.
call
(
null
,
instance
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录