From 4956ed2f1f875ce212cdd0aac34eb020be703dd4 Mon Sep 17 00:00:00 2001 From: limqhz Date: Thu, 10 Nov 2022 17:13:00 +0800 Subject: [PATCH] project init --- .eslintrc.js | 31 + app.js | 19 + app.json | 21 + app.wxss | 10 + components/badge/README.md | 56 ++ components/badge/badge.d.ts | 15 + components/badge/badge.js | 29 + components/badge/badge.json | 5 + components/badge/badge.wxml | 15 + components/badge/badge.wxs | 69 ++ components/badge/badge.wxss | 97 +++ components/badge/index.d.ts | 3 + components/badge/index.js | 3 + components/badge/props.d.ts | 3 + components/badge/props.js | 42 + components/badge/type.d.ts | 53 ++ components/badge/type.js | 2 + components/common/common.d.ts | 34 + components/common/common.js | 1 + components/common/component.d.ts | 3 + components/common/component.js | 5 + components/common/config.d.ts | 4 + components/common/config.js | 3 + components/common/index.wxss | 27 + components/common/shared/calendar/index.d.ts | 19 + components/common/shared/calendar/index.js | 128 +++ components/common/shared/calendar/type.d.ts | 11 + components/common/shared/calendar/type.js | 1 + components/common/shared/date.d.ts | 21 + components/common/shared/date.js | 41 + components/common/src/control.d.ts | 15 + components/common/src/control.js | 40 + components/common/src/flatTool.d.ts | 15 + components/common/src/flatTool.js | 57 ++ components/common/src/index.d.ts | 4 + components/common/src/index.js | 4 + .../common/src/instantiationDecorator.d.ts | 3 + .../common/src/instantiationDecorator.js | 98 +++ components/common/src/superComponent.d.ts | 19 + components/common/src/superComponent.js | 5 + components/common/style/_variables.wxss | 0 components/common/style/base.wxss | 0 components/common/style/index.wxss | 27 + components/common/style/mixins/_clearfix.wxss | 0 components/common/style/mixins/_ellipsis.wxss | 0 components/common/style/mixins/_hairline.wxss | 0 components/common/style/mixins/_index.wxss | 0 components/common/style/theme/_index.wxss | 0 .../common/style/utilities/_animation.wxss | 8 + components/common/style/utilities/_float.wxss | 6 + components/common/style/utilities/_index.wxss | 27 + components/common/template/button.wxml | 34 + components/common/utils.d.ts | 19 + components/common/utils.js | 143 ++++ components/common/utils.wxs | 39 + components/common/version.d.ts | 1 + components/common/version.js | 37 + components/icon/README.md | 89 ++ components/icon/icon.d.ts | 19 + components/icon/icon.js | 51 ++ components/icon/icon.json | 4 + components/icon/icon.wxml | 6 + components/icon/icon.wxss | 770 ++++++++++++++++++ components/icon/props.d.ts | 3 + components/icon/props.js | 24 + components/icon/type.d.ts | 27 + components/icon/type.js | 1 + components/tab-bar/README.en-US.md | 29 + components/tab-bar/README.md | 85 ++ components/tab-bar/props.d.ts | 3 + components/tab-bar/props.js | 30 + components/tab-bar/tab-bar-item-props.d.ts | 3 + components/tab-bar/tab-bar-item-props.js | 16 + components/tab-bar/tab-bar-item.d.ts | 28 + components/tab-bar/tab-bar-item.js | 92 +++ components/tab-bar/tab-bar-item.json | 7 + components/tab-bar/tab-bar-item.wxml | 44 + components/tab-bar/tab-bar-item.wxss | 158 ++++ components/tab-bar/tab-bar.d.ts | 26 + components/tab-bar/tab-bar.js | 84 ++ components/tab-bar/tab-bar.json | 6 + components/tab-bar/tab-bar.wxml | 5 + components/tab-bar/tab-bar.wxss | 60 ++ components/tab-bar/type.d.ts | 53 ++ components/tab-bar/type.js | 1 + pages/foot-tab/foot-tab.js | 57 ++ pages/foot-tab/foot-tab.json | 7 + pages/foot-tab/foot-tab.wxml | 7 + pages/foot-tab/foot-tab.wxss | 1 + pages/index/index.js | 48 ++ pages/index/index.json | 5 + pages/index/index.wxml | 26 + pages/index/index.wxss | 19 + pages/logs/logs.js | 18 + pages/logs/logs.json | 4 + pages/logs/logs.wxml | 6 + pages/logs/logs.wxss | 8 + pages/message/index.js | 66 ++ pages/message/index.json | 5 + pages/message/index.wxml | 5 + pages/message/index.wxss | 1 + pages/myself/index.js | 66 ++ pages/myself/index.json | 5 + pages/myself/index.wxml | 5 + pages/myself/index.wxss | 1 + pages/today/index.js | 66 ++ pages/today/index.json | 5 + pages/today/index.wxml | 5 + pages/today/index.wxss | 1 + project.config.json | 51 ++ project.private.config.json | 7 + sitemap.json | 7 + utils/util.js | 19 + 113 files changed, 3617 insertions(+) create mode 100644 .eslintrc.js create mode 100644 app.js create mode 100644 app.json create mode 100644 app.wxss create mode 100644 components/badge/README.md create mode 100644 components/badge/badge.d.ts create mode 100644 components/badge/badge.js create mode 100644 components/badge/badge.json create mode 100644 components/badge/badge.wxml create mode 100644 components/badge/badge.wxs create mode 100644 components/badge/badge.wxss create mode 100644 components/badge/index.d.ts create mode 100644 components/badge/index.js create mode 100644 components/badge/props.d.ts create mode 100644 components/badge/props.js create mode 100644 components/badge/type.d.ts create mode 100644 components/badge/type.js create mode 100644 components/common/common.d.ts create mode 100644 components/common/common.js create mode 100644 components/common/component.d.ts create mode 100644 components/common/component.js create mode 100644 components/common/config.d.ts create mode 100644 components/common/config.js create mode 100644 components/common/index.wxss create mode 100644 components/common/shared/calendar/index.d.ts create mode 100644 components/common/shared/calendar/index.js create mode 100644 components/common/shared/calendar/type.d.ts create mode 100644 components/common/shared/calendar/type.js create mode 100644 components/common/shared/date.d.ts create mode 100644 components/common/shared/date.js create mode 100644 components/common/src/control.d.ts create mode 100644 components/common/src/control.js create mode 100644 components/common/src/flatTool.d.ts create mode 100644 components/common/src/flatTool.js create mode 100644 components/common/src/index.d.ts create mode 100644 components/common/src/index.js create mode 100644 components/common/src/instantiationDecorator.d.ts create mode 100644 components/common/src/instantiationDecorator.js create mode 100644 components/common/src/superComponent.d.ts create mode 100644 components/common/src/superComponent.js create mode 100644 components/common/style/_variables.wxss create mode 100644 components/common/style/base.wxss create mode 100644 components/common/style/index.wxss create mode 100644 components/common/style/mixins/_clearfix.wxss create mode 100644 components/common/style/mixins/_ellipsis.wxss create mode 100644 components/common/style/mixins/_hairline.wxss create mode 100644 components/common/style/mixins/_index.wxss create mode 100644 components/common/style/theme/_index.wxss create mode 100644 components/common/style/utilities/_animation.wxss create mode 100644 components/common/style/utilities/_float.wxss create mode 100644 components/common/style/utilities/_index.wxss create mode 100644 components/common/template/button.wxml create mode 100644 components/common/utils.d.ts create mode 100644 components/common/utils.js create mode 100644 components/common/utils.wxs create mode 100644 components/common/version.d.ts create mode 100644 components/common/version.js create mode 100644 components/icon/README.md create mode 100644 components/icon/icon.d.ts create mode 100644 components/icon/icon.js create mode 100644 components/icon/icon.json create mode 100644 components/icon/icon.wxml create mode 100644 components/icon/icon.wxss create mode 100644 components/icon/props.d.ts create mode 100644 components/icon/props.js create mode 100644 components/icon/type.d.ts create mode 100644 components/icon/type.js create mode 100644 components/tab-bar/README.en-US.md create mode 100644 components/tab-bar/README.md create mode 100644 components/tab-bar/props.d.ts create mode 100644 components/tab-bar/props.js create mode 100644 components/tab-bar/tab-bar-item-props.d.ts create mode 100644 components/tab-bar/tab-bar-item-props.js create mode 100644 components/tab-bar/tab-bar-item.d.ts create mode 100644 components/tab-bar/tab-bar-item.js create mode 100644 components/tab-bar/tab-bar-item.json create mode 100644 components/tab-bar/tab-bar-item.wxml create mode 100644 components/tab-bar/tab-bar-item.wxss create mode 100644 components/tab-bar/tab-bar.d.ts create mode 100644 components/tab-bar/tab-bar.js create mode 100644 components/tab-bar/tab-bar.json create mode 100644 components/tab-bar/tab-bar.wxml create mode 100644 components/tab-bar/tab-bar.wxss create mode 100644 components/tab-bar/type.d.ts create mode 100644 components/tab-bar/type.js create mode 100644 pages/foot-tab/foot-tab.js create mode 100644 pages/foot-tab/foot-tab.json create mode 100644 pages/foot-tab/foot-tab.wxml create mode 100644 pages/foot-tab/foot-tab.wxss create mode 100644 pages/index/index.js create mode 100644 pages/index/index.json create mode 100644 pages/index/index.wxml create mode 100644 pages/index/index.wxss create mode 100644 pages/logs/logs.js create mode 100644 pages/logs/logs.json create mode 100644 pages/logs/logs.wxml create mode 100644 pages/logs/logs.wxss create mode 100644 pages/message/index.js create mode 100644 pages/message/index.json create mode 100644 pages/message/index.wxml create mode 100644 pages/message/index.wxss create mode 100644 pages/myself/index.js create mode 100644 pages/myself/index.json create mode 100644 pages/myself/index.wxml create mode 100644 pages/myself/index.wxss create mode 100644 pages/today/index.js create mode 100644 pages/today/index.json create mode 100644 pages/today/index.wxml create mode 100644 pages/today/index.wxss create mode 100644 project.config.json create mode 100644 project.private.config.json create mode 100644 sitemap.json create mode 100644 utils/util.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..115cc02 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,31 @@ +/* + * Eslint config file + * Documentation: https://eslint.org/docs/user-guide/configuring/ + * Install the Eslint extension before using this feature. + */ +module.exports = { + env: { + es6: true, + browser: true, + node: true, + }, + ecmaFeatures: { + modules: true, + }, + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + globals: { + wx: true, + App: true, + Page: true, + getCurrentPages: true, + getApp: true, + Component: true, + requirePlugin: true, + requireMiniProgram: true, + }, + // extends: 'eslint:recommended', + rules: {}, +} diff --git a/app.js b/app.js new file mode 100644 index 0000000..1ed57c4 --- /dev/null +++ b/app.js @@ -0,0 +1,19 @@ +// app.js +App({ + onLaunch() { + // 展示本地存储能力 + const logs = wx.getStorageSync('logs') || [] + logs.unshift(Date.now()) + wx.setStorageSync('logs', logs) + + // 登录 + wx.login({ + success: res => { + // 发送 res.code 到后台换取 openId, sessionKey, unionId + } + }) + }, + globalData: { + userInfo: null + } +}) diff --git a/app.json b/app.json new file mode 100644 index 0000000..f289833 --- /dev/null +++ b/app.json @@ -0,0 +1,21 @@ +{ + "pages": [ + "pages/index/index", + "pages/logs/logs", + "pages/myself/index", + "pages/today/index", + "pages/message/index" + ], + "usingComponents": { + "t-tab-bar": "/components/tab-bar/tab-bar", + "t-tab-bar-item": "/components/tab-bar/tab-bar-item" + }, + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "奎因清单", + "navigationBarTextStyle": "black" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} \ No newline at end of file diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..06c6fc9 --- /dev/null +++ b/app.wxss @@ -0,0 +1,10 @@ +/**app.wxss**/ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} diff --git a/components/badge/README.md b/components/badge/README.md new file mode 100644 index 0000000..e48c861 --- /dev/null +++ b/components/badge/README.md @@ -0,0 +1,56 @@ +--- +title: Badge 徽标 +description: 用于告知用户,该区域的状态变化或者待处理任务的数量。 +spline: data +isComponent: true +--- + + +## 引入 + +全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 + +```json +"usingComponents": { + "t-badge": "tdesign-miniprogram/badge/badge" +} +``` + +## 代码演示 + +### 普通徽标 + + + +{{ base }} + +### 按钮徽标 + +{{ button }} + +### 单行徽标 + +{{ cell }} + +### 标签栏徽标 + + + +{{ tab-item }} + +## API + +### Badge Props + +| 名称 | 类型 | 默认值 | 说明 | 必传 | +| ---------------- | ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------- | -------- | +| color | String | - | 颜色 | N | +| content | String | - | 徽标内容,示例:`content='自定义内容'`。也可以使用默认插槽定义 | N | +| count | String / Number / Slot | 0 | 徽标右上角内容。可以是数字,也可以是文字。如:'new'/3/99+。特殊:值为空表示使用插槽渲染 | N | +| dot | Boolean | false | 是否为红点 | N | +| external-classes | Array | - | 组件类名,分别用于设置外层元素、默认内容、右上角内容等元素类名。`['t-class', 't-class-content', 't-class-count']` | N | +| max-count | Number | 99 | 封顶的数字值 | N | +| offset | Array | - | 设置状态点的位置偏移,示例:[-10, 20] 或 ['10em', '8rem']。TS 类型:`Array` | N | +| shape | String | circle | 形状。可选项:circle/square/round/ribbon | N | +| show-zero | Boolean | false | 当数值为 0 时,是否展示徽标 | N | +| size | String | medium | 尺寸。可选项:small/medium | N | diff --git a/components/badge/badge.d.ts b/components/badge/badge.d.ts new file mode 100644 index 0000000..e25ad3d --- /dev/null +++ b/components/badge/badge.d.ts @@ -0,0 +1,15 @@ +import { SuperComponent } from '../common/src/index'; +import type { TdBadgeProps } from './type'; +export interface BadgeProps extends TdBadgeProps { +} +export default class Badge extends SuperComponent { + options: { + multipleSlots: boolean; + }; + externalClasses: string[]; + properties: TdBadgeProps; + data: { + classPrefix: string; + value: string; + }; +} diff --git a/components/badge/badge.js b/components/badge/badge.js new file mode 100644 index 0000000..0918f85 --- /dev/null +++ b/components/badge/badge.js @@ -0,0 +1,29 @@ +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}-badge`; +let Badge = class Badge extends SuperComponent { + constructor() { + super(...arguments); + this.options = { + multipleSlots: true, + }; + this.externalClasses = [`${prefix}-class`, `${prefix}-class-count`, `${prefix}-class-content`]; + this.properties = props; + this.data = { + classPrefix: name, + value: '', + }; + } +}; +Badge = __decorate([ + wxComponent() +], Badge); +export default Badge; diff --git a/components/badge/badge.json b/components/badge/badge.json new file mode 100644 index 0000000..a7a3e7a --- /dev/null +++ b/components/badge/badge.json @@ -0,0 +1,5 @@ +{ + "component": true, + "usingComponents": {} +} + diff --git a/components/badge/badge.wxml b/components/badge/badge.wxml new file mode 100644 index 0000000..1ea7666 --- /dev/null +++ b/components/badge/badge.wxml @@ -0,0 +1,15 @@ + + + + + + {{content}} + + {{ this.getBadgeValue({dot, count, maxCount}) }} + + + diff --git a/components/badge/badge.wxs b/components/badge/badge.wxs new file mode 100644 index 0000000..3b403be --- /dev/null +++ b/components/badge/badge.wxs @@ -0,0 +1,69 @@ +var getBadgeValue = function (props) { + if (props.dot) { + return ''; + } + if (isNaN(props.count) || isNaN(props.maxCount)) { + return props.count; + } + return parseInt(props.count) > props.maxCount ? props.maxCount + '+' : props.count; +}; + +var hasUnit = function (unit) { + return ( + unit.indexOf('px') > 0 || + unit.indexOf('rpx') > 0 || + unit.indexOf('em') > 0 || + unit.indexOf('rem') > 0 || + unit.indexOf('%') > 0 || + unit.indexOf('vh') > 0 || + unit.indexOf('vm') > 0 + ); +}; + +var getBadgeStyles = function (props) { + var styleStr = ''; + if (props.color) { + styleStr += 'background:' + props.color + ';'; + } + if (props.offset[0]) { + styleStr += 'top:' + (hasUnit(props.offset[0].toString()) ? props.offset[0] : props.offset[0] + 'px') + ';'; + } + if (props.offset[1]) { + styleStr += 'right:' + (hasUnit(props.offset[1].toString()) ? props.offset[1] : props.offset[1] + 'px') + ';'; + } + return styleStr; +}; + +var getBadgeOuterClass = function (props) { + var baseClass = 't-badge'; + var classNames = [baseClass, props.shape === 'ribbon' ? baseClass + '__ribbon--outer' : '']; + return classNames.join(' '); +}; + +var getBadgeInnerClass = function (props) { + var baseClass = 't-badge'; + var classNames = [ + baseClass + '--basic', + props.dot ? baseClass + '--dot' : '', + props.size === 'small' ? baseClass + '--small' : '', + baseClass + '--' + props.shape, + !props.dot && props.count ? baseClass + '--count' : '', + ]; + return classNames.join(' '); +}; + +var isShowBadge = function (props) { + if (props.dot) { + return true; + } + if (!props.showZero && !isNaN(props.count) && parseInt(props.count) === 0) { + return false; + } + return true; +}; + +module.exports.getBadgeValue = getBadgeValue; +module.exports.getBadgeStyles = getBadgeStyles; +module.exports.getBadgeOuterClass = getBadgeOuterClass; +module.exports.getBadgeInnerClass = getBadgeInnerClass; +module.exports.isShowBadge = isShowBadge; diff --git a/components/badge/badge.wxss b/components/badge/badge.wxss new file mode 100644 index 0000000..1302525 --- /dev/null +++ b/components/badge/badge.wxss @@ -0,0 +1,97 @@ +.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-badge { + position: relative; + display: inline-block; +} +.t-badge--basic { + display: inline-block; + z-index: 100; + font-size: 20rpx; + color: #fff; + background-color: #e34d59; + height: 32rpx; + padding: 0 8rpx; + text-align: center; + line-height: 32rpx; + font-weight: normal; +} +.t-badge--dot { + height: 20rpx; + border-radius: 8rpx; + min-width: 20rpx; + padding: 0; +} +.t-badge--count { + min-width: 32rpx; + white-space: nowrap; + box-sizing: border-box; +} +.t-badge--small { + transform: translate(50%, -50%) scale(0.75); +} +.t-badge--circle { + border-radius: 32rpx; +} +.t-badge--round { + border-radius: 8rpx; +} +.t-badge__ribbon--outer { + position: absolute; + top: 0; + right: 0; +} +.t-badge--ribbon { + transform: rotate(45deg); +} +.t-badge--ribbon::before { + content: ''; + position: absolute; + width: 0; + height: 0; + bottom: 0; + left: -32rpx; + border-bottom: 32rpx solid #e34d59; + border-left: 32rpx solid transparent; +} +.t-badge--ribbon::after { + content: ''; + position: absolute; + width: 0; + height: 0; + bottom: 0; + right: -32rpx; + border-bottom: 32rpx solid #e34d59; + border-right: 32rpx solid transparent; +} +.t-badge__content:not(:empty) + .t-has-count { + transform: translate(50%, -50%); + position: absolute; + right: 0; + top: 0; +} diff --git a/components/badge/index.d.ts b/components/badge/index.d.ts new file mode 100644 index 0000000..85b119a --- /dev/null +++ b/components/badge/index.d.ts @@ -0,0 +1,3 @@ +export * from './type'; +export * from './props'; +export * from './badge'; diff --git a/components/badge/index.js b/components/badge/index.js new file mode 100644 index 0000000..85b119a --- /dev/null +++ b/components/badge/index.js @@ -0,0 +1,3 @@ +export * from './type'; +export * from './props'; +export * from './badge'; diff --git a/components/badge/props.d.ts b/components/badge/props.d.ts new file mode 100644 index 0000000..e1702ff --- /dev/null +++ b/components/badge/props.d.ts @@ -0,0 +1,3 @@ +import { TdBadgeProps } from './type'; +declare const props: TdBadgeProps; +export default props; diff --git a/components/badge/props.js b/components/badge/props.js new file mode 100644 index 0000000..bafd0f1 --- /dev/null +++ b/components/badge/props.js @@ -0,0 +1,42 @@ +const props = { + color: { + type: String, + value: '', + }, + content: { + type: String, + value: '', + }, + count: { + type: String, + optionalTypes: [Number], + value: 0, + }, + dot: { + type: Boolean, + value: false, + }, + externalClasses: { + type: Array, + }, + maxCount: { + type: Number, + value: 99, + }, + offset: { + type: Array, + }, + shape: { + type: String, + value: 'circle', + }, + showZero: { + type: Boolean, + value: false, + }, + size: { + type: String, + value: 'medium', + }, +}; +export default props; diff --git a/components/badge/type.d.ts b/components/badge/type.d.ts new file mode 100644 index 0000000..f9d8914 --- /dev/null +++ b/components/badge/type.d.ts @@ -0,0 +1,53 @@ +export interface TdBadgeProps { + color?: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + content?: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + count?: { + type: StringConstructor; + optionalTypes: Array; + value?: string | number; + required?: boolean; + }; + dot?: { + type: BooleanConstructor; + value?: boolean; + required?: boolean; + }; + externalClasses?: { + type: ArrayConstructor; + value?: ['t-class', 't-class-content', 't-class-count']; + required?: boolean; + }; + maxCount?: { + type: NumberConstructor; + value?: number; + required?: boolean; + }; + offset?: { + type: ArrayConstructor; + value?: Array; + required?: boolean; + }; + shape?: { + type: StringConstructor; + value?: 'circle' | 'square' | 'round' | 'ribbon'; + required?: boolean; + }; + showZero?: { + type: BooleanConstructor; + value?: boolean; + required?: boolean; + }; + size?: { + type: StringConstructor; + value?: 'small' | 'medium'; + required?: boolean; + }; +} diff --git a/components/badge/type.js b/components/badge/type.js new file mode 100644 index 0000000..95da36c --- /dev/null +++ b/components/badge/type.js @@ -0,0 +1,2 @@ +; +export {}; diff --git a/components/common/common.d.ts b/components/common/common.d.ts new file mode 100644 index 0000000..9a0f207 --- /dev/null +++ b/components/common/common.d.ts @@ -0,0 +1,34 @@ +export declare type Classes = Array; +export interface Styles { + [css: string]: string | number; +} +export declare type OptionData = { + label?: string; + value?: string | number; +} & { + [key: string]: any; +}; +export declare type TreeOptionData = { + children?: Array; +} & OptionData; +export declare type SizeEnum = 'small' | 'medium' | 'large'; +export declare type HorizontalAlignEnum = 'left' | 'center' | 'right'; +export declare type VerticalAlignEnum = 'top' | 'middle' | 'bottom'; +export declare type ClassName = { + [className: string]: any; +} | ClassName[] | string; +export declare type CSSSelector = string; +export interface KeysType { + value?: string; + label?: string; +} +export interface HTMLElementAttributes { + [css: string]: string; +} +export interface TScroll { + bufferSize?: number; + isFixedRowHeight?: boolean; + rowHeight?: number; + threshold?: number; + type: 'lazy' | 'virtual'; +} diff --git a/components/common/common.js b/components/common/common.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/common/common.js @@ -0,0 +1 @@ +export {}; diff --git a/components/common/component.d.ts b/components/common/component.d.ts new file mode 100644 index 0000000..a8d86ae --- /dev/null +++ b/components/common/component.d.ts @@ -0,0 +1,3 @@ +/// +declare const TComponent: typeof Component; +export default TComponent; diff --git a/components/common/component.js b/components/common/component.js new file mode 100644 index 0000000..4e01a69 --- /dev/null +++ b/components/common/component.js @@ -0,0 +1,5 @@ +const TComponent = (options) => { + options.options = Object.assign({ multipleSlots: true, addGlobalClass: true }, options.options); + return Component(options); +}; +export default TComponent; diff --git a/components/common/config.d.ts b/components/common/config.d.ts new file mode 100644 index 0000000..796377e --- /dev/null +++ b/components/common/config.d.ts @@ -0,0 +1,4 @@ +declare const _default: { + prefix: string; +}; +export default _default; diff --git a/components/common/config.js b/components/common/config.js new file mode 100644 index 0000000..063fdb8 --- /dev/null +++ b/components/common/config.js @@ -0,0 +1,3 @@ +export default { + prefix: "t", +}; diff --git a/components/common/index.wxss b/components/common/index.wxss new file mode 100644 index 0000000..1d532d2 --- /dev/null +++ b/components/common/index.wxss @@ -0,0 +1,27 @@ +.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); +} diff --git a/components/common/shared/calendar/index.d.ts b/components/common/shared/calendar/index.d.ts new file mode 100644 index 0000000..880b456 --- /dev/null +++ b/components/common/shared/calendar/index.d.ts @@ -0,0 +1,19 @@ +import type { TDate, TCalendarType } from './type'; +export default class TCalendar { + firstDayOfWeek: number; + value: TDate; + type: TCalendarType; + minDate: Date; + maxDate: Date; + format: (day: TDate) => TDate; + constructor(options: any); + getTrimValue(): Date | Date[]; + getDays(): any[]; + getMonths(): any[]; + select({ cellType, year, month, date }: { + cellType: any; + year: any; + month: any; + date: any; + }): Date | Date[]; +} diff --git a/components/common/shared/calendar/index.js b/components/common/shared/calendar/index.js new file mode 100644 index 0000000..6630a67 --- /dev/null +++ b/components/common/shared/calendar/index.js @@ -0,0 +1,128 @@ +import { getDateRect, isSameDate, getMonthDateRect, isValidDate, getDate } from '../date'; +export default class TCalendar { + constructor(options) { + this.type = 'single'; + Object.assign(this, options); + if (!this.minDate) + this.minDate = getDate(); + if (!this.maxDate) + this.maxDate = getDate(6); + } + getTrimValue() { + const { value, type } = this; + const format = (val) => { + if (val instanceof Date) + return val; + if (typeof val === 'number') + return new Date(val); + return new Date(); + }; + if (type === 'single') + return isValidDate(value) ? format(value) : new Date(); + if (type === 'multiple' || type === 'range') { + if (Array.isArray(value)) { + const isValid = value.every((item) => isValidDate(item)); + return isValid ? value.map((item) => format(item)) : []; + } + return []; + } + } + getDays() { + const raw = '日一二三四五六'; + const ans = []; + let i = this.firstDayOfWeek % 7; + while (ans.length < 7) { + ans.push(raw[i]); + i = (i + 1) % 7; + } + return ans; + } + getMonths() { + const ans = []; + const selectedDate = this.getTrimValue(); + const { minDate, maxDate, type, format } = this; + let { year: minYear, month: minMonth, time: minTime } = getDateRect(minDate); + const { year: maxYear, month: maxMonth, time: maxTime } = getDateRect(maxDate); + const calcType = (year, month, date) => { + const curDate = new Date(year, month, date, 23, 59, 59); + if (type === 'single') { + if (isSameDate({ year, month, date }, selectedDate)) + return 'selected'; + } + if (type === 'multiple') { + const hit = selectedDate.some((item) => isSameDate({ year, month, date }, item)); + if (hit) { + return 'selected'; + } + } + if (type === 'range') { + if (Array.isArray(selectedDate)) { + const [startDate, endDate] = selectedDate; + if (startDate && isSameDate({ year, month, date }, startDate)) + return 'start'; + if (endDate && isSameDate({ year, month, date }, endDate)) + return 'end'; + if (startDate && endDate && curDate.getTime() > startDate.getTime() && curDate.getTime() < endDate.getTime()) + return 'centre'; + } + } + const minCurDate = new Date(year, month, date, 0, 0, 0); + if (curDate.getTime() < minTime || minCurDate.getTime() > maxTime) { + return 'disabled'; + } + return ''; + }; + while (minYear < maxYear || (minYear === maxYear && minMonth <= maxMonth)) { + const target = getMonthDateRect(new Date(minYear, minMonth, 1)); + const months = []; + for (let i = 1; i <= 31; i++) { + if (i > target.lastDate) + break; + const dateObj = { + date: new Date(minYear, minMonth, i), + day: i, + type: calcType(minYear, minMonth, i), + }; + months.push(format ? format(dateObj) : dateObj); + } + ans.push({ + year: minYear, + month: minMonth, + months, + weekdayOfFirstDay: target.weekdayOfFirstDay, + }); + const curDate = getDateRect(new Date(minYear, minMonth + 1, 1)); + minYear = curDate.year; + minMonth = curDate.month; + } + return ans; + } + select({ cellType, year, month, date }) { + const { type } = this; + const selectedDate = this.getTrimValue(); + if (cellType === 'disabled') + return; + const selected = new Date(year, month, date); + if (type === 'range' && Array.isArray(selectedDate)) { + if (selectedDate.length === 1) { + if (selectedDate[0] > selected) { + return [selected]; + } + return [selectedDate[0], selected]; + } + return [selected]; + } + else if (type === 'multiple' && Array.isArray(selectedDate)) { + const newVal = [...selectedDate]; + const index = selectedDate.findIndex((item) => isSameDate(item, selected)); + if (index > -1) { + newVal.splice(index, 1); + } + else { + newVal.push(selected); + } + return newVal; + } + return selected; + } +} diff --git a/components/common/shared/calendar/type.d.ts b/components/common/shared/calendar/type.d.ts new file mode 100644 index 0000000..621b949 --- /dev/null +++ b/components/common/shared/calendar/type.d.ts @@ -0,0 +1,11 @@ +export interface TDate { + date: Date; + day: number; + type: TDateType; + className?: string; + prefix?: string; + suffix?: string; +} +export declare type TCalendarValue = number | Date; +export declare type TDateType = 'selected' | 'disabled' | 'start' | 'centre' | 'end' | ''; +export declare type TCalendarType = 'single' | 'multiple' | 'range'; diff --git a/components/common/shared/calendar/type.js b/components/common/shared/calendar/type.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/common/shared/calendar/type.js @@ -0,0 +1 @@ +export {}; diff --git a/components/common/shared/date.d.ts b/components/common/shared/date.d.ts new file mode 100644 index 0000000..e123831 --- /dev/null +++ b/components/common/shared/date.d.ts @@ -0,0 +1,21 @@ +export declare type CompareDate = Date | number | { + year: number; + month: number; + date: number; +}; +export declare const getDateRect: (date: Date | number) => { + year: number; + month: number; + date: number; + day: number; + time: number; +}; +export declare const isSameDate: (date1: CompareDate, date2: CompareDate) => boolean; +export declare const getMonthDateRect: (date: Date | number) => { + year: number; + month: number; + weekdayOfFirstDay: number; + lastDate: number; +}; +export declare const isValidDate: (val: any) => boolean; +export declare const getDate: (...args: any[]) => any; diff --git a/components/common/shared/date.js b/components/common/shared/date.js new file mode 100644 index 0000000..3ac46b3 --- /dev/null +++ b/components/common/shared/date.js @@ -0,0 +1,41 @@ +export const getDateRect = (date) => { + const _date = new Date(date); + return { + year: _date.getFullYear(), + month: _date.getMonth(), + date: _date.getDate(), + day: _date.getDay(), + time: _date.getTime(), + }; +}; +export const isSameDate = (date1, date2) => { + if (date1 instanceof Date || typeof date1 === 'number') + date1 = getDateRect(date1); + if (date2 instanceof Date || typeof date2 === 'number') + date2 = getDateRect(date2); + const keys = ['year', 'month', 'date']; + return keys.every((key) => date1[key] === date2[key]); +}; +export const getMonthDateRect = (date) => { + const { year, month } = getDateRect(date); + const firstDay = new Date(year, month, 1); + const weekdayOfFirstDay = firstDay.getDay(); + const lastDate = new Date(+new Date(year, month + 1, 1) - 24 * 3600 * 1000).getDate(); + return { + year, + month, + weekdayOfFirstDay, + lastDate, + }; +}; +export const isValidDate = (val) => typeof val === 'number' || val instanceof Date; +export const getDate = (...args) => { + const now = new Date(); + if (args.length === 0) + return now; + if (args.length === 1 && args[0] <= 1000) { + const { year, month, date } = getDateRect(now); + return new Date(year, month + args[0], date); + } + return Date.apply(null, args); +}; diff --git a/components/common/src/control.d.ts b/components/common/src/control.d.ts new file mode 100644 index 0000000..ed3f4a0 --- /dev/null +++ b/components/common/src/control.d.ts @@ -0,0 +1,15 @@ +declare type ControlInstance = { + controlled: boolean; + initValue: any; + set(newVal: any, extObj?: Object, fn?: any): void; + get(): any; + change(newVal: any, customChangeData?: any, customUpdateFn?: any): void; +}; +declare type ControlOption = { + valueKey?: string; + defaultValueKey?: string; + changeEventName?: string; + strict?: boolean; +}; +declare function useControl(this: any, option?: ControlOption): ControlInstance; +export { ControlOption, ControlInstance, useControl }; diff --git a/components/common/src/control.js b/components/common/src/control.js new file mode 100644 index 0000000..03c9e77 --- /dev/null +++ b/components/common/src/control.js @@ -0,0 +1,40 @@ +const defaultOption = { + valueKey: 'value', + defaultValueKey: 'defaultValue', + changeEventName: 'change', + strict: true, +}; +function useControl(option = {}) { + const { valueKey, defaultValueKey, changeEventName, strict } = Object.assign(Object.assign({}, defaultOption), option); + const props = this.properties || {}; + const value = props[valueKey]; + const defaultValue = props[strict ? defaultValueKey : valueKey]; + let controlled = false; + if (strict && typeof value !== 'undefined' && value !== null) { + controlled = true; + } + const set = (newVal, extObj, fn) => { + this.setData(Object.assign({ [`_${valueKey}`]: newVal }, extObj), fn); + }; + return { + controlled, + initValue: controlled ? value : defaultValue, + set, + get: () => { + return this.data[`_${valueKey}`]; + }, + change: (newVal, customChangeData, customUpdateFn) => { + this.triggerEvent(changeEventName, typeof customChangeData !== 'undefined' ? customChangeData : newVal); + if (controlled) { + return; + } + if (typeof customUpdateFn === 'function') { + customUpdateFn(); + } + else { + set(newVal); + } + }, + }; +} +export { useControl }; diff --git a/components/common/src/flatTool.d.ts b/components/common/src/flatTool.d.ts new file mode 100644 index 0000000..4183d79 --- /dev/null +++ b/components/common/src/flatTool.d.ts @@ -0,0 +1,15 @@ +export declare const getPrototypeOf: (obj: any) => any; +export declare const isObject: (something: any) => boolean; +export declare const iterateInheritedPrototype: (callback: (proto: Record) => boolean | void, fromCtor: any, toCtor: any, includeToCtor?: boolean) => void; +export interface ClassInstanceToObjectOptions { + bindTo?: any; + excludes?: string[]; + till?: any; + enumerable?: 0 | boolean; + configurable?: 0 | boolean; + writable?: 0 | boolean; +} +export declare const toObject: (something: any, options?: ClassInstanceToObjectOptions) => { + [key: string]: any; +}; +export declare const isPlainObject: (something: any) => boolean; diff --git a/components/common/src/flatTool.js b/components/common/src/flatTool.js new file mode 100644 index 0000000..045abd7 --- /dev/null +++ b/components/common/src/flatTool.js @@ -0,0 +1,57 @@ +export const getPrototypeOf = function (obj) { + return Object.getPrototypeOf ? Object.getPrototypeOf(obj) : obj.__proto__; +}; +export const isObject = function isObject(something) { + const type = typeof something; + return something !== null && (type === 'function' || type === 'object'); +}; +export const iterateInheritedPrototype = function iterateInheritedPrototype(callback, fromCtor, toCtor, includeToCtor = true) { + let proto = fromCtor.prototype || fromCtor; + const toProto = toCtor.prototype || toCtor; + while (proto) { + if (!includeToCtor && proto === toProto) + break; + if (callback(proto) === false) + break; + if (proto === toProto) + break; + proto = getPrototypeOf(proto); + } +}; +export const toObject = function toObject(something, options = {}) { + const obj = {}; + if (!isObject(something)) + return obj; + const excludes = options.excludes || ['constructor']; + const { enumerable = true, configurable = 0, writable = 0 } = options; + const defaultDesc = {}; + if (enumerable !== 0) + defaultDesc.enumerable = enumerable; + if (configurable !== 0) + defaultDesc.configurable = configurable; + if (writable !== 0) + defaultDesc.writable = writable; + iterateInheritedPrototype((proto) => { + Object.getOwnPropertyNames(proto).forEach((key) => { + if (excludes.indexOf(key) >= 0) + return; + if (Object.prototype.hasOwnProperty.call(obj, key)) + return; + const desc = Object.getOwnPropertyDescriptor(proto, key); + const fnKeys = ['get', 'set', 'value']; + fnKeys.forEach((k) => { + if (typeof desc[k] === 'function') { + const oldFn = desc[k]; + desc[k] = function (...args) { + return oldFn.apply(Object.prototype.hasOwnProperty.call(options, 'bindTo') ? options.bindTo : this, args); + }; + } + }); + Object.defineProperty(obj, key, Object.assign(Object.assign({}, desc), defaultDesc)); + }); + }, something, options.till || Object, false); + return obj; +}; +export const isPlainObject = function isPlainObject(something) { + return Object.prototype.toString.call(something) === '[object Object]'; +}; diff --git a/components/common/src/index.d.ts b/components/common/src/index.d.ts new file mode 100644 index 0000000..94e7ce1 --- /dev/null +++ b/components/common/src/index.d.ts @@ -0,0 +1,4 @@ +export * from './superComponent'; +export * from './flatTool'; +export * from './instantiationDecorator'; +export * from './control'; diff --git a/components/common/src/index.js b/components/common/src/index.js new file mode 100644 index 0000000..94e7ce1 --- /dev/null +++ b/components/common/src/index.js @@ -0,0 +1,4 @@ +export * from './superComponent'; +export * from './flatTool'; +export * from './instantiationDecorator'; +export * from './control'; diff --git a/components/common/src/instantiationDecorator.d.ts b/components/common/src/instantiationDecorator.d.ts new file mode 100644 index 0000000..3a06f2c --- /dev/null +++ b/components/common/src/instantiationDecorator.d.ts @@ -0,0 +1,3 @@ +import { SuperComponent } from './superComponent'; +export declare const toComponent: (options: Record) => Record; +export declare const wxComponent: () => (constructor: new () => SuperComponent) => void; diff --git a/components/common/src/instantiationDecorator.js b/components/common/src/instantiationDecorator.js new file mode 100644 index 0000000..c3f8c66 --- /dev/null +++ b/components/common/src/instantiationDecorator.js @@ -0,0 +1,98 @@ +import { isPlainObject, toObject } from './flatTool'; +const RawLifeCycles = ['Created', 'Attached', 'Ready', 'Moved', 'Detached', 'Error']; +const NativeLifeCycles = RawLifeCycles.map((k) => k.toLowerCase()); +const ComponentNativeProps = [ + 'properties', + 'data', + 'observers', + 'methods', + 'behaviors', + ...NativeLifeCycles, + 'relations', + 'externalClasses', + 'options', + 'lifetimes', + 'pageLifeTimes', + 'definitionFilter', +]; +export const toComponent = function toComponent(options) { + if (options.properties) { + Object.keys(options.properties).forEach((k) => { + let opt = options.properties[k]; + if (!isPlainObject(opt)) { + opt = { type: opt }; + } + options.properties[k] = opt; + }); + } + if (!options.methods) + options.methods = {}; + if (!options.lifetimes) + options.lifetimes = {}; + const inits = {}; + Object.getOwnPropertyNames(options).forEach((k) => { + const desc = Object.getOwnPropertyDescriptor(options, k); + if (!desc) + return; + if (NativeLifeCycles.indexOf(k) < 0 && typeof desc.value === 'function') { + Object.defineProperty(options.methods, k, desc); + delete options[k]; + } + else if (ComponentNativeProps.indexOf(k) < 0) { + inits[k] = desc; + } + else if (NativeLifeCycles.indexOf(k) >= 0) { + options.lifetimes[k] = options[k]; + } + }); + if (Object.keys(inits).length) { + const oldCreated = options.lifetimes.created; + const oldAttached = options.lifetimes.attached; + const { controlledProps = [] } = options; + options.lifetimes.created = function (...args) { + Object.defineProperties(this, inits); + if (oldCreated) + oldCreated.apply(this, args); + }; + options.lifetimes.attached = function (...args) { + if (oldAttached) + oldAttached.apply(this, args); + controlledProps.forEach(({ key }) => { + const defaultKey = `default${key.replace(/^(\w)/, (m, m1) => m1.toUpperCase())}`; + const props = this.properties; + if (props[key] == null && props[defaultKey] != null) { + this.setData({ + [key]: props[defaultKey], + }); + this._controlled = true; + } + }); + }; + options.methods._trigger = function (evtName, detail, opts) { + const target = controlledProps.find((item) => item.event == evtName); + if (target) { + const { key } = target; + if (this._controlled) { + this.setData({ + [key]: detail[key], + }); + } + } + this.triggerEvent(evtName, detail, opts); + }; + } + return options; +}; +export const wxComponent = function wxComponent() { + return function (constructor) { + class WxComponent extends constructor { + } + const current = new WxComponent(); + current.options = current.options || {}; + if (current.options.addGlobalClass === undefined) { + current.options.addGlobalClass = true; + } + const obj = toComponent(toObject(current)); + Component(obj); + }; +}; diff --git a/components/common/src/superComponent.d.ts b/components/common/src/superComponent.d.ts new file mode 100644 index 0000000..4455e19 --- /dev/null +++ b/components/common/src/superComponent.d.ts @@ -0,0 +1,19 @@ +/// +export interface ComponentsOptionsType extends WechatMiniprogram.Component.ComponentOptions { + styleIsolation?: 'isolated' | 'apply-shared' | 'shared' | 'page-isolated' | 'page-apply-shared' | 'page-shared'; +} +export interface RelationsOptions { + [componentName: string]: WechatMiniprogram.Component.RelationOption; +} +export interface SuperComponent extends WechatMiniprogram.Component.Lifetimes, WechatMiniprogram.Component.OtherOption, WechatMiniprogram.Component.InstanceMethods { + properties: P; + data: D; + options: ComponentsOptionsType; + methods: M | Record any>; + $global: Function; + [x: string]: any; +} +export declare class SuperComponent { + readonly app: any; + constructor(); +} diff --git a/components/common/src/superComponent.js b/components/common/src/superComponent.js new file mode 100644 index 0000000..3cb17dc --- /dev/null +++ b/components/common/src/superComponent.js @@ -0,0 +1,5 @@ +export class SuperComponent { + constructor() { + this.app = getApp(); + } +} diff --git a/components/common/style/_variables.wxss b/components/common/style/_variables.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/base.wxss b/components/common/style/base.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/index.wxss b/components/common/style/index.wxss new file mode 100644 index 0000000..1d532d2 --- /dev/null +++ b/components/common/style/index.wxss @@ -0,0 +1,27 @@ +.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); +} diff --git a/components/common/style/mixins/_clearfix.wxss b/components/common/style/mixins/_clearfix.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/mixins/_ellipsis.wxss b/components/common/style/mixins/_ellipsis.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/mixins/_hairline.wxss b/components/common/style/mixins/_hairline.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/mixins/_index.wxss b/components/common/style/mixins/_index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/theme/_index.wxss b/components/common/style/theme/_index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/components/common/style/utilities/_animation.wxss b/components/common/style/utilities/_animation.wxss new file mode 100644 index 0000000..a04e7c5 --- /dev/null +++ b/components/common/style/utilities/_animation.wxss @@ -0,0 +1,8 @@ +@keyframes tdesign-fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} diff --git a/components/common/style/utilities/_float.wxss b/components/common/style/utilities/_float.wxss new file mode 100644 index 0000000..e88ef0e --- /dev/null +++ b/components/common/style/utilities/_float.wxss @@ -0,0 +1,6 @@ +.t-float-left { + float: left; +} +.t-float-right { + float: right; +} diff --git a/components/common/style/utilities/_index.wxss b/components/common/style/utilities/_index.wxss new file mode 100644 index 0000000..1d532d2 --- /dev/null +++ b/components/common/style/utilities/_index.wxss @@ -0,0 +1,27 @@ +.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); +} diff --git a/components/common/template/button.wxml b/components/common/template/button.wxml new file mode 100644 index 0000000..4b6518f --- /dev/null +++ b/components/common/template/button.wxml @@ -0,0 +1,34 @@ + diff --git a/components/common/utils.d.ts b/components/common/utils.d.ts new file mode 100644 index 0000000..e0934e1 --- /dev/null +++ b/components/common/utils.d.ts @@ -0,0 +1,19 @@ +/// +/// +declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance; +export declare const debounce: (func: any, wait?: number) => (...rest: any[]) => void; +export declare const classNames: (...args: any[]) => string; +export declare const styles: (styleObj: any) => string; +export declare const getAnimationFrame: (cb: Function) => WechatMiniprogram.NodesRef; +export declare const getRect: (context: any, selector: string) => Promise; +export declare const isNumber: (value: any) => boolean; +export declare const addUnit: (value?: string | number) => string | undefined; +export declare const getCharacterLength: (type: string, str: string, max?: number) => { + length: number; + characters: string; +}; +export declare const chunk: (arr: any[], size: number) => any[][]; +export declare const equal: (v1: any, v2: any) => any; +export declare const clone: (val: any) => any; +export declare const getInstance: (context?: Context, selector?: string) => WechatMiniprogram.Component.TrivialInstance; +export {}; diff --git a/components/common/utils.js b/components/common/utils.js new file mode 100644 index 0000000..ff86d56 --- /dev/null +++ b/components/common/utils.js @@ -0,0 +1,143 @@ +export const debounce = function (func, wait = 500) { + let timerId; + return function (...rest) { + if (timerId) { + clearTimeout(timerId); + } + timerId = setTimeout(() => { + func.apply(this, rest); + }, wait); + }; +}; +export const classNames = function (...args) { + const hasOwn = {}.hasOwnProperty; + const classes = []; + args.forEach((arg) => { + if (!arg) + return; + const argType = typeof arg; + if (argType === 'string' || argType === 'number') { + classes.push(arg); + } + else if (Array.isArray(arg) && arg.length) { + const inner = classNames(...arg); + if (inner) { + classes.push(inner); + } + } + else if (argType === 'object') { + for (const key in arg) { + if (hasOwn.call(arg, key) && arg[key]) { + classes.push(key); + } + } + } + }); + return classes.join(' '); +}; +export const styles = function (styleObj) { + return Object.keys(styleObj) + .map((styleKey) => `${styleKey}: ${styleObj[styleKey]}`) + .join('; '); +}; +export const getAnimationFrame = function (cb) { + return wx + .createSelectorQuery() + .selectViewport() + .boundingClientRect() + .exec(() => { + cb(); + }); +}; +export const getRect = function (context, selector) { + return new Promise((resolve) => { + wx.createSelectorQuery() + .in(context) + .select(selector) + .boundingClientRect() + .exec((rect = []) => resolve(rect[0])); + }); +}; +const isDef = function (value) { + return value !== undefined && value !== null; +}; +export const isNumber = function (value) { + return /^\d+(\.\d+)?$/.test(value); +}; +export const addUnit = function (value) { + if (!isDef(value)) { + return undefined; + } + value = String(value); + return isNumber(value) ? `${value}px` : value; +}; +export const getCharacterLength = (type, str, max) => { + if (!str || str.length === 0) { + return { + length: 0, + characters: '', + }; + } + if (type === 'maxcharacter') { + let len = 0; + for (let i = 0; i < str.length; i += 1) { + let currentStringLength = 0; + if (str.charCodeAt(i) > 127 || str.charCodeAt(i) === 94) { + currentStringLength = 2; + } + else { + currentStringLength = 1; + } + if (len + currentStringLength > max) { + return { + length: len, + characters: str.slice(0, i), + }; + } + len += currentStringLength; + } + return { + length: len, + characters: str, + }; + } + else if (type === 'maxlength') { + const length = str.length > max ? max : str.length; + return { + length, + characters: str.slice(0, length), + }; + } + return { + length: str.length, + characters: str, + }; +}; +export const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size)); +export const equal = (v1, v2) => { + if (Array.isArray(v1) && Array.isArray(v2)) { + if (v1.length !== v2.length) + return false; + return v1.every((item, index) => equal(item, v2[index])); + } + return v1 === v2; +}; +export const clone = (val) => { + if (Array.isArray(val)) { + return val.map((item) => clone(item)); + } + return val; +}; +export const getInstance = function (context, selector) { + if (!context) { + const pages = getCurrentPages(); + const page = pages[pages.length - 1]; + context = page.$$basePage || page; + } + const instance = context ? context.selectComponent(selector) : null; + if (!instance) { + console.warn('未找到组件,请检查selector是否正确'); + return null; + } + return instance; +}; diff --git a/components/common/utils.wxs b/components/common/utils.wxs new file mode 100644 index 0000000..57249ff --- /dev/null +++ b/components/common/utils.wxs @@ -0,0 +1,39 @@ +/* utils */ + +/** + * addUnit */ +// 为 css 添加单位 +function addUnit(value) { + var REGEXP = getRegExp('^d+(.d+)?$'); + if (value == null) { + return undefined; + } + return REGEXP.test('' + value) ? value + 'px' : value; +} + +function isArray(array) { + return array && array.constructor === 'Array'; +} + +function isObject(obj) { + return obj && obj.constructor === 'Object'; +} + +function includes(arr, value) { + if (!arr || !isArray(arr)) return false; + + var i = 0; + var len = arr.length; + + for (; i < len; i++) { + if (arr[i] === value) return true; + } + return false; +} + +module.exports = { + addUnit: addUnit, + isArray: isArray, + isObject: isObject, + includes: includes, +}; diff --git a/components/common/version.d.ts b/components/common/version.d.ts new file mode 100644 index 0000000..25e4c38 --- /dev/null +++ b/components/common/version.d.ts @@ -0,0 +1 @@ +export declare function canIUseFormFieldButton(): boolean; diff --git a/components/common/version.js b/components/common/version.js new file mode 100644 index 0000000..b0612ed --- /dev/null +++ b/components/common/version.js @@ -0,0 +1,37 @@ +let systemInfo; +function getSystemInfo() { + if (systemInfo == null) { + systemInfo = wx.getSystemInfoSync(); + } + return systemInfo; +} +function compareVersion(v1, v2) { + v1 = v1.split('.'); + v2 = v2.split('.'); + const len = Math.max(v1.length, v2.length); + while (v1.length < len) { + v1.push('0'); + } + while (v2.length < len) { + v2.push('0'); + } + for (let i = 0; i < len; i++) { + const num1 = parseInt(v1[i]); + const num2 = parseInt(v2[i]); + if (num1 > num2) { + return 1; + } + else if (num1 < num2) { + return -1; + } + } + return 0; +} +function judgeByVersion(version) { + const currentSDKVersion = getSystemInfo().SDKVersion; + return compareVersion(currentSDKVersion, version) >= 0; +} +export function canIUseFormFieldButton() { + const version = '2.10.3'; + return judgeByVersion(version); +} diff --git a/components/icon/README.md b/components/icon/README.md new file mode 100644 index 0000000..c991911 --- /dev/null +++ b/components/icon/README.md @@ -0,0 +1,89 @@ +--- +title: Icon 图标 +description: 图标。 +spline: base +isComponent: true +--- + + +## 引入 + +全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 + +```json +"usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon" +} +``` + +## 代码演示 + +### 基础图标 + +{{ base }} + +### 自定义图标 + +{{ custom }} + +自定义图标用法,下面以 `iconfont` 为例 + +#### 准备图标文件 + +文件后缀应为`.wxss`,如下方代码块所示: + +```css +@font-face { + font-family: 'icon'; // 使用自定义的字体名称 + ··· +} + +.icon { + font-family: 'icon' !important; // 字体名称 + ··· +} + +.icon-a-0:before { // icon 图标。注意 FontClass 前缀与 font-family 保持一致 + content: '\e64d'; +} +``` +- 添加所需图标,下载图标。图标库一般会提供 **在线链接** 或者 **下载至本地** 等使用方式。**在线链接** 方式会指向一个 `.css` 文件,可以下载或复制其内容,将其修改成后缀名为 `.wxss` 的文件 +- 将 `.wxss` 文件中的 `FontClass/Symbol前缀` 与 `Font Family` 两项内容保持一致,如: `FontClass/Symbol` 前缀为 `icon-`,则 `Font Family` 为 `icon`。 + +> 注:若是采用 `下载至本地` 方式,需关注 `.css` 和 `.ttf` 文件。由于微信小程序不支持处理 `ttf、woff、eot` 等文件,但支持 `base64`,所以需要将 `.ttf` 文件转换为 `base64` (可借助转换工具,如 [transfonter.org](https://transfonter.org/),会得到一个 `stylesheet.css` 文件),然后将 `.css` 文件中的 `@font-face {}` 内容替换为 `stylesheet.css` 中的 `base64` 内容,最后将 `.css` 文件修改后缀为 `.wxss` + +#### 引入自定义图标 + +- 全局引入:在项目 `app.wxss`,使用 `@import` 引入上述的 `.wxss` 文件 +- 局部引入:在 `page` 对应的 `.wxss` 中,使用 `@import` 引入上述的 `.wxss` 文件 + +#### 自定义图标的使用 + + `` 组件中的 `prefix` 属性值与前面设置的 `Font Family` 保持一致,即 `prefix="icon"`,`name` 属性值为自定义图标名称,如图标的 `className` 为 `icon-a-1h`,则 `name="a-1h"`。 + +### 图片链接 + +{{ iconImage }} + +### 全部图标 + + + +## API + +#### Props + +| 属性 | 值类型 | 默认值 | 必传 | 说明 | +| ----------- | -------- | ---------- | ---- |----------------------------------------------------------------- | +| name | String | - | Y | 图标名称或图片链接 | +| size | String | inherit | N | 图标大小, 如 `20`, `20px`, `48rpx`, 默认单位是 `px` | +| color | String | initial | N | 图标颜色 | +| prefix | String | - | N | 自定义图标前缀 | +| customStyle | String | - | N | 自定义样式 | +| external-classes | Array | - | 组件类名,分别用于设置 组件外层元素、图片图标、基础图标等元素类名。`['t-class']` | N + +#### Events + +| 事件 | event.detail | 说明 | +| ---------- | ------------ | -------------- | +| bind:click | - | 点击图标时触发 | diff --git a/components/icon/icon.d.ts b/components/icon/icon.d.ts new file mode 100644 index 0000000..f2ddef4 --- /dev/null +++ b/components/icon/icon.d.ts @@ -0,0 +1,19 @@ +import { SuperComponent } from '../common/src/index'; +export default class Icon extends SuperComponent { + behaviors: ['wx://form-field-icon']; + externalClasses: string[]; + properties: import("./type").TdIconProps; + data: { + componentPrefix: string; + classPrefix: string; + isImage: boolean; + iconStyle: any; + }; + observers: { + 'name, color, size, customStyle'(): void; + }; + methods: { + onTap(event: any): void; + setIconStyle(): void; + }; +} diff --git a/components/icon/icon.js b/components/icon/icon.js new file mode 100644 index 0000000..6b8b5d2 --- /dev/null +++ b/components/icon/icon.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'; +import { styles, addUnit } from '../common/utils'; +const { prefix } = config; +const name = `${prefix}-icon`; +let Icon = class Icon extends SuperComponent { + constructor() { + super(...arguments); + this.externalClasses = [`${prefix}-class`]; + this.properties = props; + this.data = { + componentPrefix: prefix, + classPrefix: name, + isImage: false, + iconStyle: undefined, + }; + this.observers = { + 'name, color, size, customStyle'() { + this.setIconStyle(); + }, + }; + this.methods = { + onTap(event) { + this.triggerEvent('click', event.detail); + }, + setIconStyle() { + const { name, color, size, customStyle } = this.properties; + const isImage = name.indexOf('/') !== -1; + const sizeValue = addUnit(size); + const sizeStyle = isImage ? { width: sizeValue, height: sizeValue } : {}; + const colorStyle = color ? { color: color } : {}; + const fontStyle = size ? { 'font-size': sizeValue } : {}; + this.setData({ + isImage, + iconStyle: styles(Object.assign(Object.assign(Object.assign({}, colorStyle), fontStyle), sizeStyle)) + customStyle, + }); + }, + }; + } +}; +Icon = __decorate([ + wxComponent() +], Icon); +export default Icon; diff --git a/components/icon/icon.json b/components/icon/icon.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/icon/icon.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/icon/icon.wxml b/components/icon/icon.wxml new file mode 100644 index 0000000..63c077c --- /dev/null +++ b/components/icon/icon.wxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/components/icon/icon.wxss b/components/icon/icon.wxss new file mode 100644 index 0000000..9b6c865 --- /dev/null +++ b/components/icon/icon.wxss @@ -0,0 +1,770 @@ +.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); +} +@font-face { + font-family: t; + src: url('https://tdesign.gtimg.com/icon/0.1.2/fonts/t.eot'), url('https://tdesign.gtimg.com/icon/0.1.2/fonts/t.eot?#iefix') format('ded-opentype'), url('https://tdesign.gtimg.com/icon/0.1.2/fonts/t.woff') format('woff'), url('https://tdesign.gtimg.com/icon/0.1.2/fonts/t.ttf') format('truetype'), url('https://tdesign.gtimg.com/icon/0.1.2/fonts/t.svg') format('svg'); + /* iOS 4.1- */ + font-weight: normal; + font-style: normal; +} +.t-icon--image { + width: 1em; + height: 1em; +} +.t-icon__image { + vertical-align: top; + width: 100%; + height: 100%; +} +.t-icon-base { + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + text-align: center; + display: block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.t-icon { + /* stylelint-disable-next-line declaration-no-important */ + font-family: t !important; + /* prevent issues with browser extensions that change fonts */ +} +.t-icon-add-circle:before { + content: '\E001'; +} +.t-icon-add-rectangle:before { + content: '\E002'; +} +.t-icon-add:before { + content: '\E003'; +} +.t-icon-app:before { + content: '\E004'; +} +.t-icon-arrow-down-rectangle:before { + content: '\E005'; +} +.t-icon-arrow-down:before { + content: '\E006'; +} +.t-icon-arrow-left:before { + content: '\E007'; +} +.t-icon-arrow-right:before { + content: '\E008'; +} +.t-icon-arrow-up:before { + content: '\E009'; +} +.t-icon-attach:before { + content: '\E00A'; +} +.t-icon-backtop-rectangle:before { + content: '\E00B'; +} +.t-icon-backtop:before { + content: '\E00C'; +} +.t-icon-backward:before { + content: '\E00D'; +} +.t-icon-barcode:before { + content: '\E00E'; +} +.t-icon-books:before { + content: '\E00F'; +} +.t-icon-browse-off:before { + content: '\E010'; +} +.t-icon-browse:before { + content: '\E011'; +} +.t-icon-bulletpoint:before { + content: '\E012'; +} +.t-icon-calendar:before { + content: '\E013'; +} +.t-icon-call:before { + content: '\E014'; +} +.t-icon-caret-down-small:before { + content: '\E015'; +} +.t-icon-caret-down:before { + content: '\E016'; +} +.t-icon-caret-left-small:before { + content: '\E017'; +} +.t-icon-caret-left:before { + content: '\E018'; +} +.t-icon-caret-right-small:before { + content: '\E019'; +} +.t-icon-caret-right:before { + content: '\E01A'; +} +.t-icon-caret-up-small:before { + content: '\E01B'; +} +.t-icon-caret-up:before { + content: '\E01C'; +} +.t-icon-cart:before { + content: '\E01D'; +} +.t-icon-chart-bar:before { + content: '\E01E'; +} +.t-icon-chart-bubble:before { + content: '\E01F'; +} +.t-icon-chart-pie:before { + content: '\E020'; +} +.t-icon-chart:before { + content: '\E021'; +} +.t-icon-chat:before { + content: '\E022'; +} +.t-icon-check-circle-filled:before { + content: '\E023'; +} +.t-icon-check-circle:before { + content: '\E024'; +} +.t-icon-check-rectangle-filled:before { + content: '\E025'; +} +.t-icon-check-rectangle:before { + content: '\E026'; +} +.t-icon-check:before { + content: '\E027'; +} +.t-icon-chevron-down-circle:before { + content: '\E028'; +} +.t-icon-chevron-down-rectangle:before { + content: '\E029'; +} +.t-icon-chevron-down:before { + content: '\E02A'; +} +.t-icon-chevron-left-circle:before { + content: '\E02B'; +} +.t-icon-chevron-left-double:before { + content: '\E02C'; +} +.t-icon-chevron-left-rectangle:before { + content: '\E02D'; +} +.t-icon-chevron-left:before { + content: '\E02E'; +} +.t-icon-chevron-right-circle:before { + content: '\E02F'; +} +.t-icon-chevron-right-double:before { + content: '\E030'; +} +.t-icon-chevron-right-rectangle:before { + content: '\E031'; +} +.t-icon-chevron-right:before { + content: '\E032'; +} +.t-icon-chevron-up-circle:before { + content: '\E033'; +} +.t-icon-chevron-up-rectangle:before { + content: '\E034'; +} +.t-icon-chevron-up:before { + content: '\E035'; +} +.t-icon-circle:before { + content: '\E036'; +} +.t-icon-clear:before { + content: '\E037'; +} +.t-icon-close-circle-filled:before { + content: '\E038'; +} +.t-icon-close-circle:before { + content: '\E039'; +} +.t-icon-close-rectangle:before { + content: '\E03A'; +} +.t-icon-close:before { + content: '\E03B'; +} +.t-icon-cloud-download:before { + content: '\E03C'; +} +.t-icon-cloud-upload:before { + content: '\E03D'; +} +.t-icon-cloud:before { + content: '\E03E'; +} +.t-icon-code:before { + content: '\E03F'; +} +.t-icon-control-platform:before { + content: '\E040'; +} +.t-icon-creditcard:before { + content: '\E041'; +} +.t-icon-dashboard:before { + content: '\E042'; +} +.t-icon-delete:before { + content: '\E043'; +} +.t-icon-desktop:before { + content: '\E044'; +} +.t-icon-discount-filled:before { + content: '\E045'; +} +.t-icon-discount:before { + content: '\E046'; +} +.t-icon-download:before { + content: '\E047'; +} +.t-icon-edit-1:before { + content: '\E048'; +} +.t-icon-edit:before { + content: '\E049'; +} +.t-icon-ellipsis:before { + content: '\E04A'; +} +.t-icon-enter:before { + content: '\E04B'; +} +.t-icon-error-circle-filled:before { + content: '\E04C'; +} +.t-icon-error-circle:before { + content: '\E04D'; +} +.t-icon-error:before { + content: '\E04E'; +} +.t-icon-file-add:before { + content: '\E04F'; +} +.t-icon-file-copy:before { + content: '\E050'; +} +.t-icon-file-excel:before { + content: '\E051'; +} +.t-icon-file-icon:before { + content: '\E052'; +} +.t-icon-file-image:before { + content: '\E053'; +} +.t-icon-file-paste:before { + content: '\E054'; +} +.t-icon-file-pdf:before { + content: '\E055'; +} +.t-icon-file-powerpoint:before { + content: '\E056'; +} +.t-icon-file-unknown:before { + content: '\E057'; +} +.t-icon-file-word:before { + content: '\E058'; +} +.t-icon-file:before { + content: '\E059'; +} +.t-icon-filter-clear:before { + content: '\E05A'; +} +.t-icon-filter:before { + content: '\E05B'; +} +.t-icon-flag:before { + content: '\E05C'; +} +.t-icon-folder-add:before { + content: '\E05D'; +} +.t-icon-folder-open:before { + content: '\E05E'; +} +.t-icon-folder:before { + content: '\E05F'; +} +.t-icon-fork:before { + content: '\E060'; +} +.t-icon-format-horizontal-align-bottom:before { + content: '\E061'; +} +.t-icon-format-horizontal-align-center:before { + content: '\E062'; +} +.t-icon-format-horizontal-align-top:before { + content: '\E063'; +} +.t-icon-format-vertical-align-center:before { + content: '\E064'; +} +.t-icon-format-vertical-align-left:before { + content: '\E065'; +} +.t-icon-format-vertical-align-right:before { + content: '\E066'; +} +.t-icon-forward:before { + content: '\E067'; +} +.t-icon-fullscreen-exit:before { + content: '\E068'; +} +.t-icon-fullscreen:before { + content: '\E069'; +} +.t-icon-gender-female:before { + content: '\E06A'; +} +.t-icon-gender-male:before { + content: '\E06B'; +} +.t-icon-gift:before { + content: '\E06C'; +} +.t-icon-heart-filled:before { + content: '\E06D'; +} +.t-icon-heart:before { + content: '\E06E'; +} +.t-icon-help-circle-filled:before { + content: '\E06F'; +} +.t-icon-help-circle:before { + content: '\E070'; +} +.t-icon-help:before { + content: '\E071'; +} +.t-icon-history:before { + content: '\E072'; +} +.t-icon-home:before { + content: '\E073'; +} +.t-icon-hourglass:before { + content: '\E074'; +} +.t-icon-image-error:before { + content: '\E075'; +} +.t-icon-image:before { + content: '\E076'; +} +.t-icon-info-circle-filled:before { + content: '\E077'; +} +.t-icon-info-circle:before { + content: '\E078'; +} +.t-icon-internet:before { + content: '\E079'; +} +.t-icon-jump:before { + content: '\E07A'; +} +.t-icon-laptop:before { + content: '\E07B'; +} +.t-icon-layers:before { + content: '\E07C'; +} +.t-icon-link-unlink:before { + content: '\E07D'; +} +.t-icon-link:before { + content: '\E07E'; +} +.t-icon-loading:before { + content: '\E07F'; +} +.t-icon-location:before { + content: '\E080'; +} +.t-icon-lock-off:before { + content: '\E081'; +} +.t-icon-lock-on:before { + content: '\E082'; +} +.t-icon-login:before { + content: '\E083'; +} +.t-icon-logo-android:before { + content: '\E084'; +} +.t-icon-logo-apple-filled:before { + content: '\E085'; +} +.t-icon-logo-apple:before { + content: '\E086'; +} +.t-icon-logo-chrome-filled:before { + content: '\E087'; +} +.t-icon-logo-chrome:before { + content: '\E088'; +} +.t-icon-logo-codepen:before { + content: '\E089'; +} +.t-icon-logo-github-filled:before { + content: '\E08A'; +} +.t-icon-logo-github:before { + content: '\E08B'; +} +.t-icon-logo-ie-filled:before { + content: '\E08C'; +} +.t-icon-logo-ie:before { + content: '\E08D'; +} +.t-icon-logo-qq:before { + content: '\E08E'; +} +.t-icon-logo-wechat:before { + content: '\E08F'; +} +.t-icon-logo-wecom:before { + content: '\E090'; +} +.t-icon-logo-windows-filled:before { + content: '\E091'; +} +.t-icon-logo-windows:before { + content: '\E092'; +} +.t-icon-logout:before { + content: '\E093'; +} +.t-icon-mail:before { + content: '\E094'; +} +.t-icon-menu-fold:before { + content: '\E095'; +} +.t-icon-menu-unfold:before { + content: '\E096'; +} +.t-icon-minus-circle-filled:before { + content: '\E097'; +} +.t-icon-minus-circle:before { + content: '\E098'; +} +.t-icon-minus-rectangle:before { + content: '\E099'; +} +.t-icon-mirror:before { + content: '\E09A'; +} +.t-icon-mobile-vibrate:before { + content: '\E09B'; +} +.t-icon-mobile:before { + content: '\E09C'; +} +.t-icon-money-circle:before { + content: '\E09D'; +} +.t-icon-more:before { + content: '\E09E'; +} +.t-icon-move:before { + content: '\E09F'; +} +.t-icon-next:before { + content: '\E0A0'; +} +.t-icon-notification-filled:before { + content: '\E0A1'; +} +.t-icon-notification:before { + content: '\E0A2'; +} +.t-icon-order-adjustment-column:before { + content: '\E0A3'; +} +.t-icon-order-ascending:before { + content: '\E0A4'; +} +.t-icon-order-descending:before { + content: '\E0A5'; +} +.t-icon-page-first:before { + content: '\E0A6'; +} +.t-icon-page-last:before { + content: '\E0A7'; +} +.t-icon-pause-circle-filled:before { + content: '\E0A8'; +} +.t-icon-photo:before { + content: '\E0A9'; +} +.t-icon-pin-filled:before { + content: '\E0AA'; +} +.t-icon-pin:before { + content: '\E0AB'; +} +.t-icon-play-circle-filled:before { + content: '\E0AC'; +} +.t-icon-play-circle-stroke:before { + content: '\E0AD'; +} +.t-icon-play-circle:before { + content: '\E0AE'; +} +.t-icon-play:before { + content: '\E0AF'; +} +.t-icon-poweroff:before { + content: '\E0B0'; +} +.t-icon-precise-monitor:before { + content: '\E0B1'; +} +.t-icon-previous:before { + content: '\E0B2'; +} +.t-icon-print:before { + content: '\E0B3'; +} +.t-icon-qrcode:before { + content: '\E0B4'; +} +.t-icon-queue:before { + content: '\E0B5'; +} +.t-icon-rectangle:before { + content: '\E0B6'; +} +.t-icon-refresh:before { + content: '\E0B7'; +} +.t-icon-relativity:before { + content: '\E0B8'; +} +.t-icon-remove:before { + content: '\E0B9'; +} +.t-icon-rollback:before { + content: '\E0BA'; +} +.t-icon-rollfront:before { + content: '\E0BB'; +} +.t-icon-root-list:before { + content: '\E0BC'; +} +.t-icon-rotation:before { + content: '\E0BD'; +} +.t-icon-round:before { + content: '\E0BE'; +} +.t-icon-save:before { + content: '\E0BF'; +} +.t-icon-scan:before { + content: '\E0C0'; +} +.t-icon-search:before { + content: '\E0C1'; +} +.t-icon-secured:before { + content: '\E0C2'; +} +.t-icon-server:before { + content: '\E0C3'; +} +.t-icon-service:before { + content: '\E0C4'; +} +.t-icon-setting:before { + content: '\E0C5'; +} +.t-icon-share:before { + content: '\E0C6'; +} +.t-icon-shop:before { + content: '\E0C7'; +} +.t-icon-slash:before { + content: '\E0C8'; +} +.t-icon-sound:before { + content: '\E0C9'; +} +.t-icon-star-filled:before { + content: '\E0CA'; +} +.t-icon-star:before { + content: '\E0CB'; +} +.t-icon-stop-circle-1:before { + content: '\E0CC'; +} +.t-icon-stop-circle-filled:before { + content: '\E0CD'; +} +.t-icon-stop-circle:before { + content: '\E0CE'; +} +.t-icon-stop:before { + content: '\E0CF'; +} +.t-icon-swap-left:before { + content: '\E0D0'; +} +.t-icon-swap-right:before { + content: '\E0D1'; +} +.t-icon-swap:before { + content: '\E0D2'; +} +.t-icon-thumb-down:before { + content: '\E0D3'; +} +.t-icon-thumb-up:before { + content: '\E0D4'; +} +.t-icon-time-filled:before { + content: '\E0D5'; +} +.t-icon-time:before { + content: '\E0D6'; +} +.t-icon-tips:before { + content: '\E0D7'; +} +.t-icon-tools:before { + content: '\E0D8'; +} +.t-icon-unfold-less:before { + content: '\E0D9'; +} +.t-icon-unfold-more:before { + content: '\E0DA'; +} +.t-icon-upload:before { + content: '\E0DB'; +} +.t-icon-usb:before { + content: '\E0DC'; +} +.t-icon-user-add:before { + content: '\E0DD'; +} +.t-icon-user-avatar:before { + content: '\E0DE'; +} +.t-icon-user-circle:before { + content: '\E0DF'; +} +.t-icon-user-clear:before { + content: '\E0E0'; +} +.t-icon-user-talk:before { + content: '\E0E1'; +} +.t-icon-user:before { + content: '\E0E2'; +} +.t-icon-usergroup-add:before { + content: '\E0E3'; +} +.t-icon-usergroup-clear:before { + content: '\E0E4'; +} +.t-icon-usergroup:before { + content: '\E0E5'; +} +.t-icon-video:before { + content: '\E0E6'; +} +.t-icon-view-column:before { + content: '\E0E7'; +} +.t-icon-view-list:before { + content: '\E0E8'; +} +.t-icon-view-module:before { + content: '\E0E9'; +} +.t-icon-wallet:before { + content: '\E0EA'; +} +.t-icon-wifi:before { + content: '\E0EB'; +} +.t-icon-zoom-in:before { + content: '\E0EC'; +} +.t-icon-zoom-out:before { + content: '\E0ED'; +} diff --git a/components/icon/props.d.ts b/components/icon/props.d.ts new file mode 100644 index 0000000..a472c01 --- /dev/null +++ b/components/icon/props.d.ts @@ -0,0 +1,3 @@ +import { TdIconProps } from './type'; +declare const props: TdIconProps; +export default props; diff --git a/components/icon/props.js b/components/icon/props.js new file mode 100644 index 0000000..36da4e5 --- /dev/null +++ b/components/icon/props.js @@ -0,0 +1,24 @@ +const props = { + customStyle: { + type: String, + value: '', + }, + color: { + type: String, + value: '', + }, + name: { + type: String, + value: '', + required: true, + }, + size: { + type: String, + value: undefined, + }, + prefix: { + type: String, + value: undefined, + }, +}; +export default props; diff --git a/components/icon/type.d.ts b/components/icon/type.d.ts new file mode 100644 index 0000000..159aa0b --- /dev/null +++ b/components/icon/type.d.ts @@ -0,0 +1,27 @@ +export interface TdIconProps { + customStyle?: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + color?: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + name: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + size?: { + type: StringConstructor; + value?: string; + required?: boolean; + }; + prefix?: { + type: StringConstructor; + value?: string; + reuqired?: boolean; + }; +} diff --git a/components/icon/type.js b/components/icon/type.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/icon/type.js @@ -0,0 +1 @@ +export {}; diff --git a/components/tab-bar/README.en-US.md b/components/tab-bar/README.en-US.md new file mode 100644 index 0000000..2f7eac1 --- /dev/null +++ b/components/tab-bar/README.en-US.md @@ -0,0 +1,29 @@ +:: BASE_DOC :: + +## API +### TabBar Props + +name | type | default | description | required +-- | -- | -- | -- | -- +bordered | Boolean | true | \- | N +external-classes | Array | - | `['t-class']` | N +fixed | Boolean | true | \- | N +safe-area-inset-bottom | Boolean | true | \- | N +split | Boolean | true | \- | N +value | String / Number / Array | undefined | Typescript:`string | number | Array` | N +default-value | String / Number / Array | undefined | uncontrolled property。Typescript:`string | number | Array` | N + +### TabBar Events + +name | params | description +-- | -- | -- +change | `(value: string | number)` | \- + +### TabBarItem Props + +name | type | default | description | required +-- | -- | -- | -- | -- +badge-props | Object | - | Typescript:`BadgeProps`,[Badge API Documents](./badge?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/tab-bar/type.ts) | N +icon | String / Slot | - | \- | N +sub-tab-bar | Array | - | Typescript:`SubTabBarItem[] ` `interface SubTabBarItem { value: string; label: string }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/tab-bar/type.ts) | N +value | String / Number | - | \- | N diff --git a/components/tab-bar/README.md b/components/tab-bar/README.md new file mode 100644 index 0000000..cd28521 --- /dev/null +++ b/components/tab-bar/README.md @@ -0,0 +1,85 @@ +--- +title: TabBar 标签栏 +description: 用于在不同功能模块之间进行快速切换,位于页面底部。 +spline: navigation +isComponent: true +--- + + +## 引入 + +全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。 + +```json +"usingComponents": { + "t-tab-bar": "/components/tab-bar/tab-bar", + "t-tab-bar-item": "/components/tab-bar/tab-bar-item" +} +``` + +### 主题定制 + +CSS 变量名|说明 +--|-- +--td-tab-bar-border-color|顶部边框颜色 +--td-tab-bar-bg-color|背景色 +--td-tab-bar-hover-color|hover 时背景色 +--td-tab-bar-item-color | 字体颜色 +--td-tab-bar-item-active-color | 激活时字体颜色 +## 代码演示 + + + +### 基础标签栏 + +文本标签栏,分为单层双层,可以自定义标签栏内容 + +{{ base }} + +### 带徽章标签栏 + +{{ badge }} + +### 纯文本标签栏 + +{{ text-only }} + +### 纯图标标签栏 + +{{ icon-only }} + +### 双层级纯文本标签栏 + +{{ sub }} + +### 自定义主题 + +{{ custom }} + +## API +### TabBar Props + +名称 | 类型 | 默认值 | 说明 | 必传 +-- | -- | -- | -- | -- +bordered | Boolean | true | 是否显示外边框 | N +external-classes | Array | - | 组件类名,用于设置外层元素类名。`['t-class']` | N +fixed | Boolean | true | 是否固定在底部 | N +safe-area-inset-bottom | Boolean | true | 是否为 iPhoneX 留出底部安全距离 | N +split | Boolean | true | 是否需要分割线 | N +value | String / Number / Array | undefined | 当前选中标签的索引。TS 类型:`string | number | Array` | N +default-value | String / Number / Array | undefined | 当前选中标签的索引。非受控属性。TS 类型:`string | number | Array` | N + +### TabBar Events + +名称 | 参数 | 描述 +-- | -- | -- +change | `(value: string | number)` | 选中标签切换时触发 + +### TabBarItem Props + +名称 | 类型 | 默认值 | 说明 | 必传 +-- | -- | -- | -- | -- +badge-props | Object | - | 图标右上角提示信息。TS 类型:`BadgeProps`,[Badge API Documents](./badge?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/tab-bar/type.ts) | N +icon | String / Slot | - | 图标名称 | N +sub-tab-bar | Array | - | 二级菜单。TS 类型:`SubTabBarItem[] ` `interface SubTabBarItem { value: string; label: string }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/tab-bar/type.ts) | N +value | String / Number | - | 标识符 | N diff --git a/components/tab-bar/props.d.ts b/components/tab-bar/props.d.ts new file mode 100644 index 0000000..338c35e --- /dev/null +++ b/components/tab-bar/props.d.ts @@ -0,0 +1,3 @@ +import { TdTabBarProps } from './type'; +declare const props: TdTabBarProps; +export default props; diff --git a/components/tab-bar/props.js b/components/tab-bar/props.js new file mode 100644 index 0000000..96289f0 --- /dev/null +++ b/components/tab-bar/props.js @@ -0,0 +1,30 @@ +const props = { + bordered: { + type: Boolean, + value: true, + }, + externalClasses: { + type: Array, + }, + fixed: { + type: Boolean, + value: true, + }, + safeAreaInsetBottom: { + type: Boolean, + value: true, + }, + split: { + type: Boolean, + value: true, + }, + value: { + type: null, + value: null, + }, + defaultValue: { + type: null, + value: null, + }, +}; +export default props; diff --git a/components/tab-bar/tab-bar-item-props.d.ts b/components/tab-bar/tab-bar-item-props.d.ts new file mode 100644 index 0000000..026ee8b --- /dev/null +++ b/components/tab-bar/tab-bar-item-props.d.ts @@ -0,0 +1,3 @@ +import { TdTabBarItemProps } from './type'; +declare const props: TdTabBarItemProps; +export default props; diff --git a/components/tab-bar/tab-bar-item-props.js b/components/tab-bar/tab-bar-item-props.js new file mode 100644 index 0000000..8099828 --- /dev/null +++ b/components/tab-bar/tab-bar-item-props.js @@ -0,0 +1,16 @@ +const props = { + badgeProps: { + type: Object, + }, + icon: { + type: String, + }, + subTabBar: { + type: Array, + }, + value: { + type: null, + value: null, + }, +}; +export default props; diff --git a/components/tab-bar/tab-bar-item.d.ts b/components/tab-bar/tab-bar-item.d.ts new file mode 100644 index 0000000..f314a67 --- /dev/null +++ b/components/tab-bar/tab-bar-item.d.ts @@ -0,0 +1,28 @@ +import { SuperComponent, RelationsOptions } from '../common/src/index'; +export default class TabbarItem extends SuperComponent { + parent: any; + relations: RelationsOptions; + options: { + multipleSlots: boolean; + }; + data: { + prefix: string; + classPrefix: string; + isSpread: boolean; + isChecked: boolean; + hasChildren: boolean; + currentName: string; + split: boolean; + }; + properties: import("./type").TdTabBarItemProps; + observers: { + subTabBar(value: Record[]): void; + }; + methods: { + showSpread(): void; + toggle(): void; + selectChild(event: any): void; + checkActive(value: any): void; + closeSpread(): void; + }; +} diff --git a/components/tab-bar/tab-bar-item.js b/components/tab-bar/tab-bar-item.js new file mode 100644 index 0000000..054e8f7 --- /dev/null +++ b/components/tab-bar/tab-bar-item.js @@ -0,0 +1,92 @@ +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 { wxComponent, SuperComponent } from '../common/src/index'; +import config from '../common/config'; +import props from './tab-bar-item-props'; +const { prefix } = config; +const classPrefix = `${prefix}-tab-bar-item`; +let TabbarItem = class TabbarItem extends SuperComponent { + constructor() { + super(...arguments); + this.parent = null; + this.relations = { + './tab-bar': { + type: 'ancestor', + linked(parent) { + this.parent = parent; + this.setData({ + split: parent.data.split, + currentName: this.properties.value ? this.properties.value : parent.initName(), + }); + parent.updateChildren(); + }, + }, + }; + this.options = { + multipleSlots: true, + }; + this.data = { + prefix, + classPrefix, + isSpread: false, + isChecked: false, + hasChildren: false, + currentName: '', + split: true, + }; + this.properties = props; + this.observers = { + subTabBar(value) { + this.setData({ + hasChildren: value.length > 0, + }); + }, + }; + this.methods = { + showSpread() { + this.setData({ + isSpread: true, + }); + }, + toggle() { + const { parent } = this; + const { currentName, hasChildren, isSpread } = this.data; + if (hasChildren) { + this.setData({ + isSpread: !isSpread, + }); + } + parent.updateValue(currentName); + parent.changeOtherSpread(currentName); + }, + selectChild(event) { + const { parent } = this; + const { value } = event.target.dataset; + parent.updateValue(value); + this.setData({ + isSpread: false, + }); + }, + checkActive(value) { + const { currentName, subTabBar } = this.data; + const isChecked = (subTabBar === null || subTabBar === void 0 ? void 0 : subTabBar.some((item) => item.value === value)) || currentName === value; + this.setData({ + isChecked, + }); + }, + closeSpread() { + this.setData({ + isSpread: false, + }); + }, + }; + } +}; +TabbarItem = __decorate([ + wxComponent() +], TabbarItem); +export default TabbarItem; diff --git a/components/tab-bar/tab-bar-item.json b/components/tab-bar/tab-bar-item.json new file mode 100644 index 0000000..69017ce --- /dev/null +++ b/components/tab-bar/tab-bar-item.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "t-icon": "../icon/icon", + "t-badge": "../badge/badge" + } +} diff --git a/components/tab-bar/tab-bar-item.wxml b/components/tab-bar/tab-bar-item.wxml new file mode 100644 index 0000000..0bfc6c7 --- /dev/null +++ b/components/tab-bar/tab-bar-item.wxml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + {{ child.label }} + + + diff --git a/components/tab-bar/tab-bar-item.wxss b/components/tab-bar/tab-bar-item.wxss new file mode 100644 index 0000000..83e8d63 --- /dev/null +++ b/components/tab-bar/tab-bar-item.wxss @@ -0,0 +1,158 @@ +.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-tab-bar-bg-color: #fff; + --td-tab-bar-hover-color: rgba(0, 0, 0, 0.05); + --td-tab-bar-item-color: rgba(0, 0, 0, 0.6); + --td-tab-bar-item-active-color: #0052d9; +} +:host { + flex: 1; +} +.t-tab-bar-item { + height: 48px; + box-sizing: border-box; + user-select: none; + position: relative; + background-color: var(--td-tab-bar-bg-color, #fff); +} +.t-tab-bar-item--active { + background-color: var(--td-tab-bar-hover-color, rgba(0, 0, 0, 0.05)); +} +.t-tab-bar-item.t-is-split:before { + 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); + top: 8px; + bottom: 8px; +} +.t-tab-bar-item__content { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: var(--td-tab-bar-item-color, rgba(0, 0, 0, 0.6)); +} +.t-tab-bar-item__content.t-is-checked { + color: var(--td-tab-bar-item-active-color, #0052d9); +} +.t-tab-bar-item__content.t-is-checked .t-tab-bar-item__icon-menu { + background-color: var(--td-tab-bar-item-active-color, #0052d9); +} +.t-tab-bar-item .t-badge-class { + transform: translate(50%, -10%) !important; +} +.t-tab-bar-item__text { + display: flex; + align-items: center; +} +.t-tab-bar-item__text.t-size-s { + font-size: 10px; + line-height: 18px; +} +.t-tab-bar-item__icon { + height: 24px; +} +.t-tab-bar-item__icon-menu { + width: 8px; + height: 1px; + background-color: #666; + position: relative; + margin-right: 4px; +} +.t-tab-bar-item__icon-menu::before, +.t-tab-bar-item__icon-menu::after { + display: block; + content: ''; + position: absolute; + left: 0; + background-color: inherit; + width: inherit; + height: inherit; +} +.t-tab-bar-item__icon-menu::before { + top: -4px; +} +.t-tab-bar-item__icon-menu::after { + bottom: -4px; +} +.t-tab-bar-item__spread { + position: absolute; + top: 0; + left: 7%; + width: 86%; + background-color: #fff; + transform: translate3d(0, calc(-100% - 16px), 0); + z-index: 1; +} +.t-tab-bar-item__spread::before { + display: block; + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 0; + border: 8px solid transparent; + border-top: 8px solid #fff; + transform: translate3d(-50%, 16px, 0); +} +.t-tab-bar-item__spread-item { + width: 100%; + height: 50px; + display: flex; + align-items: center; + justify-content: center; +} +.t-tab-bar-item__spread-item--active { + background-color: rgba(0, 0, 0, 0.05); +} +.t-tab-bar-item__spread-item + .t-tab-bar-item__spread-item { + position: relative; +} +.t-tab-bar-item__spread-item + .t-tab-bar-item__spread-item:before { + position: absolute; + box-sizing: border-box; + content: ' '; + pointer-events: none; + top: 0; + border-top: 1px solid #e6e6e6; + transform: scaleY(0.5); + border-top-width: 1px; + border-top-style: solid; + border-top-color: #e6e6e6; + width: 80%; +} diff --git a/components/tab-bar/tab-bar.d.ts b/components/tab-bar/tab-bar.d.ts new file mode 100644 index 0000000..5748a58 --- /dev/null +++ b/components/tab-bar/tab-bar.d.ts @@ -0,0 +1,26 @@ +import { SuperComponent, RelationsOptions } from '../common/src/index'; +export default class Tabbar extends SuperComponent { + relations: RelationsOptions; + externalClasses: string[]; + backupValue: number; + data: { + prefix: string; + classPrefix: string; + }; + properties: import("./type").TdTabBarProps; + controlledProps: { + key: string; + event: string; + }[]; + observers: { + value(): void; + }; + ready(): void; + methods: { + showChildren(): void; + updateChildren(): void; + updateValue(value: any): void; + changeOtherSpread(value: any): void; + initName(): any; + }; +} diff --git a/components/tab-bar/tab-bar.js b/components/tab-bar/tab-bar.js new file mode 100644 index 0000000..82c8b29 --- /dev/null +++ b/components/tab-bar/tab-bar.js @@ -0,0 +1,84 @@ +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 { wxComponent, SuperComponent } from '../common/src/index'; +import config from '../common/config'; +import props from './props'; +const { prefix } = config; +const classPrefix = `${prefix}-tab-bar`; +let Tabbar = class Tabbar extends SuperComponent { + constructor() { + super(...arguments); + this.relations = { + './tab-bar-item': { + type: 'descendant', + }, + }; + this.externalClasses = [`${prefix}-class`]; + this.backupValue = -1; + this.data = { + prefix, + classPrefix, + }; + this.properties = props; + this.controlledProps = [ + { + key: 'value', + event: 'change', + }, + ]; + this.observers = { + value() { + this.updateChildren(); + }, + }; + this.methods = { + showChildren() { + const items = this.getRelationNodes('./tab-bar-item'); + const len = items.length; + const { value } = this.data; + if (len > 0) { + items.forEach((child) => { + if (child.properties.value === value) { + child.showSpread(); + } + }); + } + }, + updateChildren() { + const items = this.getRelationNodes('./tab-bar-item'); + const len = items.length; + const { value } = this.data; + if (len > 0) { + items.forEach((child) => { + child.checkActive(value); + }); + } + }, + updateValue(value) { + this._trigger('change', { value }); + }, + changeOtherSpread(value) { + const items = this.getRelationNodes('./tab-bar-item'); + items.forEach((child) => { + if (child.properties.value !== value) { + child.closeSpread(); + } + }); + }, + initName() { + return (this.backupValue += 1); + }, + }; + } + ready() { + this.showChildren(); + } +}; +Tabbar = __decorate([ + wxComponent() +], Tabbar); +export default Tabbar; diff --git a/components/tab-bar/tab-bar.json b/components/tab-bar/tab-bar.json new file mode 100644 index 0000000..dc2cffb --- /dev/null +++ b/components/tab-bar/tab-bar.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "t-tab-bar-item": "./tab-bar-item" + } +} diff --git a/components/tab-bar/tab-bar.wxml b/components/tab-bar/tab-bar.wxml new file mode 100644 index 0000000..b8b97de --- /dev/null +++ b/components/tab-bar/tab-bar.wxml @@ -0,0 +1,5 @@ + + + diff --git a/components/tab-bar/tab-bar.wxss b/components/tab-bar/tab-bar.wxss new file mode 100644 index 0000000..707f7f1 --- /dev/null +++ b/components/tab-bar/tab-bar.wxss @@ -0,0 +1,60 @@ +.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-tab-bar-border-color: #e6e6e6; +} +.t-tab-bar { + width: 100%; + display: flex; + flex-wrap: nowrap; + align-items: center; + position: relative; + font-size: 16px; + background-color: var(--td-tab-bar-bg-color, #fff); +} +.t-tab-bar--border::before { + z-index: 1; + position: absolute; + box-sizing: border-box; + content: ' '; + pointer-events: none; + right: 0; + left: 0; + top: 0; + border-top: 1px solid var(--td-tab-bar-border-color); + transform: scaleY(0.5); +} +.t-tab-bar--fixed { + position: fixed; + left: 0; + bottom: 0; +} +.t-tab-bar--safe { + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); +} diff --git a/components/tab-bar/type.d.ts b/components/tab-bar/type.d.ts new file mode 100644 index 0000000..8232051 --- /dev/null +++ b/components/tab-bar/type.d.ts @@ -0,0 +1,53 @@ +import { BadgeProps } from '../badge/index'; +export interface TdTabBarProps { + bordered?: { + type: BooleanConstructor; + value?: boolean; + }; + externalClasses?: { + type: ArrayConstructor; + value?: ['t-class']; + }; + fixed?: { + type: BooleanConstructor; + value?: boolean; + }; + safeAreaInsetBottom?: { + type: BooleanConstructor; + value?: boolean; + }; + split?: { + type: BooleanConstructor; + value?: boolean; + }; + value?: { + type: null; + value?: string | number | Array; + }; + defaultValue?: { + type: null; + value?: string | number | Array; + }; +} +export interface TdTabBarItemProps { + badgeProps?: { + type: ObjectConstructor; + value?: BadgeProps; + }; + icon?: { + type: StringConstructor; + value?: string; + }; + subTabBar?: { + type: ArrayConstructor; + value?: SubTabBarItem[]; + }; + value?: { + type: null; + value?: string | number; + }; +} +export interface SubTabBarItem { + value: string; + label: string; +} diff --git a/components/tab-bar/type.js b/components/tab-bar/type.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/components/tab-bar/type.js @@ -0,0 +1 @@ +export {}; diff --git a/pages/foot-tab/foot-tab.js b/pages/foot-tab/foot-tab.js new file mode 100644 index 0000000..10193eb --- /dev/null +++ b/pages/foot-tab/foot-tab.js @@ -0,0 +1,57 @@ +// pages/component/foot-tab.js +let aIconList = ['check-rectangle','star','notification','circle']; +let cure = 1 +Component({ + /** + * 组件的属性列表 + */ + properties: { + clickValue: { + type: Array, + value: aIconList + } + }, + + /** + * 组件的初始数据 + */ + data: { + clickValue: cure, + message: {dot: true} + }, + + /** + * 组件的方法列表 + */ + methods: { + setIconData(cur){ + cure = cur; + this.setData({ + clickValue: cur + }) + if (cur == 1){ + wx.redirectTo({ + url: '../index/index' + }) + } + if (cur == 2){ + wx.redirectTo({ + url: '../today/index' + }) + } + if (cur == 3){ + wx.redirectTo({ + url: '../message/index' + }) + } + if (cur == 4){ + wx.redirectTo({ + url: '../myself/index' + }) + } + }, + onChange(event) { + this.setIconData(event.detail.value); + }, + } +}) diff --git a/pages/foot-tab/foot-tab.json b/pages/foot-tab/foot-tab.json new file mode 100644 index 0000000..ec11f61 --- /dev/null +++ b/pages/foot-tab/foot-tab.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "t-tab-bar": "/components/tab-bar/tab-bar", + "t-tab-bar-item": "/components/tab-bar/tab-bar-item" + } +} diff --git a/pages/foot-tab/foot-tab.wxml b/pages/foot-tab/foot-tab.wxml new file mode 100644 index 0000000..4719ac0 --- /dev/null +++ b/pages/foot-tab/foot-tab.wxml @@ -0,0 +1,7 @@ + + + 清单 + 今日任务 + 消息 + 我的 + diff --git a/pages/foot-tab/foot-tab.wxss b/pages/foot-tab/foot-tab.wxss new file mode 100644 index 0000000..d85e96e --- /dev/null +++ b/pages/foot-tab/foot-tab.wxss @@ -0,0 +1 @@ +/* pages/component/foot-tab.wxss */ \ No newline at end of file diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..92eb37c --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,48 @@ +// index.js +// 获取应用实例 +const app = getApp() +Page({ + data: { + aIconList: ['check-rectangle-filled','star','notification','circle'], + motto: 'Hello World', + userInfo: {}, + hasUserInfo: false, + canIUse: wx.canIUse('button.open-type.getUserInfo'), + canIUseGetUserProfile: false, + canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false + }, + // 事件处理函数 + bindViewTap() { + wx.navigateTo({ + url: '../logs/logs' + }) + }, + onLoad() { + if (wx.getUserProfile) { + this.setData({ + canIUseGetUserProfile: true + }) + } + }, + getUserProfile(e) { + // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 + wx.getUserProfile({ + desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 + success: (res) => { + console.log(res) + this.setData({ + userInfo: res.userInfo, + hasUserInfo: true + }) + } + }) + }, + getUserInfo(e) { + // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息 + console.log(e) + this.setData({ + userInfo: e.detail.userInfo, + hasUserInfo: true + }) + } +}) diff --git a/pages/index/index.json b/pages/index/index.json new file mode 100644 index 0000000..59a2e0b --- /dev/null +++ b/pages/index/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "foot-tab": "../foot-tab/foot-tab" + } +} \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..a67fe7c --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + 请使用1.4.4及以上版本基础库 + + + + {{userInfo.nickName}} + + + + {{motto}} + + + + + \ No newline at end of file diff --git a/pages/index/index.wxss b/pages/index/index.wxss new file mode 100644 index 0000000..eb64203 --- /dev/null +++ b/pages/index/index.wxss @@ -0,0 +1,19 @@ +/**index.wxss**/ +.userinfo { + display: flex; + flex-direction: column; + align-items: center; + color: #aaa; +} + +.userinfo-avatar { + overflow: hidden; + width: 128rpx; + height: 128rpx; + margin: 20rpx; + border-radius: 50%; +} + +.usermotto { + margin-top: 200px; +} \ No newline at end of file diff --git a/pages/logs/logs.js b/pages/logs/logs.js new file mode 100644 index 0000000..85f6aac --- /dev/null +++ b/pages/logs/logs.js @@ -0,0 +1,18 @@ +// logs.js +const util = require('../../utils/util.js') + +Page({ + data: { + logs: [] + }, + onLoad() { + this.setData({ + logs: (wx.getStorageSync('logs') || []).map(log => { + return { + date: util.formatTime(new Date(log)), + timeStamp: log + } + }) + }) + } +}) diff --git a/pages/logs/logs.json b/pages/logs/logs.json new file mode 100644 index 0000000..3ee76c1 --- /dev/null +++ b/pages/logs/logs.json @@ -0,0 +1,4 @@ +{ + "navigationBarTitleText": "查看启动日志", + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/logs/logs.wxml b/pages/logs/logs.wxml new file mode 100644 index 0000000..0b6b645 --- /dev/null +++ b/pages/logs/logs.wxml @@ -0,0 +1,6 @@ + + + + {{index + 1}}. {{log.date}} + + diff --git a/pages/logs/logs.wxss b/pages/logs/logs.wxss new file mode 100644 index 0000000..94d4b88 --- /dev/null +++ b/pages/logs/logs.wxss @@ -0,0 +1,8 @@ +.log-list { + display: flex; + flex-direction: column; + padding: 40rpx; +} +.log-item { + margin: 10rpx; +} diff --git a/pages/message/index.js b/pages/message/index.js new file mode 100644 index 0000000..b73fc1f --- /dev/null +++ b/pages/message/index.js @@ -0,0 +1,66 @@ +// pages/message/index.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + aIconList: ['check-rectangle','star','notification-filled','circle'], + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) diff --git a/pages/message/index.json b/pages/message/index.json new file mode 100644 index 0000000..b36ebcb --- /dev/null +++ b/pages/message/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "foot-tab": "../foot-tab/foot-tab" + } +} diff --git a/pages/message/index.wxml b/pages/message/index.wxml new file mode 100644 index 0000000..95710e7 --- /dev/null +++ b/pages/message/index.wxml @@ -0,0 +1,5 @@ + +您有新的消息 + + + diff --git a/pages/message/index.wxss b/pages/message/index.wxss new file mode 100644 index 0000000..97b283a --- /dev/null +++ b/pages/message/index.wxss @@ -0,0 +1 @@ +/* pages/message/index.wxss */ \ No newline at end of file diff --git a/pages/myself/index.js b/pages/myself/index.js new file mode 100644 index 0000000..a8d1d8c --- /dev/null +++ b/pages/myself/index.js @@ -0,0 +1,66 @@ +// pages/myself/index.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + aIconList: ['check-rectangle','star','notification','info-circle-filled'], + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) diff --git a/pages/myself/index.json b/pages/myself/index.json new file mode 100644 index 0000000..b36ebcb --- /dev/null +++ b/pages/myself/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "foot-tab": "../foot-tab/foot-tab" + } +} diff --git a/pages/myself/index.wxml b/pages/myself/index.wxml new file mode 100644 index 0000000..91dee11 --- /dev/null +++ b/pages/myself/index.wxml @@ -0,0 +1,5 @@ + +关于我的 + + + diff --git a/pages/myself/index.wxss b/pages/myself/index.wxss new file mode 100644 index 0000000..505d799 --- /dev/null +++ b/pages/myself/index.wxss @@ -0,0 +1 @@ +/* pages/myself/index.wxss */ \ No newline at end of file diff --git a/pages/today/index.js b/pages/today/index.js new file mode 100644 index 0000000..51c576b --- /dev/null +++ b/pages/today/index.js @@ -0,0 +1,66 @@ +// pages/today/index.js +Page({ + + /** + * 页面的初始数据 + */ + data: { + aIconList: ['check-rectangle','star-filled','notification','info-circle'], + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + } +}) diff --git a/pages/today/index.json b/pages/today/index.json new file mode 100644 index 0000000..b36ebcb --- /dev/null +++ b/pages/today/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "foot-tab": "../foot-tab/foot-tab" + } +} diff --git a/pages/today/index.wxml b/pages/today/index.wxml new file mode 100644 index 0000000..da94a01 --- /dev/null +++ b/pages/today/index.wxml @@ -0,0 +1,5 @@ + +今日任务 + + + diff --git a/pages/today/index.wxss b/pages/today/index.wxss new file mode 100644 index 0000000..acffbb0 --- /dev/null +++ b/pages/today/index.wxss @@ -0,0 +1 @@ +/* pages/today/index.wxss */ \ No newline at end of file diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..9a85eac --- /dev/null +++ b/project.config.json @@ -0,0 +1,51 @@ +{ + "description": "项目配置文件", + "packOptions": { + "ignore": [], + "include": [] + }, + "setting": { + "bundle": false, + "userConfirmedBundleSwitch": false, + "urlCheck": true, + "scopeDataCheck": false, + "coverView": true, + "es6": true, + "postcss": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "preloadBackgroundData": false, + "minified": true, + "autoAudits": false, + "newFeature": false, + "uglifyFileName": false, + "uploadWithSourceMap": true, + "useIsolateContext": true, + "nodeModules": false, + "enhance": true, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "showShadowRootInWxmlPanel": true, + "packNpmManually": false, + "enableEngineNative": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "showES6CompileOption": false, + "minifyWXML": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + } + }, + "compileType": "miniprogram", + "libVersion": "2.19.4", + "appid": "wxb1f499f0a173865b", + "projectname": "miniprogram-92", + "condition": {}, + "editorSetting": { + "tabIndent": "insertSpaces", + "tabSize": 4 + } +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..6635189 --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,7 @@ +{ + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "projectname": "quinn", + "setting": { + "compileHotReLoad": true + } +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..764bc2c --- /dev/null +++ b/utils/util.js @@ -0,0 +1,19 @@ +const formatTime = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : `0${n}` +} + +module.exports = { + formatTime +}