mirror of
https://github.com/jekip/naive-ui-admin.git
synced 2026-02-13 09:42:27 +08:00
Fixes bug add baseModal | baseForm 组件
This commit is contained in:
3
src/components/Modal/index.ts
Normal file
3
src/components/Modal/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as basicModal } from './src/basicModal.vue';
|
||||
export { useModal } from './src/hooks/useModal';
|
||||
export * from './src/type';
|
||||
127
src/components/Modal/src/basicModal.vue
Normal file
127
src/components/Modal/src/basicModal.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<n-modal id="basic-modal" v-bind="getBindValue" v-model:show="isModal" @close="onCloseModal">
|
||||
<template #header>
|
||||
<div class="w-full cursor-move" id="basic-modal-bar">{{ getBindValue.title }}</div>
|
||||
</template>
|
||||
<template #default>
|
||||
<slot name="default"></slot>
|
||||
</template>
|
||||
<template #action v-if="!$slots.action">
|
||||
<n-space>
|
||||
<n-button @click="closeModal">取消</n-button>
|
||||
<n-button type="primary" :loading="subLoading" @click="handleSubmit">{{
|
||||
subBtuText
|
||||
}}</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
<template v-else #action>
|
||||
<slot name="action"></slot>
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
getCurrentInstance,
|
||||
ref,
|
||||
nextTick,
|
||||
unref,
|
||||
toRefs,
|
||||
reactive,
|
||||
computed,
|
||||
} from 'vue';
|
||||
import { basicProps } from './props';
|
||||
import startDrag from '@/utils/Drag';
|
||||
import { deepMerge } from '@/utils';
|
||||
import { FormProps } from '@/components/Form';
|
||||
export default defineComponent({
|
||||
name: 'BasicModal',
|
||||
components: {},
|
||||
props: {
|
||||
...basicProps,
|
||||
},
|
||||
emits: ['on-close', 'on-ok', 'register'],
|
||||
setup(props, { emit, attrs }) {
|
||||
const propsRef = ref<Partial>({});
|
||||
|
||||
const state = reactive({
|
||||
isModal: false,
|
||||
subLoading: false,
|
||||
});
|
||||
|
||||
const getProps = computed((): FormProps => {
|
||||
const modalProps = { ...props, ...unref(propsRef) };
|
||||
return { ...modalProps };
|
||||
});
|
||||
|
||||
async function setProps(modalProps: Partial): Promise<void> {
|
||||
propsRef.value = deepMerge(unref(propsRef) || {}, modalProps);
|
||||
}
|
||||
|
||||
const getBindValue = computed(() => {
|
||||
return {
|
||||
...attrs,
|
||||
...unref(getProps),
|
||||
};
|
||||
});
|
||||
|
||||
function setSubLoading(status: boolean) {
|
||||
state.subLoading = status;
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
state.isModal = true;
|
||||
nextTick(() => {
|
||||
const oBox = document.getElementById('basic-modal');
|
||||
const oBar = document.getElementById('basic-modal-bar');
|
||||
startDrag(oBar, oBox);
|
||||
});
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
state.isModal = false;
|
||||
state.subLoading = false;
|
||||
emit('on-close');
|
||||
}
|
||||
|
||||
function onCloseModal() {
|
||||
state.isModal = false;
|
||||
emit('on-close');
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
state.subLoading = true;
|
||||
emit('on-ok');
|
||||
}
|
||||
|
||||
const modalMethods: ModalMethods = {
|
||||
setProps,
|
||||
openModal,
|
||||
closeModal,
|
||||
setSubLoading,
|
||||
};
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
if (instance) {
|
||||
emit('register', modalMethods);
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
getBindValue,
|
||||
openModal,
|
||||
closeModal,
|
||||
onCloseModal,
|
||||
handleSubmit,
|
||||
setProps,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.cursor-move {
|
||||
cursor: move;
|
||||
}
|
||||
</style>
|
||||
57
src/components/Modal/src/hooks/useModal.ts
Normal file
57
src/components/Modal/src/hooks/useModal.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { ref, onUnmounted, unref, getCurrentInstance, watch } from 'vue';
|
||||
import { isProdMode } from '@/utils/env';
|
||||
import { UseModalReturnType, ModalMethods } from './type';
|
||||
import { getDynamicProps } from '@/utils';
|
||||
export function useModal(props?: Props): UseModalReturnType {
|
||||
const modal = ref<Nullable<ModalMethods>>(null);
|
||||
const loaded = ref<Nullable<boolean>>(false);
|
||||
|
||||
function register(modalMethod: ModalMethods) {
|
||||
if (!getCurrentInstance()) {
|
||||
throw new Error('useModal() can only be used inside setup() or functional components!');
|
||||
}
|
||||
isProdMode() &&
|
||||
onUnmounted(() => {
|
||||
modal.value = null;
|
||||
loaded.value = false;
|
||||
});
|
||||
if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return;
|
||||
modal.value = modalMethod;
|
||||
|
||||
watch(
|
||||
() => props,
|
||||
() => {
|
||||
const { setProps } = modal.value;
|
||||
props && setProps(getDynamicProps(props));
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const getInstance = () => {
|
||||
const instance = unref(modal);
|
||||
if (!instance) {
|
||||
error('useModal instance is undefined!');
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
const methods: ReturnMethods = {
|
||||
setProps: (props: Partial<ModalProps>): void => {
|
||||
getInstance()?.setProps(props);
|
||||
},
|
||||
openModal: () => {
|
||||
getInstance()?.openModal();
|
||||
},
|
||||
closeModal: () => {
|
||||
getInstance()?.closeModal();
|
||||
},
|
||||
setSubLoading: () => {
|
||||
getInstance()?.setSubLoading();
|
||||
},
|
||||
};
|
||||
return [register, methods];
|
||||
}
|
||||
30
src/components/Modal/src/props.ts
Normal file
30
src/components/Modal/src/props.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NModal } from 'naive-ui';
|
||||
|
||||
export const basicProps = {
|
||||
...NModal.props,
|
||||
// 确认按钮文字
|
||||
subBtuText: {
|
||||
type: String,
|
||||
default: '确认',
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 446,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
preset: {
|
||||
type: String,
|
||||
default: 'dialog',
|
||||
},
|
||||
};
|
||||
12
src/components/Modal/src/type/index.ts
Normal file
12
src/components/Modal/src/type/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface ModalProps {
|
||||
subBtuText?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 弹窗对外暴露的方法
|
||||
*/
|
||||
export interface ModalMethods {
|
||||
setProps: (props: Partial<ModalProps>) => void;
|
||||
openModal: () => void;
|
||||
closeModal: () => void;
|
||||
}
|
||||
Reference in New Issue
Block a user