16 changed files with 463 additions and 354 deletions
@ -1,106 +0,0 @@ |
|||
import type { PropType } from 'vue'; |
|||
|
|||
import { renderThumbStyle, BAR_MAP } from './util'; |
|||
import { defineComponent, computed, unref, inject, Ref, reactive, ref, onBeforeUnmount } from 'vue'; |
|||
import { on, off } from '/@/utils/domUtils'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'Bar', |
|||
props: { |
|||
vertical: { |
|||
type: Boolean as PropType<boolean>, |
|||
default: false, |
|||
}, |
|||
size: String as PropType<string>, |
|||
move: Number as PropType<number>, |
|||
}, |
|||
setup(props) { |
|||
const thumbRef = ref<Nullable<HTMLDivElement>>(null); |
|||
const elRef = ref<Nullable<HTMLDivElement>>(null); |
|||
const commonState = reactive<Indexable>({}); |
|||
const getBarRef = computed(() => { |
|||
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal']; |
|||
}); |
|||
const parentElRef = inject('scroll-bar-wrap') as Ref<Nullable<HTMLDivElement>>; |
|||
|
|||
function clickThumbHandler(e: any) { |
|||
const { ctrlKey, button, currentTarget } = e; |
|||
// prevent click event of right button
|
|||
if (ctrlKey || button === 2 || !currentTarget) { |
|||
return; |
|||
} |
|||
startDrag(e); |
|||
const bar = unref(getBarRef); |
|||
commonState[bar.axis] = |
|||
currentTarget[bar.offset] - |
|||
(e[bar.client as keyof typeof e] - currentTarget.getBoundingClientRect()[bar.direction]); |
|||
} |
|||
|
|||
function clickTrackHandler(e: any) { |
|||
const bar = unref(getBarRef); |
|||
const offset = Math.abs(e.target.getBoundingClientRect()[bar.direction] - e[bar.client]); |
|||
const thumbEl = unref(thumbRef) as any; |
|||
const parentEl = unref(parentElRef) as any; |
|||
const el = unref(elRef) as any; |
|||
if (!thumbEl || !el || !parentEl) return; |
|||
const thumbHalf = thumbEl[bar.offset] / 2; |
|||
const thumbPositionPercentage = ((offset - thumbHalf) * 100) / el[bar.offset]; |
|||
parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100; |
|||
} |
|||
|
|||
function startDrag(e: Event) { |
|||
e.stopImmediatePropagation(); |
|||
commonState.cursorDown = true; |
|||
|
|||
on(document, 'mousemove', mouseMoveDocumentHandler); |
|||
on(document, 'mouseup', mouseUpDocumentHandler); |
|||
document.onselectstart = () => false; |
|||
} |
|||
|
|||
function mouseMoveDocumentHandler(e: any) { |
|||
if (commonState.cursorDown === false) return; |
|||
const bar = unref(getBarRef); |
|||
const prevPage = commonState[bar.axis]; |
|||
const el = unref(elRef) as any; |
|||
const parentEl = unref(parentElRef) as any; |
|||
const thumbEl = unref(thumbRef) as any; |
|||
if (!prevPage || !el || !thumbEl || !parentEl) return; |
|||
const rect = el.getBoundingClientRect() as any; |
|||
const offset = (rect[bar.direction] - e[bar.client]) * -1; |
|||
const thumbClickPosition = thumbEl[bar.offset] - prevPage; |
|||
const thumbPositionPercentage = ((offset - thumbClickPosition) * 100) / el[bar.offset]; |
|||
|
|||
parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100; |
|||
} |
|||
|
|||
function mouseUpDocumentHandler() { |
|||
const bar = unref(getBarRef); |
|||
commonState.cursorDown = false; |
|||
commonState[bar.axis] = 0; |
|||
off(document, 'mousemove', mouseMoveDocumentHandler); |
|||
document.onselectstart = null; |
|||
} |
|||
|
|||
onBeforeUnmount(() => { |
|||
off(document, 'mouseup', mouseUpDocumentHandler); |
|||
}); |
|||
return () => { |
|||
const bar = unref(getBarRef); |
|||
const { size, move } = props; |
|||
return ( |
|||
<div |
|||
class={['scrollbar__bar', 'is-' + bar.key]} |
|||
onMousedown={clickTrackHandler} |
|||
ref={elRef} |
|||
> |
|||
<div |
|||
ref={thumbRef} |
|||
class="scrollbar__thumb" |
|||
onMousedown={clickThumbHandler} |
|||
style={renderThumbStyle({ size, move, bar })} |
|||
/> |
|||
</div> |
|||
); |
|||
}; |
|||
}, |
|||
}); |
|||
@ -1,146 +0,0 @@ |
|||
import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent'; |
|||
import scrollbarWidth from '/@/utils/scrollbarWidth'; |
|||
import { toObject } from './util'; |
|||
import Bar from './Bar'; |
|||
import { isString } from '/@/utils/is'; |
|||
import { |
|||
defineComponent, |
|||
PropType, |
|||
unref, |
|||
reactive, |
|||
ref, |
|||
provide, |
|||
onMounted, |
|||
nextTick, |
|||
onBeforeUnmount, |
|||
} from 'vue'; |
|||
import { getSlot } from '/@/utils/helper/tsxHelper'; |
|||
import './index.less'; |
|||
import { useExpose } from '/@/hooks/core/useExpose'; |
|||
import { ScrollbarType } from './types'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'Scrollbar', |
|||
props: { |
|||
native: Boolean as PropType<boolean>, |
|||
wrapStyle: { |
|||
type: Object as PropType<any>, |
|||
}, |
|||
wrapClass: { type: String as PropType<string>, required: false }, |
|||
viewClass: { type: String as PropType<string> }, |
|||
viewStyle: { type: Object as PropType<any> }, |
|||
noresize: Boolean as PropType<boolean>, |
|||
tag: { |
|||
type: String as PropType<string>, |
|||
default: 'div', |
|||
}, |
|||
}, |
|||
setup(props, { slots }) { |
|||
const resizeRef = ref<Nullable<HTMLDivElement>>(null); |
|||
const wrapElRef = ref<Nullable<HTMLDivElement>>(null); |
|||
provide('scroll-bar-wrap', wrapElRef); |
|||
const state = reactive({ |
|||
sizeWidth: '0', |
|||
sizeHeight: '0', |
|||
moveX: 0, |
|||
moveY: 0, |
|||
}); |
|||
|
|||
function handleScroll() { |
|||
const warpEl = unref(wrapElRef); |
|||
if (!warpEl) return; |
|||
const { scrollTop, scrollLeft, clientHeight, clientWidth } = warpEl; |
|||
|
|||
state.moveY = (scrollTop * 100) / clientHeight; |
|||
state.moveX = (scrollLeft * 100) / clientWidth; |
|||
} |
|||
function update() { |
|||
const warpEl = unref(wrapElRef); |
|||
if (!warpEl) return; |
|||
const { scrollHeight, scrollWidth, clientHeight, clientWidth } = warpEl; |
|||
const heightPercentage = (clientHeight * 100) / scrollHeight; |
|||
const widthPercentage = (clientWidth * 100) / scrollWidth; |
|||
|
|||
state.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : ''; |
|||
state.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : ''; |
|||
} |
|||
|
|||
onMounted(() => { |
|||
useExpose<ScrollbarType>({ |
|||
wrap: unref(wrapElRef), |
|||
}); |
|||
const { native, noresize } = props; |
|||
const resizeEl = unref(resizeRef); |
|||
const warpEl = unref(wrapElRef); |
|||
if (native || !resizeEl || !warpEl) return; |
|||
nextTick(update); |
|||
if (!noresize) { |
|||
addResizeListener(resizeEl, update); |
|||
addResizeListener(warpEl, update); |
|||
} |
|||
}); |
|||
onBeforeUnmount(() => { |
|||
const { native, noresize } = props; |
|||
const resizeEl = unref(resizeRef); |
|||
const warpEl = unref(wrapElRef); |
|||
if (native || !resizeEl || !warpEl) return; |
|||
if (!noresize) { |
|||
removeResizeListener(resizeEl, update); |
|||
removeResizeListener(warpEl, update); |
|||
} |
|||
}); |
|||
return () => { |
|||
const { native, tag, viewClass, viewStyle, wrapClass, wrapStyle } = props; |
|||
let style: any = wrapStyle; |
|||
const gutter = scrollbarWidth(); |
|||
|
|||
if (gutter) { |
|||
const gutterWith = `-${gutter}px`; |
|||
const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`; |
|||
|
|||
if (Array.isArray(wrapStyle)) { |
|||
style = toObject(wrapStyle); |
|||
style.marginRight = style.marginBottom = gutterWith; |
|||
} else if (isString(wrapStyle)) { |
|||
style += gutterStyle; |
|||
} else { |
|||
style = gutterStyle; |
|||
} |
|||
} |
|||
|
|||
const Tag = tag as any; |
|||
const view = ( |
|||
<Tag class={['scrollbar__view', viewClass]} style={viewStyle} ref={resizeRef}> |
|||
{getSlot(slots)} |
|||
</Tag> |
|||
); |
|||
const wrap = ( |
|||
<div |
|||
ref={wrapElRef} |
|||
style={style} |
|||
onScroll={handleScroll} |
|||
class={[wrapClass, 'scrollbar__wrap', gutter ? '' : 'scrollbar__wrap--hidden-default']} |
|||
> |
|||
{[view]} |
|||
</div> |
|||
); |
|||
let nodes: any[] = []; |
|||
const { moveX, sizeWidth, moveY, sizeHeight } = state; |
|||
if (!native) { |
|||
nodes = [ |
|||
wrap, |
|||
/* eslint-disable */ |
|||
<Bar move={moveX} size={sizeWidth}></Bar>, |
|||
<Bar vertical move={moveY} size={sizeHeight}></Bar>, |
|||
]; |
|||
} else { |
|||
nodes = [ |
|||
<div ref="wrap" class={[wrapClass, 'scrollbar__wrap']} style={style}> |
|||
{[view]} |
|||
</div>, |
|||
]; |
|||
} |
|||
return <div class="scrollbar">{nodes}</div>; |
|||
}; |
|||
}, |
|||
}); |
|||
@ -0,0 +1,109 @@ |
|||
import { |
|||
defineComponent, |
|||
h, |
|||
computed, |
|||
ref, |
|||
getCurrentInstance, |
|||
onUnmounted, |
|||
inject, |
|||
Ref, |
|||
} from 'vue'; |
|||
import { on, off } from '/@/utils/domUtils'; |
|||
|
|||
import { renderThumbStyle, BAR_MAP } from './util'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'Bar', |
|||
|
|||
props: { |
|||
vertical: Boolean, |
|||
size: String, |
|||
move: Number, |
|||
}, |
|||
|
|||
setup(props) { |
|||
const instance = getCurrentInstance(); |
|||
const thumb = ref<any>(null); |
|||
const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any; |
|||
const bar = computed(() => { |
|||
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal']; |
|||
}); |
|||
const barStore = ref<Indexable>({}); |
|||
const cursorDown = ref<any>(null); |
|||
const clickThumbHandler = (e: any) => { |
|||
// prevent click event of right button
|
|||
if (e.ctrlKey || e.button === 2) { |
|||
return; |
|||
} |
|||
startDrag(e); |
|||
barStore.value[bar.value.axis] = |
|||
e.currentTarget[bar.value.offset] - |
|||
(e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]); |
|||
}; |
|||
|
|||
const clickTrackHandler = (e: any) => { |
|||
const offset = Math.abs( |
|||
e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client] |
|||
); |
|||
const thumbHalf = thumb.value[bar.value.offset] / 2; |
|||
const thumbPositionPercentage = |
|||
((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset]; |
|||
|
|||
wrap.value[bar.value.scroll] = |
|||
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100; |
|||
}; |
|||
const startDrag = (e: any) => { |
|||
e.stopImmediatePropagation(); |
|||
cursorDown.value = true; |
|||
on(document, 'mousemove', mouseMoveDocumentHandler); |
|||
on(document, 'mouseup', mouseUpDocumentHandler); |
|||
document.onselectstart = () => false; |
|||
}; |
|||
|
|||
const mouseMoveDocumentHandler = (e: any) => { |
|||
if (cursorDown.value === false) return; |
|||
const prevPage = barStore.value[bar.value.axis]; |
|||
|
|||
if (!prevPage) return; |
|||
|
|||
const offset = |
|||
(instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * |
|||
-1; |
|||
const thumbClickPosition = thumb.value[bar.value.offset] - prevPage; |
|||
const thumbPositionPercentage = |
|||
((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset]; |
|||
wrap.value[bar.value.scroll] = |
|||
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100; |
|||
}; |
|||
|
|||
function mouseUpDocumentHandler() { |
|||
cursorDown.value = false; |
|||
barStore.value[bar.value.axis] = 0; |
|||
off(document, 'mousemove', mouseMoveDocumentHandler); |
|||
document.onselectstart = null; |
|||
} |
|||
|
|||
onUnmounted(() => { |
|||
off(document, 'mouseup', mouseUpDocumentHandler); |
|||
}); |
|||
|
|||
return () => |
|||
h( |
|||
'div', |
|||
{ |
|||
class: ['scrollbar__bar', 'is-' + bar.value.key], |
|||
onMousedown: clickTrackHandler, |
|||
}, |
|||
h('div', { |
|||
ref: thumb, |
|||
class: 'scrollbar__thumb', |
|||
onMousedown: clickThumbHandler, |
|||
style: renderThumbStyle({ |
|||
size: props.size, |
|||
move: props.move, |
|||
bar: bar.value, |
|||
}), |
|||
}) |
|||
); |
|||
}, |
|||
}); |
|||
@ -1,69 +0,0 @@ |
|||
.scrollbar { |
|||
position: relative; |
|||
overflow: hidden; |
|||
|
|||
&__wrap { |
|||
height: 100%; |
|||
overflow: scroll; |
|||
|
|||
&--hidden-default { |
|||
scrollbar-width: none; |
|||
|
|||
&::-webkit-scrollbar { |
|||
width: 0; |
|||
height: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&__thumb { |
|||
position: relative; |
|||
display: block; |
|||
width: 0; |
|||
height: 0; |
|||
cursor: pointer; |
|||
background-color: rgba(144, 147, 153, 0.3); |
|||
border-radius: inherit; |
|||
transition: 0.3s background-color; |
|||
|
|||
&:hover { |
|||
background-color: rgba(144, 147, 153, 0.5); |
|||
} |
|||
} |
|||
|
|||
&__bar { |
|||
position: absolute; |
|||
right: 2px; |
|||
bottom: 2px; |
|||
z-index: 1; |
|||
border-radius: 4px; |
|||
opacity: 0; |
|||
-webkit-transition: opacity 80ms ease; |
|||
transition: opacity 80ms ease; |
|||
|
|||
&.is-vertical { |
|||
top: 2px; |
|||
width: 5px; |
|||
|
|||
& > div { |
|||
width: 100%; |
|||
} |
|||
} |
|||
|
|||
&.is-horizontal { |
|||
left: 2px; |
|||
height: 5px; |
|||
|
|||
& > div { |
|||
height: 100%; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.scrollbar:active > .scrollbar__bar, |
|||
.scrollbar:focus > .scrollbar__bar, |
|||
.scrollbar:hover > .scrollbar__bar { |
|||
opacity: 1; |
|||
transition: opacity 180ms ease; |
|||
} |
|||
@ -0,0 +1,195 @@ |
|||
<template> |
|||
<div class="scrollbar"> |
|||
<div |
|||
ref="wrap" |
|||
:class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']" |
|||
:style="style" |
|||
@scroll="handleScroll" |
|||
> |
|||
<component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle"> |
|||
<slot></slot> |
|||
</component> |
|||
</div> |
|||
<template v-if="!native"> |
|||
<bar :move="moveX" :size="sizeWidth" /> |
|||
<bar vertical :move="moveY" :size="sizeHeight" /> |
|||
</template> |
|||
</div> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent'; |
|||
|
|||
import { toObject } from './util'; |
|||
import { |
|||
defineComponent, |
|||
ref, |
|||
onMounted, |
|||
onBeforeUnmount, |
|||
nextTick, |
|||
provide, |
|||
computed, |
|||
} from 'vue'; |
|||
import Bar from './bar'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'Scrollbar', |
|||
components: { Bar }, |
|||
props: { |
|||
native: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
wrapStyle: { |
|||
type: [String, Array], |
|||
default: '', |
|||
}, |
|||
wrapClass: { |
|||
type: [String, Array], |
|||
default: '', |
|||
}, |
|||
viewClass: { |
|||
type: [String, Array], |
|||
default: '', |
|||
}, |
|||
viewStyle: { |
|||
type: [String, Array], |
|||
default: '', |
|||
}, |
|||
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能 |
|||
tag: { |
|||
type: String, |
|||
default: 'div', |
|||
}, |
|||
}, |
|||
setup(props) { |
|||
const sizeWidth = ref('0'); |
|||
const sizeHeight = ref('0'); |
|||
const moveX = ref(0); |
|||
const moveY = ref(0); |
|||
const wrap = ref<any>(null); |
|||
const resize = ref<any>(null); |
|||
|
|||
provide('scroll-bar-wrap', wrap); |
|||
|
|||
const handleScroll = () => { |
|||
if (!props.native) { |
|||
moveY.value = (wrap.value.scrollTop * 100) / wrap.value.clientHeight; |
|||
moveX.value = (wrap.value.scrollLeft * 100) / wrap.value.clientWidth; |
|||
} |
|||
}; |
|||
|
|||
const update = () => { |
|||
if (!wrap.value) return; |
|||
|
|||
const heightPercentage = (wrap.value.clientHeight * 100) / wrap.value.scrollHeight; |
|||
const widthPercentage = (wrap.value.clientWidth * 100) / wrap.value.scrollWidth; |
|||
|
|||
sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : ''; |
|||
sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : ''; |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
if (props.native) return; |
|||
nextTick(update); |
|||
!props.noresize && addResizeListener(resize.value, update); |
|||
}); |
|||
|
|||
onBeforeUnmount(() => { |
|||
if (props.native) return; |
|||
!props.noresize && removeResizeListener(resize.value, update); |
|||
}); |
|||
const style = computed(() => { |
|||
let style: any = props.wrapStyle; |
|||
if (Array.isArray(props.wrapStyle)) { |
|||
style = toObject(props.wrapStyle); |
|||
} |
|||
return style; |
|||
}); |
|||
return { |
|||
moveX, |
|||
moveY, |
|||
sizeWidth, |
|||
sizeHeight, |
|||
style, |
|||
wrap, |
|||
resize, |
|||
update, |
|||
handleScroll, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
<style lang="less"> |
|||
.scrollbar { |
|||
position: relative; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
|
|||
&__wrap { |
|||
height: 100%; |
|||
overflow: scroll; |
|||
|
|||
&--hidden-default { |
|||
scrollbar-width: none; |
|||
|
|||
&::-webkit-scrollbar { |
|||
display: none; |
|||
width: 0; |
|||
height: 0; |
|||
opacity: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&__thumb { |
|||
position: relative; |
|||
display: block; |
|||
width: 0; |
|||
height: 0; |
|||
cursor: pointer; |
|||
background-color: rgba(144, 147, 153, 0.3); |
|||
border-radius: inherit; |
|||
transition: 0.3s background-color; |
|||
|
|||
&:hover { |
|||
background-color: rgba(144, 147, 153, 0.5); |
|||
} |
|||
} |
|||
|
|||
&__bar { |
|||
position: absolute; |
|||
right: 2px; |
|||
bottom: 2px; |
|||
z-index: 1; |
|||
border-radius: 4px; |
|||
opacity: 0; |
|||
-webkit-transition: opacity 80ms ease; |
|||
transition: opacity 80ms ease; |
|||
|
|||
&.is-vertical { |
|||
top: 2px; |
|||
width: 6px; |
|||
|
|||
& > div { |
|||
width: 100%; |
|||
} |
|||
} |
|||
|
|||
&.is-horizontal { |
|||
left: 2px; |
|||
height: 6px; |
|||
|
|||
& > div { |
|||
height: 100%; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.scrollbar:active > .scrollbar__bar, |
|||
.scrollbar:focus > .scrollbar__bar, |
|||
.scrollbar:hover > .scrollbar__bar { |
|||
opacity: 1; |
|||
transition: opacity 340ms ease-out; |
|||
} |
|||
</style> |
|||
@ -1 +1 @@ |
|||
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja'; |
|||
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko'; |
|||
|
|||
@ -0,0 +1,58 @@ |
|||
<template> |
|||
<div class="m-4"> |
|||
<CollapseContainer title="MarkDown表单"> |
|||
<BasicForm |
|||
:labelWidth="100" |
|||
:schemas="schemas" |
|||
:actionColOptions="{ span: 24 }" |
|||
@submit="handleSubmit" |
|||
> |
|||
</BasicForm> |
|||
</CollapseContainer> |
|||
</div> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent, h } from 'vue'; |
|||
import { BasicForm, FormSchema } from '/@/components/Form/index'; |
|||
import { CollapseContainer } from '/@/components/Container/index'; |
|||
import { useMessage } from '/@/hooks/web/useMessage'; |
|||
import { MarkDown } from '/@/components/Markdown'; |
|||
|
|||
const schemas: FormSchema[] = [ |
|||
{ |
|||
field: 'title', |
|||
component: 'Input', |
|||
label: 'title', |
|||
defaultValue: '标题', |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
field: 'markdown', |
|||
component: 'Input', |
|||
label: 'markdown', |
|||
defaultValue: 'defaultValue', |
|||
rules: [{ required: true, trigger: 'blur' }], |
|||
render: ({ model, field }) => { |
|||
return h(MarkDown, { |
|||
value: model[field], |
|||
onChange: (value: string) => { |
|||
model[field] = value; |
|||
}, |
|||
}); |
|||
}, |
|||
}, |
|||
]; |
|||
export default defineComponent({ |
|||
components: { BasicForm, CollapseContainer }, |
|||
setup() { |
|||
const { createMessage } = useMessage(); |
|||
|
|||
return { |
|||
schemas, |
|||
handleSubmit: (values: any) => { |
|||
createMessage.success('click search,values:' + JSON.stringify(values)); |
|||
}, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
Loading…
Reference in new issue