feat: 添加prettier格式化代码

This commit is contained in:
539943419 committed 2024-12-25 19:44:18 +08:00
1 parent 5823d5876b
commit f33e9386cd
81 files changed
+8114 -7395

No files matched your search

+130 -107
View File
@@ -1,36 +1,57 @@
<template>
<div class="miao-message-provider" ref="rootRef">
<slot></slot>
<transition-group name="message-fade" tag="div" class="miao-message-provider-container">
<div class="miao-message" v-for="msg in messageList" :key="msg.id"
:style="{ maxWidth: maxMessageWidth + 'px' }">
<n-icon class="miao-message-item" size="18" :color="msg.iconColor">
<component :is="msg.icon"></component>
</n-icon>
<div class="miao-message-item miao-message-item-content">{{ msg.content }}</div>
<div
class="miao-message-provider"
ref="rootRef"
>
<slot></slot>
<transition-group
name="message-fade"
tag="div"
class="miao-message-provider-container"
>
<div
class="miao-message"
v-for="msg in messageList"
:key="msg.id"
:style="{ maxWidth: maxMessageWidth + 'px' }"
>
<n-icon
class="miao-message-item"
size="18"
:color="msg.iconColor"
>
<component :is="msg.icon"></component>
</n-icon>
<div class="miao-message-item miao-message-item-content">
{{ msg.content }}
</div>
</transition-group>
</div>
</div>
</transition-group>
</div>
</template>
<script setup lang="ts">
import generateId from '@/hooks/generateId';
import { NIcon } from 'naive-ui';
import { computed, onMounted, ref, shallowReactive } from 'vue';
import { InformationCircle, CheckmarkCircle, CloseCircle } from '@vicons/ionicons5'
import { AlertTipMessageOptions } from '@/types/type';
import generateId from '@/hooks/generateId'
import { NIcon } from 'naive-ui'
import { computed, onMounted, ref, shallowReactive } from 'vue'
import {
InformationCircle,
CheckmarkCircle,
CloseCircle
} from '@vicons/ionicons5'
import { AlertTipMessageOptions } from '@/types/type'
interface Message {
icon: any,
timer: any,
iconColor: string,
content: string,
icon: any
timer: any
iconColor: string
content: string
}
const iconMap = {
'info': { icon: InformationCircle, color: 'blue' },
'success': { icon: CheckmarkCircle, color: 'green' },
'error': { icon: CloseCircle, color: 'red' },
info: { icon: InformationCircle, color: 'blue' },
success: { icon: CheckmarkCircle, color: 'green' },
error: { icon: CloseCircle, color: 'red' }
}
const messageMap = shallowReactive<Record<string, Message | undefined>>({})
@@ -38,107 +59,109 @@ const rootRef = ref<HTMLDivElement>()
const maxMessageWidth = ref<number>(-1)
const messageList = computed(() => {
return Object.keys(messageMap).map(v => ({
id: v,
...messageMap[v],
}))
return Object.keys(messageMap).map((v) => ({
id: v,
...messageMap[v]
}))
})
const alertTip = (content: string, options?: AlertTipMessageOptions) => {
let timer: any
const { timeout = 0, type = 'info', id = generateId() } = options ?? {}
if (timeout > 0) {
messageMap[id]?.timer && clearTimeout(messageMap[id]?.timer)
timer = setTimeout(() => {
delete messageMap[id]
}, timeout)
}
messageMap[id] = {
icon: iconMap[type].icon,
iconColor: iconMap[type].color,
content,
timer
}
return (newContent: string, newOptions?: AlertTipMessageOptions) => {
newOptions = newOptions ?? {}
newOptions.id = id
alertTip(newContent, newOptions)
}
let timer: any
const { timeout = 0, type = 'info', id = generateId() } = options ?? {}
if (timeout > 0) {
messageMap[id]?.timer && clearTimeout(messageMap[id]?.timer)
timer = setTimeout(() => {
delete messageMap[id]
}, timeout)
}
messageMap[id] = {
icon: iconMap[type].icon,
iconColor: iconMap[type].color,
content,
timer
}
return (newContent: string, newOptions?: AlertTipMessageOptions) => {
newOptions = newOptions ?? {}
newOptions.id = id
alertTip(newContent, newOptions)
}
}
onMounted(async () => {
// const set = message('test', { timeout: 5000 })
// setTimeout(() => {
// set('miao', { type: 'success' })
// }, 1000);
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
maxMessageWidth.value = entry.contentRect.width * 0.8;
}
});
if (rootRef.value) {
observer.observe(rootRef.value);
}
// const set = message('test', { timeout: 5000 })
// setTimeout(() => {
// set('miao', { type: 'success' })
// }, 1000);
const observer = new ResizeObserver((entries) => {
for (let entry of entries) {
maxMessageWidth.value = entry.contentRect.width * 0.8
}
})
if (rootRef.value) {
observer.observe(rootRef.value)
}
})
defineExpose({ alertTip });
defineExpose({ alertTip })
</script>
<style scoped lang="scss">
.miao-message-provider {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
.miao-message-provider-container {
position: absolute;
width: 0;
height: 0;
left: 50%;
top: 30px;
display: flex;
flex-direction: column;
align-items: center;
overflow: visible;
z-index: 70582140539943419;
.miao-message-provider-container {
position: absolute;
width: 0;
height: 0;
left: 50%;
top: 30px;
display: flex;
flex-direction: column;
align-items: center;
overflow: visible;
z-index: 70582140539943419;
.miao-message {
display: flex;
align-items: center;
width: max-content;
background-color: rgb(249, 249, 249);
padding: 5px 10px;
background-color: rgb(255 255 255);
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05);
border-radius: 5px;
user-select: none;
margin-top: 10px;
.miao-message {
display: flex;
align-items: center;
width: max-content;
background-color: rgb(249, 249, 249);
padding: 5px 10px;
background-color: rgb(255 255 255);
box-shadow:
0 3px 6px -4px rgba(0, 0, 0, 0.12),
0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 9px 28px 8px rgba(0, 0, 0, 0.05);
border-radius: 5px;
user-select: none;
margin-top: 10px;
.miao-message-item {
margin: 0 5px;
}
.miao-message-item {
margin: 0 5px;
}
.miao-message-item-content {
white-space: pre-wrap;
}
}
}
.miao-message-item-content {
white-space: pre-wrap;
}
}
}
.message-fade-move,
.message-fade-enter-active,
.message-fade-leave-active {
transition: all 0.5s ease;
}
.message-fade-move,
.message-fade-enter-active,
.message-fade-leave-active {
transition: all 0.5s ease;
}
.message-fade-enter-from,
.message-fade-leave-to {
opacity: 0;
transform: translateX(30px);
}
.message-fade-enter-from,
.message-fade-leave-to {
opacity: 0;
transform: translateX(30px);
}
.message-fade-leave-active {
position: absolute;
}
.message-fade-leave-active {
position: absolute;
}
}
</style>
+46 -34
View File
@@ -1,26 +1,39 @@
<!-- 基于naiveui的下拉菜单实现的自定义下拉菜单 -->
<!-- 支持长按和右键呼出下拉菜单 -->
<template>
<div class="main" @contextmenu="handleContextMenu" @mouseleave="handleMainMouseLeave">
<slot></slot>
</div>
<n-dropdown placement="bottom-start" trigger="manual" :x="x" :y="y" :options="props.options"
:show="showContextMenu > 0" :on-clickoutside="onClickoutside" @select="handleSelect" @mouseleave="
showContextMenu -= 1" @mouseenter="showContextMenu += 1" />
<div
class="main"
@contextmenu="handleContextMenu"
@mouseleave="handleMainMouseLeave"
>
<slot></slot>
</div>
<n-dropdown
placement="bottom-start"
trigger="manual"
:x="x"
:y="y"
:options="props.options"
:show="showContextMenu > 0"
:on-clickoutside="onClickoutside"
@select="handleSelect"
@mouseleave="showContextMenu -= 1"
@mouseenter="showContextMenu += 1"
/>
</template>
<script setup lang="ts">
import { NDropdown } from 'naive-ui/es/dropdown';
import { DropdownOption } from 'naive-ui/es/dropdown';
import { nextTick, ref } from 'vue';
import { NDropdown } from 'naive-ui/es/dropdown'
import { DropdownOption } from 'naive-ui/es/dropdown'
import { nextTick, ref } from 'vue'
const props = defineProps<{
options: DropdownOption[]
// 长按呼出右键菜单的时延,undefined时不生效
touchTimeOut?: number
options: DropdownOption[]
// 长按呼出右键菜单的时延,undefined时不生效
touchTimeOut?: number
}>()
const emit = defineEmits<{
select: [key: string]
select: [key: string]
}>()
const x = ref(0)
@@ -30,31 +43,31 @@ const showContextMenu = ref(0)
// let timer_touch: string | number | NodeJS.Timeout | undefined
const onClickoutside = async () => {
showContextMenu.value = 0
showContextMenu.value = 0
}
const handleMainMouseLeave = async () => {
setTimeout(() => {
showContextMenu.value -= 1
}, 20)
// nextTick(()=>{
// showContextMenu.value -= 1
// })
setTimeout(() => {
showContextMenu.value -= 1
}, 20)
// nextTick(()=>{
// showContextMenu.value -= 1
// })
}
const handleSelect = async (key: string) => {
emit('select', key)
showContextMenu.value = 0
emit('select', key)
showContextMenu.value = 0
}
const handleContextMenu = (e: MouseEvent) => {
e.preventDefault()
showContextMenu.value = 0
nextTick().then(() => {
showContextMenu.value += 1
x.value = e.clientX
y.value = e.clientY
})
e.preventDefault()
showContextMenu.value = 0
nextTick().then(() => {
showContextMenu.value += 1
x.value = e.clientX
y.value = e.clientY
})
}
// const handleTouchStart = (e: TouchEvent) => {
@@ -76,13 +89,12 @@ const handleContextMenu = (e: MouseEvent) => {
// }
// }
</script>
<style>
.main {
width: 100%;
height: 100%;
position: relative;
width: 100%;
height: 100%;
position: relative;
}
</style>
</style>
+18 -13
View File
@@ -1,34 +1,39 @@
<template>
<div ref="divRef" @dragstart="onDs" :draggable="isDraggable">
<slot></slot>
</div>
<div
ref="divRef"
@dragstart="onDs"
:draggable="isDraggable"
>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { onMounted, ref } from 'vue'
// import Sortable from 'sortablejs'
const props = defineProps<{
isDraggable: boolean
isDraggable: boolean
}>()
props
const emit = defineEmits<{
onDragStart: [e: DragEvent]
onDragStart: [e: DragEvent]
}>()
const divRef = ref<HTMLDivElement>()
const onDs = (e: DragEvent) => {
emit('onDragStart', e)
emit('onDragStart', e)
}
onMounted(() => {
divRef?.value?.addEventListener('dragstart', function (ev) {
var img = new Image();
img.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E";
ev?.dataTransfer?.setDragImage(img, 0, 0);
})
divRef?.value?.addEventListener('dragstart', function (ev) {
var img = new Image()
img.src =
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' %3E%3Cpath /%3E%3C/svg%3E"
ev?.dataTransfer?.setDragImage(img, 0, 0)
})
})
</script>
<style scoped></style>
<style scoped></style>
+84 -83
View File
@@ -1,12 +1,13 @@
<template>
<div
class="container"
@dragover="handleDragOver"
@dragleave="handleDragLeave"
@drop="handleDrop">
<slot></slot>
<miao-mask v-model:show="showMask"></miao-mask>
</div>
<div
class="container"
@dragover="handleDragOver"
@dragleave="handleDragLeave"
@drop="handleDrop"
>
<slot></slot>
<miao-mask v-model:show="showMask"></miao-mask>
</div>
</template>
<script setup lang="ts">
@@ -17,10 +18,10 @@ import config from '@/config'
import useDataBus from '@/hooks/useDataBus'
const props = defineProps({
disable: {
type: Boolean,
default: false
}
disable: {
type: Boolean,
default: false
}
})
const dataBus = useDataBus()
@@ -28,104 +29,104 @@ const dataBus = useDataBus()
const { uploadSizeLimit } = config
const emit = defineEmits<{
onFiles: [files: File[]]
onVirtualFiles: [vFiles: VirtualFile[]]
onVirtualDirectory: [vDirectory: VirtualDirectory[]]
onFiles: [files: File[]]
onVirtualFiles: [vFiles: VirtualFile[]]
onVirtualDirectory: [vDirectory: VirtualDirectory[]]
}>()
const showMask = ref<number>(0)
// File類型的數據可能爲文件夾,通過FileReader進行判斷
const isFile = (file: File) =>
new Promise((resolve) => {
const reader = new FileReader()
reader.onload = () => {
resolve(true)
reader.abort()
}
reader.onerror = () => {
resolve(false)
reader.abort()
}
reader.readAsText(file)
})
new Promise((resolve) => {
const reader = new FileReader()
reader.onload = () => {
resolve(true)
reader.abort()
}
reader.onerror = () => {
resolve(false)
reader.abort()
}
reader.readAsText(file)
})
/**
* 只保留文件,移去文件夹
* @param {File[]} files
*/
const removeDirectory = async (files: File[]) => {
let index = 0
while (index < files.length) {
const currentFile = files[index]
const _isFile = await isFile(currentFile)
if (_isFile) {
index += 1
continue
} else {
files.splice(index, 1)
continue
}
}
let index = 0
while (index < files.length) {
const currentFile = files[index]
const _isFile = await isFile(currentFile)
if (_isFile) {
index += 1
continue
} else {
files.splice(index, 1)
continue
}
}
}
const check = (event: DragEvent) => {
return (
[
...(event.dataTransfer?.types?.filter(v=>v === 'Files') ?? []),
...(dataBus.get('dragData_vFiles') ?? []),
...(dataBus.get('dragData_vDirectory') ?? [])
].length !== 0
)
return (
[
...(event.dataTransfer?.types?.filter((v) => v === 'Files') ?? []),
...(dataBus.get('dragData_vFiles') ?? []),
...(dataBus.get('dragData_vDirectory') ?? [])
].length !== 0
)
}
const handleDragOver = async (event: DragEvent) => {
if (props.disable || check(event) === false) {
return
}
event.preventDefault()
if (showMask.value === 1) {
return
}
showMask.value = 1
if (props.disable || check(event) === false) {
return
}
event.preventDefault()
if (showMask.value === 1) {
return
}
showMask.value = 1
}
const handleDragLeave = async () => {
showMask.value = 0
showMask.value = 0
}
const handleDrop = async (event: DragEvent) => {
if (props.disable || check(event) === false) {
return
}
showMask.value = 0
event.preventDefault()
event.stopPropagation()
// todo: uploadSize的限制不應該在這裏
const files = [...(event.dataTransfer?.files ?? [])].filter(
(file) => file.size < uploadSizeLimit
)
await removeDirectory(files)
const virtualFiles: VirtualFile[] = dataBus.pop('dragData_vFiles')
const virtualDirectory: VirtualDirectory[] = dataBus.pop(
'dragData_vDirectory'
)
// console.log({ virtualDirectory, virtualFiles })
if (files && files.length) {
emit('onFiles', files)
}
if (virtualFiles && virtualFiles.length) {
emit('onVirtualFiles', virtualFiles)
}
if (virtualDirectory && virtualDirectory.length) {
emit('onVirtualDirectory', virtualDirectory)
}
if (props.disable || check(event) === false) {
return
}
showMask.value = 0
event.preventDefault()
event.stopPropagation()
// todo: uploadSize的限制不應該在這裏
const files = [...(event.dataTransfer?.files ?? [])].filter(
(file) => file.size < uploadSizeLimit
)
await removeDirectory(files)
const virtualFiles: VirtualFile[] = dataBus.pop('dragData_vFiles')
const virtualDirectory: VirtualDirectory[] = dataBus.pop(
'dragData_vDirectory'
)
// console.log({ virtualDirectory, virtualFiles })
if (files && files.length) {
emit('onFiles', files)
}
if (virtualFiles && virtualFiles.length) {
emit('onVirtualFiles', virtualFiles)
}
if (virtualDirectory && virtualDirectory.length) {
emit('onVirtualDirectory', virtualDirectory)
}
}
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 100%;
position: relative;
width: 100%;
height: 100%;
position: relative;
}
</style>
+101 -86
View File
@@ -1,41 +1,53 @@
<!-- 只适合用于渲染过程较为复杂的组件,不然可能得不偿失
这么泛用的组件,性能差点也能理解 -->
<template>
<div class="miao-lazy" ref="miaoLazyRoot"
:style="!show ? { minHeight: _autoHeight !== undefined ? _autoHeight : props.minHeight, minWidth, margin } : {}">
<slot v-if="show" />
</div>
<div
class="miao-lazy"
ref="miaoLazyRoot"
:style="
!show
? {
minHeight:
_autoHeight !== undefined ? _autoHeight : props.minHeight,
minWidth,
margin
}
: {}
"
>
<slot v-if="show" />
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue';
import { onBeforeUnmount, onMounted, ref } from 'vue'
const props = defineProps({
// disable: {
// type: Boolean,
// default: false,
// },
disableLazy: {
type: Boolean,
default: false,
},
// 仅在内容未加载时生效,用于占位
minHeight: {
type: String,
default: 'none',
},
minWidth: {
type: String,
default: 'none',
},
margin: {
type: String,
default: 'none',
},
autoHeight: {
type: Boolean,
default: false
}
// disable: {
// type: Boolean,
// default: false,
// },
disableLazy: {
type: Boolean,
default: false
},
// 仅在内容未加载时生效,用于占位
minHeight: {
type: String,
default: 'none'
},
minWidth: {
type: String,
default: 'none'
},
margin: {
type: String,
default: 'none'
},
autoHeight: {
type: Boolean,
default: false
}
})
const miaoLazyRoot = ref<HTMLDivElement>()
@@ -45,74 +57,77 @@ const _autoHeight = ref<string>()
const show = ref<boolean>(props.disableLazy)
const isVisible = (dom: HTMLDivElement) => {
const offset = dom.getBoundingClientRect().top
return offset > 0 && offset < 2000
const offset = dom.getBoundingClientRect().top
return offset > 0 && offset < 2000
}
const { showSlot, hideSlot, clearTimer } = (() => {
let timer: any
let timerInterval: any
const clearTimer = () => {
timer && clearTimeout(timer)
timerInterval && clearInterval(timerInterval)
timer = undefined
timerInterval = undefined
}
const hideSlot = () => {
clearTimer()
if (props.autoHeight) {
_autoHeight.value = `${miaoLazyRoot.value?.clientHeight}px`
}
show.value = false
}
const showSlot = () => {
if (show.value === true) {
let timer: any
let timerInterval: any
const clearTimer = () => {
timer && clearTimeout(timer)
timerInterval && clearInterval(timerInterval)
timer = undefined
timerInterval = undefined
}
const hideSlot = () => {
clearTimer()
if (props.autoHeight) {
_autoHeight.value = `${miaoLazyRoot.value?.clientHeight}px`
}
show.value = false
}
const showSlot = () => {
if (show.value === true) {
return
}
clearTimer()
// timer = setTimeout(() => {
if (!miaoLazyRoot.value || isVisible(miaoLazyRoot.value) === false) {
return
}
show.value = true
timerInterval = setInterval(() => {
if (show.value === false || miaoLazyRoot.value === undefined) {
return
}
clearTimer()
// timer = setTimeout(() => {
if (!miaoLazyRoot.value || isVisible(miaoLazyRoot.value) === false) {
return
}
show.value = true
timerInterval = setInterval(() => {
if (show.value === false || miaoLazyRoot.value === undefined) {
return
}
if (isVisible(miaoLazyRoot.value) === false) {
hideSlot()
}
}, 1000)
// if (props.autoHeight) {
// nextTick(() => {
// console.log(miaoLazyRoot.value?.clientHeight)
// _autoHeight.value = `${miaoLazyRoot.value?.clientHeight}px`
// })
// }
}
return { showSlot, hideSlot, clearTimer }
}
if (isVisible(miaoLazyRoot.value) === false) {
hideSlot()
}
}, 1000)
// if (props.autoHeight) {
// nextTick(() => {
// console.log(miaoLazyRoot.value?.clientHeight)
// _autoHeight.value = `${miaoLazyRoot.value?.clientHeight}px`
// })
// }
}
return { showSlot, hideSlot, clearTimer }
})()
onMounted(() => {
if (show.value === false) {
let options = {
threshold: 0
};
if (show.value === false) {
let options = {
threshold: 0
}
let observer: IntersectionObserver | undefined = new IntersectionObserver((entries) => {
let observer: IntersectionObserver | undefined = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
showSlot()
// miaoLazyRoot.value && observer?.unobserve(miaoLazyRoot.value)
// observer = undefined
showSlot()
// miaoLazyRoot.value && observer?.unobserve(miaoLazyRoot.value)
// observer = undefined
} else {
hideSlot()
hideSlot()
}
}, options);
miaoLazyRoot.value && observer.observe(miaoLazyRoot.value);
}
},
options
)
miaoLazyRoot.value && observer.observe(miaoLazyRoot.value)
}
})
onBeforeUnmount(() => {
clearTimer()
clearTimer()
})
</script>
</script>
+38 -32
View File
@@ -1,55 +1,61 @@
<template>
<transition name="transition">
<div class="mask-body" ref="maskBodyRef" v-show="showMask">
<slot></slot>
</div>
</transition>
<transition name="transition">
<div
class="mask-body"
ref="maskBodyRef"
v-show="showMask"
>
<slot></slot>
</div>
</transition>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref } from 'vue'
const maskBodyRef = ref<HTMLDivElement>()
const showMask = defineModel<boolean | number>('show', { default: false, required: true })
const showMask = defineModel<boolean | number>('show', {
default: false,
required: true
})
</script>
<style lang="scss" scoped>
.mask-body {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
z-index: 7058214053994319;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
z-index: 7058214053994319;
// &-container {
// &-container {
// }
// }
&-show {
display: flex;
transition: opacity 0.3s 0.01s;
opacity: 1;
}
&-show {
display: flex;
transition: opacity 0.3s 0.01s;
opacity: 1;
}
&-hide {
opacity: 0;
transition: display 0.01s 0.3s;
display: none;
}
&-hide {
opacity: 0;
transition: display 0.01s 0.3s;
display: none;
}
}
.transition-enter-active,
.transition-leave-active {
transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
}
.transition-enter-from,
.transition-leave-to {
opacity: 0;
opacity: 0;
}
</style>
+78 -72
View File
@@ -1,27 +1,33 @@
<template>
<miao-mask v-model:show="showMask">
<n-card class="popup-card" :title="popupConfig?.title" size="medium">
{{ popupConfig?.content }}
<n-input
class="popup-input"
v-model:value="inputValue"
type="text"
v-bind="popupConfig?.inputProps"
passively-activated
autofocus
v-if="popupConfig?.inputProps" />
<div class="popup-button-container">
<n-button
class="popup-button-container-button"
v-for="option in popupConfig?.options"
:key="option.label"
:type="option.type"
@click="_resolve && _resolve(option.key)">
{{ option.label }}
</n-button>
</div>
</n-card>
</miao-mask>
<miao-mask v-model:show="showMask">
<n-card
class="popup-card"
:title="popupConfig?.title"
size="medium"
>
{{ popupConfig?.content }}
<n-input
class="popup-input"
v-model:value="inputValue"
type="text"
v-bind="popupConfig?.inputProps"
passively-activated
autofocus
v-if="popupConfig?.inputProps"
/>
<div class="popup-button-container">
<n-button
class="popup-button-container-button"
v-for="option in popupConfig?.options"
:key="option.label"
:type="option.type"
@click="_resolve && _resolve(option.key)"
>
{{ option.label }}
</n-button>
</div>
</n-card>
</miao-mask>
</template>
<script lang="ts" setup>
import { ref, nextTick } from 'vue'
@@ -34,43 +40,43 @@ const inputValue = ref<string>('')
const _resolve = ref()
type popupConfigType = {
title: string
content?: string
inputValue?: string
inputProps?: InputProps
options: {
label: string
key: unknown
type:
| 'default'
| 'tertiary'
| 'primary'
| 'success'
| 'info'
| 'warning'
| 'error'
}[]
title: string
content?: string
inputValue?: string
inputProps?: InputProps
options: {
label: string
key: unknown
type:
| 'default'
| 'tertiary'
| 'primary'
| 'success'
| 'info'
| 'warning'
| 'error'
}[]
}
const popupConfig = ref<popupConfigType>()
const popup = async (config: popupConfigType) => {
popupConfig.value = config
inputValue.value = config.inputValue ?? ''
showMask.value = true
const key = await new Promise((resolve: (key: unknown) => unknown) => {
_resolve.value = resolve
})
const text = inputValue.value
showMask.value = false
nextTick(() => {
inputValue.value = ''
_resolve.value = undefined
})
return {
text,
key
}
popupConfig.value = config
inputValue.value = config.inputValue ?? ''
showMask.value = true
const key = await new Promise((resolve: (key: unknown) => unknown) => {
_resolve.value = resolve
})
const text = inputValue.value
showMask.value = false
nextTick(() => {
inputValue.value = ''
_resolve.value = undefined
})
return {
text,
key
}
}
defineExpose({ popup })
@@ -78,25 +84,25 @@ defineExpose({ popup })
<style scoped lang="scss">
.popup-card {
width: 80%;
width: 80%;
.popup-input {
margin-bottom: 10px;
}
.popup-input {
margin-bottom: 10px;
}
.popup-button-container {
height: 100%;
width: 100%;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
.popup-button-container {
height: 100%;
width: 100%;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
.popup-button-container-button {
margin-top: 3px;
&:not(:last-child) {
margin-right: 5px;
}
}
}
.popup-button-container-button {
margin-top: 3px;
&:not(:last-child) {
margin-right: 5px;
}
}
}
}
</style>