diff --git a/app.json b/app.json
index fecc057..22c15fb 100644
--- a/app.json
+++ b/app.json
@@ -3,12 +3,16 @@
"pages/index/index",
"pages/logs/logs",
"pages/myself/index",
- "pages/today/index",
- "pages/message/index"
+ "pages/task/index",
+ "pages/message/index",
+ "pages/taskDetail/index"
],
"usingComponents": {
"t-icon": "/components/icon/icon",
- "t-checkbox": "/components/checkbox/checkbox"
+ "t-checkbox": "/components/checkbox/checkbox",
+ "t-input": "/components/input/input",
+ "t-textarea": "/components/textarea/textarea",
+ "t-cell": "/components/cell/cell"
},
"window": {
"backgroundTextStyle": "light",
diff --git a/components/button/README.md b/components/button/README.md
new file mode 100644
index 0000000..d1bca6a
--- /dev/null
+++ b/components/button/README.md
@@ -0,0 +1,88 @@
+---
+title: Button 按钮
+description: 用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。
+spline: base
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-button": "tdesign-miniprogram/button/button",
+ "t-button-group": "tdesign-miniprogram/button-group/button-group"
+}
+```
+
+## 代码演示
+
+### 基础按钮
+
+
+基础类型分为主按钮、次按钮、文字按钮
+
+#### 次按钮
+使用场景:在用户进行的操作为流程中的辅助操作,或者进行不那么重要的交互行为时,选择用次按钮;次要按钮通常和主要按钮一起出现
+
+#### 主按钮
+使用场景:大部分场景都可以使用,例如反馈页、表单页、对话框,一个页面建议最多只出现一个主按钮;
+
+#### 文字按钮
+使用场景:它的操作通常和其旁边内容相关,通常出现在标题旁、字段旁、列表最下方
+
+{{ base }}
+
+### 带图标按钮
+{{ icon-btn }}
+
+### 不同尺寸
+
+{{ size }}
+
+## API
+### Button Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+block | Boolean | false | 是否为块级元素 | N
+content | String / Slot | - | 按钮内容 | N
+custom-dataset | Any | - | 自定义 dataset,可通过 event.detail.currentTarget.dataset.custom 获取。当open-type 为 share 时,可在 onShareAppMessage 事件的 event.target.dataset.custom 中看到传入的值。TS 类型:`any` | N
+disabled | Boolean | false | 是否禁用按钮 | N
+external-classes | Array | - | 组件类名。`['t-class', 't-class-icon', 't-class-loading']` | N
+ghost | Boolean | false | 是否为幽灵按钮(镂空按钮) | N
+icon | String | - | 图标名称 | N
+icon-props | Object | {} | 图标属性,透传至 icon | N
+loading | Boolean | false | 是否显示为加载状态 | N
+loading-props | Object | - | 加载loading属性,透传至loading。TS 类型:`LoadingProps` | N
+shape | String | rectangle | 按钮形状,有 4 种:长方形、正方形、圆角长方形、圆形。可选项:rectangle/square/round/circle | N
+size | String | medium | 组件尺寸。可选项:small/medium/large。TS 类型:`SizeEnum` | N
+theme | String | default | 组件风格,依次为品牌色、危险色。可选项:default/primary/danger | N
+type | String | - | 同小程序的 formType。可选项:submit/reset | N
+variant | String | base | 按钮形式,基础、线框、文字。可选项:base/outline/text | N
+open-type | String | - | 微信开放能力。
具体释义:
`contact` 打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明 (*小程序插件中不能使用*);
`share` 触发用户转发,使用前建议先阅读使用指引;
`getPhoneNumber` 获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息,具体说明 (*小程序插件中不能使用*);
`getUserInfo` 获取用户信息,可以从 bindgetuserinfo 回调中获取到用户信息 (*小程序插件中不能使用*);
`launchApp` 打开APP,可以通过 app-parameter 属性设定向 APP 传的参数具体说明;
`openSetting` 打开授权设置页;
`feedback` 打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容;
`chooseAvatar` 获取用户头像,可以从 bindchooseavatar 回调中获取到头像信息。
[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)。可选项:contact/share/getPhoneNumber/getUserInfo/launchApp/openSetting/feedback/chooseAvatar | N
+hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态 | N
+hover-start-time | Number | 20 | 按住后多久出现点击态,单位毫秒 | N
+hover-stay-time | Number | 70 | 手指松开后点击态保留时间,单位毫秒 | N
+lang | String | en | 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。。
具体释义:
`en` 英文;
`zh_CN` 简体中文;
`zh_TW` 繁体中文。
[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)。可选项:en/zh_CN/zh_TW | N
+session-from | String | - | 会话来源,open-type="contact"时有效 | N
+send-message-title | String | 当前标题 | 会话内消息卡片标题,open-type="contact"时有效 | N
+send-message-path | String | 当前分享路径 | 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 | N
+send-message-img | String | 截图 | 会话内消息卡片图片,open-type="contact"时有效 | N
+app-parameter | String | - | 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 | N
+show-message-card | Boolean | false | 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,open-type="contact"时有效 | N
+bindgetuserinfo | Eventhandle | - | 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与wx.getUserInfo返回的一致,open-type="getUserInfo"时有效 | N
+bindcontact | Eventhandle | - | 客服消息回调,open-type="contact"时有效 | N
+bindgetphonenumber | Eventhandle | - | 获取用户手机号回调,open-type=getPhoneNumber时有效 | N
+binderror | Eventhandle | - | 当使用开放能力时,发生错误的回调,open-type=launchApp时有效 | N
+bindopensetting | Eventhandle | - | 在打开授权设置页后回调,open-type=openSetting时有效 | N
+bindlaunchapp | Eventhandle | - | 打开 APP 成功的回调,open-type=launchApp时有效 | N
+bindchooseavatar | Eventhandle | - | 获取用户头像回调,open-type=chooseAvatar时有效 | N
+
+### Button Events
+
+名称 | 参数 | 描述
+-- | -- | --
+tap | `event` | 点击时触发
diff --git a/components/button/button.d.ts b/components/button/button.d.ts
new file mode 100644
index 0000000..4b2d7c7
--- /dev/null
+++ b/components/button/button.d.ts
@@ -0,0 +1,31 @@
+import { SuperComponent } from '../common/src/index';
+import type { TdButtonProps } from './type';
+export interface ButtonProps extends TdButtonProps {
+}
+export default class Button extends SuperComponent {
+ externalClasses: string[];
+ behaviors: string[];
+ properties: TdButtonProps;
+ data: {
+ prefix: string;
+ className: string;
+ classPrefix: string;
+ };
+ observers: {
+ 'theme, size, plain, block, shape, disabled, loading'(): void;
+ };
+ lifetimes: {
+ attached(): void;
+ };
+ methods: {
+ setClass(): void;
+ getuserinfo(e: any): void;
+ contact(e: any): void;
+ getphonenumber(e: any): void;
+ error(e: any): void;
+ opensetting(e: any): void;
+ launchapp(e: any): void;
+ chooseavatar(e: any): void;
+ handleTap(e: any): void;
+ };
+}
diff --git a/components/button/button.js b/components/button/button.js
new file mode 100644
index 0000000..0efc4e4
--- /dev/null
+++ b/components/button/button.js
@@ -0,0 +1,89 @@
+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 { canIUseFormFieldButton } from '../common/version';
+const { prefix } = config;
+const name = `${prefix}-button`;
+let Button = class Button extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.externalClasses = [`${prefix}-class`, `${prefix}-class-icon`, `${prefix}-class-loading`];
+ this.behaviors = canIUseFormFieldButton() ? ['wx://form-field-button'] : [];
+ this.properties = props;
+ this.data = {
+ prefix,
+ className: '',
+ classPrefix: name,
+ };
+ this.observers = {
+ 'theme, size, plain, block, shape, disabled, loading'() {
+ this.setClass();
+ },
+ };
+ this.lifetimes = {
+ attached() {
+ this.setClass();
+ },
+ };
+ this.methods = {
+ setClass() {
+ const classList = [
+ name,
+ `${prefix}-class`,
+ `${name}--${this.data.theme}`,
+ `${name}--size-${this.data.size.slice(0, 1)}`,
+ ];
+ classList.push(`${name}--${this.data.shape}`);
+ if (this.data.block) {
+ classList.push(`${prefix}-is-block`);
+ }
+ if (this.data.disabled) {
+ classList.push(`${prefix}-is-disabled`);
+ }
+ classList.push(`${name}--${this.data.variant}`);
+ if (this.data.ghost) {
+ classList.push(`${name}--ghost`);
+ }
+ this.setData({
+ className: classList.join(' '),
+ });
+ },
+ getuserinfo(e) {
+ this.triggerEvent('getuserinfo', e.detail);
+ },
+ contact(e) {
+ this.triggerEvent('contact', e.detail);
+ },
+ getphonenumber(e) {
+ this.triggerEvent('getphonenumber', e.detail);
+ },
+ error(e) {
+ this.triggerEvent('error', e.detail);
+ },
+ opensetting(e) {
+ this.triggerEvent('opensetting', e.detail);
+ },
+ launchapp(e) {
+ this.triggerEvent('launchapp', e.detail);
+ },
+ chooseavatar(e) {
+ this.triggerEvent('chooseavatar', e.detail);
+ },
+ handleTap(e) {
+ if (this.data.disabled)
+ return;
+ this.triggerEvent('tap', e);
+ },
+ };
+ }
+};
+Button = __decorate([
+ wxComponent()
+], Button);
+export default Button;
diff --git a/components/button/button.json b/components/button/button.json
new file mode 100644
index 0000000..708bd1b
--- /dev/null
+++ b/components/button/button.json
@@ -0,0 +1,7 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-icon": "../icon/icon",
+ "t-loading": "../loading/loading"
+ }
+}
diff --git a/components/button/button.wxml b/components/button/button.wxml
new file mode 100644
index 0000000..d967852
--- /dev/null
+++ b/components/button/button.wxml
@@ -0,0 +1,58 @@
+
diff --git a/components/button/button.wxss b/components/button/button.wxss
new file mode 100644
index 0000000..8e3012c
--- /dev/null
+++ b/components/button/button.wxss
@@ -0,0 +1,248 @@
+.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-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ white-space: nowrap;
+ text-align: center;
+ background-image: none;
+ border: 1px solid transparent;
+ cursor: pointer;
+ transition: all 0.3s;
+ user-select: none;
+ touch-action: manipulation;
+ font-size: 28rpx;
+ height: 80rpx;
+ border-radius: 8rpx;
+ color: rgba(0, 0, 0, 0.9);
+ border-color: #dcdcdc;
+ background-color: #fff;
+ outline: none;
+ font-family: PingFang SC, Microsoft YaHei, Arial Regular;
+ /* stylelint-disable-next-line */
+ -webkit-appearance: none;
+}
+.t-button::after {
+ background-color: #000;
+ content: ' ';
+ opacity: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ position: absolute;
+}
+.t-button:not(.t-is-disabled):active::after {
+ opacity: 0.1;
+}
+.t-button--default {
+ color: rgba(0, 0, 0, 0.9);
+ background-color: #ffffff;
+ border: 1px solid #dcdcdc;
+}
+.t-button--default.t-is-disabled {
+ color: rgba(0, 0, 0, 0.26);
+}
+.t-button--primary {
+ color: #fff;
+ background-color: #0052d9;
+ border: 1px solid #0052d9;
+}
+.t-button--primary.t-is-disabled {
+ background-color: #bbd3fb;
+ border-color: #bbd3fb;
+}
+.t-button--danger {
+ color: #fff;
+ background-color: #e34d59;
+ border: 1px solid #e34d59;
+}
+.t-button--danger.t-is-disabled {
+ background-color: #f8b9be;
+ border-color: #f8b9be;
+}
+.t-button--text {
+ color: #0052d9;
+ background: none;
+ border: 0;
+}
+.t-button--text.t-button--size-default {
+ width: auto;
+ height: auto;
+ line-height: normal;
+ padding: 0;
+}
+.t-button--text.t-is-disabled {
+ color: #bbd3fb;
+}
+.t-button--ghost {
+ background-color: transparent;
+ border: 1px solid #fff;
+ color: #fff;
+}
+.t-button--ghost.t-is-disabled {
+ color: rgba(255, 255, 255, 0.35);
+ border-color: rgba(255, 255, 255, 0.35);
+}
+.t-button--outline {
+ background-color: transparent;
+}
+.t-button--outline.t-button--primary {
+ color: #0052d9;
+}
+.t-button--outline.t-button--primary.t-is-disabled {
+ background-color: transparent;
+ color: #bbd3fb;
+}
+.t-button--outline.t-button--danger {
+ color: #e34d59;
+}
+.t-button--outline.t-button--danger.t-is-disabled {
+ background-color: transparent;
+ color: #f8b9be;
+}
+.t-button--dashed {
+ background-color: transparent;
+ border-style: dashed;
+}
+.t-button--dashed.t-button--primary {
+ color: #0052d9;
+}
+.t-button--dashed.t-button--primary.t-is-disabled {
+ background-color: transparent;
+ color: #bbd3fb;
+}
+.t-button--dashed.t-button--danger {
+ color: #e34d59;
+}
+.t-button--dashed.t-button--danger.t-is-disabled {
+ background-color: transparent;
+ color: #f8b9be;
+}
+.t-button--base {
+ height: 80rpx;
+ line-height: 80rpx;
+ padding-left: 31rpx;
+ padding-right: 31rpx;
+ font-size: 28rpx;
+}
+.t-button--size-l {
+ height: 88rpx;
+ line-height: 88rpx;
+}
+.t-button--size-l .t-button__icon {
+ font-size: 48rpx;
+}
+.t-button--size-l .t-button__loading + .t-button__content:not(:empty),
+.t-button--size-l .t-button__icon + .t-button__content:not(:empty) {
+ margin-left: 16rpx;
+}
+.t-button--size-m .t-button__icon {
+ font-size: 44rpx;
+}
+.t-button--size-m .t-button__loading + .t-button__content:not(:empty),
+.t-button--size-m .t-button__icon + .t-button__content:not(:empty) {
+ margin-left: 8rpx;
+}
+.t-button--size-s {
+ height: 72rpx;
+ line-height: 72rpx;
+}
+.t-button--size-s .t-button__icon {
+ font-size: 40rpx;
+}
+.t-button--size-s .t-button__loading + .t-button__content:not(:empty),
+.t-button--size-s .t-button__icon + .t-button__content:not(:empty) {
+ margin-left: 8rpx;
+}
+.t-button__icon {
+ border-radius: 8rpx;
+}
+.t-button--round.t-button--size-l {
+ border-radius: 44rpx;
+}
+.t-button--round.t-button--size-m {
+ border-radius: 40rpx;
+}
+.t-button--round.t-button--size-s {
+ border-radius: 36rpx;
+}
+.t-button--square {
+ padding: 0;
+}
+.t-button--square.t-button--size-l {
+ width: 88rpx;
+}
+.t-button--square.t-button--size-m {
+ width: 80rpx;
+}
+.t-button--square.t-button--size-s {
+ width: 72rpx;
+}
+.t-button--circle {
+ padding: 0;
+}
+.t-button--circle.t-button--size-l {
+ border-radius: 50%;
+ width: 88rpx;
+}
+.t-button--circle.t-button--size-m {
+ border-radius: 50%;
+ width: 80rpx;
+}
+.t-button--circle.t-button--size-s {
+ border-radius: 50%;
+ width: 72rpx;
+}
+.t-button.t-is-block {
+ display: flex;
+ width: 100%;
+}
+.t-button.t-is-disabled {
+ cursor: not-allowed;
+}
+.t-button.button-hover:after {
+ border-radius: 8rpx;
+}
+.t-button .position-center {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.t-button .indicator-blue {
+ color: white;
+}
+.t-button-group .t-button {
+ border: 0;
+ border-radius: 0;
+ box-shadow: 0;
+ width: 100%;
+ height: 100%;
+}
diff --git a/components/button/index.d.ts b/components/button/index.d.ts
new file mode 100644
index 0000000..beb0ad5
--- /dev/null
+++ b/components/button/index.d.ts
@@ -0,0 +1,3 @@
+export * from './props';
+export * from './type';
+export * from './button';
diff --git a/components/button/index.js b/components/button/index.js
new file mode 100644
index 0000000..beb0ad5
--- /dev/null
+++ b/components/button/index.js
@@ -0,0 +1,3 @@
+export * from './props';
+export * from './type';
+export * from './button';
diff --git a/components/button/props.d.ts b/components/button/props.d.ts
new file mode 100644
index 0000000..00dc5fb
--- /dev/null
+++ b/components/button/props.d.ts
@@ -0,0 +1,3 @@
+import { TdButtonProps } from './type';
+declare const props: TdButtonProps;
+export default props;
diff --git a/components/button/props.js b/components/button/props.js
new file mode 100644
index 0000000..110cca6
--- /dev/null
+++ b/components/button/props.js
@@ -0,0 +1,101 @@
+const props = {
+ block: {
+ type: Boolean,
+ value: false,
+ },
+ content: {
+ type: String,
+ },
+ customDataset: {
+ type: null,
+ },
+ disabled: {
+ type: Boolean,
+ value: false,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ ghost: {
+ type: Boolean,
+ value: false,
+ },
+ icon: {
+ type: String,
+ value: '',
+ },
+ iconProps: {
+ type: Object,
+ value: {},
+ },
+ loading: {
+ type: Boolean,
+ value: false,
+ },
+ loadingProps: {
+ type: Object,
+ },
+ shape: {
+ type: String,
+ value: 'rectangle',
+ },
+ size: {
+ type: String,
+ value: 'medium',
+ },
+ theme: {
+ type: String,
+ value: 'default',
+ },
+ type: {
+ type: String,
+ },
+ variant: {
+ type: String,
+ value: 'base',
+ },
+ openType: {
+ type: String,
+ },
+ hoverStopPropagation: {
+ type: Boolean,
+ value: false,
+ },
+ hoverStartTime: {
+ type: Number,
+ value: 20,
+ },
+ hoverStayTime: {
+ type: Number,
+ value: 70,
+ },
+ lang: {
+ type: String,
+ value: 'en',
+ },
+ sessionFrom: {
+ type: String,
+ value: '',
+ },
+ sendMessageTitle: {
+ type: String,
+ value: '',
+ },
+ sendMessagePath: {
+ type: String,
+ value: '',
+ },
+ sendMessageImg: {
+ type: String,
+ value: '',
+ },
+ appParameter: {
+ type: String,
+ value: '',
+ },
+ showMessageCard: {
+ type: Boolean,
+ value: false,
+ },
+};
+export default props;
diff --git a/components/button/type.d.ts b/components/button/type.d.ts
new file mode 100644
index 0000000..bb716b6
--- /dev/null
+++ b/components/button/type.d.ts
@@ -0,0 +1,108 @@
+import { SizeEnum } from '../common/common';
+import { LoadingProps } from '../loading/index';
+export interface TdButtonProps {
+ block?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ content?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ customDataset?: {
+ type: ObjectConstructor;
+ value?: any;
+ };
+ disabled?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-icon', 't-class-loading'];
+ };
+ ghost?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ icon?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ iconProps?: {
+ type: ObjectConstructor;
+ value?: object;
+ };
+ loading?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ loadingProps?: {
+ type: ObjectConstructor;
+ value?: LoadingProps;
+ };
+ shape?: {
+ type: StringConstructor;
+ value?: 'rectangle' | 'square' | 'round' | 'circle';
+ };
+ size?: {
+ type: StringConstructor;
+ value?: SizeEnum;
+ };
+ theme?: {
+ type: StringConstructor;
+ value?: 'default' | 'primary' | 'danger';
+ };
+ type?: {
+ type: StringConstructor;
+ value?: 'submit' | 'reset';
+ };
+ variant?: {
+ type: StringConstructor;
+ value?: 'base' | 'outline' | 'text';
+ };
+ openType?: {
+ type: StringConstructor;
+ value?: 'contact' | 'share' | 'getPhoneNumber' | 'getUserInfo' | 'launchApp' | 'openSetting' | 'feedback' | 'chooseAvatar';
+ };
+ hoverStopPropagation?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ hoverStartTime?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ hoverStayTime?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ lang?: {
+ type: StringConstructor;
+ value?: 'en' | 'zh_CN' | 'zh_TW';
+ };
+ sessionFrom?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ sendMessageTitle?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ sendMessagePath?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ sendMessageImg?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ appParameter?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ showMessageCard?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+}
diff --git a/components/button/type.js b/components/button/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/button/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/cell/README.md b/components/cell/README.md
new file mode 100644
index 0000000..4bdc541
--- /dev/null
+++ b/components/cell/README.md
@@ -0,0 +1,57 @@
+---
+title: Cell 单元格
+description: 用于各个类别行的信息展示。
+spline: data
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-cell": "tdesign-miniprogram/cell/cell"
+}
+```
+
+## 代码演示
+
+### 单行单元格
+
+
+
+{{ base }}
+
+### 多行单元格
+
+
+
+{{ multiple }}
+
+## API
+### Cell Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+align | String | middle | 内容的对齐方式,默认居中对齐。可选项:top/middle/bottom | N
+arrow | Boolean | false | 是否显示右侧箭头 | N
+bordered | Boolean | true | 是否显示下边框 | N
+description | String / Slot | - | 下方内容描述 | N
+external-classes | Array | - | 组件类名,分别用于设置 组件外层类名、标题类名、下方描述内容类名、右侧说明文字类名、激活态类名、图片类名、左侧内容、左侧图标类名、右侧内容、右侧图标类名 等。`['t-class', 't-class-title', 't-class-description', 't-class-note', 't-class-hover', 't-class-image', 't-class-left', 't-class-left-icon', 't-class-right', 't-class-right-icon']` | N
+hover | Boolean | - | 是否开启点击反馈 | N
+image | String / Slot | - | 主图 | N
+jump-type | String | navigateTo | 链接跳转类型。可选项:switchTab/reLaunch/redirectTo/navigateTo | N
+left-icon | String / Slot | - | 左侧图标,出现在单元格标题的左侧 | N
+note | String / Slot | - | 和标题同行的说明文字 | N
+required | Boolean | false | 是否显示表单必填星号 | N
+right-icon | String / Slot | - | 最右侧图标 | N
+title | String / Slot | - | 标题 | N
+url | String | - | 点击后跳转链接地址。如果值为空,则表示不需要跳转 | N
+
+### Cell Events
+
+名称 | 参数 | 描述
+-- | -- | --
+click | - | 右侧内容
diff --git a/components/cell/cell.d.ts b/components/cell/cell.d.ts
new file mode 100644
index 0000000..92eb1c9
--- /dev/null
+++ b/components/cell/cell.d.ts
@@ -0,0 +1,14 @@
+import { SuperComponent } from '../common/src/index';
+export default class Cell extends SuperComponent {
+ externalClasses: string[];
+ options: {
+ multipleSlots: boolean;
+ };
+ properties: import("./type").TdCellProps;
+ data: {
+ prefix: string;
+ classPrefix: string;
+ };
+ onClick(e: any): void;
+ jumpLink(urlKey?: string, link?: string): void;
+}
diff --git a/components/cell/cell.js b/components/cell/cell.js
new file mode 100644
index 0000000..7950416
--- /dev/null
+++ b/components/cell/cell.js
@@ -0,0 +1,51 @@
+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';
+const { prefix } = config;
+const name = `${prefix}-cell`;
+let Cell = class Cell extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.externalClasses = [
+ `${prefix}-class`,
+ `${prefix}-class-title`,
+ `${prefix}-class-description`,
+ `${prefix}-class-note`,
+ `${prefix}-class-hover`,
+ `${prefix}-class-image`,
+ `${prefix}-class-left`,
+ `${prefix}-class-left-icon`,
+ `${prefix}-class-right`,
+ `${prefix}-class-right-icon`,
+ ];
+ this.options = {
+ multipleSlots: true,
+ };
+ this.properties = props;
+ this.data = {
+ prefix,
+ classPrefix: name,
+ };
+ }
+ onClick(e) {
+ this.triggerEvent('click', e.detail);
+ this.jumpLink();
+ }
+ jumpLink(urlKey = 'url', link = 'jumpType') {
+ const url = this.data[urlKey];
+ const jumpType = this.data[link];
+ if (url) {
+ wx[jumpType]({ url });
+ }
+ }
+};
+Cell = __decorate([
+ wxComponent()
+], Cell);
+export default Cell;
diff --git a/components/cell/cell.json b/components/cell/cell.json
new file mode 100644
index 0000000..049940c
--- /dev/null
+++ b/components/cell/cell.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-icon": "../icon/icon"
+ }
+}
diff --git a/components/cell/cell.wxml b/components/cell/cell.wxml
new file mode 100644
index 0000000..c3ba655
--- /dev/null
+++ b/components/cell/cell.wxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+ {{ title}}
+
+
+ *
+
+
+
+
+ {{description}}
+
+
+
+
+
+ {{note}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/cell/cell.wxss b/components/cell/cell.wxss
new file mode 100644
index 0000000..57394d6
--- /dev/null
+++ b/components/cell/cell.wxss
@@ -0,0 +1,122 @@
+.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-cell {
+ position: relative;
+ display: flex;
+ box-sizing: border-box;
+ width: 100%;
+ padding: 24rpx 32rpx;
+ font-size: 32rpx;
+ line-height: 48rpx;
+ color: rgba(0, 0, 0, 0.9);
+ background-color: #ffffff;
+}
+.t-cell::after {
+ position: absolute;
+ box-sizing: border-box;
+ content: ' ';
+ pointer-events: none;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ border-bottom: 1px solid #e7e7e7;
+ transform: scaleY(0.5);
+ left: 32rpx;
+}
+.t-cell--borderless::after {
+ display: none;
+}
+.t-cell__description {
+ font-size: 28rpx;
+ line-height: 44rpx;
+ color: rgba(0, 0, 0, 0.4);
+}
+.t-cell__description-text {
+ margin-top: 8rpx;
+}
+.t-cell__note {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ overflow: hidden;
+ color: rgba(0, 0, 0, 0.4);
+}
+.t-cell__title,
+.t-cell__note {
+ flex: 1 1 auto;
+}
+.t-cell__title:empty,
+.t-cell__note:empty {
+ display: none;
+}
+.t-cell__title-text {
+ font-size: 35rpx;
+ display: flex;
+}
+.t-cell__left,
+.t-cell__right {
+ display: flex;
+ align-items: center;
+ font-size: 48rpx;
+ line-height: 48rpx;
+}
+.t-cell__left :not(:empty) {
+ margin-right: 16rpx;
+}
+.t-cell__left-icon {
+ font-size: 48rpx;
+}
+.t-cell__left-image {
+ height: 112rpx;
+ width: 112rpx;
+}
+.t-cell__right {
+ margin-left: 8rpx;
+ color: #bbb;
+}
+.t-cell__right-icon {
+ color: #bbb;
+ font-size: 48rpx;
+ line-height: 48rpx;
+}
+.t-cell--hover.t-cell--hover-class {
+ background-color: #f2f3f5;
+}
+.t-cell--required {
+ font-size: 32rpx;
+ color: #e34d59;
+}
+.t-cell--middle {
+ align-items: center;
+}
+.t-cell--top {
+ align-items: flex-start;
+}
+.t-cell--bottom {
+ align-items: flex-end;
+}
diff --git a/components/cell/props.d.ts b/components/cell/props.d.ts
new file mode 100644
index 0000000..ad657e5
--- /dev/null
+++ b/components/cell/props.d.ts
@@ -0,0 +1,3 @@
+import { TdCellProps } from './type';
+declare const props: TdCellProps;
+export default props;
diff --git a/components/cell/props.js b/components/cell/props.js
new file mode 100644
index 0000000..8e741e8
--- /dev/null
+++ b/components/cell/props.js
@@ -0,0 +1,51 @@
+const props = {
+ align: {
+ type: String,
+ value: 'middle',
+ },
+ arrow: {
+ type: Boolean,
+ value: false,
+ },
+ bordered: {
+ type: Boolean,
+ value: true,
+ },
+ description: {
+ type: String,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ hover: {
+ type: Boolean,
+ },
+ image: {
+ type: String,
+ },
+ jumpType: {
+ type: String,
+ value: 'navigateTo',
+ },
+ leftIcon: {
+ type: String,
+ },
+ note: {
+ type: String,
+ },
+ required: {
+ type: Boolean,
+ value: false,
+ },
+ rightIcon: {
+ type: String,
+ },
+ title: {
+ type: String,
+ },
+ url: {
+ type: String,
+ value: '',
+ },
+};
+export default props;
diff --git a/components/cell/type.d.ts b/components/cell/type.d.ts
new file mode 100644
index 0000000..00d874b
--- /dev/null
+++ b/components/cell/type.d.ts
@@ -0,0 +1,72 @@
+export interface TdCellProps {
+ align?: {
+ type: StringConstructor;
+ value?: 'top' | 'middle' | 'bottom';
+ required?: boolean;
+ };
+ arrow?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ bordered?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ description?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-title', 't-class-note', 't-class-description', 't-class-thumb', 't-class-hover', 't-class-left', 't-class-right'];
+ required?: boolean;
+ };
+ hover?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ image?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ jumpType?: {
+ type: StringConstructor;
+ value?: 'switchTab' | 'reLaunch' | 'redirectTo' | 'navigateTo';
+ required?: boolean;
+ };
+ leftIcon?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ note?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ required?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ rightIcon?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ title?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ url?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+}
diff --git a/components/cell/type.js b/components/cell/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/cell/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/date-time-picker/README.md b/components/date-time-picker/README.md
new file mode 100644
index 0000000..6cad303
--- /dev/null
+++ b/components/date-time-picker/README.md
@@ -0,0 +1,67 @@
+---
+title: DateTimePicker 时间选择器
+description: 用于选择一个时间点或者一个时间段。
+spline: form
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker"
+}
+```
+
+## 代码演示
+
+### 基础时间选择器
+
+
+
+#### 选择日期(年月日)
+
+{{ year-month-date }}
+
+#### 选择日期(年月)
+
+{{ year-month }}
+
+#### 选择时间(时分)
+
+{{ time-min }}
+
+#### 选择日期时间(年月日时分)
+
+{{ date-all }}
+
+## API
+### DateTimePicker Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+cancel-btn | String | 取消 | 取消按钮文字 | N
+confirm-btn | String | - | 确定按钮文字 | N
+end | String / Number | - | 选择器的结束时间 | N
+external-classes | Array | - | 组件类名,分别用于设置组件外层元素、确认按钮、取消按钮、标题等元素类名。`['t-class', 't-class-confirm', 't-class-cancel', 't-class-title']` | N
+footer | Slot | true | 底部内容 | N
+format | String | '' | 用于格式化日期,[详细文档](https://day.js.org/docs/en/display/format) | N
+header | Boolean / Slot | true | 头部内容。值为 true 显示空白头部,值为 false 不显示任何内容,值类型为 TNode 表示自定义头部内容 | N
+mode | String / Array | 'date' | year = 年;month = 年月;date = 年月日;hour = 年月日时; minute = 年月日时分;当类型为数组时,第一个值控制年月日,第二个值控制时分秒。TS 类型:`DateTimePickerMode` `type DateTimePickerMode = TimeModeValues | Array ` `type TimeModeValues = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/date-time-picker/type.ts) | N
+show-week | Boolean | false | 【开发中】是否在日期旁边显示周几(如周一,周二,周日等) | N
+start | String / Number | - | 选择器的开始时间 | N
+title | String | - | 标题 | N
+value | String / Number | - | 选中值。TS 类型:`DateValue` `type DateValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/date-time-picker/type.ts) | N
+default-value | String / Number | undefined | 选中值。非受控属性。TS 类型:`DateValue` `type DateValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/date-time-picker/type.ts) | N
+visible | Boolean | false | 是否显示 | N
+
+### DateTimePicker Events
+
+名称 | 参数 | 描述
+-- | -- | --
+cancel | \- | 取消按钮点击时触发
+change | `(value: DateValue)` | 确认按钮点击时触发
+pick | `(value: DateValue)` | 选中值发生变化时触发
diff --git a/components/date-time-picker/date-time-picker.d.ts b/components/date-time-picker/date-time-picker.d.ts
new file mode 100644
index 0000000..aadd2e7
--- /dev/null
+++ b/components/date-time-picker/date-time-picker.d.ts
@@ -0,0 +1,107 @@
+import dayjs from 'dayjs';
+import type { Dayjs } from 'dayjs';
+import { SuperComponent } from '../common/src/index';
+declare enum ModeItem {
+ YEAR = "year",
+ MONTH = "month",
+ DATE = "date",
+ HOUR = "hour",
+ MINUTE = "minute"
+}
+interface ColumnItemValue {
+ value: string | number;
+ label: string | number;
+}
+export default class DateTimePicker extends SuperComponent {
+ properties: import("./type").TdDateTimePickerProps;
+ externalClasses: string[];
+ options: {
+ multipleSlots: boolean;
+ };
+ observers: {
+ 'start, end, value': () => void;
+ mode(m: any): void;
+ };
+ date: any;
+ data: {
+ prefix: string;
+ classPrefix: string;
+ columns: any[];
+ columnsValue: any[];
+ fullModes: any[];
+ locale: {
+ year: string;
+ month: string;
+ day: string;
+ hour: string;
+ minute: string;
+ am: string;
+ pm: string;
+ confirm: string;
+ cancel: string;
+ };
+ };
+ controlledProps: {
+ key: string;
+ event: string;
+ }[];
+ methods: {
+ updateColumns(): void;
+ getParseDate(): Dayjs;
+ getMinDate(): Dayjs;
+ getMaxDate(): Dayjs;
+ getMinYear(): number;
+ getMaxYear(): number;
+ getMinMonth(): number;
+ getMaxMonth(): number;
+ getMinDay(): number;
+ getMaxDay(): number;
+ getMinHour(): number;
+ getMaxHour(): number;
+ getMinMinute(): number;
+ getMaxMinute(): number;
+ getDate(): Dayjs;
+ clipDate(date: Dayjs): Dayjs;
+ setYear(date: Dayjs, year: number): Dayjs;
+ setMonth(date: Dayjs, month: number): Dayjs;
+ getColumnOptions(): any[];
+ getCommonDateParams(): {
+ date: dayjs.Dayjs;
+ selYear: number;
+ selMonth: number;
+ selDate: number;
+ selHour: number;
+ minDateYear: any;
+ maxDateYear: any;
+ minDateMonth: any;
+ maxDateMonth: any;
+ minDateDay: any;
+ maxDateDay: any;
+ minDateHour: any;
+ maxDateHour: any;
+ minDateMinute: any;
+ maxDateMinute: any;
+ };
+ getOptionByType(type: any, dateParams: any): any;
+ getYearOptions(dateParams: any): ColumnItemValue[];
+ getMonthOptions(dateParams: any): ColumnItemValue[];
+ getDayOptions(dateParams: any): ColumnItemValue[];
+ getHourOptions(dateParams: any): ColumnItemValue[];
+ getMinuteOptions(dateParams: any): ColumnItemValue[];
+ getValueCols(this: DateTimePicker): {
+ columns: any;
+ columnsValue: any;
+ };
+ getColumnsValue(): string[];
+ getNewDate(value: number, type: ModeItem): Dayjs;
+ onColumnChange(e: WechatMiniprogram.CustomEvent): void;
+ onConfirm(): void;
+ onCancel(): void;
+ onVisibleChange(e: any): void;
+ resetColumns(): void;
+ };
+ getFullModeArray(mode: any): any;
+ getFullModeByModeString(modeString: any, matchModes: any): any;
+ isTimeMode(): boolean;
+}
+export {};
diff --git a/components/date-time-picker/date-time-picker.js b/components/date-time-picker/date-time-picker.js
new file mode 100644
index 0000000..903121e
--- /dev/null
+++ b/components/date-time-picker/date-time-picker.js
@@ -0,0 +1,405 @@
+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 dayjs from './dayjs/index';
+import config from '../common/config';
+import { SuperComponent, wxComponent } from '../common/src/index';
+import defaultLocale from './locale/zh';
+import props from './props';
+const { prefix } = config;
+const name = `${prefix}-date-time-picker`;
+var ModeItem;
+(function (ModeItem) {
+ ModeItem["YEAR"] = "year";
+ ModeItem["MONTH"] = "month";
+ ModeItem["DATE"] = "date";
+ ModeItem["HOUR"] = "hour";
+ ModeItem["MINUTE"] = "minute";
+})(ModeItem || (ModeItem = {}));
+const DATE_MODES = ['year', 'month', 'date'];
+const TIME_MODES = ['hour', 'minute'];
+const FULL_MODES = [...DATE_MODES, ...TIME_MODES];
+const DEFAULT_MIN_DATE = dayjs('2000-01-01 00:00:00');
+const DEFAULT_MAX_DATE = dayjs('2030-12-31 23:59:59');
+let DateTimePicker = class DateTimePicker extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.properties = props;
+ this.externalClasses = [`${prefix}-class`, `${prefix}-class-confirm`, `${prefix}-class-cancel`, `${prefix}-class-title`];
+ this.options = {
+ multipleSlots: true,
+ };
+ this.observers = {
+ 'start, end, value': function () {
+ this.updateColumns();
+ },
+ mode(m) {
+ const fullModes = this.getFullModeArray(m);
+ this.setData({
+ fullModes,
+ });
+ this.updateColumns();
+ },
+ };
+ this.date = null;
+ this.data = {
+ prefix,
+ classPrefix: name,
+ columns: [],
+ columnsValue: [],
+ fullModes: [],
+ locale: defaultLocale,
+ };
+ this.controlledProps = [
+ {
+ key: 'value',
+ event: 'change',
+ },
+ ];
+ this.methods = {
+ updateColumns() {
+ this.date = this.getParseDate();
+ const { columns, columnsValue } = this.getValueCols();
+ this.setData({
+ columns,
+ columnsValue,
+ });
+ },
+ getParseDate() {
+ const { value, defaultValue } = this.properties;
+ const minDate = this.getMinDate();
+ const isTimeMode = this.isTimeMode();
+ let currentValue = value || defaultValue;
+ if (isTimeMode) {
+ const dateStr = dayjs(minDate).format('YYYY-MM-DD');
+ currentValue = dayjs(`${dateStr} ${currentValue}`);
+ }
+ const parseDate = dayjs(currentValue || minDate);
+ const isDateValid = parseDate.isValid();
+ return isDateValid ? parseDate : minDate;
+ },
+ getMinDate() {
+ const { start } = this.properties;
+ return start ? dayjs(start) : DEFAULT_MIN_DATE;
+ },
+ getMaxDate() {
+ const { end } = this.properties;
+ return end ? dayjs(end) : DEFAULT_MAX_DATE;
+ },
+ getMinYear() {
+ return this.getMinDate().year();
+ },
+ getMaxYear() {
+ return this.getMaxDate().year();
+ },
+ getMinMonth() {
+ return this.getMinDate().month();
+ },
+ getMaxMonth() {
+ return this.getMaxDate().month();
+ },
+ getMinDay() {
+ return this.getMinDate().date();
+ },
+ getMaxDay() {
+ return this.getMaxDate().date();
+ },
+ getMinHour() {
+ return this.getMinDate().hour();
+ },
+ getMaxHour() {
+ return this.getMaxDate().hour();
+ },
+ getMinMinute() {
+ return this.getMinDate().minute();
+ },
+ getMaxMinute() {
+ return this.getMaxDate().minute();
+ },
+ getDate() {
+ return this.clipDate((this === null || this === void 0 ? void 0 : this.date) || DEFAULT_MIN_DATE);
+ },
+ clipDate(date) {
+ const minDate = this.getMinDate();
+ const maxDate = this.getMaxDate();
+ return dayjs(Math.min(Math.max(minDate.valueOf(), date.valueOf()), maxDate.valueOf()));
+ },
+ setYear(date, year) {
+ const beforeMonthDays = date.date();
+ const afterMonthDays = date.year(year).daysInMonth();
+ const tempDate = date.date(Math.min(beforeMonthDays.valueOf(), afterMonthDays.valueOf()));
+ return tempDate.year(year);
+ },
+ setMonth(date, month) {
+ const beforeMonthDays = date.date();
+ const afterMonthDays = date.month(month).daysInMonth();
+ const tempDate = date.date(Math.min(beforeMonthDays.valueOf(), afterMonthDays.valueOf()));
+ return tempDate.month(month);
+ },
+ getColumnOptions() {
+ const { fullModes } = this.data;
+ const dateParams = this.getCommonDateParams();
+ const columnOptions = [];
+ fullModes === null || fullModes === void 0 ? void 0 : fullModes.forEach((mode) => {
+ const columnOption = this.getOptionByType(mode, dateParams);
+ columnOptions.push(columnOption);
+ });
+ return columnOptions;
+ },
+ getCommonDateParams() {
+ const date = this.getDate();
+ const selYear = date.year();
+ const selMonth = date.month();
+ const selDate = date.date();
+ const selHour = date.hour();
+ const minDateYear = this.getMinYear();
+ const maxDateYear = this.getMaxYear();
+ const minDateMonth = this.getMinMonth();
+ const maxDateMonth = this.getMaxMonth();
+ const minDateDay = this.getMinDay();
+ const maxDateDay = this.getMaxDay();
+ const minDateHour = this.getMinHour();
+ const maxDateHour = this.getMaxHour();
+ const minDateMinute = this.getMinMinute();
+ const maxDateMinute = this.getMaxMinute();
+ return {
+ date,
+ selYear,
+ selMonth,
+ selDate,
+ selHour,
+ minDateYear,
+ maxDateYear,
+ minDateMonth,
+ maxDateMonth,
+ minDateDay,
+ maxDateDay,
+ minDateHour,
+ maxDateHour,
+ minDateMinute,
+ maxDateMinute,
+ };
+ },
+ getOptionByType(type, dateParams) {
+ switch (type) {
+ case ModeItem.YEAR:
+ return this.getYearOptions(dateParams);
+ case ModeItem.MONTH:
+ return this.getMonthOptions(dateParams);
+ case ModeItem.DATE:
+ return this.getDayOptions(dateParams);
+ case ModeItem.HOUR:
+ return this.getHourOptions(dateParams);
+ case ModeItem.MINUTE:
+ return this.getMinuteOptions(dateParams);
+ default:
+ break;
+ }
+ },
+ getYearOptions(dateParams) {
+ const { locale } = this.data;
+ const { minDateYear, maxDateYear } = dateParams;
+ const years = [];
+ for (let i = minDateYear; i <= maxDateYear; i += 1) {
+ years.push({
+ value: `${i}`,
+ label: `${i + locale.year}`,
+ });
+ }
+ return years;
+ },
+ getMonthOptions(dateParams) {
+ const { locale } = this.data;
+ const { minDateYear, maxDateYear, selYear, minDateMonth, maxDateMonth } = dateParams;
+ const months = [];
+ let minMonth = 0;
+ let maxMonth = 11;
+ if (minDateYear === selYear) {
+ minMonth = minDateMonth;
+ }
+ if (maxDateYear === selYear) {
+ maxMonth = maxDateMonth;
+ }
+ for (let i = minMonth; i <= maxMonth; i += 1) {
+ months.push({
+ value: `${i}`,
+ label: `${i + 1 + locale.month}`,
+ });
+ }
+ return months;
+ },
+ getDayOptions(dateParams) {
+ const { locale } = this.data;
+ const { minDateYear, maxDateYear, minDateMonth, maxDateMonth, minDateDay, maxDateDay, selYear, selMonth, date } = dateParams;
+ const days = [];
+ let minDay = 1;
+ let maxDay = date.daysInMonth();
+ if (minDateYear === selYear && minDateMonth === selMonth) {
+ minDay = minDateDay;
+ }
+ if (maxDateYear === selYear && maxDateMonth === selMonth) {
+ maxDay = maxDateDay;
+ }
+ for (let i = minDay; i <= maxDay; i += 1) {
+ days.push({
+ value: `${i}`,
+ label: `${i + locale.day}`,
+ });
+ }
+ return days;
+ },
+ getHourOptions(dateParams) {
+ const { locale } = this.data;
+ const { minDateYear, maxDateYear, minDateMonth, maxDateMonth, minDateDay, minDateHour, maxDateDay, maxDateHour, selYear, selMonth, selDate, } = dateParams;
+ const hours = [];
+ let minHour = 0;
+ let maxHour = 23;
+ if (minDateYear === selYear && minDateMonth === selMonth && minDateDay === selDate) {
+ minHour = minDateHour;
+ }
+ if (maxDateYear === selYear && maxDateMonth === selMonth && maxDateDay === selDate) {
+ maxHour = maxDateHour;
+ }
+ for (let i = minHour; i <= maxHour; i += 1) {
+ hours.push({
+ value: `${i}`,
+ label: `${i + locale.hour}`,
+ });
+ }
+ return hours;
+ },
+ getMinuteOptions(dateParams) {
+ const { locale } = this.data;
+ const { minDateYear, maxDateYear, minDateMonth, maxDateMonth, minDateDay, maxDateDay, minDateHour, maxDateHour, minDateMinute, maxDateMinute, selYear, selMonth, selDate, selHour, } = dateParams;
+ const minutes = [];
+ let minMinute = 0;
+ let maxMinute = 59;
+ if (minDateYear === selYear && minDateMonth === selMonth && minDateDay === selDate && minDateHour === selHour) {
+ minMinute = minDateMinute;
+ }
+ if (maxDateYear === selYear && maxDateMonth === selMonth && maxDateDay === selDate && maxDateHour === selHour) {
+ maxMinute = maxDateMinute;
+ }
+ for (let i = minMinute; i <= maxMinute; i += 1) {
+ minutes.push({
+ value: `${i}`,
+ label: `${i + locale.minute}`,
+ });
+ }
+ return minutes;
+ },
+ getValueCols() {
+ return {
+ columns: this.getColumnOptions(),
+ columnsValue: this.getColumnsValue(),
+ };
+ },
+ getColumnsValue() {
+ const { fullModes } = this.data;
+ const date = this.getDate();
+ const columnsValue = [];
+ fullModes === null || fullModes === void 0 ? void 0 : fullModes.forEach((mode) => {
+ columnsValue.push(`${date[mode]()}`);
+ });
+ return columnsValue;
+ },
+ getNewDate(value, type) {
+ let newValue = this.getDate();
+ switch (type) {
+ case ModeItem.YEAR:
+ newValue = this.setYear(newValue, value);
+ break;
+ case ModeItem.MONTH:
+ newValue = this.setMonth(newValue, value);
+ break;
+ case ModeItem.DATE:
+ newValue = newValue.date(value);
+ break;
+ case ModeItem.HOUR:
+ newValue = newValue.hour(value);
+ break;
+ case ModeItem.MINUTE:
+ newValue = newValue.minute(value);
+ break;
+ default:
+ break;
+ }
+ return this.clipDate(newValue);
+ },
+ onColumnChange(e) {
+ const { value, column } = e === null || e === void 0 ? void 0 : e.detail;
+ const { fullModes, format } = this.data;
+ const columnValue = value === null || value === void 0 ? void 0 : value[column];
+ const columnType = fullModes === null || fullModes === void 0 ? void 0 : fullModes[column];
+ const newValue = this.getNewDate(parseInt(columnValue, 10), columnType);
+ this.date = newValue;
+ const { columns, columnsValue } = this.getValueCols();
+ this.setData({
+ columns,
+ columnsValue,
+ });
+ const date = this.getDate();
+ const pickValue = format ? date.format(format) : date.valueOf();
+ this.triggerEvent('pick', { value: pickValue });
+ },
+ onConfirm() {
+ const { format } = this.properties;
+ const date = this.getDate();
+ const value = format ? date.format(format) : date.valueOf();
+ this._trigger('change', { value });
+ this.resetColumns();
+ },
+ onCancel() {
+ this.resetColumns();
+ this.triggerEvent('cancel');
+ },
+ onVisibleChange(e) {
+ if (!e.detail.visible) {
+ this.resetColumns();
+ }
+ },
+ resetColumns() {
+ const parseDate = this.getParseDate();
+ this.date = parseDate;
+ const { columns, columnsValue } = this.getValueCols();
+ this.setData({
+ columns,
+ columnsValue,
+ });
+ },
+ };
+ }
+ getFullModeArray(mode) {
+ if (typeof mode === 'string' || mode instanceof String) {
+ return this.getFullModeByModeString(mode, FULL_MODES);
+ }
+ if (Array.isArray(mode)) {
+ if ((mode === null || mode === void 0 ? void 0 : mode.length) === 1) {
+ return this.getFullModeByModeString(mode[0], FULL_MODES);
+ }
+ if ((mode === null || mode === void 0 ? void 0 : mode.length) === 2) {
+ const dateModes = this.getFullModeByModeString(mode[0], DATE_MODES);
+ const timeModes = this.getFullModeByModeString(mode[1], TIME_MODES);
+ return [...dateModes, ...timeModes];
+ }
+ }
+ }
+ getFullModeByModeString(modeString, matchModes) {
+ if (!modeString) {
+ return [];
+ }
+ const endIndex = matchModes === null || matchModes === void 0 ? void 0 : matchModes.findIndex((mode) => modeString === mode);
+ return matchModes === null || matchModes === void 0 ? void 0 : matchModes.slice(0, endIndex + 1);
+ }
+ isTimeMode() {
+ const { fullModes } = this.data;
+ return fullModes[0] === ModeItem.HOUR;
+ }
+};
+DateTimePicker = __decorate([
+ wxComponent()
+], DateTimePicker);
+export default DateTimePicker;
diff --git a/components/date-time-picker/date-time-picker.json b/components/date-time-picker/date-time-picker.json
new file mode 100644
index 0000000..036831c
--- /dev/null
+++ b/components/date-time-picker/date-time-picker.json
@@ -0,0 +1,7 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-picker": "../picker/picker",
+ "t-picker-item": "../picker/picker-item"
+ }
+}
diff --git a/components/date-time-picker/date-time-picker.wxml b/components/date-time-picker/date-time-picker.wxml
new file mode 100644
index 0000000..2b1ea87
--- /dev/null
+++ b/components/date-time-picker/date-time-picker.wxml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/components/date-time-picker/date-time-picker.wxss b/components/date-time-picker/date-time-picker.wxss
new file mode 100644
index 0000000..e69de29
diff --git a/components/date-time-picker/dayjs/index.js b/components/date-time-picker/dayjs/index.js
new file mode 100644
index 0000000..4acc24c
--- /dev/null
+++ b/components/date-time-picker/dayjs/index.js
@@ -0,0 +1 @@
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",f="month",h="quarter",c="year",d="date",$="Invalid Date",l=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},g={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(v=i),i||!r&&v},w=function(t,e){if(p(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},O=g;O.l=S,O.i=p,O.w=function(t,e){return w(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=S(t.locale,null,!0),this.parse(t)}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(O.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(l);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return O},m.isValid=function(){return!(this.$d.toString()===$)},m.isSame=function(t,e){var n=w(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return w(t);
+export declare type TimeModeValues = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second';
+export declare type DateValue = string | number;
diff --git a/components/date-time-picker/type.js b/components/date-time-picker/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/date-time-picker/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/fab/README.md b/components/fab/README.md
new file mode 100644
index 0000000..0ba9127
--- /dev/null
+++ b/components/fab/README.md
@@ -0,0 +1,44 @@
+---
+title: Fab
+description: 当功能使用图标即可表意清楚时,可使用纯图标悬浮按钮,例如:添加、发布。
+spline: form
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+
+```json
+"usingComponents": {
+ "t-fab": "tdesign-miniprogram/fab/fab"
+}
+```
+
+## 代码演示
+
+### 基础使用
+
+{{ base }}
+
+### 进阶使用
+
+{{ advance }}
+
+## API
+### Fab Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+button-props | Object | - | 透传至 Button 组件 | N
+icon | String | - | 图标 | N
+style | String | right: 16px; bottom: 32px; | 悬浮按钮的样式,常用于调整位置 | N
+text | String | - | 文本内容 | N
+
+### Fab Events
+
+名称 | 参数 | 描述
+-- | -- | --
+click | `({e: Event})` | 悬浮按钮点击事件
diff --git a/components/fab/fab.d.ts b/components/fab/fab.d.ts
new file mode 100644
index 0000000..00e06b5
--- /dev/null
+++ b/components/fab/fab.d.ts
@@ -0,0 +1,20 @@
+import { SuperComponent } from '../common/src/index';
+export default class Fab extends SuperComponent {
+ properties: import("./type").TdFabProps;
+ externalClasses: string[];
+ data: {
+ prefix: string;
+ classPrefix: string;
+ baseButtonProps: {
+ size: string;
+ shape: string;
+ theme: string;
+ };
+ };
+ observers: {
+ text(val: any): void;
+ };
+ methods: {
+ onTplButtonTap(e: any): void;
+ };
+}
diff --git a/components/fab/fab.js b/components/fab/fab.js
new file mode 100644
index 0000000..e30f4f3
--- /dev/null
+++ b/components/fab/fab.js
@@ -0,0 +1,47 @@
+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';
+const { prefix } = config;
+const name = `${prefix}-fab`;
+let Fab = class Fab extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.properties = props;
+ this.externalClasses = [`${prefix}-class`, `${prefix}-class-button`];
+ this.data = {
+ prefix,
+ classPrefix: name,
+ baseButtonProps: {
+ size: 'large',
+ shape: 'circle',
+ theme: 'primary',
+ },
+ };
+ this.observers = {
+ text(val) {
+ if (val) {
+ this.setData({
+ baseButtonProps: {
+ shape: 'round',
+ },
+ });
+ }
+ },
+ };
+ this.methods = {
+ onTplButtonTap(e) {
+ this.triggerEvent('click', e);
+ },
+ };
+ }
+};
+Fab = __decorate([
+ wxComponent()
+], Fab);
+export default Fab;
diff --git a/components/fab/fab.json b/components/fab/fab.json
new file mode 100644
index 0000000..e73f3ad
--- /dev/null
+++ b/components/fab/fab.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-button": "../button/button"
+ }
+}
diff --git a/components/fab/fab.wxml b/components/fab/fab.wxml
new file mode 100644
index 0000000..41fcc64
--- /dev/null
+++ b/components/fab/fab.wxml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/components/fab/fab.wxss b/components/fab/fab.wxss
new file mode 100644
index 0000000..7d7ee86
--- /dev/null
+++ b/components/fab/fab.wxss
@@ -0,0 +1,52 @@
+.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-fab {
+ position: fixed;
+ width: auto;
+ min-width: 86rpx;
+ height: 86rpx;
+ line-height: normal;
+ padding: 0 40rpx;
+ box-sizing: border-box;
+ border-radius: 48rpx;
+ margin-bottom: 60rpx;
+}
+.t-fab .t-button__text {
+ display: flex;
+ align-items: center;
+}
+.t-fab::after {
+ border-radius: inherit;
+}
+.t-fab__text {
+ margin-left: 16rpx;
+}
+.t-fab--icononly {
+ padding: 0;
+ border-radius: 50%;
+}
diff --git a/components/fab/props.d.ts b/components/fab/props.d.ts
new file mode 100644
index 0000000..2cf4647
--- /dev/null
+++ b/components/fab/props.d.ts
@@ -0,0 +1,3 @@
+import { TdFabProps } from './type';
+declare const props: TdFabProps;
+export default props;
diff --git a/components/fab/props.js b/components/fab/props.js
new file mode 100644
index 0000000..e27ba06
--- /dev/null
+++ b/components/fab/props.js
@@ -0,0 +1,18 @@
+const props = {
+ buttonProps: {
+ type: Object,
+ },
+ icon: {
+ type: String,
+ value: '',
+ },
+ style: {
+ type: String,
+ value: 'right: 16px; bottom: 32px;',
+ },
+ text: {
+ type: String,
+ value: '',
+ },
+};
+export default props;
diff --git a/components/fab/type.d.ts b/components/fab/type.d.ts
new file mode 100644
index 0000000..1d9287f
--- /dev/null
+++ b/components/fab/type.d.ts
@@ -0,0 +1,18 @@
+export interface TdFabProps {
+ buttonProps?: {
+ type: ObjectConstructor;
+ value?: object;
+ };
+ icon?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ style?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ text?: {
+ type: StringConstructor;
+ value?: string;
+ };
+}
diff --git a/components/fab/type.js b/components/fab/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/fab/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/input/README.md b/components/input/README.md
new file mode 100644
index 0000000..4a11133
--- /dev/null
+++ b/components/input/README.md
@@ -0,0 +1,129 @@
+---
+title: Input 输入框
+description: 用于单行文本信息输入。
+spline: form
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-input": "tdesign-miniprogram/input/input"
+}
+```
+### 主题定制
+CSS 变量名|说明
+--|--
+--td-input-bg-color | 输入框背景颜色
+--td-input-text-color | 输入框文本颜色
+--td-input-placeholder-text-color | 输入框placeholder占位符颜色
+--td-input-error-text-color | 输入错误时文本颜色
+--td-input-disabled-text-color | 禁用输入框颜色
+--td-input-border-color | 输入框边框颜色
+--td-input-error-msg-color | 错误提示文本颜色
+--td-input-icon-color | 图标颜色
+--td-input-suffix-text-color | 后置文本内容颜色
+
+## 代码演示
+
+## 类型
+### 基础文本框
+
+
+
+{{ base }}
+
+### 必填、选填文本框
+
+{{ require }}
+
+### 带提示信息文本框
+
+{{ suffix }}
+
+## 状态
+### 文本框状态
+
+{{ status }}
+
+## 特殊类型
+### 特殊文本类型
+
+{{ special }}
+
+## 规格
+### 文本框尺寸规格
+
+{{ size }}
+
+## 内容位置
+### 文本框内容位置
+
+{{ align }}
+
+## 字数限制
+### 文本框字数限制
+
+{{ maxlength }}
+
+## API
+### Input Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+align | String | left | 文本内容位置,居左/居中/居右。可选项:left/center/right | N
+borderless | Boolean | true | 是否开启无边框模式 | N
+clearable | Boolean | false | 是否可清空 | N
+disabled | Boolean | false | 是否禁用输入框 | N
+error-message | String | - | 错误提示文本,值为空不显示(废弃属性,如果需要,请更为使用 status 和 tips) | N
+external-classes | Array | - | 组件类名,用于设置组件外层元素、输入框、占位符、错误信息等元素类名。`['t-class','t-class-icon', 't-class-label', 't-class-input', 't-class-clearable', 't-class-suffix', 't-class-suffix-icon', 't-class-error-msg']` | N
+format | Function | - | 【开发中】指定输入框展示值的格式。TS 类型:`InputFormatType` `type InputFormatType = (value: InputValue) => number | string`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/input/type.ts) | N
+label | String / Slot | - | 左侧文本 | N
+maxcharacter | Number | - | 用户最多可以输入的字符个数,一个中文汉字表示两个字符长度。`maxcharacter` 和 `maxlength` 二选一使用 | N
+maxlength | Number | - | 用户最多可以输入的文本长度,一个中文等于一个计数长度。值小于等于 0 的时候,则表示不限制输入长度。`maxcharacter` 和 `maxlength` 二选一使用 | N
+placeholder | String | undefined | 占位符 | N
+prefix-icon | String / Slot | - | 组件前置图标,值为字符串则表示图标名称 | N
+readonly | Boolean | false | 【开发中】只读状态 | N
+size | String | small | 输入框尺寸。可选项:small/medium。TS 类型:`'medium' | 'small'` | N
+status | String | - | 【开发中】输入框状态。可选项:success/warning/error | N
+suffix | String / Slot | - | 后置图标前的后置内容 | N
+suffix-icon | String / Slot | - | 后置文本内容,值为字符串则表示图标名称 | N
+tips | String / Slot | - | 【开发中】输入框下方提示文本,会根据不同的 `status` 呈现不同的样式 | N
+type | String | text | 输入框类型。可选项:text/number/idcard/digit/safe-password/password | N
+value | String / Number | - | 输入框的值。TS 类型:`InputValue` `type InputValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/input/type.ts) | N
+default-value | String / Number | undefined | 输入框的值。非受控属性。TS 类型:`InputValue` `type InputValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/input/type.ts) | N
+password | Boolean | false | 是否是密码类型(已废弃,请更为使用 type 指定输入框类型) | N
+placeholder-style | String | - | 必需。指定 placeholder 的样式 | Y
+placeholder-class | String | input-placeholder | 指定 placeholder 的样式类 | N
+cursor-spacing | Number | 0 | 指定光标与键盘的距离,取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离 | N
+auto-focus | Boolean | false | (即将废弃,请直接使用 focus )自动聚焦,拉起键盘 | N
+focus | Boolean | false | 获取焦点 | N
+confirm-type | String | done | 设置键盘右下角按钮的文字,仅在type='text'时生效。
具体释义:
`send` 右下角按钮为“发送”;
`search` 右下角按钮为“搜索”;
`next` 右下角按钮为“下一个”;
`go` 右下角按钮为“前往”;
`done` 右下角按钮为“完成”。
[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/input.html)。可选项:send/search/next/go/done | N
+always-embed | Boolean | false | 强制 input 处于同层状态,默认 focus 时 input 会切到非同层状态 (仅在 iOS 下生效) | N
+confirm-hold | Boolean | false | 点击键盘右下角按钮时是否保持键盘不收起 | N
+cursor | Number | - | 必需。指定focus时的光标位置 | Y
+selection-start | Number | -1 | 光标起始位置,自动聚集时有效,需与selection-end搭配使用 | N
+selection-end | Number | -1 | 光标结束位置,自动聚集时有效,需与selection-start搭配使用 | N
+adjust-position | Boolean | true | 键盘弹起时,是否自动上推页面 | N
+hold-keyboard | Boolean | false | focus时,点击页面的时候不收起键盘 | N
+safe-password-cert-path | String | - | 安全键盘加密公钥的路径,只支持包内路径 | N
+safe-password-length | Number | - | 安全键盘输入密码长度 | N
+safe-password-time-stamp | Number | - | 安全键盘加密时间戳 | N
+safe-password-nonce | String | - | 安全键盘加密盐值 | N
+safe-password-salt | String | - | 安全键盘计算hash盐值,若指定custom-hash 则无效 | N
+safe-password-custom-hash | String | - | 安全键盘计算hash的算法表达式,如 `md5(sha1('foo' + sha256(sm3(password + 'bar'))))` | N
+
+### Input Events
+
+名称 | 参数 | 描述
+-- | -- | --
+blur | `(value: InputValue)` | 失去焦点时触发
+change | `(value: InputValue, cursor: number, keyCode: number)` | 输入框值发生变化时触发;cursor 为光标位置;keyCode 为键值
+clear | - | 清空按钮点击时触发
+enter | `(value: InputValue)` | 回车键按下时触发
+focus | `(value: InputValue)` | 获得焦点时触发
+keyboardheightchange | `(height: number, duration: number)` | 键盘高度发生变化的时候触发此事件
diff --git a/components/input/input.d.ts b/components/input/input.d.ts
new file mode 100644
index 0000000..6a732a5
--- /dev/null
+++ b/components/input/input.d.ts
@@ -0,0 +1,26 @@
+import { SuperComponent } from '../common/src/index';
+export default class Input extends SuperComponent {
+ options: {
+ multipleSlots: boolean;
+ };
+ externalClasses: string[];
+ behaviors: string[];
+ properties: import("./type").TdInputProps;
+ data: {
+ prefix: string;
+ classPrefix: string;
+ classBasePrefix: string;
+ };
+ lifetimes: {
+ ready(): void;
+ };
+ methods: {
+ updateValue(value: any): void;
+ onInput(e: any): void;
+ onFocus(e: any): void;
+ onBlur(e: any): void;
+ onConfirm(e: any): void;
+ clearInput(e: any): void;
+ onKeyboardHeightChange(e: any): void;
+ };
+}
diff --git a/components/input/input.js b/components/input/input.js
new file mode 100644
index 0000000..29a43cf
--- /dev/null
+++ b/components/input/input.js
@@ -0,0 +1,93 @@
+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 { getCharacterLength } from '../common/utils';
+const { prefix } = config;
+const name = `${prefix}-input`;
+let Input = class Input extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.options = {
+ multipleSlots: true,
+ };
+ this.externalClasses = [
+ `${prefix}-class`,
+ `${prefix}-class-icon`,
+ `${prefix}-class-label`,
+ `${prefix}-class-input`,
+ `${prefix}-class-clearable`,
+ `${prefix}-class-suffix`,
+ `${prefix}-class-suffix-icon`,
+ `${prefix}-class-error-msg`,
+ ];
+ this.behaviors = ['wx://form-field'];
+ this.properties = props;
+ this.data = {
+ prefix,
+ classPrefix: name,
+ classBasePrefix: prefix,
+ };
+ this.lifetimes = {
+ ready() {
+ const { value } = this.properties;
+ this.updateValue(value);
+ },
+ };
+ this.methods = {
+ updateValue(value) {
+ const { maxcharacter, maxlength } = this.properties;
+ if (maxcharacter && maxcharacter > 0 && !Number.isNaN(maxcharacter)) {
+ const { length, characters } = getCharacterLength('maxcharacter', value, maxcharacter);
+ this.setData({
+ value: characters,
+ count: length,
+ });
+ }
+ else if (maxlength > 0 && !Number.isNaN(maxlength)) {
+ const { length, characters } = getCharacterLength('maxlength', value, maxlength);
+ this.setData({
+ value: characters,
+ count: length,
+ });
+ }
+ else {
+ this.setData({
+ value,
+ count: value ? String(value).length : 0,
+ });
+ }
+ },
+ onInput(e) {
+ const { value, cursor, keyCode } = e.detail;
+ this.updateValue(value);
+ this.triggerEvent('change', { value: this.data.value, cursor, keyCode });
+ },
+ onFocus(e) {
+ this.triggerEvent('focus', e.detail);
+ },
+ onBlur(e) {
+ this.triggerEvent('blur', e.detail);
+ },
+ onConfirm(e) {
+ this.triggerEvent('enter', e.detail);
+ },
+ clearInput(e) {
+ this.triggerEvent('clear', e.detail);
+ this.setData({ value: '' });
+ },
+ onKeyboardHeightChange(e) {
+ this.triggerEvent('keyboardheightchange', e.detail);
+ },
+ };
+ }
+};
+Input = __decorate([
+ wxComponent()
+], Input);
+export default Input;
diff --git a/components/input/input.json b/components/input/input.json
new file mode 100644
index 0000000..049940c
--- /dev/null
+++ b/components/input/input.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-icon": "../icon/icon"
+ }
+}
diff --git a/components/input/input.wxml b/components/input/input.wxml
new file mode 100644
index 0000000..9e10e77
--- /dev/null
+++ b/components/input/input.wxml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+ {{label}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{suffix}}
+
+
+
+
+
+ {{errorMessage}}
+
+
+
diff --git a/components/input/input.wxss b/components/input/input.wxss
new file mode 100644
index 0000000..c7326e7
--- /dev/null
+++ b/components/input/input.wxss
@@ -0,0 +1,180 @@
+.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);
+}
+page {
+ --td-input-bg-color: #fff;
+ --td-input-text-color: #000000;
+ --td-input-placeholder-text-color: rgba(0, 0, 0, 0.4);
+ --td-input-error-msg-color: rgba(0, 0, 0, 0.4);
+ --td-input-disabled-text-color: #000000;
+ --td-input-label-color: #000;
+ --td-input-icon-color: #bbbbbb;
+ --td-input-error-text-color: #e34d59;
+ --td-input-suffix-text-color: #000000;
+ --td-input-border-color: #e7e7e7;
+}
+.t-input--bordered::after {
+ position: absolute;
+ box-sizing: border-box;
+ content: ' ';
+ pointer-events: none;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ border-bottom: 1px solid var(--td-input-border-color);
+ transform: scaleY(0.5);
+ left: 32rpx;
+}
+.t-input {
+ position: relative;
+ display: flex;
+ padding: 24rpx 32rpx;
+ background: var(--td-input-bg-color);
+}
+.t-input__label {
+ width: 164rpx;
+ color: var(--td-input-label-color);
+ margin-right: 32rpx;
+ flex: none;
+ font-size: 35rpx;
+}
+.t-input__icon-wrap,
+.t-input__icon--prefix,
+.t-input__icon--suffix {
+ display: flex;
+ align-items: center;
+}
+.t-input__icon--prefix {
+ margin-right: 8rpx;
+}
+.t-input__content {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ font-size: 32rpx;
+}
+.t-input__wrap {
+ display: flex;
+ flex-wrap: wrap;
+ flex: auto;
+}
+.t-input__wrap--suffix,
+.t-input__wrap--icon {
+ flex: 0 0 auto;
+ margin-left: 24rpx;
+ color: var(--td-input-icon-color);
+ font-size: 32rpx;
+}
+.t-input__wrap--suffix:empty,
+.t-input__wrap--icon:empty {
+ display: none;
+}
+.t-input__wrap--suffix {
+ position: relative;
+ padding-left: 24rpx;
+}
+.t-input__wrap--suffix::after {
+ position: absolute;
+ box-sizing: border-box;
+ content: ' ';
+ pointer-events: none;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ border-left: 1px solid #e6e6e6;
+ transform: scaleX(0.5);
+}
+.t-input__wrap--suffix-text {
+ position: relative;
+ padding-left: 24rpx;
+ color: var(--td-input-suffix-text-color);
+}
+.t-input__control {
+ display: block;
+ box-sizing: border-box;
+ width: 100%;
+ min-width: 0;
+ margin: 0;
+ padding: 0;
+ color: var(--td-input-text-color);
+ line-height: inherit;
+ text-align: left;
+ background-color: transparent;
+ border: 0;
+ resize: none;
+ font-size: inherit;
+}
+.t-input__control::placeholder {
+ color: var(--td-input-placeholder-text-color);
+}
+.t-input__control:disabled {
+ color: var(--td-input-disabled-text-color);
+ background-color: transparent;
+ cursor: not-allowed;
+ opacity: 1;
+ -webkit-text-fill-color: currentColor;
+}
+.t-input__control:read-only {
+ cursor: default;
+}
+.t-input__control--right {
+ text-align: right;
+}
+.t-input__control--center {
+ text-align: center;
+}
+.t-input__placeholder {
+ color: var(--td-input-placeholder-text-color);
+}
+.t-input.t-is-error {
+ align-items: flex-start;
+}
+.t-input.t-is-error .t-input__control {
+ color: var(--td-input-error-text-color);
+}
+.t-input.t-is-error .t-input__control::placeholder {
+ color: var(--td-input-error-text-color);
+}
+.t-input.t-is-error .t-input__placeholder {
+ color: var(--td-input-error-text-color);
+}
+.t-input.t-is-error .t-input__error-msg {
+ text-align: left;
+ padding-top: 24rpx;
+ font-size: 24rpx;
+ line-height: 1;
+ color: var(--td-input-error-msg-color);
+ width: 100%;
+}
+.t-input--size-medium {
+ padding-top: 32rpx;
+ padding-bottom: 32rpx;
+}
+.t-input--size-small {
+ padding-top: 24rpx;
+ padding-bottom: 24rpx;
+}
diff --git a/components/input/props.d.ts b/components/input/props.d.ts
new file mode 100644
index 0000000..1bd2f9a
--- /dev/null
+++ b/components/input/props.d.ts
@@ -0,0 +1,3 @@
+import { TdInputProps } from './type';
+declare const props: TdInputProps;
+export default props;
diff --git a/components/input/props.js b/components/input/props.js
new file mode 100644
index 0000000..cf1c3b1
--- /dev/null
+++ b/components/input/props.js
@@ -0,0 +1,152 @@
+const props = {
+ align: {
+ type: String,
+ value: 'left',
+ },
+ borderless: {
+ type: Boolean,
+ value: false,
+ },
+ clearable: {
+ type: Boolean,
+ value: false,
+ },
+ disabled: {
+ type: Boolean,
+ value: false,
+ },
+ errorMessage: {
+ type: String,
+ value: '',
+ },
+ externalClasses: {
+ type: Array,
+ },
+ format: {
+ type: null,
+ },
+ label: {
+ type: String,
+ },
+ maxcharacter: {
+ type: Number,
+ },
+ maxlength: {
+ type: Number,
+ },
+ placeholder: {
+ type: String,
+ value: undefined,
+ },
+ prefixIcon: {
+ type: String,
+ },
+ readonly: {
+ type: Boolean,
+ value: false,
+ },
+ size: {
+ type: String,
+ value: 'small',
+ },
+ status: {
+ type: String,
+ value: 'default',
+ },
+ suffix: {
+ type: String,
+ },
+ suffixIcon: {
+ type: String,
+ },
+ tips: {
+ type: String,
+ },
+ value: {
+ type: String,
+ optionalTypes: [Number],
+ value: null,
+ },
+ defaultValue: {
+ type: String,
+ optionalTypes: [Number],
+ },
+ type: {
+ type: String,
+ value: 'text',
+ },
+ placeholderStyle: {
+ type: String,
+ value: '',
+ },
+ placeholderClass: {
+ type: String,
+ value: 'input-placeholder',
+ },
+ cursorSpacing: {
+ type: Number,
+ value: 0,
+ },
+ autoFocus: {
+ type: Boolean,
+ value: false,
+ },
+ focus: {
+ type: Boolean,
+ value: false,
+ },
+ confirmType: {
+ type: String,
+ value: 'done',
+ },
+ alwaysEmbed: {
+ type: Boolean,
+ value: false,
+ },
+ confirmHold: {
+ type: Boolean,
+ value: false,
+ },
+ cursor: {
+ type: Number,
+ },
+ selectionStart: {
+ type: Number,
+ value: -1,
+ },
+ selectionEnd: {
+ type: Number,
+ value: -1,
+ },
+ adjustPosition: {
+ type: Boolean,
+ value: true,
+ },
+ holdKeyboard: {
+ type: Boolean,
+ value: false,
+ },
+ safePasswordCertPath: {
+ type: String,
+ value: '',
+ },
+ safePasswordLength: {
+ type: Number,
+ },
+ safePasswordTimeStamp: {
+ type: Number,
+ },
+ safePasswordNonce: {
+ type: String,
+ value: '',
+ },
+ safePasswordSalt: {
+ type: String,
+ value: '',
+ },
+ safePasswordCustomHash: {
+ type: String,
+ value: '',
+ },
+};
+export default props;
diff --git a/components/input/type.d.ts b/components/input/type.d.ts
new file mode 100644
index 0000000..6a7c9f9
--- /dev/null
+++ b/components/input/type.d.ts
@@ -0,0 +1,166 @@
+export interface TdInputProps {
+ align?: {
+ type: StringConstructor;
+ value?: 'left' | 'center' | 'right';
+ };
+ borderless?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ clearable?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ disabled?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ errorMessage?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-input', 't-class-placeholder', 't-class-error-msg'];
+ };
+ format?: {
+ type: null;
+ value?: InputFormatType;
+ };
+ label?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ maxcharacter?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ maxlength?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ placeholder?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ prefixIcon?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ readonly?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ size?: {
+ type: StringConstructor;
+ value?: 'medium' | 'small';
+ };
+ status?: {
+ type: StringConstructor;
+ value?: 'default' | 'success' | 'warning' | 'error';
+ };
+ suffix?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ suffixIcon?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ tips?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ type?: {
+ type: StringConstructor;
+ value?: 'text' | 'number' | 'idcard' | 'digit' | 'safe-password' | 'password';
+ };
+ value?: {
+ type: StringConstructor;
+ optionalTypes: Array;
+ value?: InputValue;
+ };
+ defaultValue?: {
+ type: StringConstructor;
+ optionalTypes: Array;
+ value?: InputValue;
+ };
+ placeholderStyle: {
+ type: StringConstructor;
+ value?: string;
+ };
+ placeholderClass?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ cursorSpacing?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ autoFocus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ focus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ confirmType?: {
+ type: StringConstructor;
+ value?: 'send' | 'search' | 'next' | 'go' | 'done';
+ };
+ alwaysEmbed?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ confirmHold?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ cursor: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ selectionStart?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ selectionEnd?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ adjustPosition?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ holdKeyboard?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ safePasswordCertPath?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ safePasswordLength?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ safePasswordTimeStamp?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ safePasswordNonce?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ safePasswordSalt?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ safePasswordCustomHash?: {
+ type: StringConstructor;
+ value?: string;
+ };
+}
+export declare type InputFormatType = (value: InputValue) => number | string;
+export declare type InputValue = string | number;
diff --git a/components/input/type.js b/components/input/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/input/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/loading/README.md b/components/loading/README.md
new file mode 100644
index 0000000..8cd1459
--- /dev/null
+++ b/components/loading/README.md
@@ -0,0 +1,70 @@
+---
+title: Loading 加载
+description: 用于表示页面或操作的加载状态,给予用户反馈的同时减缓等待的焦虑感,由一个或一组反馈动效组成。
+spline: message
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-loading": "tdesign-miniprogram/loading/loading"
+}
+```
+
+## 代码演示
+
+### 纯icon
+
+{{ base }}
+
+### icon加文字横向
+
+{{ horizontal }}
+
+### icon加文字竖向
+
+{{ vertical }}
+
+### 纯文字
+
+{{ text }}
+
+### 加载失败
+
+{{ error }}
+
+### 状态
+
+{{ status }}
+
+### 加载速度
+
+{{ duration }}
+
+### 规格
+
+{{ size }}
+
+## API
+### Loading Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+delay | Number | 0 | 延迟显示加载效果的时间,用于防止请求速度过快引起的加载闪烁,单位:毫秒 | N
+duration | Number | 800 | 加载动画执行完成一次的时间,单位:毫秒 | N
+external-classes | Array | - | 组件类名,分别用于设置加载组件外层元素,加载组件文本,加载组件指示符,加载指示符内侧同心圆等元素类名。`['t-class', 't-class-text', 't-class-indicator']` | N
+indicator | Boolean | true | 是否显示加载指示符 | N
+inherit-color | Boolean | false | 是否继承父元素颜色 | N
+layout | String | horizontal | 对齐方式。可选项:horizontal/vertical | N
+loading | Boolean | true | 是否处于加载状态 | N
+pause | Boolean | false | 是否暂停动画 | N
+progress | Number | - | 加载进度 | N
+reverse | Boolean | - | 加载动画是否反向 | N
+size | String | '40rpx' | 尺寸,示例:40rpx/20px | N
+text | String / Slot | - | 加载提示文案 | N
+theme | String | circular | 加载组件类型。可选项:circular/spinner/bar/error/dots | N
diff --git a/components/loading/index.d.ts b/components/loading/index.d.ts
new file mode 100644
index 0000000..2806bd6
--- /dev/null
+++ b/components/loading/index.d.ts
@@ -0,0 +1,3 @@
+export * from './props';
+export * from './type';
+export * from './loading';
diff --git a/components/loading/index.js b/components/loading/index.js
new file mode 100644
index 0000000..2806bd6
--- /dev/null
+++ b/components/loading/index.js
@@ -0,0 +1,3 @@
+export * from './props';
+export * from './type';
+export * from './loading';
diff --git a/components/loading/loading.d.ts b/components/loading/loading.d.ts
new file mode 100644
index 0000000..9f5f54a
--- /dev/null
+++ b/components/loading/loading.d.ts
@@ -0,0 +1,77 @@
+import { SuperComponent } from '../common/src/index';
+import type { TdLoadingProps } from './type';
+export interface LoadingProps extends TdLoadingProps {
+}
+export default class Loading extends SuperComponent {
+ externalClasses: string[];
+ data: {
+ prefix: string;
+ classPrefix: string;
+ show: boolean;
+ };
+ options: {
+ multipleSlots: boolean;
+ };
+ properties: {
+ delay?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ duration?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ["t-class", "t-class-text", "t-class-indicator"];
+ };
+ indicator?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ inheritColor?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ layout?: {
+ type: StringConstructor;
+ value?: "horizontal" | "vertical";
+ };
+ loading?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ pause?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ progress?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ reverse?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ size?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ text?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ theme?: {
+ type: StringConstructor;
+ value?: "error" | "circular" | "spinner" | "bar" | "dots";
+ };
+ };
+ timer: any;
+ observers: {
+ loading(this: any, cur: any): void;
+ };
+ lifetimes: {
+ detached(): void;
+ };
+ refreshPage(): void;
+}
diff --git a/components/loading/loading.js b/components/loading/loading.js
new file mode 100644
index 0000000..f59a423
--- /dev/null
+++ b/components/loading/loading.js
@@ -0,0 +1,61 @@
+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';
+const { prefix } = config;
+const name = `${prefix}-loading`;
+let Loading = class Loading extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.externalClasses = [`${prefix}-class`, `${prefix}-class-text`, `${prefix}-class-indicator`];
+ this.data = {
+ prefix,
+ classPrefix: name,
+ show: true,
+ };
+ this.options = {
+ multipleSlots: true,
+ };
+ this.properties = Object.assign({}, props);
+ this.timer = null;
+ this.observers = {
+ loading(cur) {
+ const { delay } = this.properties;
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ if (cur) {
+ if (delay) {
+ this.timer = setTimeout(() => {
+ this.setData({ show: cur });
+ this.timer = null;
+ }, delay);
+ }
+ else {
+ this.setData({ show: cur });
+ }
+ }
+ else {
+ this.setData({ show: cur });
+ }
+ },
+ };
+ this.lifetimes = {
+ detached() {
+ clearTimeout(this.timer);
+ },
+ };
+ }
+ refreshPage() {
+ this.triggerEvent('reload');
+ }
+};
+Loading = __decorate([
+ wxComponent()
+], Loading);
+export default Loading;
diff --git a/components/loading/loading.json b/components/loading/loading.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/components/loading/loading.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/components/loading/loading.wxml b/components/loading/loading.wxml
new file mode 100644
index 0000000..e998f4e
--- /dev/null
+++ b/components/loading/loading.wxml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 加载失败
+ 刷新
+
+
+ {{text}}
+
+
+
+
+
diff --git a/components/loading/loading.wxss b/components/loading/loading.wxss
new file mode 100644
index 0000000..3343e69
--- /dev/null
+++ b/components/loading/loading.wxss
@@ -0,0 +1,235 @@
+.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-loading {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24rpx;
+}
+.t-loading__spinner {
+ position: relative;
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ max-width: 100%;
+ max-height: 100%;
+ animation: rotate 0.8s linear infinite;
+ color: #0052d9;
+}
+.t-loading__spinner.reverse {
+ animation-name: rotateReverse;
+}
+.t-loading__spinner--spinner {
+ animation-timing-function: steps(12);
+}
+.t-loading__spinner--spinner .t-loading__dot {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+.t-loading__spinner--spinner .t-loading__dot::before {
+ display: block;
+ width: 5rpx;
+ height: 25%;
+ margin: 0 auto;
+ background-color: currentColor;
+ border-radius: 40%;
+ content: ' ';
+}
+.t-loading__spinner--circular .t-loading__circular {
+ border-radius: 100%;
+ width: 100%;
+ height: 100%;
+ background: conic-gradient(from 180deg at 50% 50%, rgba(255, 255, 255, 0) 0deg, rgba(255, 255, 255, 0) 60deg, currentColor 330deg, rgba(255, 255, 255, 0) 360deg);
+ mask: radial-gradient(transparent calc(50% - 1rpx), #fff 50%);
+ /* stylelint-disable-next-line */
+ -webkit-mask: radial-gradient(transparent calc(50% - 1rpx), #fff 50%);
+}
+.t-loading__spinner--dots {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ animation: none;
+}
+.t-loading__spinner--dots .t-loading__dot {
+ width: 20%;
+ height: 20%;
+ border-radius: 50%;
+ background-color: currentColor;
+ animation-duration: 1.8s;
+ animation-name: dotting;
+ animation-timing-function: linear;
+ animation-iteration-count: infinite;
+ animation-fill-mode: both;
+}
+.t-loading--vertical {
+ flex-direction: column;
+}
+.t-loading--vertical .t-loading__text {
+ margin-top: 12rpx;
+}
+.t-loading--horizontal {
+ flex-direction: row;
+}
+.t-loading--horizontal .t-loading__text {
+ margin-left: 16rpx;
+}
+.t-loading__refresh-btn {
+ margin-left: 16rpx;
+ color: #0052d9;
+}
+.t-loading__bar {
+ height: 6rpx;
+ width: 80%;
+ transition: 0.5s;
+ background-color: #0052d9;
+ display: none;
+}
+.t-loading__bar--static {
+ display: block;
+}
+.t-loading__bar--loaded {
+ opacity: 0;
+ height: 0;
+ animation: t-bar-loaded 1s ease-out;
+}
+.t-loading__bar--animation {
+ animation: t-bar 8s linear;
+ display: block;
+}
+@keyframes t-bar {
+ 0% {
+ width: 0;
+ }
+ 50% {
+ width: 70%;
+ }
+ 100% {
+ width: 80%;
+ }
+}
+@keyframes t-bar-loaded {
+ 0% {
+ height: 6rpx;
+ opacity: 1;
+ width: 90%;
+ }
+ 50% {
+ height: 6rpx;
+ opacity: 1;
+ width: 100%;
+ }
+ 100% {
+ height: 0;
+ opacity: 0;
+ width: 100%;
+ }
+}
+.t-loading__dot:nth-of-type(1) {
+ transform: rotate(30deg);
+ opacity: 0;
+}
+.t-loading__dot:nth-of-type(2) {
+ transform: rotate(60deg);
+ opacity: 0.08333333;
+}
+.t-loading__dot:nth-of-type(3) {
+ transform: rotate(90deg);
+ opacity: 0.16666667;
+}
+.t-loading__dot:nth-of-type(4) {
+ transform: rotate(120deg);
+ opacity: 0.25;
+}
+.t-loading__dot:nth-of-type(5) {
+ transform: rotate(150deg);
+ opacity: 0.33333333;
+}
+.t-loading__dot:nth-of-type(6) {
+ transform: rotate(180deg);
+ opacity: 0.41666667;
+}
+.t-loading__dot:nth-of-type(7) {
+ transform: rotate(210deg);
+ opacity: 0.5;
+}
+.t-loading__dot:nth-of-type(8) {
+ transform: rotate(240deg);
+ opacity: 0.58333333;
+}
+.t-loading__dot:nth-of-type(9) {
+ transform: rotate(270deg);
+ opacity: 0.66666667;
+}
+.t-loading__dot:nth-of-type(10) {
+ transform: rotate(300deg);
+ opacity: 0.75;
+}
+.t-loading__dot:nth-of-type(11) {
+ transform: rotate(330deg);
+ opacity: 0.83333333;
+}
+.t-loading__dot:nth-of-type(12) {
+ transform: rotate(360deg);
+ opacity: 0.91666667;
+}
+@keyframes rotate {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+@keyframes rotateReverse {
+ from {
+ transform: rotate(360deg);
+ }
+ to {
+ transform: rotate(0deg);
+ }
+}
+@keyframes dotting {
+ 0% {
+ opacity: 0.4;
+ }
+ 1% {
+ opacity: 0.8;
+ }
+ 33% {
+ opacity: 0.8;
+ }
+ 34% {
+ opacity: 0.4;
+ }
+ 100% {
+ opacity: 0.4;
+ }
+}
diff --git a/components/loading/props.d.ts b/components/loading/props.d.ts
new file mode 100644
index 0000000..a05a659
--- /dev/null
+++ b/components/loading/props.d.ts
@@ -0,0 +1,3 @@
+import { TdLoadingProps } from './type';
+declare const props: TdLoadingProps;
+export default props;
diff --git a/components/loading/props.js b/components/loading/props.js
new file mode 100644
index 0000000..d86ae7a
--- /dev/null
+++ b/components/loading/props.js
@@ -0,0 +1,51 @@
+const props = {
+ delay: {
+ type: Number,
+ value: 0,
+ },
+ duration: {
+ type: Number,
+ value: 800,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ indicator: {
+ type: Boolean,
+ value: true,
+ },
+ inheritColor: {
+ type: Boolean,
+ value: false,
+ },
+ layout: {
+ type: String,
+ value: 'horizontal',
+ },
+ loading: {
+ type: Boolean,
+ value: true,
+ },
+ pause: {
+ type: Boolean,
+ value: false,
+ },
+ progress: {
+ type: Number,
+ },
+ reverse: {
+ type: Boolean,
+ },
+ size: {
+ type: String,
+ value: '40rpx',
+ },
+ text: {
+ type: String,
+ },
+ theme: {
+ type: String,
+ value: 'circular',
+ },
+};
+export default props;
diff --git a/components/loading/type.d.ts b/components/loading/type.d.ts
new file mode 100644
index 0000000..5c12648
--- /dev/null
+++ b/components/loading/type.d.ts
@@ -0,0 +1,54 @@
+export interface TdLoadingProps {
+ delay?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ duration?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-text', 't-class-indicator'];
+ };
+ indicator?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ inheritColor?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ layout?: {
+ type: StringConstructor;
+ value?: 'horizontal' | 'vertical';
+ };
+ loading?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ pause?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ progress?: {
+ type: NumberConstructor;
+ value?: number;
+ };
+ reverse?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ size?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ text?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ theme?: {
+ type: StringConstructor;
+ value?: 'circular' | 'spinner' | 'bar' | 'error' | 'dots';
+ };
+}
diff --git a/components/loading/type.js b/components/loading/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/loading/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/picker/README.md b/components/picker/README.md
new file mode 100644
index 0000000..6097849
--- /dev/null
+++ b/components/picker/README.md
@@ -0,0 +1,57 @@
+---
+title: Picker 选择器
+description: 用于一组预设数据中的选择。
+spline: form
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-picker": "tdesign-miniprogram/picker/picker",
+ "t-picker-item": "tdesign-miniprogram/picker/picker-item",
+}
+```
+
+## 代码演示
+
+### 基础选择器
+
+{{ base }}
+
+## API
+### Picker Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+auto-close | Boolean | true | 自动关闭;在确认、取消、点击遮罩层自动关闭,不需要手动设置 visible | N
+cancel-btn | String / Boolean / Object | true | 取消按钮文字。TS 类型:`boolean | string | ButtonProps` | N
+columns | Array / Function | [] | 【开发中】必需。配置每一列的选项。TS 类型:`Array | ((item: Array) => Array)` `type PickerColumn = PickerColumnItem[]` `interface PickerColumnItem { label: string,value: string}`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/picker/type.ts) | Y
+confirm-btn | String / Boolean / Object | true | 确定按钮文字。TS 类型:`boolean | string | ButtonProps`,[Button API Documents](./button?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/picker/type.ts) | N
+footer | Slot | - | 底部内容 | N
+header | Boolean / Slot | true | 头部内容。值为 true 显示空白头部,值为 false 不显示任何内容,值类型为 TNode 表示自定义头部内容 | N
+render-label | String / Function | - | 【开发中】自定义label。TS 类型:`(item: PickerColumnItem) => string` | N
+title | String | '' | 标题 | N
+value | Array | - | 选中值。TS 类型:`Array` `type PickerValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/picker/type.ts) | N
+default-value | Array | undefined | 选中值。非受控属性。TS 类型:`Array` `type PickerValue = string | number`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/picker/type.ts) | N
+visible | Boolean | false | 是否显示 | N
+
+### Picker Events
+
+名称 | 参数 | 描述
+-- | -- | --
+cancel | - | 点击取消按钮时触发
+change | `(detail: { value: Array; columns: Array<{ column: number; label: string; index: number }> })` | 选中变化时候触发
+confirm | `(detail: { value: Array; columns: Array<{ column: number; label: string; index: number }> })` | 选中变化时候触发
+pick | `(detail: { value: Array; label: string; index: number; column: number;})` | 任何一列选中都会触发,不同的列参数不同。`context.column` 表示第几列变化,`context.index` 表示变化那一列的选中项下标
+
+### PickerItem Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+format | Function | - | 格式化标签。TS 类型:`(option: PickerItemOption) => string` | N
+options | Array | [] | 数据源。TS 类型:`Array` `interface PickerItemOption { label: string; value: string | number }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/picker/type.ts) | N
\ No newline at end of file
diff --git a/components/picker/picker-item-props.d.ts b/components/picker/picker-item-props.d.ts
new file mode 100644
index 0000000..1140c78
--- /dev/null
+++ b/components/picker/picker-item-props.d.ts
@@ -0,0 +1,3 @@
+import { TdPickerItemProps } from './type';
+declare const props: TdPickerItemProps;
+export default props;
diff --git a/components/picker/picker-item-props.js b/components/picker/picker-item-props.js
new file mode 100644
index 0000000..a55e0af
--- /dev/null
+++ b/components/picker/picker-item-props.js
@@ -0,0 +1,10 @@
+const props = {
+ format: {
+ type: null,
+ },
+ options: {
+ type: Array,
+ value: [],
+ },
+};
+export default props;
diff --git a/components/picker/picker-item.d.ts b/components/picker/picker-item.d.ts
new file mode 100644
index 0000000..217109c
--- /dev/null
+++ b/components/picker/picker-item.d.ts
@@ -0,0 +1,24 @@
+import { SuperComponent, RelationsOptions } from '../common/src/index';
+export default class PickerItem extends SuperComponent {
+ relations: RelationsOptions;
+ properties: import("./type").TdPickerItemProps;
+ observers: {
+ options(this: PickerItem): void;
+ };
+ data: {
+ prefix: string;
+ offset: number;
+ duration: number;
+ value: string;
+ };
+ methods: {
+ onTouchStart(event: any): void;
+ onTouchMove(event: any): void;
+ onTouchEnd(): void;
+ update(): void;
+ resetOrigin(): void;
+ getCount(): any;
+ };
+ calculateViewDeltaY(touchDeltaY: number): number;
+ created(): void;
+}
diff --git a/components/picker/picker-item.js b/components/picker/picker-item.js
new file mode 100644
index 0000000..2d9959c
--- /dev/null
+++ b/components/picker/picker-item.js
@@ -0,0 +1,110 @@
+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 './picker-item-props';
+const itemHeight = 80;
+const DefaultDuration = 240;
+const { windowWidth } = wx.getSystemInfoSync();
+const rpx2px = (rpx) => Math.floor((windowWidth * rpx) / 750);
+const range = function (num, min, max) {
+ return Math.min(Math.max(num, min), max);
+};
+let PickerItem = class PickerItem extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.relations = {
+ './picker': {
+ type: 'parent',
+ linked(parent) {
+ this.parent = parent;
+ },
+ },
+ };
+ this.properties = props;
+ this.observers = {
+ options() {
+ this.update();
+ },
+ };
+ this.data = {
+ prefix: `${config.prefix}-picker-item`,
+ offset: 0,
+ duration: 0,
+ value: '',
+ };
+ this.methods = {
+ onTouchStart(event) {
+ this.StartY = event.touches[0].clientY;
+ this.StartOffset = this.data.offset;
+ this.setData({ duration: 0 });
+ },
+ onTouchMove(event) {
+ const { StartY, StartOffset, itemHeight } = this;
+ const touchDeltaY = event.touches[0].clientY - StartY;
+ const deltaY = this.calculateViewDeltaY(touchDeltaY);
+ this.setData({
+ offset: range(StartOffset + deltaY, -(this.getCount() * itemHeight), 0),
+ duration: DefaultDuration,
+ });
+ },
+ onTouchEnd() {
+ const { offset } = this.data;
+ const { options } = this.properties;
+ if (offset === this.StartOffset) {
+ return;
+ }
+ const index = range(Math.round(-offset / this.itemHeight), 0, this.getCount() - 1);
+ this.setData({
+ offset: -index * this.itemHeight,
+ });
+ if (index === this._selectedIndex) {
+ return;
+ }
+ wx.nextTick(() => {
+ var _a, _b, _c;
+ this._selectedIndex = index;
+ this._selectedValue = (_a = options[index]) === null || _a === void 0 ? void 0 : _a.value;
+ this._selectedLabel = (_b = options[index]) === null || _b === void 0 ? void 0 : _b.label;
+ (_c = this.parent) === null || _c === void 0 ? void 0 : _c.triggerColumnChange({
+ index,
+ column: this.columnIndex || 0,
+ });
+ });
+ },
+ update() {
+ var _a, _b;
+ const { options, value } = this.data;
+ const index = options.findIndex((item) => item.value === value);
+ const selectedIndex = index > 0 ? index : 0;
+ this.setData({ offset: -selectedIndex * this.itemHeight });
+ this._selectedIndex = selectedIndex;
+ this._selectedValue = (_a = options[selectedIndex]) === null || _a === void 0 ? void 0 : _a.value;
+ this._selectedLabel = (_b = options[selectedIndex]) === null || _b === void 0 ? void 0 : _b.label;
+ },
+ resetOrigin() {
+ this.update();
+ },
+ getCount() {
+ var _a, _b;
+ return (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.length;
+ },
+ };
+ }
+ calculateViewDeltaY(touchDeltaY) {
+ return Math.abs(touchDeltaY) > itemHeight ? 1.2 * touchDeltaY : touchDeltaY;
+ }
+ created() {
+ this.StartY = 0;
+ this.StartOffset = 0;
+ this.itemHeight = rpx2px(itemHeight);
+ }
+};
+PickerItem = __decorate([
+ wxComponent()
+], PickerItem);
+export default PickerItem;
diff --git a/components/picker/picker-item.json b/components/picker/picker-item.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/components/picker/picker-item.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/components/picker/picker-item.wxml b/components/picker/picker-item.wxml
new file mode 100644
index 0000000..3a59fbd
--- /dev/null
+++ b/components/picker/picker-item.wxml
@@ -0,0 +1,16 @@
+
+
+
+ {{option.label}}
+
+
+
diff --git a/components/picker/picker-item.wxss b/components/picker/picker-item.wxss
new file mode 100644
index 0000000..78c2923
--- /dev/null
+++ b/components/picker/picker-item.wxss
@@ -0,0 +1,47 @@
+.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);
+}
+:host {
+ display: flex;
+ flex: 1;
+}
+.t-picker-item__group {
+ height: 400rpx;
+ overflow: hidden;
+ flex: 1;
+}
+.t-picker-item__wrapper {
+ padding: 160rpx 0;
+}
+.t-picker-item__item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 80rpx;
+ line-height: 80rpx;
+ color: #000;
+}
diff --git a/components/picker/picker.d.ts b/components/picker/picker.d.ts
new file mode 100644
index 0000000..b0f54a0
--- /dev/null
+++ b/components/picker/picker.d.ts
@@ -0,0 +1,30 @@
+import { SuperComponent, RelationsOptions } from '../common/src/index';
+export default class Picker extends SuperComponent {
+ properties: import("./type").TdPickerProps;
+ externalClasses: string[];
+ options: {
+ multipleSlots: boolean;
+ };
+ relations: RelationsOptions;
+ observers: {
+ value(): void;
+ };
+ data: {
+ classPrefix: string;
+ };
+ methods: {
+ getPickerColumns(): any[];
+ updateChildren(): void;
+ getSelectedValue(): any[];
+ getColumnIndexes(): any;
+ onConfirm(): void;
+ triggerColumnChange({ column, index }: {
+ column: any;
+ index: any;
+ }): void;
+ onCancel(): void;
+ onPopupChange(e: any): void;
+ close(): void;
+ };
+ ready(): void;
+}
diff --git a/components/picker/picker.js b/components/picker/picker.js
new file mode 100644
index 0000000..0f90fb2
--- /dev/null
+++ b/components/picker/picker.js
@@ -0,0 +1,108 @@
+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';
+const { prefix } = config;
+const name = `${prefix}-picker`;
+let Picker = class Picker extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.properties = props;
+ this.externalClasses = ['t-class', 't-class-confirm', 't-class-cancel', 't-class-title'];
+ this.options = {
+ multipleSlots: true,
+ };
+ this.relations = {
+ './picker-item': {
+ type: 'child',
+ linked() {
+ this.updateChildren();
+ },
+ },
+ };
+ this.observers = {
+ value() {
+ this.updateChildren();
+ },
+ };
+ this.data = {
+ classPrefix: name,
+ };
+ this.methods = {
+ getPickerColumns() {
+ const pickerColumns = this.getRelationNodes('./picker-item');
+ if (Array.isArray(pickerColumns)) {
+ return pickerColumns;
+ }
+ return [];
+ },
+ updateChildren() {
+ const { value } = this.properties;
+ const pickerColumns = this.getPickerColumns();
+ if (!(pickerColumns === null || pickerColumns === void 0 ? void 0 : pickerColumns.length)) {
+ return;
+ }
+ pickerColumns.forEach((child, index) => {
+ child.setData({
+ value: (value === null || value === void 0 ? void 0 : value[index]) || '',
+ });
+ child.update();
+ });
+ },
+ getSelectedValue() {
+ const pickerColumns = this.getPickerColumns();
+ const value = pickerColumns.map((item) => item._selectedValue);
+ const label = pickerColumns.map((item) => item._selectedLabel);
+ return [value, label];
+ },
+ getColumnIndexes() {
+ const pickerColumns = this.getPickerColumns();
+ const columns = pickerColumns.map((pickerColumn, columnIndex) => {
+ return {
+ column: columnIndex,
+ index: pickerColumn._selectedIndex,
+ };
+ });
+ return columns;
+ },
+ onConfirm() {
+ const [value, label] = this.getSelectedValue();
+ const columns = this.getColumnIndexes();
+ this.close();
+ this.triggerEvent('change', { value, label, columns });
+ this.triggerEvent('confirm', { value, label, columns });
+ },
+ triggerColumnChange({ column, index }) {
+ const [value, label] = this.getSelectedValue();
+ this.triggerEvent('pick', { value, label, column, index });
+ },
+ onCancel() {
+ this.close();
+ this.triggerEvent('cancel');
+ },
+ onPopupChange(e) {
+ const { visible } = e.detail;
+ this.close();
+ this.triggerEvent('visible-change', { visible });
+ },
+ close() {
+ if (this.data.autoClose) {
+ this.setData({ visible: false });
+ }
+ },
+ };
+ }
+ ready() {
+ const columns = this.getPickerColumns();
+ columns.map((column, index) => (column.columnIndex = index));
+ }
+};
+Picker = __decorate([
+ wxComponent()
+], Picker);
+export default Picker;
diff --git a/components/picker/picker.json b/components/picker/picker.json
new file mode 100644
index 0000000..b93d975
--- /dev/null
+++ b/components/picker/picker.json
@@ -0,0 +1,6 @@
+{
+ "component": true,
+ "usingComponents": {
+ "t-popup": "../popup/popup"
+ }
+}
diff --git a/components/picker/picker.wxml b/components/picker/picker.wxml
new file mode 100644
index 0000000..9df6181
--- /dev/null
+++ b/components/picker/picker.wxml
@@ -0,0 +1,20 @@
+
+
+
+ {{cancelBtn}}
+ {{title}}
+ {{confirmBtn}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/picker/picker.wxss b/components/picker/picker.wxss
new file mode 100644
index 0000000..5e42200
--- /dev/null
+++ b/components/picker/picker.wxss
@@ -0,0 +1,119 @@
+.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-picker {
+ position: relative;
+ background-color: #ffffff;
+ font-size: 32rpx;
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+}
+.t-picker__toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ overflow: hidden;
+ height: 96rpx;
+ box-shadow: inset 0 -1rpx 0 0 #e6e6e6;
+}
+.t-picker__title {
+ flex: 1;
+ text-align: center;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ color: #000000;
+ font-weight: 500;
+}
+.t-picker__cancel,
+.t-picker__confirm {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ user-select: none;
+ font-size: 32rpx;
+ height: 100%;
+ padding: 0 32rpx;
+}
+.t-picker__cancel {
+ color: #444444;
+}
+.t-picker__confirm {
+ color: #0052d9;
+}
+.t-picker__main {
+ position: relative;
+ display: flex;
+}
+.t-picker__mask {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0 auto;
+ z-index: 3;
+ background-image: linear-gradient(top, #fff, hsla(0, 0%, 100%, 0.4)), -webkit-linear-gradient(bottom, hsla(0, 0%, 100%, 0.92), hsla(0, 0%, 100%, 0.4));
+ background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0.92), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.92), hsla(0, 0%, 100%, 0.4));
+ background-size: 100% 160rpx;
+ background-repeat: no-repeat;
+ background-position: top, bottom;
+ transform: translateZ(0);
+ backface-visibility: hidden;
+ pointer-events: none;
+}
+.t-picker__indicator {
+ width: 100%;
+ height: 80rpx;
+ position: absolute;
+ left: 0;
+ top: 160rpx;
+ z-index: 3;
+ pointer-events: none;
+}
+.t-picker__indicator::before {
+ content: ' ';
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ height: 1rpx;
+ border-top: 1rpx solid #e6e6e6;
+ color: #e6e6e6;
+ transform-origin: 0 0;
+}
+.t-picker__indicator::after {
+ content: ' ';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ height: 1rpx;
+ transform-origin: 0 100%;
+ color: #e6e6e6;
+ border-bottom: 1rpx solid #e6e6e6;
+}
diff --git a/components/picker/props.d.ts b/components/picker/props.d.ts
new file mode 100644
index 0000000..d673411
--- /dev/null
+++ b/components/picker/props.d.ts
@@ -0,0 +1,3 @@
+import { TdPickerProps } from './type';
+declare const props: TdPickerProps;
+export default props;
diff --git a/components/picker/props.js b/components/picker/props.js
new file mode 100644
index 0000000..322e00c
--- /dev/null
+++ b/components/picker/props.js
@@ -0,0 +1,41 @@
+const props = {
+ autoClose: {
+ type: Boolean,
+ value: true,
+ },
+ cancelBtn: {
+ type: null,
+ value: true,
+ },
+ columns: {
+ type: null,
+ value: [],
+ },
+ confirmBtn: {
+ type: null,
+ value: true,
+ },
+ header: {
+ type: Boolean,
+ value: true,
+ },
+ renderLabel: {
+ type: null,
+ },
+ title: {
+ type: String,
+ value: '',
+ },
+ value: {
+ type: Array,
+ value: null,
+ },
+ defaultValue: {
+ type: Array,
+ },
+ visible: {
+ type: Boolean,
+ value: false,
+ },
+};
+export default props;
diff --git a/components/picker/type.d.ts b/components/picker/type.d.ts
new file mode 100644
index 0000000..8fae6fe
--- /dev/null
+++ b/components/picker/type.d.ts
@@ -0,0 +1,59 @@
+import { ButtonProps } from '../button/index';
+export interface TdPickerProps {
+ autoClose?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ cancelBtn?: {
+ type: null;
+ value?: boolean | string | ButtonProps;
+ };
+ columns: {
+ type: ArrayConstructor;
+ value?: Array | ((item: Array) => Array);
+ };
+ confirmBtn?: {
+ type: null;
+ value?: boolean | string | ButtonProps;
+ };
+ header?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+ renderLabel?: {
+ type: StringConstructor;
+ value?: (item: PickerColumnItem) => string;
+ };
+ title?: {
+ type: StringConstructor;
+ value?: string;
+ };
+ value?: {
+ type: ArrayConstructor;
+ value?: Array;
+ };
+ defaultValue?: {
+ type: ArrayConstructor;
+ value?: Array;
+ };
+ visible?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ };
+}
+export interface TdPickerItemProps {
+ format?: {
+ type: null;
+ value?: (option: PickerColumnItem) => string;
+ };
+ options?: {
+ type: ArrayConstructor;
+ value?: Array;
+ };
+}
+export declare type PickerColumn = PickerColumnItem[];
+export interface PickerColumnItem {
+ label: string;
+ value: string;
+}
+export declare type PickerValue = string | number;
diff --git a/components/picker/type.js b/components/picker/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/picker/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/components/textarea/README.md b/components/textarea/README.md
new file mode 100644
index 0000000..8ee4f66
--- /dev/null
+++ b/components/textarea/README.md
@@ -0,0 +1,78 @@
+---
+title: Textarea 多行文本框
+description: 用于多行文本信息输入。
+spline: form
+isComponent: true
+---
+
+


+## 引入
+
+全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
+
+```json
+"usingComponents": {
+ "t-textarea": "tdesign-miniprogram/textarea/textarea"
+}
+```
+
+## 代码演示
+
+### 基础多行文本框
+
+
+
+{{ base }}
+
+### 带标题多行文本框
+
+{{ label }}
+
+### 自动增高多行文本框
+
+{{ autoSize }}
+
+### 禁用多行文本框
+
+{{ disabled }}
+
+### 设置最大字符个数
+
+{{ maxlength }}
+
+### 设置最大字符个数,一个汉字表示两个字符
+
+{{ maxcharacter }}
+
+## 提示
+
+- 如果需要在页面中调整 `textarea` 中 `placeholder` 样式,请使用名称为`t-textarea__placeholder`的Class选择器,直接覆盖组件内部样式(注意权重)。
+
+## API
+### Textarea Props
+
+名称 | 类型 | 默认值 | 说明 | 必传
+-- | -- | -- | -- | --
+adjust-position | Boolean | true | 键盘弹起时,是否自动上推页面 | N
+autofocus | Boolean | false | 自动聚焦,拉起键盘 | N
+autosize | Boolean | false | 是否自动增高,值为 autosize 时,style.height 不生效 | N
+confirm-hold | Boolean | false | 点击键盘右下角按钮时是否保持键盘不收起点 | N
+confirm-type | String | done | 设置键盘右下角按钮的文字,仅在 type='text'时生效。可选项:send/search/next/go/done/return。TS 类型:`'send' | 'search' | 'next' | 'go' | 'done' | 'return'` | N
+disabled | Boolean | false | 是否禁用文本框 | N
+external-classes | Array | - | 组件类名,分别用于表示组件外层元素、输入框、占位符、标签名等元素类名。`['t-class', 't-class-textarea', 't-class-label']` | N
+focus | Boolean | false | 自动聚焦 | N
+label | String / Slot | - | 左侧文本 | N
+maxcharacter | Number | - | 用户最多可以输入的字符个数,一个中文汉字表示两个字符长度 | N
+maxlength | Number | - | 用户最多可以输入的字符个数 | N
+placeholder | String | undefined | 占位符 | N
+value | String | - | 文本框值 | N
+cursor-spacing | Number | - | 0 | 指定光标与键盘的距离。取textarea距离底部的距离和cursor-spacing指定的距离的最小值作为光标与键盘的距离 | N |
+### Textarea Events
+
+名称 | 参数 | 描述
+-- | -- | --
+blur | `(value: TextareaValue)` | 失去焦点时触发
+change | `(value: TextareaValue)` | 输入内容变化时触发
+enter | `(value: TextareaValue)` | 点击完成时触发
+focus | `(value: TextareaValue)` | 获得焦点时触发
+line-change | `(value: TextareaValue)` | 行高发生变化时触发
diff --git a/components/textarea/props.d.ts b/components/textarea/props.d.ts
new file mode 100644
index 0000000..83213f6
--- /dev/null
+++ b/components/textarea/props.d.ts
@@ -0,0 +1,3 @@
+import { TdTextareaProps } from './type';
+declare const props: TdTextareaProps;
+export default props;
diff --git a/components/textarea/props.js b/components/textarea/props.js
new file mode 100644
index 0000000..8fafaa0
--- /dev/null
+++ b/components/textarea/props.js
@@ -0,0 +1,51 @@
+const props = {
+ adjustPosition: {
+ type: Boolean,
+ value: true,
+ },
+ autofocus: {
+ type: Boolean,
+ value: false,
+ },
+ autosize: {
+ type: Boolean,
+ value: false,
+ },
+ confirmHold: {
+ type: Boolean,
+ value: false,
+ },
+ confirmType: {
+ type: String,
+ value: 'done',
+ },
+ disabled: {
+ type: Boolean,
+ value: false,
+ },
+ externalClasses: {
+ type: Array,
+ },
+ focus: {
+ type: Boolean,
+ value: false,
+ },
+ label: {
+ type: String,
+ },
+ maxcharacter: {
+ type: Number,
+ },
+ maxlength: {
+ type: Number,
+ },
+ placeholder: {
+ type: String,
+ value: undefined,
+ },
+ value: {
+ type: String,
+ value: null,
+ },
+};
+export default props;
diff --git a/components/textarea/textarea.d.ts b/components/textarea/textarea.d.ts
new file mode 100644
index 0000000..35d8594
--- /dev/null
+++ b/components/textarea/textarea.d.ts
@@ -0,0 +1,95 @@
+import { SuperComponent } from '../common/src/index';
+export default class Textarea extends SuperComponent {
+ options: {
+ multipleSlots: boolean;
+ };
+ behaviors: string[];
+ externalClasses: string[];
+ properties: {
+ cursorSpacing: {
+ type: NumberConstructor;
+ value: number;
+ };
+ adjustPosition?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ autofocus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ autosize?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ confirmHold?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ confirmType?: {
+ type: StringConstructor;
+ value?: "send" | "search" | "next" | "go" | "done";
+ required?: boolean;
+ };
+ disabled?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ["t-class", "t-class-textarea", "t-class-placeholder", "t-class-name"];
+ required?: boolean;
+ };
+ focus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ label?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ maxcharacter?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+ maxlength?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+ placeholder?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ value?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ };
+ data: {
+ prefix: string;
+ classPrefix: string;
+ count: number;
+ };
+ lifetimes: {
+ ready(): void;
+ };
+ methods: {
+ updateValue(value: any): void;
+ onInput(event: any): void;
+ onFocus(event: any): void;
+ onBlur(event: any): void;
+ onConfirm(event: any): void;
+ onLineChange(event: any): void;
+ };
+}
diff --git a/components/textarea/textarea.js b/components/textarea/textarea.js
new file mode 100644
index 0000000..f6f5b74
--- /dev/null
+++ b/components/textarea/textarea.js
@@ -0,0 +1,83 @@
+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 { getCharacterLength } from '../common/utils';
+const { prefix } = config;
+const name = `${prefix}-textarea`;
+let Textarea = class Textarea extends SuperComponent {
+ constructor() {
+ super(...arguments);
+ this.options = {
+ multipleSlots: true,
+ };
+ this.behaviors = ['wx://form-field'];
+ this.externalClasses = [`${prefix}-class`, `${prefix}-class-textarea`, `${prefix}-class-label`];
+ this.properties = Object.assign(Object.assign({}, props), { cursorSpacing: {
+ type: Number,
+ value: 0,
+ } });
+ this.data = {
+ prefix,
+ classPrefix: name,
+ count: 0,
+ };
+ this.lifetimes = {
+ ready() {
+ const { value } = this.properties;
+ this.updateValue(value);
+ },
+ };
+ this.methods = {
+ updateValue(value) {
+ const { maxcharacter, maxlength } = this.properties;
+ if (maxcharacter > 0 && !Number.isNaN(maxcharacter)) {
+ const { length, characters } = getCharacterLength('maxcharacter', value, maxcharacter);
+ this.setData({
+ value: characters,
+ count: length,
+ });
+ }
+ else if (maxlength > 0 && !Number.isNaN(maxlength)) {
+ const { length, characters } = getCharacterLength('maxlength', value, maxlength);
+ this.setData({
+ value: characters,
+ count: length,
+ });
+ }
+ else {
+ this.setData({
+ value,
+ count: value ? String(value).length : 0,
+ });
+ }
+ },
+ onInput(event) {
+ const { value } = event.detail;
+ this.updateValue(value);
+ this.triggerEvent('change', { value: this.data.value });
+ },
+ onFocus(event) {
+ this.triggerEvent('focus', Object.assign({}, event.detail));
+ },
+ onBlur(event) {
+ this.triggerEvent('blur', Object.assign({}, event.detail));
+ },
+ onConfirm(event) {
+ this.triggerEvent('enter', Object.assign({}, event.detail));
+ },
+ onLineChange(event) {
+ this.triggerEvent('lineChange', Object.assign({}, event.detail));
+ },
+ };
+ }
+};
+Textarea = __decorate([
+ wxComponent()
+], Textarea);
+export default Textarea;
diff --git a/components/textarea/textarea.json b/components/textarea/textarea.json
new file mode 100644
index 0000000..a89ef4d
--- /dev/null
+++ b/components/textarea/textarea.json
@@ -0,0 +1,4 @@
+{
+ "component": true,
+ "usingComponents": {}
+}
diff --git a/components/textarea/textarea.wxml b/components/textarea/textarea.wxml
new file mode 100644
index 0000000..5425b46
--- /dev/null
+++ b/components/textarea/textarea.wxml
@@ -0,0 +1,30 @@
+
+
+ {{ label }}
+
+
+
+
+
+ {{count }} / {{maxcharacter || maxlength}}
+
+
+
diff --git a/components/textarea/textarea.wxss b/components/textarea/textarea.wxss
new file mode 100644
index 0000000..992ae2c
--- /dev/null
+++ b/components/textarea/textarea.wxss
@@ -0,0 +1,81 @@
+.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-textarea {
+ position: relative;
+ background-color: #fff;
+}
+.t-textarea__name:not(:empty) {
+ position: relative;
+ padding: 24rpx 32rpx;
+ font-size: 32rpx;
+ color: #000000;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.t-textarea__name:not(:empty)::after {
+ position: absolute;
+ box-sizing: border-box;
+ content: ' ';
+ pointer-events: none;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ border-bottom: 1px solid #e6e6e6;
+ transform: scaleY(0.5);
+ left: 32rpx;
+}
+.t-textarea__wrapper {
+ padding: 24rpx 32rpx;
+ font-size: 32rpx;
+ color: #000000;
+}
+.t-textarea__wrapper-textarea {
+ display: block;
+ box-sizing: border-box;
+ width: 100%;
+ min-width: 0;
+ margin: 0;
+ padding: 0;
+ text-align: left;
+ background-color: transparent;
+ border: 0;
+ resize: none;
+ font-size: 32rpx;
+ line-height: 48rpx;
+}
+.t-textarea__placeholder,
+.t-textarea__count {
+ color: #888888;
+ font-size: 32rpx;
+ line-height: 48rpx;
+}
+.t-textarea__count {
+ font-size: 24rpx;
+ text-align: right;
+}
diff --git a/components/textarea/type.d.ts b/components/textarea/type.d.ts
new file mode 100644
index 0000000..01a8307
--- /dev/null
+++ b/components/textarea/type.d.ts
@@ -0,0 +1,67 @@
+export interface TdTextareaProps {
+ adjustPosition?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ autofocus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ autosize?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ confirmHold?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ confirmType?: {
+ type: StringConstructor;
+ value?: 'send' | 'search' | 'next' | 'go' | 'done';
+ required?: boolean;
+ };
+ disabled?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ externalClasses?: {
+ type: ArrayConstructor;
+ value?: ['t-class', 't-class-textarea', 't-class-placeholder', 't-class-name'];
+ required?: boolean;
+ };
+ focus?: {
+ type: BooleanConstructor;
+ value?: boolean;
+ required?: boolean;
+ };
+ label?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ maxcharacter?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+ maxlength?: {
+ type: NumberConstructor;
+ value?: number;
+ required?: boolean;
+ };
+ placeholder?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+ value?: {
+ type: StringConstructor;
+ value?: string;
+ required?: boolean;
+ };
+}
diff --git a/components/textarea/type.js b/components/textarea/type.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/components/textarea/type.js
@@ -0,0 +1 @@
+export {};
diff --git a/pages/foot-tab/foot-tab.js b/pages/foot-tab/foot-tab.js
index 50d834a..34fc591 100644
--- a/pages/foot-tab/foot-tab.js
+++ b/pages/foot-tab/foot-tab.js
@@ -41,7 +41,7 @@ Component({
'iconList[1]': 'star-filled'
})
wx.redirectTo({
- url: '../today/index'
+ url: '../task/index'
})
}
if (cur == 3){
diff --git a/pages/today/index.js b/pages/task/index.js
similarity index 74%
rename from pages/today/index.js
rename to pages/task/index.js
index deb7feb..1aa22b0 100644
--- a/pages/today/index.js
+++ b/pages/task/index.js
@@ -1,4 +1,4 @@
-// pages/today/index.js
+// pages/task/index.js
const app = getApp();
import ActionSheet, { ActionSheetTheme } from '../../components/action-sheet/index';
let pageStart = 1;
@@ -9,23 +9,24 @@ Page({
*/
data: {
tapCheckHandle: undefined,
+ dateVisible: true,
aIconList: ['check-rectangle', 'star-filled', 'notification', 'info-circle'],
taskList: [{'taskId':'1','title':'标题德外旗舰店1','note':'2022-11-11'},{'taskId':'2','title':'标题德外旗舰店2','note':'2022-11-11'}],
todayList: [{'taskId':'1','title':'标题德外旗舰店1','note':'2022-11-11'},{'taskId':'2','title':'标题德外旗舰店2','note':'2022-11-11'}],
- delayList: [{'taskId':'1','title':'si哦大家艾吉奥是我','note':'2022-11-11','complete':true},
- {'taskId':'2','title':'si哦大家艾吉奥是2321','note':'2022-11-11','complete':true},
- {'taskId':'3','title':'打SD卡我怕','note':'2022-11-11','complete':true},
- {'taskId':'4','title':'标无间道i文件舰店1','note':'2022-11-11','complete':true},
- {'taskId':'5','title':'标题大家啊我i家1','note':'2022-11-11','complete':false},
- {'taskId':'6','title':'标题德外而我却','note':'2022-11-11','complete':true},
- {'taskId':'7','title':'标题德外旗额我去问1','note':'2022-11-11','complete':false},
- {'taskId':'8','title':'千而万请问确京东卡来接我i的骄傲问你,我就是准备看看最棒的是的多长定德外旗舰店1','note':'2022-11-11','complete':true},
- {'taskId':'9','title':'标请问请问破千万1','note':'2022-11-11','complete':true},
- {'taskId':'10','title':'标而且我请问请问1','note':'2022-11-11','complete':true},
- {'taskId':'11','title':'代欧王大炮物品代码','note':'2022-11-11','complete':true},
- {'taskId':'12','title':'到ID我们','note':'2022-11-11','complete':true},
- {'taskId':'13','title':'我去哦额陪娃欧美大片请我们','note':'2022-11-11','complete':true},
- {'taskId':'14','title':'请问哦气雾剂群殴','note':'2022-11-11','complete':true}
+ delayList: [{'taskId':'1','title':'si哦大家艾吉奥是我','note':'2022-11-11','complete':true,'notification':false},
+ {'taskId':'2','title':'si哦大家艾吉奥是2321','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'3','title':'打SD卡我怕','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'4','title':'标无间道i文件舰店1','note':'2022-11-11','complete':true,'notification':false},
+ {'taskId':'5','title':'标题大家啊我i家1','note':'2022-11-11','complete':false,'notification':true},
+ {'taskId':'6','title':'标题德外而我却','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'7','title':'标题德外旗额我去问1','note':'2022-11-11','complete':false,'notification':true},
+ {'taskId':'8','title':'千而万请问确京东卡来接我i的骄傲问你,我就是准备看看最棒的是的多长定德外旗舰店1','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'9','title':'标请问请问破千万1','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'10','title':'标而且我请问请问1','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'11','title':'代欧王大炮物品代码','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'12','title':'到ID我们','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'13','title':'我去哦额陪娃欧美大片请我们','note':'2022-11-11','complete':true,'notification':true},
+ {'taskId':'14','title':'请问哦气雾剂群殴','note':'2022-11-11','complete':true,'notification':true}
],
duration: 300, // swiper-item 切换过渡时间
categoryCur: 0, // 当前数据列索引
@@ -123,32 +124,49 @@ Page({
this.setCurrentData(currentCur,categoryData);
},
handleAction(e) {
- console.log(e.detail);
+ let itemId = e.currentTarget.dataset.id;
+ let items = [];
+ items.push({
+ label: '配置',
+ operate: '0',
+ dataId: itemId,
+ });
+ if (e.currentTarget.dataset.notify){
+ items.push({
+ label: '取消提醒',
+ operate: '1',
+ dataId: itemId,
+ disabled: !e.currentTarget.dataset.notify,
+ });
+ }
+ items.push({
+ label: '删除',
+ operate: '2',
+ dataId: itemId,
+ color: '#e34d59',
+ });
this.data.tapCheckHandle = ActionSheet.show({
theme: ActionSheetTheme.List,
selector: '#t-action-sheet',
context: this,
- items: [
- {
- label: '详情xxx',
- },
- {
- label: '截止日期xxx',
- color: '#0052D9',
- },
- {
- label: '配置提醒',
- color: '#0052D9',
- },
- {
- label: '删除xxx',
- color: '#e34d59',
- },
- ],
+ items: items
});
},
handleSelected(e) {
- console.log(e.detail);
+ let operate = e.detail.selected.operate;
+ let dataId = e.detail.selected.dataId;
+ if (operate == 0){
+ //进入详情页面 TODO
+ wx.navigateTo({
+ url: '/pages/taskDetail/index?id=' + dataId
+ });
+ }
+ if (operate == 1){
+ //取消提醒 //TODO
+ }
+ if (operate == 2){
+ //删除 TODO
+ }
},
selectCancel() {
this.data.tapCheckHandle.close();
diff --git a/pages/today/index.json b/pages/task/index.json
similarity index 82%
rename from pages/today/index.json
rename to pages/task/index.json
index 9265f29..79e7229 100644
--- a/pages/today/index.json
+++ b/pages/task/index.json
@@ -3,6 +3,7 @@
"foot-tab": "../foot-tab/foot-tab",
"tab": "../../components/tab/index",
"scroll": "../../components/scroll/index",
- "t-action-sheet": "../../components/action-sheet/action-sheet"
+ "t-action-sheet": "../../components/action-sheet/action-sheet",
+ "t-fab": "../../components/fab/fab"
}
}
diff --git a/pages/today/index.wxml b/pages/task/index.wxml
similarity index 76%
rename from pages/today/index.wxml
rename to pages/task/index.wxml
index 49e182e..48b2fea 100644
--- a/pages/today/index.wxml
+++ b/pages/task/index.wxml
@@ -1,4 +1,4 @@
-
+
@@ -30,16 +31,20 @@
+
diff --git a/pages/today/index.wxss b/pages/task/index.wxss
similarity index 91%
rename from pages/today/index.wxss
rename to pages/task/index.wxss
index 290587c..42a6248 100644
--- a/pages/today/index.wxss
+++ b/pages/task/index.wxss
@@ -1,4 +1,4 @@
-/* pages/today/index.wxss */
+/* pages/task/index.wxss */
.top-wrap {
position: fixed;
left: 0;
@@ -40,6 +40,7 @@ checkbox {
.cell .remark {
display: flex;
+ align-items:center;
color: #999999;
}
@@ -47,7 +48,3 @@ checkbox {
text-decoration:line-through;
}
-.note {
- font-size: 28rpx;
-}
-
diff --git a/pages/taskDetail/index.js b/pages/taskDetail/index.js
new file mode 100644
index 0000000..7d64a20
--- /dev/null
+++ b/pages/taskDetail/index.js
@@ -0,0 +1,52 @@
+let taskId = '';
+Page({
+ data: {
+ mode: '',
+ dateVisible: false,
+ date: new Date('2021-12-23').getTime(), // 支持时间戳传入
+ dateText: '',
+ // 指定选择区间起始值
+ start: '2008-01-01 00:00:00',
+ end: '2040-12-31 23:59:59',
+ },
+ onLoad: function (options) {
+ taskId = options.id;
+ },
+
+ onShow() {
+
+ },
+
+ showPicker(e) {
+ const { mode } = e?.currentTarget?.dataset;
+ this.setData({
+ mode,
+ [`${mode}Visible`]: true,
+ });
+ },
+ hidePicker() {
+ const { mode } = this.data;
+ this.setData({
+ [`${mode}Visible`]: false,
+ });
+ },
+ onConfirm(e) {
+ const { value } = e?.detail;
+ const { mode } = this.data;
+
+ console.log('confim', value);
+
+ this.setData({
+ [mode]: value,
+ [`${mode}Text`]: value,
+ });
+
+ this.hidePicker();
+ },
+
+ onColumnChange(e) {
+ console.log('pick', e?.detail?.value);
+ },
+
+
+});
diff --git a/pages/taskDetail/index.json b/pages/taskDetail/index.json
new file mode 100644
index 0000000..1155386
--- /dev/null
+++ b/pages/taskDetail/index.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {
+ "t-date-time-picker": "../../components/date-time-picker/date-time-picker"
+ }
+}
diff --git a/pages/taskDetail/index.wxml b/pages/taskDetail/index.wxml
new file mode 100644
index 0000000..c60d6df
--- /dev/null
+++ b/pages/taskDetail/index.wxml
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/pages/taskDetail/index.wxss b/pages/taskDetail/index.wxss
new file mode 100644
index 0000000..e8a484a
--- /dev/null
+++ b/pages/taskDetail/index.wxss
@@ -0,0 +1,18 @@
+.pannel-item {
+ font-size: 32rpx;
+ margin-bottom: 32rpx;
+}
+
+.pannel-item::after {
+ border: 0;
+}
+
+.sub-text {
+ color: #000;
+ opacity: 0.9;
+}
+
+.empty {
+ color: #000;
+ opacity: 0.32;
+}