Skip to content

Commit 92f248e

Browse files
author
Tenny
committed
feat(MessageDialog)
Signed-off-by: Tenny <joel.shu@qq.com>
1 parent 77838c6 commit 92f248e

File tree

11 files changed

+205
-41
lines changed

11 files changed

+205
-41
lines changed

docs/.vitepress/theme/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import '../../../style/tooltip';
3131
import '../../../style/util/tabs.css';
3232
import '../../../style/list';
3333
import '../../../style/dialog';
34+
import '../../../style/dialog-box';
3435

3536
export default {
3637
extends: DefaultTheme,

docs/components/dialog.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,25 @@
3030
}
3131
}
3232

33-
DialogBox.alert()
33+
function openAlert() {
34+
DialogBox.alert("这是 Alert Content", 'Alert Title').then((result) => {
35+
if (result === true) {
36+
Message.success("点击了确定")
37+
} else {
38+
Message.info("点击了关闭")
39+
}
40+
})
41+
}
42+
43+
function openConfirm() {
44+
DialogBox.confirm("这是 Confirm Content", 'Confirm Title', { type: 'success' }).then((result) => {
45+
if (result === true) {
46+
Message.success("点击了确定")
47+
} else {
48+
Message.info("点击了关闭")
49+
}
50+
})
51+
}
3452
</script>
3553

3654
### 基础用法
@@ -180,6 +198,28 @@
180198
</CodePreview>
181199
</ClientOnly>
182200

201+
### 消息弹窗
202+
203+
模拟系统的消息提示框而实现的一套模态对话框组件,用于消息提示、确认消息和提交内容。系统自带有3种消息弹窗:`alert``confirm``prompt` 但是其样式比较简陋不太美观,消息弹窗优化了样式。
204+
205+
分别通过 `NtDialogBox.alert()``NtDialogBox.confirm()``NtDialogBox.prompt()` 调用
206+
207+
<ClientOnly>
208+
<CodePreview>
209+
<textarea lang="vue">
210+
<script setup>
211+
</script>
212+
<template>
213+
</template>
214+
</textarea>
215+
<template #preview>
216+
<Button @click="openAlert">alert</Button>
217+
<Button @click="openConfirm">confirm</Button>
218+
<Button>prompt</Button>
219+
</template>
220+
</CodePreview>
221+
</ClientOnly>
222+
183223
## API
184224

185225
### Dialog Props

src/components/dialog/AlertDialog.vue

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/components/dialog/Dialog.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ export default defineComponent({
6969
type: String,
7070
default: undefined,
7171
},
72+
to: {
73+
type: [Object, String] as PropType<HTMLElement | 'string'>,
74+
default: 'body',
75+
},
7276
/** 主题, normal - 普通, mobile - 移动风格 */
7377
theme: {
7478
type: String as PropType<'normal' | 'mobile'>,
@@ -111,9 +115,10 @@ export default defineComponent({
111115
}
112116
113117
return () => {
118+
console.log(props.to);
114119
return h(
115120
Teleport,
116-
{ to: 'body' },
121+
{ to: props.to },
117122
h(
118123
Transition,
119124
{

src/components/dialog/DialogBox.ts

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,56 @@
1-
import { h, render, createVNode } from 'vue';
2-
import Dialog from './Dialog.vue';
1+
import { render, createVNode } from 'vue';
2+
import AlertDialog from './MessageDialog.vue';
3+
import { isBlank } from 'ph-utils';
34

4-
export default {
5-
alert() {
6-
return new Promise((resolve, reject) => {
7-
const vnode = createVNode(
8-
Dialog,
9-
{
10-
title: 'Alert',
11-
modelValue: true,
12-
'onUpdate:modelValue': onUpdate,
13-
},
14-
() => 'Alert',
15-
);
16-
function onUpdate(val: boolean) {
17-
if (vnode.component != null) {
18-
vnode.component.props.modelValue = val;
19-
}
5+
function getContainer() {
6+
return document.createElement('div');
7+
}
8+
9+
type MessageOption = {
10+
showCancel?: boolean;
11+
type?: string;
12+
};
13+
14+
function alert(message: string, title?: string, option?: MessageOption) {
15+
return new Promise((resolve) => {
16+
const opts = { showCancel: false, ...option };
17+
let container = getContainer();
18+
const onClose = (action: 'close' | 'ok') => {
19+
resolve(action === 'ok' ? true : false);
20+
if (vnode != null && vnode.component != null) {
21+
vnode.component.props.show = false;
2022
}
21-
render(vnode, document.body);
22-
});
23-
},
23+
vnode = undefined as any;
24+
container = undefined as any;
25+
};
26+
const props: any = {
27+
message,
28+
show: true,
29+
showCancel: opts.showCancel,
30+
onClose,
31+
to: container,
32+
};
33+
34+
if (!isBlank(title)) {
35+
props.title = title;
36+
}
37+
38+
if (!isBlank(opts.type)) {
39+
props.type = opts.type;
40+
}
41+
42+
let vnode = createVNode(AlertDialog, props);
43+
render(vnode, container);
44+
document.body.appendChild(container.firstElementChild as any);
45+
});
46+
}
47+
48+
function confirm(message: string, title?: string, option?: MessageOption) {
49+
const opts = { type: 'info', showCancel: true, ...option };
50+
return alert(message, title, opts);
51+
}
52+
53+
export default {
54+
alert,
55+
confirm,
2456
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<template>
2+
<Dialog
3+
:model-value="show"
4+
:title="title"
5+
:show-cancel="showCancel"
6+
:mask-closable="false"
7+
:before-close="handleClose"
8+
container-class="nt-message-dialog-container"
9+
:to="to"
10+
>
11+
<component
12+
v-if="IconComponentName != null"
13+
:is="IconComponentName"
14+
:class="['nt-confirm-icon', 'nt-confirm-icon--' + props.type]"
15+
></component>
16+
{{ message }}</Dialog
17+
>
18+
</template>
19+
20+
<script setup lang="ts">
21+
import { defineAsyncComponent, ref, computed } from 'vue';
22+
import Dialog from './Dialog.vue';
23+
24+
const AsyncInfoIcon = defineAsyncComponent(() => import('../icon/Info.vue'));
25+
const AsyncErrorIcon = defineAsyncComponent(
26+
() => import('../icon/MaskClose.vue'),
27+
);
28+
const AsyncWarnIcon = defineAsyncComponent(() => import('../icon/Warn.vue'));
29+
const AsyncSuccessIcon = defineAsyncComponent(
30+
() => import('../icon/Success.vue'),
31+
);
32+
33+
const IconComponentName = computed(() => {
34+
if (props.type === 'success') {
35+
return AsyncSuccessIcon;
36+
} else if (props.type === 'warn') {
37+
return AsyncWarnIcon;
38+
} else if (props.type === 'error') {
39+
return AsyncErrorIcon;
40+
} else if (props.type === 'info') {
41+
return AsyncInfoIcon;
42+
}
43+
return null;
44+
});
45+
46+
const props = withDefaults(
47+
defineProps<{
48+
show?: boolean;
49+
title?: string;
50+
message: string;
51+
showCancel?: boolean;
52+
type?: 'success' | 'error' | 'warn' | 'info';
53+
to: HTMLElement;
54+
}>(),
55+
{
56+
title: '提示',
57+
showCancel: true,
58+
type: undefined,
59+
show: false,
60+
},
61+
);
62+
63+
const emits = defineEmits(['close']);
64+
65+
const handleClose = (action: 'cancel' | 'ok' | 'close') => {
66+
emits('close', action);
67+
};
68+
</script>
69+
70+
<style></style>

src/components/message/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
:style="bindStyle"
1212
:class="['nt-message', `nt-message-${type}`, customClass]"
1313
>
14-
<div>
14+
<div class="nt-message-container">
1515
<component :is="icon" class="nt-message-icon"></component>
1616
<span class="nt-message-content">{{ message }}</span>
1717
</div>

src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export { default as Card } from './components/Card.vue';
4040
export { default as Popover } from './components/popover/Popover.vue';
4141
export { default as Tooltip } from './components/popover/Tooltip.vue';
4242
export { default as Dialog } from './components/dialog/Dialog.vue';
43-
export { default as AlertDialog } from './components/dialog/AlertDialog.vue';
4443
export { default as DialogBox } from './components/dialog/DialogBox';
4544

4645
export { default as Qrcode } from './components/Qrcode.vue';

style/dialog-box/index.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.nt-message-dialog-container {
2+
display: flex;
3+
align-items: center;
4+
}
5+
6+
.nt-confirm-icon {
7+
margin-right: 5px;
8+
}
9+
.nt-confirm-icon--info {
10+
color: var(--nt-success-color, #999999);
11+
}
12+
.nt-confirm-icon--success {
13+
color: var(--nt-success-color, #19bf6c);
14+
}
15+
.nt-confirm-icon--error {
16+
color: var(--nt-error-color, #ed3f13);
17+
}
18+
.nt-confirm-icon--warn {
19+
color: var(--nt-warn-color, #f90);
20+
}

style/dialog-box/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './index.css';

0 commit comments

Comments
 (0)