first commit

This commit is contained in:
lingxiao865
2026-02-10 08:05:03 +08:00
commit c5af079d8c
1094 changed files with 97530 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
:: BASE_DOC ::
## API
### Toast Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | Object | - | CSS(Cascading Style Sheets) | N
direction | String | row | options: row/column | N
duration | Number | 2000 | \- | N
icon | String / Object | - | \- | N
message | String | - | \- | N
overlay-props | Object | - | Typescript`OverlayProps `[Overlay API Documents](./overlay?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/toast/type.ts) | N
placement | String | middle | options: top/middle/bottom | N
prevent-scroll-through | Boolean | false | \- | N
show-overlay | Boolean | false | \- | N
theme | String | - | options: loading/success/warning/error | N
using-custom-navbar | Boolean | false | \- | N
### Toast Events
name | params | description
-- | -- | --
close | \- | \-
destroy | \- | \-
### Toast Slots
name | Description
-- | --
icon | \-
message | \-
### Toast External Classes
className | Description
-- | --
t-class | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-toast-bg-color | @mask-active | -
--td-toast-color | @text-color-anti | -
--td-toast-column-icon-size | 64rpx | -
--td-toast-max-width | 370rpx | -
--td-toast-radius | @radius-default | -
--td-toast-row-icon-size | 48rpx | -

View File

@@ -0,0 +1,78 @@
---
title: Toast 轻提示
description: 用于轻量级反馈或提示,不会打断用户操作。
spline: message
isComponent: true
---
## 引入
可在 `main.ts` 或在需要使用的页面或组件中引入。
```js
import TToast from '@tdesign/uniapp/toast/toast.vue';
```
### 基础提示
{{ base }}
### 组件状态
{{ theme }}
### 显示遮罩
{{ cover }}
### 手动关闭
{{ close }}
## API
### Toast Props
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
custom-style | Object | - | 自定义样式 | N
direction | String | row | 图标排列方式。可选项row/column | N
duration | Number | 2000 | 弹窗显示毫秒数 | N
icon | String / Object | - | 自定义图标。传入对象则透传至 Icon 组件 | N
message | String | - | 弹窗显示文字 | N
overlay-props | Object | - | 遮罩层属性,透传至 Overlay。TS 类型:`OverlayProps `[Overlay API Documents](./overlay?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/toast/type.ts) | N
placement | String | middle | 弹窗展示位置。可选项: top/middle/bottom | N
prevent-scroll-through | Boolean | false | 防止滚动穿透,即不允许点击和滚动 | N
show-overlay | Boolean | false | 是否显示遮罩层 | N
theme | String | - | 提示类型。可选项loading/success/warning/error | N
using-custom-navbar | Boolean | false | 是否使用了自定义导航栏 | N
### Toast Events
名称 | 参数 | 描述
-- | -- | --
close | \- | 轻提示隐藏的时候触发
destroy | \- | 轻提示销毁的时候触发
### Toast Slots
名称 | 描述
-- | --
icon | 自定义图标
message | 弹窗显示文字
### Toast External Classes
类名 | 描述
-- | --
t-class | 根节点样式类
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-toast-bg-color | @mask-active | -
--td-toast-color | @text-color-anti | -
--td-toast-column-icon-size | 64rpx | -
--td-toast-max-width | 370rpx | -
--td-toast-radius | @radius-default | -
--td-toast-row-icon-size | 48rpx | -

View File

@@ -0,0 +1,20 @@
declare type Context = any;
declare type ToastType = 'loading' | 'success' | 'warning' | 'error';
declare type ToastPositionType = 'top' | 'middle' | 'bottom';
declare type ToastDirectionType = 'row' | 'column';
export declare type ToastOptionsType = {
context?: Context;
selector?: string;
icon?: string;
message?: string;
duration?: number;
theme?: ToastType;
placement?: ToastPositionType;
preventScrollThrough?: boolean;
direction?: ToastDirectionType;
close?: () => void;
};
declare function Toast(options: ToastOptionsType): void;
declare function showToast(options?: ToastOptionsType): void;
declare function hideToast(options?: ToastOptionsType): void;
export { Toast as default, showToast, hideToast };

View File

@@ -0,0 +1,27 @@
import { getInstance, coalesce } from '../common/utils';
function Toast(options) {
const { context, selector = '#t-toast', ...Options } = options;
const instance = getInstance(context, selector);
if (instance) {
instance.show({
...Options,
duration: coalesce(Options.duration, 2000),
});
}
}
function showToast(options = {}) {
Toast(options);
}
function hideToast(options = {}) {
const { context, selector = '#t-toast' } = options;
const instance = getInstance(context, selector);
if (instance) {
instance.hide();
}
}
export { Toast as default, showToast, hideToast };

View File

@@ -0,0 +1,68 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdToastProps } from './type';
export default {
/** 图标排列方式 */
direction: {
type: String,
default: 'row' as TdToastProps['direction'],
validator(val: TdToastProps['direction']): boolean {
if (!val) return true;
return ['row', 'column'].includes(val);
},
},
/** 弹窗显示毫秒数 */
duration: {
type: Number,
default: 2000,
},
/** 自定义图标。传入对象则透传至 Icon 组件 */
icon: {
type: [String, Object],
},
/** 弹窗显示文字 */
message: {
type: String,
},
/** 遮罩层属性,透传至 Overlay */
overlayProps: {
type: Object,
},
/** 弹窗展示位置 */
placement: {
type: String,
default: 'middle' as TdToastProps['placement'],
validator(val: TdToastProps['placement']): boolean {
if (!val) return true;
return ['top', 'middle', 'bottom'].includes(val);
},
},
/** 防止滚动穿透,即不允许点击和滚动 */
preventScrollThrough: Boolean,
/** 是否显示遮罩层 */
showOverlay: Boolean,
/** 提示类型 */
theme: {
type: String,
validator(val: TdToastProps['theme']): boolean {
if (!val) return true;
return ['loading', 'success', 'warning', 'error'].includes(val);
},
},
/** 是否使用了自定义导航栏 */
usingCustomNavbar: Boolean,
/** 轻提示隐藏的时候触发 */
onClose: {
type: Function,
default: () => ({}),
},
/** 轻提示销毁的时候触发 */
onDestroy: {
type: Function,
default: () => ({}),
},
};

View File

@@ -0,0 +1,73 @@
.t-toast {
position: fixed;
left: 50%;
transform: translate(-50%, -50%);
z-index: 12001;
opacity: 1;
transition: opacity 300ms ease;
background-color: var(--td-toast-bg-color, var(--td-mask-active, rgba(0, 0, 0, 0.6)));
border-radius: var(--td-toast-radius, var(--td-radius-default, 12rpx));
color: var(--td-toast-color, var(--td-text-color-anti, var(--td-font-white-1, #ffffff)));
max-width: var(--td-toast-max-width, 370rpx);
min-height: 0;
width: auto;
display: flex;
flex-direction: column;
align-items: stretch;
box-sizing: border-box;
}
.t-toast--column {
padding: 48rpx;
min-width: 160rpx;
min-height: 160rpx;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
}
.t-toast--loading.t-toast--with-text {
min-width: 204rpx;
min-height: 204rpx;
padding-top: 0;
padding-bottom: 0;
}
.t-toast__content {
align-items: center;
font: var(--td-font-body-medium, 28rpx / 44rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular));
}
.t-toast__content--row {
display: flex;
text-align: left;
padding: 28rpx 44rpx;
}
.t-toast__content--column {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
:deep(.t-toast__icon)--row {
display: flex;
font-size: var(--td-toast-row-icon-size, 48rpx);
}
:deep(.t-toast__icon)--column {
font-size: var(--td-toast-column-icon-size, 64rpx);
}
.t-toast__text {
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
white-space: pre-line;
}
.t-toast__text--column:not(:empty):not(:only-child) {
margin-top: 16rpx;
}
.t-toast__text--row:not(:empty):not(:only-child) {
margin-left: 16rpx;
}
.t-toast.t-fade-enter,
.t-toast.t-fade-leave-to {
opacity: 0;
}

View File

@@ -0,0 +1,213 @@
<template>
<view>
<view
v-if="realVisible"
:class="tools.cls(classPrefix, [dataDirection, dataTheme, ['with-text', dataMessage]]) + ' ' + tClass + ' ' + transitionClass"
:style="tools._style(['top:' + (dataPlacement === 'top' ? '25%' : dataPlacement === 'bottom' ? '75%' : '45%'), customStyle])"
@transitionend="onTransitionEnd"
@touchstart.stop.prevent="loop"
>
<view :class="classPrefix + '__content ' + classPrefix + '__content--' + dataDirection">
<t-loading
v-if="isLoading"
theme="circular"
:size="dataDirection === 'row' ? '48rpx' : '64rpx'"
loading
inherit-color
layout="vertical"
/>
<block
v-else-if="_icon"
name="icon"
>
<t-icon
:custom-style="_icon.style || ''"
:t-class="iconTClass"
:class="iconClass"
:prefix="_icon.prefix"
:name="_icon.name"
:size="_icon.size"
:color="_icon.color"
:aria-hidden="true"
:aria-label="_icon.ariaLabel"
:aria-role="_icon.ariaRole"
/>
</block>
<slot name="icon" />
<view
aria-role="alert"
:class="classPrefix + '__text ' + classPrefix + '__text--' + dataDirection"
>
{{ dataMessage }}
</view>
<slot name="message" />
</view>
</view>
<t-overlay
:custom-style="(overlayProps && overlayProps.style) || ''"
:visible="visible && (showOverlay || dataPreventScrollThrough)"
:z-index="(overlayProps && overlayProps.zIndex) || 11000"
:duration="(overlayProps && overlayProps.duration) || 300"
:using-custom-navbar="(overlayProps && overlayProps.usingCustomNavbar) || usingCustomNavbar"
:custom-navbar-height="(overlayProps && overlayProps.customNavbarHeight) || customNavbarHeight"
:background-color="!showOverlay && dataPreventScrollThrough ? 'transparent' : (overlayProps && overlayProps.backgroundColor) || ''"
:prevent-scroll-through="dataPreventScrollThrough || (overlayProps && overlayProps.preventScrollThrough)"
/>
</view>
</template>
<script>
import TIcon from '../icon/icon';
import TLoading from '../loading/loading';
import TOverlay from '../overlay/overlay';
import { uniComponent } from '../common/src/index';
import { prefix } from '../common/config';
import props from './props';
import { transitionMixins } from '../mixins/transition';
import { calcIcon, toCamel, coalesce } from '../common/utils';
import useCustomNavbar from '../mixins/using-custom-navbar';
import tools from '../common/utils.wxs';
import { canUseVirtualHost } from '../common/version';
const name = `${prefix}-toast`;
const needTransformKeys = [
'direction',
'duration',
'icon',
'message',
'placement',
'preventScrollThrough',
'theme',
];
export default uniComponent({
name,
options: {
styleIsolation: 'shared',
},
externalClasses: [
`${prefix}-class`,
],
mixins: [transitionMixins, useCustomNavbar],
components: {
TIcon,
TLoading,
TOverlay,
},
props: {
...props,
},
emits: [
'leaved',
'destory',
'close',
],
data() {
const info = needTransformKeys.reduce((acc, key) => ({
...acc,
[toCamel(`data-${key}`)]: props[key].default,
}), {});
return {
prefix,
classPrefix: name,
_icon: null,
...info,
isLoading: false,
hideTimer: null,
tools,
};
},
computed: {
iconTClass() {
return canUseVirtualHost() ? this.iconRealClass : '';
},
iconClass() {
return !canUseVirtualHost() ? this.iconRealClass : '';
},
iconRealClass() {
const { classPrefix, dataDirection } = this;
return `${classPrefix}__icon ${classPrefix}__icon--${dataDirection}`;
},
},
pageLifetimes: {
hide() {
this.hide();
},
},
beforeUnMount() {
this.destroyed();
},
methods: {
show(options) {
if (this.hideTimer) clearTimeout(this.hideTimer);
const iconMap = {
loading: 'loading',
success: 'check-circle',
warning: 'error-circle',
error: 'close-circle',
};
const typeMapIcon = iconMap[options?.theme];
const defaultOptions = {
direction: props.direction.default,
duration: props.duration.default,
icon: props.icon.default,
message: props.message.default,
placement: props.placement.default,
preventScrollThrough: props.preventScrollThrough.default,
theme: props.theme.default,
close: null,
};
const data = {
...defaultOptions,
...options,
realVisible: true,
isLoading: options?.theme === 'loading',
_icon: calcIcon(coalesce(typeMapIcon, options.icon)),
};
const { duration } = data;
Object.keys(data).forEach((key) => {
if (needTransformKeys.includes(key)) {
this[toCamel(`data-${key}`)] = data[key];
} else {
this[key] = data[key];
}
});
if (duration > 0) {
this.hideTimer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
if (!this.realVisible) return; // 避免重复触发(页面关闭、定时关闭都会触发)
this.realVisible = false;
this?.close?.();
this.$emit('close');
},
destroyed() {
if (this.hideTimer) {
clearTimeout(this.hideTimer);
this.hideTimer = null;
}
this.$emit('destory');
},
loop() {},
},
});
</script>
<style scoped>
@import './toast.css';
</style>

View File

@@ -0,0 +1,64 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdOverlayProps as OverlayProps } from '../overlay/type';
export interface TdToastProps {
/**
* 图标排列方式
* @default row
*/
direction?: 'row' | 'column';
/**
* 弹窗显示毫秒数
* @default 2000
*/
duration?: number;
/**
* 自定义图标。传入对象则透传至 Icon 组件
*/
icon?: string | object;
/**
* 弹窗显示文字
*/
message?: string;
/**
* 遮罩层属性,透传至 Overlay
*/
overlayProps?: OverlayProps;
/**
* 弹窗展示位置
* @default middle
*/
placement?: 'top' | 'middle' | 'bottom';
/**
* 防止滚动穿透,即不允许点击和滚动
* @default false
*/
preventScrollThrough?: boolean;
/**
* 是否显示遮罩层
* @default false
*/
showOverlay?: boolean;
/**
* 提示类型
*/
theme?: 'loading' | 'success' | 'warning' | 'error';
/**
* 是否使用了自定义导航栏
* @default false
*/
usingCustomNavbar?: boolean;
/**
* 轻提示隐藏的时候触发
*/
onClose?: () => void;
/**
* 轻提示销毁的时候触发
*/
onDestroy?: () => void;
}