diff --git a/components/message/README.md b/components/message/README.md
new file mode 100644
index 0000000..9e900cd
--- /dev/null
+++ b/components/message/README.md
@@ -0,0 +1,74 @@
+---
+title: Message 消息通知
+description: 用于轻量级反馈或提示,不会打断用户操作。
+spline: message
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-message": "tdesign-miniprogram/message/message"
+}
+```
+
+### 引入 API
+
+若以 API 形式调用 Message,则需在页面 `page.js` 中引入组件 API:
+
+```js
+import Message from 'tdesign-miniprogram/message/index';
+```
+
+## 代码演示
+
+### 基础消息通知
+
+弹窗内容为纯文本、标题和副标题、带输入框,用 API `Message.info` 方法调用反馈类对话框。
+
+
+{{ base }}
+
+
+### 不同状态的消息通知
+
+消息通知类型为普通(info)、警示(warning)、成功(success)、错误(error)
+
+{{ status-message }}
+
+### 自定义导航栏
+
+当设置了 `navigationStyle = custom`,可以通过 offetset 来调整显示位置:
+
+{{ custom-navigation }}
+
+## API
+
+### Message Props
+
+| 名称 | 类型 | 默认值 | 说明 | 必传|
+| -- | -- | -- | -- | -- |
+| action | String / Slot | - | 操作 | N |
+| align | String | left | 文本对齐方式。可选项:left/center | N |
+| close-btn | String / Boolean / Slot | undefined | 关闭按钮,可以自定义。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string 则直接显示值,如:“关闭”。也可以完全自定义按钮 | N |
+| content | String / Slot | - | 用于自定义消息弹出内容 | N |
+| duration | Number | 3000 | 消息内置计时器,计时到达时会触发 duration-end 事件。单位:毫秒。值为 0 则表示没有计时器。 | N |
+| external-classes | Array | - | 样式类名,分别用于设置 组件外层、消息内容、左侧图标、操作按钮、关闭按钮等元素类名。`['t-class', 't-class-content', 't-class-icon', 't-class-action', 't-class-close-btn']` | N |
+| icon | String / Boolean / Slot | true | 消息提醒前面的图标。值为 true 则根据 theme 显示对应的图标,值为 false 则不显示图标。值为 'info' 或 'bell' 则显示组件内置图标。也可以完全自定义图标节点。TS 类型:`boolean | 'info' | 'bell'` | N |
+| marquee | Boolean / Object | false | 跑马灯效果。speed 指速度控制;loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放;delay 表示延迟多久开始播放。TS 类型:`boolean | DrawMarquee`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/message/type.ts) | N |
+| offset | Array | - | 相对于 placement 的偏移量,示例:[-10, 20] 或 ['10rpx', '8rpx']。TS 类型:`Array` | N |
+| theme | String | info | 消息组件风格。可选项:info/success/warning/error。TS 类型:`MessageThemeList`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/message/type.ts) | N |
+| visible | Boolean | false | 是否显示,隐藏时默认销毁组件 | N |
+| z-index | Number | 15000 | 组件层级,样式默认为 15000 | N |
+
+### Message Events
+
+| 名称 | 参数 | 描述 |
+| ---------------- | ---- | ---------------------------------------- |
+| action-btn-click | - | 当操作按钮存在时,用户点击操作按钮时触发 |
+| close-btn-click | - | 当关闭按钮存在时,用户点击关闭按钮触发 |
+| duration-end | - | 计时结束后触发 |
diff --git a/components/message/api.md b/components/message/api.md
new file mode 100644
index 0000000..26e9582
--- /dev/null
+++ b/components/message/api.md
@@ -0,0 +1,100 @@
+# Message
+
+消息组件
+
+### 特性及兼容性
+
+无
+
+## 引入
+
+### 引入组件
+
+在 `app.json` 或 `page.json` 中引入组件:
+
+```json
+"usingComponents": {
+ "t-message": "tdesign-miniprogram/message/message"
+}
+```
+
+### 引入 API
+
+若以 API 形式调用 Message,则需在页面 `page.js` 中引入组件 API:
+
+```js
+import Message from 'tdesign-miniprogram/message/index';
+```
+
+## 用法
+
+### 消息提示
+
+用 API `Message.info` 方法调用反馈类对话框
+
+```html
+
+
+```
+
+```js
+// page.js
+Message.info({
+ content: '消息内容',
+});
+```
+
+## API
+
+### `` 组件
+
+组件路径:`tdesign-miniprogram/message/message`
+
+#### Props
+
+| 属性 | 值类型 | 默认值 | 说明 |
+| --------------- | ----------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | --------------- |
+| visible | Boolean | false | 是否显示,隐藏时默认销毁组件 | N |
+| content | String / Slot | - | 用于自定义消息弹出内容。 | N |
+| theme | String | info | 消息组件风格。可选值:info/success/warning/error。 | N |
+| duration | Number | 3000 | 消息内置计时器,计时到达时会触发 duration-end 事件。单位:毫秒。值为 0 则表示没有计时器。 | N |
+| offset | `Object` | - | 偏移量,默认[0,0] |
+| closeBtn | String / Boolean /Slot | undefined | 关闭按钮,可以自定义。值为 true 显示默认关闭按钮,值为 false 不显示关闭按钮。值类型为 string 则直接显示值,如:“关闭”。也可以完全自定义按钮。 | N |
+| externalClasses | Array | - | 样式类名,分别用于设置 组件外层、消息内容、左侧图标、操作按钮、关闭按钮等元素类名。`['t-class', 't-class-content', 't-class-icon', 't-class-action', 't-class-close-btn']` | N |
+| icon | String / Boolean / Slot | true | 消息提醒前面的图标。值为 true 则根据 theme 显示对应的图标,值为 false 则不显示图标。值为 'info' 或 'bell' 则显示组件内置图标。也可以完全自定义图标节点。TS 类型:`boolean | 'warning_fill' | 'sound_fill'` N |
+| marquee | Object | - | 跑马灯效果,delay 动画延迟时间 (s);speed 滚动速率 (px/s)。N |
+| zIndex | Number | - | 元素层级,样式默认为 5000 | N |
+
+### Event
+
+| 事件名 | 说明 | 参数 |
+| -------------- | ---------------------------------------- | ---------------- |
+| closeBtnClick | 点击关闭 icon 时触发 | - |
+| actionBtnClick | 点击按钮时触发, 可通过 self 拿到组件实例 | `{ self: this }` |
+
+### Slot
+
+| 事件名 | 说明 |
+| -------- | ------------------- |
+| icon | 左侧 icon 处 |
+| action | 右侧操作按钮。 N |
+| closeBtn | 按钮(关闭 icon)处 |
+
+### 外部样式
+
+| class | 说明 |
+| ----------------- | ----------- |
+| t-class | 根节点 |
+| t-class-content | 文本内容 |
+| t-class-icon | 左侧 icon |
+| t-class-action | 右侧 button |
+| t-class-close-btn | 右侧 icon |
+
+### 编程式调用
+
+| 方法 | type | 返回值 | 说明 |
+| -------------------------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
+| Message.info(`options`) | info | `void` | 弹出消息,参数参考 Props,额外可指定`{context: WechatMiniprogram.Component.TrivialInstance,selector: string}` |
+| Message.success(`options`) | success | `void` | 弹出消息,参数参考 Props,额外可指定`{context: WechatMiniprogram.Component.TrivialInstance,selector: string}` |
+| Message.warning(`options`) | warning | `void` | 弹出消息,参数参考 Props,额外可指定`{context: WechatMiniprogram.Component.TrivialInstance,selector: string}` |
+| Message.error(`options`) | error | `void` | 弹出消息,参数参考 Props,额外可指定`{context: WechatMiniprogram.Component.TrivialInstance,selector: string}` |
diff --git a/components/message/index.d.ts b/components/message/index.d.ts
new file mode 100644
index 0000000..a8cf1e3
--- /dev/null
+++ b/components/message/index.d.ts
@@ -0,0 +1,17 @@
+///
+///
+///
+import { MessageProps } from './message.interface';
+declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
+interface MessageActionOptionsType extends Optional {
+ context?: Context;
+ selector?: string;
+}
+declare const _default: {
+ info(options: MessageActionOptionsType): WechatMiniprogram.Component.TrivialInstance;
+ success(options: MessageActionOptionsType): WechatMiniprogram.Component.TrivialInstance;
+ warning(options: MessageActionOptionsType): WechatMiniprogram.Component.TrivialInstance;
+ error(options: MessageActionOptionsType): WechatMiniprogram.Component.TrivialInstance;
+ hide(options: MessageActionOptionsType): void;
+};
+export default _default;
diff --git a/components/message/index.js b/components/message/index.js
new file mode 100644
index 0000000..02b775a
--- /dev/null
+++ b/components/message/index.js
@@ -0,0 +1,46 @@
+var __rest = (this && this.__rest) || function (s, e) {
+ var t = {};
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
+ t[p] = s[p];
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
+ t[p[i]] = s[p[i]];
+ }
+ return t;
+};
+import { MessageType } from './message.interface';
+import { getInstance } from '../common/utils';
+const showMessage = function (options, theme = MessageType.info) {
+ const { context, selector = '#t-message' } = options, otherOptions = __rest(options, ["context", "selector"]);
+ const instance = getInstance(context, selector);
+ if (instance) {
+ instance.resetData(() => {
+ instance.setData(Object.assign({ theme }, otherOptions), instance.show.bind(instance));
+ });
+ 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' } = Object.assign({}, options);
+ const instance = getInstance(context, selector);
+ if (!instance) {
+ return;
+ }
+ instance.hide();
+ },
+};
diff --git a/components/message/message.d.ts b/components/message/message.d.ts
new file mode 100644
index 0000000..0718969
--- /dev/null
+++ b/components/message/message.d.ts
@@ -0,0 +1,38 @@
+///
+import { SuperComponent, ComponentsOptionsType } from '../common/src/index';
+import { MessageProps } from './message.interface';
+export default class Message extends SuperComponent {
+ externalClasses: string[];
+ options: ComponentsOptionsType;
+ properties: MessageProps;
+ data: {
+ prefix: string;
+ classPrefix: string;
+ visible: boolean;
+ loop: number;
+ animation: any[];
+ showAnimation: any[];
+ iconName: string;
+ wrapTop: number;
+ };
+ observers: {
+ marquee(val: any): void;
+ };
+ closeTimeoutContext: number;
+ nextAnimationContext: number;
+ resetAnimation: WechatMiniprogram.Animation;
+ showAnimation: WechatMiniprogram.AnimationExportResult;
+ hideAnimation: WechatMiniprogram.AnimationExportResult;
+ ready(): void;
+ memoInitalData(): void;
+ resetData(cb: () => void): void;
+ detached(): void;
+ setIcon(icon?: string | boolean): void;
+ checkAnimation(): void;
+ clearMessageAnimation(): void;
+ show(): void;
+ hide(): void;
+ reset(): void;
+ handleClose(): void;
+ handleBtnClick(): void;
+}
diff --git a/components/message/message.interface.d.ts b/components/message/message.interface.d.ts
new file mode 100644
index 0000000..9dce180
--- /dev/null
+++ b/components/message/message.interface.d.ts
@@ -0,0 +1,24 @@
+export declare enum 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?: MessageType;
+ icon?: boolean | string;
+ closeBtn?: boolean;
+ action?: string;
+ marquee?: MessageMarquee;
+ offset?: object;
+ duration?: number;
+ zIndex?: number;
+}
diff --git a/components/message/message.interface.js b/components/message/message.interface.js
new file mode 100644
index 0000000..b345007
--- /dev/null
+++ b/components/message/message.interface.js
@@ -0,0 +1,7 @@
+export var MessageType;
+(function (MessageType) {
+ MessageType["info"] = "info";
+ MessageType["success"] = "success";
+ MessageType["warning"] = "warning";
+ MessageType["error"] = "error";
+})(MessageType || (MessageType = {}));
diff --git a/components/message/message.js b/components/message/message.js
new file mode 100644
index 0000000..1114ccc
--- /dev/null
+++ b/components/message/message.js
@@ -0,0 +1,180 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+import { SuperComponent, wxComponent } from '../common/src/index';
+import config from '../common/config';
+import props from './props';
+import { getRect } from '../common/utils';
+const { prefix } = config;
+const name = `${prefix}-message`;
+const SHOW_DURATION = 500;
+let Message = class Message extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.externalClasses = ['t-class', 't-class-content', 't-class-icon', 't-class-action', 't-class-close-btn'];
+ this.options = {
+ styleIsolation: 'apply-shared',
+ multipleSlots: true,
+ };
+ this.properties = Object.assign({}, props);
+ this.data = {
+ prefix,
+ classPrefix: name,
+ visible: false,
+ loop: -1,
+ animation: [],
+ showAnimation: [],
+ iconName: '',
+ wrapTop: -92,
+ };
+ this.observers = {
+ marquee(val) {
+ if (JSON.stringify(val) === '{}') {
+ this.setData({
+ marquee: {
+ speed: 50,
+ loop: -1,
+ delay: 5000,
+ },
+ });
+ }
+ },
+ };
+ this.closeTimeoutContext = 0;
+ this.nextAnimationContext = 0;
+ this.resetAnimation = wx.createAnimation({
+ duration: 0,
+ timingFunction: 'linear',
+ });
+ this.showAnimation = wx.createAnimation({ duration: SHOW_DURATION, timingFunction: 'ease' }).translateY(0).step().export();
+ this.hideAnimation = wx
+ .createAnimation({ duration: SHOW_DURATION, timingFunction: 'ease' })
+ .translateY(this.data.wrapTop)
+ .step()
+ .export();
+ }
+ ready() {
+ this.memoInitalData();
+ this.setIcon();
+ }
+ memoInitalData() {
+ this.initalData = Object.assign(Object.assign({}, this.properties), this.data);
+ }
+ resetData(cb) {
+ this.setData(Object.assign({}, this.initalData), cb);
+ }
+ detached() {
+ this.clearMessageAnimation();
+ }
+ setIcon(icon = this.properties.icon) {
+ if (!icon) {
+ this.setData({ iconName: '' });
+ return;
+ }
+ if (typeof icon === 'string') {
+ this.setData({
+ iconName: `${icon}`,
+ });
+ return;
+ }
+ if (icon) {
+ let nextValue = 'notification';
+ const { theme } = this.properties;
+ const themeMessage = {
+ info: 'error-circle',
+ success: 'check-circle',
+ warning: 'error-circle',
+ error: 'error-circle',
+ };
+ nextValue = themeMessage[theme];
+ this.setData({ iconName: nextValue });
+ }
+ }
+ checkAnimation() {
+ if (!this.properties.marquee) {
+ return;
+ }
+ const speeding = this.properties.marquee.speed;
+ if (this.data.loop > 0) {
+ this.data.loop -= 1;
+ }
+ else if (this.data.loop === 0) {
+ this.setData({ animation: this.resetAnimation.translateX(0).step().export() });
+ return;
+ }
+ if (this.nextAnimationContext) {
+ this.clearMessageAnimation();
+ }
+ const warpID = `#${name}__text-wrap`;
+ const nodeID = `#${name}__text`;
+ Promise.all([getRect(this, nodeID), getRect(this, warpID)]).then(([nodeRect, wrapRect]) => {
+ this.setData({
+ animation: this.resetAnimation.translateX(wrapRect.width).step().export(),
+ }, () => {
+ const durationTime = ((nodeRect.width + wrapRect.width) / speeding) * 1000;
+ const nextAnimation = wx
+ .createAnimation({
+ duration: durationTime,
+ })
+ .translateX(-nodeRect.width)
+ .step()
+ .export();
+ setTimeout(() => {
+ this.nextAnimationContext = setTimeout(this.checkAnimation.bind(this), durationTime);
+ this.setData({ animation: nextAnimation });
+ }, 20);
+ });
+ });
+ }
+ clearMessageAnimation() {
+ clearTimeout(this.nextAnimationContext);
+ this.nextAnimationContext = 0;
+ }
+ show() {
+ const { duration, icon, marquee } = this.properties;
+ this.setData({ visible: true, loop: marquee.loop });
+ this.reset();
+ this.setIcon(icon);
+ this.checkAnimation();
+ if (duration && duration > 0) {
+ this.closeTimeoutContext = setTimeout(() => {
+ this.hide();
+ this.triggerEvent('durationEnd', { self: this });
+ }, duration);
+ }
+ const wrapID = `#${name}`;
+ getRect(this, wrapID).then((wrapRect) => {
+ this.setData({ wrapTop: -wrapRect.height }, () => {
+ this.setData({ showAnimation: this.showAnimation });
+ });
+ });
+ }
+ hide() {
+ this.reset();
+ this.setData({ showAnimation: this.hideAnimation });
+ setTimeout(() => {
+ this.setData({ visible: false, animation: [] });
+ }, SHOW_DURATION);
+ }
+ reset() {
+ if (this.nextAnimationContext) {
+ this.clearMessageAnimation();
+ }
+ clearTimeout(this.closeTimeoutContext);
+ this.closeTimeoutContext = 0;
+ }
+ handleClose() {
+ this.hide();
+ this.triggerEvent('closeBtnClick');
+ }
+ handleBtnClick() {
+ this.triggerEvent('actionBtnClick', { self: this });
+ }
+};
+Message = __decorate([
+ wxComponent()
+], Message);
+export default Message;
diff --git a/components/message/message.json b/components/message/message.json
new file mode 100644
index 0000000..ef9e100
--- /dev/null
+++ b/components/message/message.json
@@ -0,0 +1,7 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-icon": "../icon/icon",
+ "t-button": "../button/button"
+ }
+}
diff --git a/components/message/message.wxml b/components/message/message.wxml
new file mode 100644
index 0000000..cca30c6
--- /dev/null
+++ b/components/message/message.wxml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ {{content}}
+
+
+
+
+ {{action}}
+
+
+
+
+
+
diff --git a/components/message/message.wxs b/components/message/message.wxs
new file mode 100644
index 0000000..44f5b56
--- /dev/null
+++ b/components/message/message.wxs
@@ -0,0 +1,16 @@
+var changeNumToStr = function (arr) {
+ return arr.map(function (item) {
+ return typeof item === 'number' ? item + 'rpx' : item;
+ });
+};
+
+var getMessageStylesOffset = function (props) {
+ var arr = changeNumToStr(props.offset);
+ var styleOffset = '';
+ styleOffset += 'top:' + arr[0] + ';';
+ styleOffset += 'right:' + arr[1] + ';';
+ styleOffset += 'left:' + arr[1] + ';';
+ return styleOffset;
+};
+
+module.exports.getMessageStylesOffset = getMessageStylesOffset;
diff --git a/components/message/message.wxss b/components/message/message.wxss
new file mode 100644
index 0000000..96aa0a7
--- /dev/null
+++ b/components/message/message.wxss
@@ -0,0 +1,89 @@
+.t-float-left {
+ float: left;
+}
+.t-float-right {
+ float: right;
+}
+@keyframes tdesign-fade-out {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+.hotspot-expanded.relative {
+ position: relative;
+}
+.hotspot-expanded::after {
+ content: '';
+ display: block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ transform: scale(1.5);
+}
+.t-message {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ z-index: 15000;
+ color: #0052d9;
+ padding: 24rpx 32rpx;
+ box-sizing: border-box;
+ border-radius: 8rpx;
+ font-size: 28rpx;
+ line-height: 1;
+ background: #ffffff;
+ box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
+}
+.t-message__text {
+ display: inline-block;
+}
+.t-message__text-wrap {
+ flex: 1 1 auto;
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ line-height: 44rpx;
+}
+.t-message__text-nowrap {
+ word-break: keep-all;
+ white-space: nowrap;
+}
+.t-message--info {
+ color: #0052d9;
+}
+.t-message--success {
+ color: #00a870;
+}
+.t-message--warning {
+ color: #ed7b2f;
+}
+.t-message--error {
+ color: #e34d59;
+}
+.t-message .t-message__icon--left {
+ margin-right: 16rpx;
+}
+.t-message .t-message__icon--right,
+.t-message .t-message__btn--right {
+ flex: 0 0 auto;
+ margin-left: 16rpx;
+}
+.t-message .t-message__btn--right {
+ font-size: inherit;
+ line-height: inherit;
+ height: 44rpx;
+ line-height: 44rpx;
+ border-radius: 8rpx;
+ border-color: inherit;
+ color: inherit;
+ min-height: 0;
+ background: transparent;
+}
diff --git a/components/message/props.d.ts b/components/message/props.d.ts
new file mode 100644
index 0000000..c5a8f65
--- /dev/null
+++ b/components/message/props.d.ts
@@ -0,0 +1,3 @@
+import { TdMessageProps } from './type';
+declare const props: TdMessageProps;
+export default props;
diff --git a/components/message/props.js b/components/message/props.js
new file mode 100644
index 0000000..4ee00a9
--- /dev/null
+++ b/components/message/props.js
@@ -0,0 +1,49 @@
+const props = {
+ action: {
+ type: String,
+ },
+ align: {
+ type: String,
+ value: 'left',
+ },
+ closeBtn: {
+ type: String,
+ optionalTypes: [Boolean],
+ value: undefined,
+ },
+ content: {
+ type: String,
+ },
+ duration: {
+ type: Number,
+ value: 3000,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ icon: {
+ type: String,
+ optionalTypes: [Boolean],
+ value: true,
+ },
+ marquee: {
+ type: null,
+ value: false,
+ },
+ offset: {
+ type: Array,
+ },
+ theme: {
+ type: String,
+ value: 'info',
+ },
+ visible: {
+ type: Boolean,
+ value: false,
+ },
+ zIndex: {
+ type: Number,
+ value: 15000,
+ },
+};
+export default props;
diff --git a/components/message/type.d.ts b/components/message/type.d.ts
new file mode 100644
index 0000000..3f49ddb
--- /dev/null
+++ b/components/message/type.d.ts
@@ -0,0 +1,70 @@
+export interface TdMessageProps {
+ action?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ align?: {
+ type: StringConstructor;
+ value?: 'left' | 'center';
+ required?: boolean;
+ };
+ closeBtn?: {
+ type: StringConstructor;
+ optionalTypes: Array;
+ value?: string | boolean;
+ required?: boolean;
+ };
+ content?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ duration?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-content', 't-class-icon', 't-class-action', 't-class-close-btn'];
+ required?: boolean;
+ };
+ icon?: {
+ type: StringConstructor;
+ optionalTypes: Array;
+ value?: boolean | 'info' | 'bell';
+ required?: boolean;
+ };
+ marquee?: {
+ type: null;
+ value?: DrawMarquee | boolean;
+ required?: boolean;
+ };
+ offset?: {
+ type: ArrayConstructor;
+ value?: Array;
+ required?: boolean;
+ };
+ theme?: {
+ type: StringConstructor;
+ value?: MessageThemeList;
+ required?: boolean;
+ };
+ visible?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ zIndex?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+}
+export interface DrawMarquee {
+ speed?: number;
+ loop?: number;
+ delay?: number;
+}
+export declare type MessageThemeList = 'info' | 'success' | 'warning' | 'error';
diff --git a/components/message/type.js b/components/message/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/message/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/toast/README.en-US.md b/components/toast/README.en-US.md
new file mode 100644
index 0000000..90969a6
--- /dev/null
+++ b/components/toast/README.en-US.md
@@ -0,0 +1,25 @@
+:: BASE_DOC ::
+
+## API
+
+### Toast Props
+
+name | type | default | description | required
+-- | -- | -- | -- | --
+direction | String | row | options:row/column | N
+duration | Number | 2000 | \- | N
+external-classes | Array | - | `['t-class']` | N
+icon | String | - | \- | N
+message | String / Slot | - | \- | N
+overlay-props | Object | {} | \- | 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/fail | N
+
+### Toast Events
+
+name | params | description
+-- | -- | --
+close | \- | \-
+destory | \- | \-
diff --git a/components/toast/README.md b/components/toast/README.md
new file mode 100644
index 0000000..affc6c0
--- /dev/null
+++ b/components/toast/README.md
@@ -0,0 +1,59 @@
+---
+title: Toast 轻提示
+description: 用于轻量级反馈或提示,不会打断用户操作。
+spline: message
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-toast": "tdesign-miniprogram/toast/toast"
+}
+```
+
+## 代码演示
+
+### 基础提示
+
+{{ base }}
+
+### 默认提示
+
+{{ normal }}
+
+### 不同位置的提示
+
+{{ display }}
+
+### 显示遮罩
+{{ cover }}
+
+### 手动关闭
+{{ close }}
+## API
+### Toast Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+direction | String | row | 图标排列方式。可选项:row/column | N
+duration | Number | 2000 | 弹窗显示毫秒数 | N
+external-classes | Array | - | 组件类名。`['t-class']` | N
+icon | String | - | 自定义图标 | N
+message | String / Slot | - | 弹窗显示文字 | N
+overlay-props | Object | {} | 遮罩层属性,透传至 Overlay | N
+placement | String | middle | 弹窗展示位置。可选项: top/middle/bottom | N
+prevent-scroll-through | Boolean | false | 防止滚动穿透,即不允许点击和滚动 | N
+show-overlay | Boolean | false | 是否显示遮罩层 | N
+theme | String | - | 提示类型。可选项:loading/success/fail | N
+
+### Toast Events
+
+名称 | 参数 | 描述
+-- | -- | --
+close | - | 轻提示隐藏的时候触发
+destory | - | 轻提示销毁的时候触发
diff --git a/components/toast/index.d.ts b/components/toast/index.d.ts
new file mode 100644
index 0000000..1d9d0f4
--- /dev/null
+++ b/components/toast/index.d.ts
@@ -0,0 +1,21 @@
+// @ts-ignore
+declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
+declare type ToastType = 'loading' | 'success' | 'fail';
+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?: () => T;
+};
+declare function Toast(options: ToastOptionsType): void;
+declare function showToast(options?: ToastOptionsType): void;
+declare function hideToast(options?: ToastOptionsType): void;
+export { Toast as default, showToast, hideToast };
diff --git a/components/toast/index.js b/components/toast/index.js
new file mode 100644
index 0000000..216f208
--- /dev/null
+++ b/components/toast/index.js
@@ -0,0 +1,31 @@
+var __rest = (this && this.__rest) || function (s, e) {
+ var t = {};
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
+ t[p] = s[p];
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
+ t[p[i]] = s[p[i]];
+ }
+ return t;
+};
+import { getInstance } from '../common/utils';
+function Toast(options) {
+ var _a;
+ const { context, selector = '#t-toast' } = options, Options = __rest(options, ["context", "selector"]);
+ const instance = getInstance(context, selector);
+ if (instance) {
+ instance.show(Object.assign(Object.assign({}, Options), { duration: (_a = Options.duration) !== null && _a !== void 0 ? _a : 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 };
diff --git a/components/toast/props.d.ts b/components/toast/props.d.ts
new file mode 100644
index 0000000..c6b0f86
--- /dev/null
+++ b/components/toast/props.d.ts
@@ -0,0 +1,3 @@
+import { TdToastProps } from './type';
+declare const props: TdToastProps;
+export default props;
diff --git a/components/toast/props.js b/components/toast/props.js
new file mode 100644
index 0000000..3ff6f41
--- /dev/null
+++ b/components/toast/props.js
@@ -0,0 +1,40 @@
+const props = {
+ direction: {
+ type: String,
+ value: 'row',
+ },
+ duration: {
+ type: Number,
+ value: 2000,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ icon: {
+ type: String,
+ value: '',
+ },
+ message: {
+ type: String,
+ },
+ overlayProps: {
+ type: Object,
+ value: {},
+ },
+ placement: {
+ type: String,
+ value: 'middle',
+ },
+ preventScrollThrough: {
+ type: Boolean,
+ value: false,
+ },
+ showOverlay: {
+ type: Boolean,
+ value: false,
+ },
+ theme: {
+ type: String,
+ },
+};
+export default props;
diff --git a/components/toast/toast.d.ts b/components/toast/toast.d.ts
new file mode 100644
index 0000000..91cc921
--- /dev/null
+++ b/components/toast/toast.d.ts
@@ -0,0 +1,25 @@
+///
+import { SuperComponent } from '../common/src/index';
+import { ToastOptionsType } from './index';
+declare type Timer = NodeJS.Timeout | null;
+export default class Toast extends SuperComponent {
+ externalClasses: string[];
+ options: {
+ multipleSlots: boolean;
+ };
+ behaviors: string[];
+ hideTimer: Timer;
+ data: {
+ prefix: string;
+ classPrefix: string;
+ typeMapIcon: string;
+ };
+ properties: import("./type").TdToastProps;
+ detached(): void;
+ methods: {
+ show(options: ToastOptionsType): void;
+ hide(): void;
+ destroyed(): void;
+ };
+}
+export {};
diff --git a/components/toast/toast.js b/components/toast/toast.js
new file mode 100644
index 0000000..b461b73
--- /dev/null
+++ b/components/toast/toast.js
@@ -0,0 +1,78 @@
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+import { SuperComponent, wxComponent } from '../common/src/index';
+import config from '../common/config';
+import props from './props';
+import transition from '../mixins/transition';
+const { prefix } = config;
+const name = `${prefix}-toast`;
+let Toast = class Toast extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.externalClasses = [`${prefix}-class`];
+ this.options = {
+ multipleSlots: true,
+ };
+ this.behaviors = [transition()];
+ this.hideTimer = null;
+ this.data = {
+ prefix,
+ classPrefix: name,
+ typeMapIcon: '',
+ };
+ this.properties = props;
+ this.methods = {
+ show(options) {
+ if (this.hideTimer)
+ clearTimeout(this.hideTimer);
+ const iconMap = {
+ loading: 'loading',
+ success: 'check-circle',
+ fail: 'error-circle',
+ };
+ const typeMapIcon = iconMap[options === null || options === void 0 ? void 0 : options.theme] || '';
+ const defaultOptions = {
+ direction: props.direction.value,
+ duration: props.duration.value,
+ icon: props.icon.value,
+ message: props.message.value,
+ placement: props.placement.value,
+ preventScrollThrough: props.preventScrollThrough.value,
+ theme: props.theme.value,
+ };
+ const data = Object.assign(Object.assign(Object.assign({}, defaultOptions), options), { visible: true, typeMapIcon });
+ const { duration } = data;
+ this.setData(data);
+ if (duration > 0) {
+ this.hideTimer = setTimeout(() => {
+ this.hide();
+ }, duration);
+ }
+ },
+ hide() {
+ var _a, _b;
+ this.setData({ visible: false });
+ (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a);
+ this.triggerEvent('close');
+ },
+ destroyed() {
+ if (this.hideTimer) {
+ clearTimeout(this.hideTimer);
+ this.hideTimer = null;
+ }
+ this.triggerEvent('destory');
+ },
+ };
+ }
+ detached() {
+ this.destroyed();
+ }
+};
+Toast = __decorate([
+ wxComponent()
+], Toast);
+export default Toast;
diff --git a/components/toast/toast.json b/components/toast/toast.json
new file mode 100644
index 0000000..b60dbbc
--- /dev/null
+++ b/components/toast/toast.json
@@ -0,0 +1,8 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-icon": "../icon/icon",
+ "t-loading": "../loading/loading",
+ "t-overlay": "../overlay/overlay"
+ }
+}
diff --git a/components/toast/toast.wxml b/components/toast/toast.wxml
new file mode 100644
index 0000000..bc91969
--- /dev/null
+++ b/components/toast/toast.wxml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ {{message}}
+
+
+
+
diff --git a/components/toast/toast.wxss b/components/toast/toast.wxss
new file mode 100644
index 0000000..7aaf84f
--- /dev/null
+++ b/components/toast/toast.wxss
@@ -0,0 +1,84 @@
+.t-float-left {
+ float: left;
+}
+.t-float-right {
+ float: right;
+}
+@keyframes tdesign-fade-out {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+.hotspot-expanded.relative {
+ position: relative;
+}
+.hotspot-expanded::after {
+ content: '';
+ display: block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ transform: scale(1.5);
+}
+.t-toast {
+ position: fixed;
+ right: -50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 12001;
+ opacity: 1;
+ transition: opacity 300ms ease;
+ background-color: rgba(0, 0, 0, 0.6);
+ border-radius: 8rpx;
+ font-size: 28rpx;
+ color: white;
+ max-width: 374rpx;
+ width: fit-content;
+ box-sizing: border-box;
+}
+.t-toast--column {
+ padding: 48rpx;
+ min-width: 272rpx;
+ min-height: 260rpx;
+ border-radius: 16rpx;
+}
+.t-toast__content {
+ align-items: center;
+ line-height: 44rpx;
+}
+.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;
+}
+.t-toast__icon--row {
+ display: flex;
+}
+.t-toast__text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-line-clamp: 3;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+}
+.t-toast__text--column {
+ margin-top: 24rpx;
+}
+.t-toast__text--row {
+ margin-left: 12rpx;
+}
+.t-toast.t-fade-enter,
+.t-toast.t-fade-leave-to {
+ opacity: 0;
+}
diff --git a/components/toast/type.d.ts b/components/toast/type.d.ts
new file mode 100644
index 0000000..9887289
--- /dev/null
+++ b/components/toast/type.d.ts
@@ -0,0 +1,42 @@
+export interface TdToastProps {
+ direction?: {
+ type: StringConstructor;
+ value?: 'row' | 'column';
+ };
+ duration?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class'];
+ };
+ icon?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ message?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ overlayProps?: {
+ type: ObjectConstructor;
+ value?: object;
+ };
+ placement?: {
+ type: StringConstructor;
+ value?: 'top' | 'middle' | 'bottom';
+ };
+ preventScrollThrough?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ showOverlay?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ theme?: {
+ type: StringConstructor;
+ value?: 'loading' | 'success' | 'fail';
+ };
+}
diff --git a/components/toast/type.js b/components/toast/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/toast/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/pages/anniversary/create/index.json b/pages/anniversary/create/index.json
index fe67fd6..d0e8daf 100644
--- a/pages/anniversary/create/index.json
+++ b/pages/anniversary/create/index.json
@@ -3,7 +3,6 @@
"t-date-time-picker": "/components/date-time-picker/date-time-picker",
"t-picker": "/components/picker/picker",
"t-picker-item": "/components/picker/picker-item",
- "jh-lunar-picker": "/components/jh-lunar-picker/index",
"t-switch": "/components/switch/switch",
"t-button": "/components/button/button"
}
diff --git a/pages/message/index.js b/pages/message/index.js
index b73fc1f..26bf446 100644
--- a/pages/message/index.js
+++ b/pages/message/index.js
@@ -1,4 +1,6 @@
// pages/message/index.js
+import Toast from '../../components/toast/index';
+import Message from '../../components/message/index';
Page({
/**
@@ -7,60 +9,27 @@ Page({
data: {
aIconList: ['check-rectangle','star','notification-filled','circle'],
},
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
-
+ toast(option) {
+ Toast({
+ context: this,
+ selector: '#t-toast',
+ ...option,
+ });
},
-
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady() {
-
- },
-
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
-
- },
-
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide() {
-
- },
-
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload() {
-
- },
-
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
-
- },
-
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
-
- },
-
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage() {
-
+ startVipButton(e){
+ this.toast({
+ message: '已获得会员资格!',
+ theme: 'success',
+ placement: 'bottom',
+ direction: 'column',
+ });
+ Message.info({
+ context: this,
+ offset: [20, 32],
+ marquee: { speed: 50, loop: -1, delay: 5000 },
+ icon: false,
+ content: '请关注微信公众号Quinn,回复"VIP"',
+ duration: -1,
+ });
}
})
diff --git a/pages/message/index.json b/pages/message/index.json
index b36ebcb..31350f3 100644
--- a/pages/message/index.json
+++ b/pages/message/index.json
@@ -1,5 +1,9 @@
{
"usingComponents": {
- "foot-tab": "../foot-tab/foot-tab"
+ "foot-tab": "../foot-tab/foot-tab",
+ "t-empty": "/components/empty/empty",
+ "t-button": "/components/button/button",
+ "t-toast": "/components/toast/toast",
+ "t-message": "/components/message/message"
}
}
diff --git a/pages/message/index.wxml b/pages/message/index.wxml
index 95710e7..5c9711e 100644
--- a/pages/message/index.wxml
+++ b/pages/message/index.wxml
@@ -1,5 +1,9 @@
-您有新的消息
+
+
+ 开通会员
+
+
diff --git a/pages/message/index.wxss b/pages/message/index.wxss
index 97b283a..50b023a 100644
--- a/pages/message/index.wxss
+++ b/pages/message/index.wxss
@@ -1 +1,4 @@
-/* pages/message/index.wxss */
\ No newline at end of file
+/* pages/message/index.wxss */
+.empty-cls {
+ margin-top: 250rpx !important;
+}