| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <template>
- <FlexRow
- :innerClass="['nana-alert', `nana-alert-${type}`]"
- :innerStyle="{
- ...themeStyles.container.value,
- backgroundColor: themeContext.resolveThemeColor(backgroundColor|| selectStyleType(
- type, 'default', {
- default: '',
- primary: 'background.primary',
- success: 'background.success',
- warning: 'background.warning',
- danger: 'background.danger',
- error: 'background.danger',
- info: 'background.info',
- }
- )),
- borderStyle: 'solid',
- borderColor: themeContext.resolveThemeColor(borderColor || selectStyleType(
- type, 'default', {
- default: 'border.default',
- primary: 'mask.primary',
- success: 'mask.success',
- warning: 'mask.warning',
- danger: 'mask.danger',
- error: 'mask.danger',
- info: 'mask.info',
- }
- )),
- borderRadius: themeContext.resolveThemeSize('AlertBorderRadius', 16),
- }"
- @click="emit('click')"
- >
- <!-- 图标 -->
- <slot name="icon">
- <Icon
- :icon="icon ?? iconTypeMap[type]"
- :color="color"
- :innerStyle="{
- ...themeStyles.icon.value,
- marginRight: hasTitle || hasContent ? themeContext.resolveThemeSize('AlertIconMarginRight', 12) : 0,
- }"
- />
- </slot>
-
- <!-- 内容区域 -->
- <FlexCol
- :innerClass="['nana-alert-content']"
- :flexGrow="1"
- :flexShrink="1"
- >
- <!-- 标题 -->
- <slot name="message">
- <Text
- v-if="message"
- :text="message"
- :fontSize="themeContext.resolveThemeSize('AlertTitleFontSize', 'fontSize.medium')"
- :fontWeight="themeContext.getVar('AlertTitleFontWeight', 'bold')"
- :color="color"
- :innerStyle="themeStyles.message.value"
- />
- </slot>
- <!-- 内容 -->
- <slot name="description">
- <Text
- v-if="description"
- :text="description"
- :fontSize="themeContext.resolveThemeSize('AlertMessageFontSize', 'fontSize.small')"
- :color="color"
- :lines="lines"
- :innerStyle="{
- ...themeStyles.description.value,
- marginTop: hasTitle ? themeContext.resolveThemeSize('AlertMessageMarginTop', 8) : 0,
- }"
- />
- </slot>
-
- <!-- 自定义内容 -->
- <slot />
- </FlexCol>
-
- <!-- 关闭按钮 -->
- <slot name="close">
- <IconButton
- v-if="closeable"
- :icon="closeIcon"
- :color="closeIconColor"
- :size="themeContext.resolveThemeSize('AlertCloseButtonSize', 42)"
- :innerStyle="{
- ...themeStyles.closeButton.value,
- marginLeft: themeContext.resolveThemeSize('AlertCloseButtonMarginLeft', 12),
- }"
- @click.stop="handleClose"
- />
- </slot>
- </FlexRow>
- </template>
- <script setup lang="ts">
- import { computed } from 'vue';
- import { useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
- import { DynamicSize, DynamicColor, selectStyleType, DynamicVar } from '../theme/ThemeTools';
- import Text from '../basic/Text.vue';
- import Icon from '../basic/Icon.vue';
- import IconButton from '../basic/IconButton.vue';
- import FlexRow from '../layout/FlexRow.vue';
- import FlexCol from '../layout/FlexCol.vue';
- export type AlertType = 'primary' | 'success' | 'warning' | 'danger' | 'error' | 'info' | 'default';
- export interface AlertProps {
- /**
- * 提示类型,可选值为 primary, success, warning, danger, error, info, default
- * @default 'default'
- */
- type?: AlertType;
- /**
- * 提示标题
- */
- message?: string;
- /**
- * 提示内容
- */
- description?: string;
- /**
- * 自定义图标
- */
- icon?: string;
- /**
- * 文字和图标的颜色
- */
- color?: string;
- /**
- * 背景颜色
- */
- backgroundColor?: string;
- /**
- * 边框颜色
- */
- borderColor?: string;
- /**
- * 是否显示关闭按钮
- * @default false
- */
- closeable?: boolean;
- /**
- * 关闭图标
- * @default 'close'
- */
- closeIcon?: string;
- /**
- * 关闭图标颜色
- */
- closeIconColor?: string;
- /**
- * 内容最多显示的行数,0表示不限制
- * @default 0
- */
- lines?: number;
- }
- const emit = defineEmits(['close', 'click']);
- const props = withDefaults(defineProps<AlertProps>(), {
- type: 'default',
- closeable: false,
- closeIcon: 'close',
- lines: 0,
- });
- const themeContext = useTheme();
- const iconTypeMap = {
- primary: 'prompt',
- success: 'success',
- warning: 'warning',
- danger: 'error',
- error: 'delete-filling',
- info: 'prompt',
- default: '',
- } as const;
- // 判断是否有标题和内容
- const hasTitle = computed(() => !!props.message);
- const hasContent = computed(() => !!props.description);
- const color = computed(() => {
- if (props.color)
- return themeContext.resolveThemeColor(props.color);
- return selectStyleType(props.type, 'default', {
- default: 'text.content',
- primary: 'text.primary',
- success: 'text.success',
- warning: 'text.warning',
- danger: 'text.danger',
- error: 'text.danger',
- info: 'text.info',
- });
- });
- const closeIconColor = computed(() => {
- if (props.closeIconColor)
- return themeContext.resolveThemeColor(props.closeIconColor);
- return themeContext.resolveThemeColor('text.second');
- });
- // 处理关闭事件
- const handleClose = () => {
- emit('close');
- };
- // 定义主题样式
- const themeStyles = themeContext.useThemeStyles({
- container: {
- position: 'relative',
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- padding: DynamicSize('AlertPadding', 16),
- borderWidth: DynamicSize('AlertBorderWidth', '1px'),
- borderStyle: DynamicVar('AlertBorderStyle', 'solid'),
- } as ViewStyle,
- icon: {
- fontSize: DynamicSize('AlertIconSize', 20),
- flexShrink: 0,
- marginTop: DynamicSize('AlertIconMarginTop', 2),
- } as ViewStyle,
- message: {
- margin: 0,
- padding: 0,
- flexShrink: 0,
- } as TextStyle,
- description: {
- margin: 0,
- padding: 0,
- flexShrink: 1,
- } as TextStyle,
- closeButton: {} as ViewStyle,
- });
- </script>
- <style lang="scss">
- .nana-alert {
- transition: all 0.3s ease;
- box-sizing: border-box;
-
- &-content {
- flex: 1;
- min-width: 0;
- }
- }
- </style>
|