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,69 @@
:: BASE_DOC ::
## API
### Message Props
name | type | default | description | required
-- | -- | -- | -- | --
custom-style | Object | - | CSS(Cascading Style Sheets) | N
action | String | - | `deprecated`。operation | N
align | String | left | options: left/center。Typescript`MessageAlignType` `type MessageAlignType = 'left' \| 'center'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
close-btn | String / Boolean / Object | false | \- | N
content | String | - | \- | N
duration | Number | 3000 | \- | N
gap | String / Number / Boolean | 12 | \- | N
icon | String / Boolean / Object | true | \- | N
link | String / Object | - | \- | N
marquee | Boolean / Object | false | Typescript`boolean \| MessageMarquee` `interface MessageMarquee { speed?: number; loop?: number; delay?: number }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
offset | Array | - | Typescript`Array<string \| number>` | N
single | Boolean | true | \- | N
theme | String | info | options: info/success/warning/error。Typescript`MessageThemeList` `type MessageThemeList = 'info' \| 'success' \| 'warning' \| 'error'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
visible | Boolean | false | `v-model:visible` is supported | N
default-visible | Boolean | false | uncontrolled property | N
z-index | Number | 15000 | \- | N
### Message Events
name | params | description
-- | -- | --
action-btn-click | `(context: { e: MouseEvent })` | \-
close-btn-click | `(context: { e: MouseEvent })` | \-
duration-end | \- | \-
link-click | `(context: { e: MouseEvent })` | \-
### Message Slots
name | Description
-- | --
\- | \-
action | `deprecated`。operation
close-btn | \-
content | \-
icon | \-
link | \-
### Message External Classes
className | Description
-- | --
t-class | \-
t-class-close-btn | \-
t-class-content | \-
t-class-icon | \-
t-class-link | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-message-bg-color | @bg-color-container | -
--td-message-border-radius | @radius-default | -
--td-message-box-shadow | @shadow-4 | -
--td-message-close-icon-color | @font-gray-3 | -
--td-message-content-font-color | @font-gray-1 | -
--td-message-error-color | @error-color | -
--td-message-info-color | @brand-color | -
--td-message-success-color | @success-color | -
--td-message-warning-color | @warning-color | -

View File

@@ -0,0 +1,105 @@
---
title: Message 消息通知
description: 用于轻量级反馈或提示,不会打断用户操作。
spline: message
isComponent: true
---
## 引入
可在 `main.ts` 或在需要使用的页面或组件中引入。
```js
import TMessage from '@tdesign/uniapp/message/message.vue';
```
### 引入 API
若以 API 形式调用 Message则需在页面 `page.js` 中引入组件 API
```js
import Message from '@tdesign/uniapp/message/index';
```
### 组件类型
弹窗内容为纯文本、标题和副标题、带输入框,用 API `Message.info` 方法调用反馈类对话框。
{{ base }}
### 组件状态
消息通知类型为普通info、警示warning、成功success、错误error
{{ theme }}
## API
### Message Props
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
custom-style | Object | - | 自定义样式 | N
action | String | - | 已废弃。操作 | N
align | String | left | 文本对齐方式。可选项left/center。TS 类型:`MessageAlignType` `type MessageAlignType = 'left' \| 'center'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
close-btn | String / Boolean / Object | false | 关闭按钮,可以自定义。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'user',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件 | N
content | String | - | 用于自定义消息弹出内容 | N
duration | Number | 3000 | 消息内置计时器,计时到达时会触发 duration-end 事件。单位:毫秒。值为 0 则表示没有计时器 | N
gap | String / Number / Boolean | 12 | 两条 `message` 之间的间距 | N
icon | String / Boolean / Object | true | 消息提醒前面的图标,可以自定义。值为 true 则根据 theme 显示对应的图标,值为 false 则不显示图标。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'info',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件 | N
link | String / Object | - | 链接名称。值为字符串表示链接名称,值为 `Object` 类型,表示透传至 `Link` | N
marquee | Boolean / Object | false | 跑马灯效果。speed 指速度控制loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放delay 表示延迟多久开始播放。TS 类型:`boolean \| MessageMarquee` `interface MessageMarquee { speed?: number; loop?: number; delay?: number }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
offset | Array | - | 相对于 placement 的偏移量,默认单位 rpx。示例[-10, 20] 或 ['10rpx', '8rpx']。TS 类型:`Array<string \| number>` | N
single | Boolean | true | 是否保持仅显示一条信息 | N
theme | String | info | 消息组件风格。可选项info/success/warning/error。TS 类型:`MessageThemeList` `type MessageThemeList = 'info' \| 'success' \| 'warning' \| 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/message/type.ts) | N
visible | Boolean | false | 是否显示,隐藏时默认销毁组件。支持语法糖 `v-model:visible` | N
default-visible | Boolean | false | 是否显示,隐藏时默认销毁组件。非受控属性 | N
z-index | Number | 15000 | 元素层级,样式默认为 15000 | N
### Message Events
名称 | 参数 | 描述
-- | -- | --
action-btn-click | `(context: { e: MouseEvent })` | 已废弃。当操作按钮存在时,用户点击操作按钮时触发
close-btn-click | `(context: { e: MouseEvent })` | 当关闭按钮存在时,用户点击关闭按钮触发
duration-end | \- | 计时结束后触发
link-click | `(context: { e: MouseEvent })` | 当`link`链接存在时,点击链接文本时触发
### Message Slots
名称 | 描述
-- | --
\- | 默认插槽,作用同 `content` 插槽
action | 已废弃。自定义 `action` 显示内容
close-btn | 关闭按钮
content | 自定义消息弹出内容
icon | 消息提醒前面的图标
link | 链接名称
### Message External Classes
类名 | 描述
-- | --
t-class | 根节点样式类
t-class-close-btn | 关闭按钮样式类
t-class-content | 内容样式类
t-class-icon | 图标样式类
t-class-link | 链接样式类
### CSS Variables
组件提供了下列 CSS 变量,可用于自定义样式。
| 名称 | 默认值 | 描述 |
| -- | -- | -- |
| --td-message-bg-color | @bg-color-container | - |
| --td-message-border-radius | @radius-default | - |
| --td-message-box-shadow | @shadow-4 | - |
| --td-message-close-icon-color | @font-gray-3 | - |
| --td-message-content-font-color | @font-gray-1 | - |
| --td-message-error-color | @error-color | - |
| --td-message-info-color | @brand-color | - |
| --td-message-success-color | @success-color | - |
| --td-message-warning-color | @warning-color | - |

View File

@@ -0,0 +1,10 @@
import props from './props';
export const messageDefaultData = Object.keys(props).reduce((acc, key) => {
const result = props[key].default;
return {
...acc,
[key]: typeof result === 'function' ? result() : result,
};
}, {});

View File

@@ -0,0 +1,17 @@
import { MessageProps } from './message.interface';
declare type Context = any;
declare type Instance = any;
interface MessageActionOptionsType extends Optional<MessageProps> {
context?: Context;
selector?: string;
}
declare const Handler: {
info(options: MessageActionOptionsType): Instance;
success(options: MessageActionOptionsType): Instance;
warning(options: MessageActionOptionsType): Instance;
error(options: MessageActionOptionsType): Instance;
hide(options: MessageActionOptionsType): void;
};
export default Handler;

View File

@@ -0,0 +1,39 @@
import { MessageType } from './message.interface';
import { getInstance } from '../common/utils';
const showMessage = function (options, theme = MessageType.info) {
const { context, selector = '#t-message', ...otherOptions } = options;
const instance = getInstance(context, selector);
if (typeof otherOptions.single !== 'boolean') {
otherOptions.single = true;
}
if (instance) {
instance.setMessage(otherOptions, theme);
return instance;
}
console.error('未找到组件,请确认 selector && context 是否正确');
};
export default {
info(options) {
return showMessage(options, MessageType.info);
},
success(options) {
return showMessage(options, MessageType.success);
},
warning(options) {
return showMessage(options, MessageType.warning);
},
error(options) {
return showMessage(options, MessageType.error);
},
hide(options) {
const { context, selector = '#t-message' } = { ...options };
const instance = getInstance(context, selector);
if (!instance) {
return;
}
instance.hide();
},
};

View File

@@ -0,0 +1,30 @@
export const MessageType = {
info: 'info',
success: 'success',
warning: 'warning',
error: 'error',
};
export interface MessageMarquee {
speed?: number;
loop?: number;
delay?: number;
}
export interface MessageProps {
visible?: boolean;
content: string;
align?: string;
theme?: keyof typeof MessageType;
icon?: boolean | string;
link?: string | object;
closeBtn?: boolean;
action?: string;
marquee?: MessageMarquee;
offset?: object;
duration?: number;
zIndex?: number;
id?: string;
gap?: string | number;
single?: boolean;
}

View File

@@ -0,0 +1,275 @@
<template>
<view>
<TMessageItem
v-for="(item) in messageList"
:key="item.id"
:ref="item.id"
@close-btn-click="handleClose($event, { tagId: item.id })"
@link-click="handleLinkClick($event, { tagId: item.id })"
@duration-end="handleDurationEnd($event, { tagId: item.id })"
>
<template #icon>
<slot
name="icon"
/>
</template>
<template #content>
<slot
name="content"
/>
</template>
<slot />
<template #link>
<slot
name="link"
/>
</template>
<template #close-btn>
<slot
name="close-btn"
/>
</template>
</TMessageItem>
</view>
</template>
<script>
import TMessageItem from '../message-item/message-item.vue';
import { uniComponent } from '../common/src/index';
import { prefix } from '../common/config';
import { MessageType } from './message.interface';
import props from './props';
import { unitConvert } from '../common/utils';
const SHOW_DURATION = 400;
const name = `${prefix}-message`;
export default uniComponent({
name,
options: {
styleIsolation: 'shared',
},
components: {
TMessageItem,
},
props: {
...props,
},
data() {
return {
prefix,
classPrefix: name,
messageList: [],
instances: [],
index: 0,
};
},
watch: {
visible: {
handler(value) {
if (value) {
const data = Object.keys(props).reduce((acc, key) => ({
...acc,
[key]: this[key],
}), {});
this.setMessage(data, this.theme);
} else {
this.messageList = [];
}
},
immediate: true,
},
},
pageLifetimes: {
show() {
this.hideAll();
},
},
mounted() {
},
methods: {
/**
* 设置消息信息
* @param msg
* @param theme
*/
setMessage(msg, theme = MessageType.info) {
let id = `${name}_${this.index}`;
if (msg.single) {
// 不能与外层的 ref 相同,否则抖音小程序报错
id = `${name}_inner`;
}
const gap = unitConvert(msg.gap || this.gap);
const msgObj = {
...msg,
theme,
id,
gap,
};
const instanceIndex = this.instances.findIndex(x => x.id === id);
if (instanceIndex < 0) {
this.addMessage(msgObj);
} else {
// 更新消息
const instance = this.instances[instanceIndex];
const offsetHeight = this.getOffsetHeight(instanceIndex);
instance.resetData(() => {
Object.keys(msgObj).forEach((key) => {
instance[key] = msgObj[key];
});
setTimeout(() => {
instance.show.call(instance, offsetHeight);
});
instance.onHide = () => {
this.close(id);
};
});
}
},
/**
* 新增消息
* @param msgObj
*/
addMessage(msgObj) {
const list = [...this.messageList, { id: msgObj.id }];
this.messageList = list;
setTimeout(() => {
const offsetHeight = this.getOffsetHeight();
const instance = this.showMessageItem(msgObj, msgObj.id, offsetHeight);
if (this.instances) {
this.instances.push(instance);
this.index += 1;
}
}, 33);
},
/**
* 获取消息显示top偏移距离
* @param index
* @returns
*/
getOffsetHeight(index = -1) {
let offsetHeight = 0;
let len = index;
if (len === -1 || len > this.instances.length) {
len = this.instances.length;
}
for (let i = 0; i < len; i += 1) {
const instance = this.instances[i];
offsetHeight += instance.height + instance.gap;
}
return offsetHeight;
},
/**
* 新增消息显示
* @param options
* @param id
* @param offsetHeight
* @returns
*/
showMessageItem(options, id, offsetHeight) {
let instance = this.$refs[`${id}`];
if (Array.isArray(instance)) {
instance = instance[0];
}
if (instance) {
instance.resetData(() => {
Object.keys(options).forEach((key) => {
instance[key] = options[key];
});
setTimeout(() => {
instance.show.call(instance, offsetHeight);
});
instance.onHide = () => {
this.close(id);
};
});
return instance;
}
console.error('未找到组件,请确认 selector && context 是否正确');
},
close(id) {
setTimeout(() => {
this.removeMsg(id);
}, SHOW_DURATION);
this.removeInstance(id);
},
/**
* 移除指定消息id为空则删除全部消息
* @param id
*/
hide(id) {
if (!id) {
this.hideAll();
}
const instance = this.instances.find(x => x.id === id);
if (instance) {
instance.hide();
}
},
/**
* 移除全部消息
*/
hideAll() {
// 消息移除后也会移除instance下标不用增加直至全部删除
for (let i = 0; i < this.instances.length;) {
const instance = this.instances[i];
instance.hide();
}
},
/**
* 移除message实例
*/
removeInstance(id) {
const index = this.instances.findIndex(x => x.id === id);
if (index < 0) return;
const instance = this.instances[index];
const removedHeight = instance.height;
this.instances.splice(index, 1);
for (let i = index; i < this.instances.length; i += 1) {
const instance = this.instances[i];
instance.wrapTop = instance.wrapTop - removedHeight - instance.gap;
}
},
/**
* 移除页面元素
* @param id
*/
removeMsg(id) {
this.messageList = this.messageList.filter(item => item.id !== id);
// #ifdef VUE2
this.$set(this, 'messageList', this.messageList);
// #endif
},
handleClose(e) {
this.$emit('close-btn-click', { e });
},
handleLinkClick(e) {
this.$emit('link-click', { e });
},
handleDurationEnd(e) {
this.$emit('duration-end', { e });
},
},
});
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,101 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
import type { TdMessageProps } from './type';
export default {
/** 文本对齐方式 */
align: {
type: String,
default: 'left' as TdMessageProps['align'],
validator(val: TdMessageProps['align']): boolean {
if (!val) return true;
return ['left', 'center'].includes(val);
},
},
/** 关闭按钮,可以自定义。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'user',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件 */
closeBtn: {
type: [String, Boolean, Object],
default: false as TdMessageProps['closeBtn'],
},
/** 用于自定义消息弹出内容 */
content: {
type: String,
},
/** 消息内置计时器,计时到达时会触发 duration-end 事件。单位:毫秒。值为 0 则表示没有计时器 */
duration: {
type: Number,
default: 3000,
},
/** 两条 `message` 之间的间距 */
gap: {
type: [String, Number, Boolean],
default: 12 as TdMessageProps['gap'],
},
/** 消息提醒前面的图标,可以自定义。值为 true 则根据 theme 显示对应的图标,值为 false 则不显示图标。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'info',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件 */
icon: {
type: [String, Boolean, Object],
default: true as TdMessageProps['icon'],
},
/** 链接名称。值为字符串表示链接名称,值为 `Object` 类型,表示透传至 `Link` */
link: {
type: [String, Object],
},
/** 跑马灯效果。speed 指速度控制loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放delay 表示延迟多久开始播放 */
marquee: {
type: [Boolean, Object],
default: false as TdMessageProps['marquee'],
},
/** 相对于 placement 的偏移量,默认单位 rpx。示例[-10, 20] 或 ['10rpx', '8rpx'] */
offset: {
type: Array,
},
/** 是否保持仅显示一条信息 */
single: {
type: Boolean,
default: true,
},
/** 消息组件风格 */
theme: {
type: String,
default: 'info' as TdMessageProps['theme'],
validator(val: TdMessageProps['theme']): boolean {
if (!val) return true;
return ['info', 'success', 'warning', 'error'].includes(val);
},
},
/** 是否显示,隐藏时默认销毁组件 */
visible: {
type: Boolean,
default: undefined,
},
/** 是否显示,隐藏时默认销毁组件,非受控属性 */
defaultVisible: Boolean,
/** 元素层级,样式默认为 15000 */
zIndex: {
type: Number,
default: 15000,
},
/** 已废弃。当操作按钮存在时,用户点击操作按钮时触发 */
onActionBtnClick: {
type: Function,
default: () => ({}),
},
/** 当关闭按钮存在时,用户点击关闭按钮触发 */
onCloseBtnClick: {
type: Function,
default: () => ({}),
},
/** 计时结束后触发 */
onDurationEnd: {
type: Function,
default: () => ({}),
},
/** 当`link`链接存在时,点击链接文本时触发 */
onLinkClick: {
type: Function,
default: () => ({}),
},
};

View File

@@ -0,0 +1,101 @@
/* eslint-disable */
/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */
export interface TdMessageProps {
/**
* 文本对齐方式
* @default left
*/
align?: MessageAlignType;
/**
* 关闭按钮,可以自定义。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'user',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件
* @default false
*/
closeBtn?: string | boolean | object;
/**
* 用于自定义消息弹出内容
*/
content?: string;
/**
* 消息内置计时器,计时到达时会触发 duration-end 事件。单位:毫秒。值为 0 则表示没有计时器
* @default 3000
*/
duration?: number;
/**
* 两条 `message` 之间的间距
* @default 12
*/
gap?: string | number | boolean;
/**
* 消息提醒前面的图标,可以自定义。值为 true 则根据 theme 显示对应的图标,值为 false 则不显示图标。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string ,如:'info',则显示组件内置图标。值类型为 object ,则会透传至 icon 组件
* @default true
*/
icon?: string | boolean | object;
/**
* 链接名称。值为字符串表示链接名称,值为 `Object` 类型,表示透传至 `Link`
*/
link?: string | object;
/**
* 跑马灯效果。speed 指速度控制loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放delay 表示延迟多久开始播放
* @default false
*/
marquee?: boolean | MessageMarquee;
/**
* 相对于 placement 的偏移量,默认单位 rpx。示例[-10, 20] 或 ['10rpx', '8rpx']
*/
offset?: Array<string | number>;
/**
* 是否保持仅显示一条信息
* @default true
*/
single?: boolean;
/**
* 消息组件风格
* @default info
*/
theme?: MessageThemeList;
/**
* 是否显示,隐藏时默认销毁组件
* @default false
*/
visible?: boolean;
/**
* 是否显示,隐藏时默认销毁组件,非受控属性
* @default false
*/
defaultVisible?: boolean;
/**
* 元素层级,样式默认为 15000
* @default 15000
*/
zIndex?: number;
/**
* 已废弃。当操作按钮存在时,用户点击操作按钮时触发
*/
onActionBtnClick?: (context: { e: MouseEvent }) => void;
/**
* 当关闭按钮存在时,用户点击关闭按钮触发
*/
onCloseBtnClick?: (context: { e: MouseEvent }) => void;
/**
* 计时结束后触发
*/
onDurationEnd?: () => void;
/**
* 当`link`链接存在时,点击链接文本时触发
*/
onLinkClick?: (context: { e: MouseEvent }) => void;
}
export type MessageAlignType = 'left' | 'center';
export interface MessageMarquee {
speed?: number;
loop?: number;
delay?: number;
}
export type MessageThemeList = 'info' | 'success' | 'warning' | 'error';