初始化:小程序同步

This commit is contained in:
Cc 2025-04-15 15:44:51 +08:00
commit a25b49fd6d
1361 changed files with 64476 additions and 0 deletions

31
.eslintrc.js Normal file
View File

@ -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: {},
}

119
README.md Normal file
View File

@ -0,0 +1,119 @@
<p align="center">
<a href="https://tdesign.tencent.com/" target="_blank">
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/site/TDesign.png">
</a>
</p>
<p align="center">
<a href="https://github.com/Tencent/tdesign-miniprogram/blob/develop/LICENSE">
<img src="https://img.shields.io/npm/l/tdesign-miniprogram.svg?sanitize=true" alt="License">
</a>
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
<img src="https://img.shields.io/npm/v/tdesign-miniprogram.svg?sanitize=true" alt="Version">
</a>
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
<img src="https://img.shields.io/npm/dw/tdesign-miniprogram" alt="Downloads">
</a>
</p>
[TDesign](https://github.com/Tencent/tdesign) 适配微信小程序的组件库。
## 预览
小程序组件示例小程序,请使用微信扫码预览 ↓
<br/>
<img width="260" src="https://user-images.githubusercontent.com/7017290/146479952-b05298e8-f6ac-44a1-b73c-7abd8b9b3914.jpeg" />
## 安装
### 使用 NPM
小程序已经支持使用 NPM 安装第三方包。
具体使用方式,可以参考小程序官网文档: [《NPM 支持》](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html?search-key=npm)
```bash
npm i tdesign-miniprogram -S --production
```
> 建议使用 NPM不再推荐“源码拷贝的方式”
## 使用组件
以按钮组件为例,只需要在 `JSON` 文件中引入按钮对应的自定义组件即可
```json
{
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button"
}
}
```
## 在开发者工具中预览
```bash
# 安装项目依赖
npm install
# 执行组件编译
npm run dev
```
打开[微信开发者工具](https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html),把 `_example` 目录添加进去就可以预览示例了。
## 基础库版本
最低基础库版本`^2.6.5`
## 反馈&共建
目前TDesign 小程序组件库已在[ github ](https://github.com/Tencent/tdesign-miniprogram)上开源,欢迎大家反馈问题和参与共建:
<img src="https://we-retail-static-1300977798.cos.ap-guangzhou.myqcloud.com/retail-mp/common/wechat-group.jpg" width = "230" height = "290" alt="模版小程序页面详情" align=center />
## 仓库
TDesign 是一个 `multi-repo` TDesign 有如下代码仓库:
### 桌面端组件库
| 仓库 | 描述 | 状态 |
| --------------------------------------------------------------- | -------------------- | -------- |
| [tdesign-vue](https://github.com/Tencent/tdesign-vue) | Vue 2.x 技术栈 | `Beta` |
| [tdesign-vue-next](https://github.com/Tencent/tdesign-vue-next) | Vue 3.x 技术栈 | `Alpha` |
| [tdesign-react](https://github.com/Tencent/tdesign-react) | React 16.x 技术栈 | `Alpha` |
| tdesign-angular | 基于 Angular 10 实现 | `待上线` |
### 移动端组件库
| 仓库 | 描述 | 状态 |
| --------------------------------------------------------------------- | ----------------- | -------- |
| [tdesign-miniprogram](https://github.com/Tencent/tdesign-miniprogram) | 微信小程序 | `Alpha` |
| [tdesign-mobile-vue](https://github.com/Tencent/tdesign-mobile-vue) | Vue 3.x 技术栈 | `Alpha` |
| tdesign-mobile-react | React 16.x 技术栈 | `待上线` |
| tdesign-flutter | 1.17.0 | `待上线` |
### 基础通用仓库
| 仓库 | 描述 |
| ----------------------------------------------------------- | -------------------- |
| [tdesign](https://github.com/Tencent/tdesign) | TDesign 主仓库和文档 |
| [tdesign-icons](https://github.com/Tencent/tdesign-icons) | TDesign 公共图标 |
| [tdesign-common](https://github.com/Tencent/tdesign-common) | TDesign 公共样式 |
### 解决方案及周边
| 仓库 | 描述 |
| --------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| [tdesign-starter-cli](https://github.com/Tencent/tdesign-starter-cli) | TDesign 解决方案的脚手架 |
| [tdesign-vue-starter](https://github.com/Tencent/tdesign-vue-starter) | 基于 tdesign-vue 的解决方案 |
| [tdesign-vue-next-starter](https://github.com/Tencent/tdesign-vue-next-starter) | 基于 tdesign-vue-next 的解决方案 |
| [tdesign-react-starter](https://github.com/Tencent/tdesign-react-starter) | 基于 tdesign-react 的解决方案 |
| [tdesign-miniprogram-starter-retail](https://github.com/Tencent/tdesign-miniprogram-starter-retail) | 基于 tdesign-miniprogram 的零售行业解决方案 |
## 开源协议
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-miniprogram/LICENSE)。

BIN
__MACOSX/pages/._.DS_Store Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
app.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

1
app.d.ts.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/app.ts"],"names":[],"mappings":"","file":"app.d.ts","sourcesContent":["import gulpError from './utils/gulpError';\n\nApp({\n onShow() {\n if (gulpError !== 'gulpErrorPlaceHolder') {\n wx.redirectTo({\n url: `/pages/gulp-error/index?gulpError=${gulpError}`,\n });\n }\n },\n});\n"]}

86
app.js Normal file
View File

@ -0,0 +1,86 @@
import gulpError from './utils/gulpError';
App({
onLaunch() {
},
UpdateManager(){
//微信小程序用户及时更新到最新版本
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
console.log('是否有新版本: ', +res.hasUpdate)
if (!res.hasUpdate) {
wx.hideLoading()
}else{
wx.showLoading({
title: '新版本加载中..',
mask: true
})
}
})
updateManager.onUpdateReady(function () {
wx.hideLoading()
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?(如您之前已登录过,更新后直接点击授权登录即可)',
showCancel: false,
success: function (res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
wx.hideLoading();
wx.showModal({
title: '提示',
content: '检查到有新版本,但下载失败,请检查网络后重试',
showCancel: false
})
})
setTimeout(wx.hideLoading, 5000)
},
onShow() {
this.UpdateManager()
if (gulpError !== 'gulpErrorPlaceHolder') {
wx.redirectTo({
url: `/pages/gulp-error/index?gulpError=${gulpError}`,
});
}
},
globalData: {
systemInfo: null, //客户端设备信息
userInfo: null,
url: 'https://wt.lidinghb.com',
fileUrl: 'https://wt.lidinghb.com/static/img/',
tabBar: {
"backgroundColor": "#ffffff",
"color": "#979795",
"selectedColor": "#1c1c1b",
"list": [{
"pagePath": "/pages/index/index",
"iconPath": "icon/icon_home.png",
"selectedIconPath": "icon/icon_home_HL.png",
"text": "首页"
},
{
"pagePath": "/pages/middle/middle",
"iconPath": "icon/icon_release.png",
"isSpecial": true,
"text": "发布"
},
{
"pagePath": "/pages/mine/mine",
"iconPath": "icon/icon_mine.png",
"selectedIconPath": "icon/icon_mine_HL.png",
"text": "我的"
}
]
}
}
});
//# sourceMappingURL=app.js.map

1
app.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/app.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,GAAG,CAAC;IACF,MAAM;QACJ,IAAI,SAAS,KAAK,sBAAsB,EAAE;YACxC,EAAE,CAAC,UAAU,CAAC;gBACZ,GAAG,EAAE,qCAAqC,SAAS,EAAE;aACtD,CAAC,CAAC;SACJ;IACH,CAAC;CACF,CAAC,CAAC","file":"app.js","sourcesContent":["import gulpError from './utils/gulpError';\n\nApp({\n onShow() {\n if (gulpError !== 'gulpErrorPlaceHolder') {\n wx.redirectTo({\n url: `/pages/gulp-error/index?gulpError=${gulpError}`,\n });\n }\n },\n});\n"]}

115
app.json Normal file
View File

@ -0,0 +1,115 @@
{
"pages": [
"pages/index/index",
"pages/resetting/resetting",
"pages/search-site/search-site",
"pages/search/search",
"pages/login/login",
"pages/t-water/t-water",
"pages/guaranteeadd/guaranteeadd",
"pages/guarantee/guarantee",
"pages/gutotask/gutotask",
"pages/u-task/u-task",
"pages/n-task/n-task",
"pages/t-query/t-query",
"pages/line/index",
"pages/t-repair/t-repair",
"pages/o-site/o-site",
"pages/live/live",
"pages/d-task/d-task",
"pages/c-dispatch/c-dispatch",
"pages/t-site/t-site",
"pages/a-task/a-task",
"pages/t-dispatch/t-dispatch",
"pages/a-dispatch/a-dispatch",
"pages/s-task/s-task",
"pages/sign/sign",
"pages/t-mail/t-mail",
"pages/s-remould/s-remould",
"pages/search-user/search-user",
"pages/s-remould-task/s-remould-task",
"pages/p-task/p-task",
"pages/t-map/t-map"
],
"subpackages": [
{
"root": "packageD",
"pages": [
"pages/video/video",
"pages/live/live",
"pages/device/device"
]
}
],
"usingComponents": {
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-avatar-group": "tdesign-miniprogram/avatar/avatar-group",
"t-badge": "tdesign-miniprogram/badge/badge",
"t-button": "tdesign-miniprogram/button/button",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
"t-collapse": "tdesign-miniprogram/collapse/collapse",
"t-collapse-panel": "tdesign-miniprogram/collapse/collapse-panel",
"t-dialog": "tdesign-miniprogram/dialog/dialog",
"t-tabs": "tdesign-miniprogram/tabs/tabs",
"t-tab-panel": "tdesign-miniprogram/tabs/tab-panel",
"t-loading": "tdesign-miniprogram/loading/loading",
"t-button-group": "tdesign-miniprogram/button-group/button-group",
"t-icon": "tdesign-miniprogram/icon/icon",
"t-rate": "tdesign-miniprogram/rate/rate",
"t-progress": "tdesign-miniprogram/progress/progress",
"t-input": "tdesign-miniprogram/input/input",
"t-textarea": "tdesign-miniprogram/textarea/textarea",
"t-message": "tdesign-miniprogram/message/message",
"t-toast": "tdesign-miniprogram/toast/toast",
"t-stepper": "tdesign-miniprogram/stepper/stepper",
"t-slider": "tdesign-miniprogram/slider/slider",
"t-radio": "tdesign-miniprogram/radio/radio",
"t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
"t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
"t-checkbox-group": "tdesign-miniprogram/checkbox-group/checkbox-group",
"t-swipe-cell": "tdesign-miniprogram/swipe-cell/swipe-cell",
"t-swiper": "tdesign-miniprogram/swiper/swiper",
"t-swiper-item": "tdesign-miniprogram/swiper/swiper-item",
"t-swiper-nav": "tdesign-miniprogram/swiper/swiper-nav",
"t-sticky": "tdesign-miniprogram/sticky/sticky",
"t-fab": "tdesign-miniprogram/fab/fab",
"t-tab-bar": "tdesign-miniprogram/tab-bar/tab-bar",
"t-tab-bar-item": "tdesign-miniprogram/tab-bar/tab-bar-item",
"t-transition": "tdesign-miniprogram/transition/transition",
"t-indexes": "tdesign-miniprogram/indexes/indexes",
"t-dropdown-menu": "tdesign-miniprogram/dropdown-menu/dropdown-menu",
"t-dropdown-item": "tdesign-miniprogram/dropdown-menu/dropdown-item",
"t-drawer": "tdesign-miniprogram/drawer/drawer",
"t-pull-down-refresh": "tdesign-miniprogram/pull-down-refresh/pull-down-refresh",
"t-footer": "tdesign-miniprogram/footer/footer",
"t-divider": "tdesign-miniprogram/divider/divider",
"t-empty": "tdesign-miniprogram/empty/empty",
"t-back-top": "tdesign-miniprogram/back-top/back-top",
"t-grid-item": "tdesign-miniprogram/grid/grid-item",
"t-grid": "tdesign-miniprogram/grid/grid",
"t-count-down": "tdesign-miniprogram/count-down/count-down",
"t-image": "tdesign-miniprogram/image/image",
"t-search": "tdesign-miniprogram/search/search",
"t-navbar": "tdesign-miniprogram/navbar/navbar",
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker",
"t-action-sheet": "tdesign-miniprogram/action-sheet/action-sheet",
"t-image-viewer": "tdesign-miniprogram/image-viewer/image-viewer"
},
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#ffffff",
"backgroundColor": "#f6f6f6",
"navigationBarTextStyle": "black"
},
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos": ["getLocation"],
"sitemapLocation": "sitemap.json",
"embeddedAppIdList": ["wxf2b3a0262975d8c2"]
}

49
app.wxss Normal file
View File

@ -0,0 +1,49 @@
page {
background: #f6f6f6;
}
.demo {
padding-bottom: 56rpx;
}
.demo-title {
font-size: 40rpx;
font-weight: 700;
line-height: 56rpx;
margin: 48rpx 32rpx 0;
color: rgba(0, 0, 0, 0.9);
}
.demo-desc {
font-size: 24rpx;
color: #999;
margin: 8rpx 32rpx;
line-height: 36rpx;
}
.demo-section {
margin-top: 56rpx;
}
.demo-section__title {
font-size: 32rpx;
margin: 32rpx 32rpx 0;
color: rgba(0, 0, 0, 0.9);
line-height: 48rpx;
}
.demo-section__sub-title {
font-size: 28rpx;
margin: 32rpx 32rpx 24rpx 32rpx;
color: rgba(0, 0, 0, 0.9);
line-height: 44rpx;
}
.demo-section__desc {
font-size: 24rpx;
color: rgba(0, 0, 0, 0.4);
margin: 8rpx 32rpx;
line-height: 40rpx;
}
.demo-section__container {
padding: 0 32rpx;
}
.demo-section .button-group {
margin: 56rrpx 0rpx;
}
.demo-section .button-group-item {
margin-bottom: 48rrpx;
}

BIN
assets/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 B

BIN
assets/device.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/index_icon01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
assets/index_icon02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
assets/index_icon03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
assets/index_icon04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
assets/index_icon05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
assets/index_icon06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
assets/index_icon07.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/index_icon08.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
assets/index_icon09.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
assets/my_marker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

BIN
assets/sing.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
assets/site.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
assets/site_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/task-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

BIN
assets/task_icon01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/task_icon02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/task_icon03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

BIN
assets/task_icon04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

BIN
assets/task_icon05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/task_icon06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

1
components/demo-block/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/components/demo-block/index.ts"],"names":[],"mappings":"","file":"index.d.ts","sourcesContent":["Component({\n options: {\n multipleSlots: true,\n addGlobalClass: true,\n },\n properties: {\n title: {\n type: String,\n default: '',\n },\n desc: {\n type: String,\n default: '',\n },\n operList: Array,\n padding: {\n type: Boolean,\n default: false,\n },\n },\n methods: {\n clickHandle(e) {\n const { type } = e.currentTarget.dataset;\n this.triggerEvent('clickoper', type);\n },\n },\n});\n"]}

View File

@ -0,0 +1,29 @@
Component({
options: {
multipleSlots: true,
addGlobalClass: true,
},
properties: {
title: {
type: String,
default: '',
},
desc: {
type: String,
default: '',
},
operList: Array,
padding: {
type: Boolean,
default: false,
},
},
methods: {
clickHandle(e) {
const { type } = e.currentTarget.dataset;
this.triggerEvent('clickoper', type);
},
},
});
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/components/demo-block/index.ts"],"names":[],"mappings":"AAAA,SAAS,CAAC;IACR,OAAO,EAAE;QACP,aAAa,EAAE,IAAI;QACnB,cAAc,EAAE,IAAI;KACrB;IACD,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE;SACZ;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,EAAE;SACZ;QACD,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE;YACP,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,KAAK;SACf;KACF;IACD,OAAO,EAAE;QACP,WAAW,CAAC,CAAC;YACX,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;KACF;CACF,CAAC,CAAC","file":"index.js","sourcesContent":["Component({\n options: {\n multipleSlots: true,\n addGlobalClass: true,\n },\n properties: {\n title: {\n type: String,\n default: '',\n },\n desc: {\n type: String,\n default: '',\n },\n operList: Array,\n padding: {\n type: Boolean,\n default: false,\n },\n },\n methods: {\n clickHandle(e) {\n const { type } = e.currentTarget.dataset;\n this.triggerEvent('clickoper', type);\n },\n },\n});\n"]}

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1,26 @@
<view class="demo-block {{!title && 'demo-block_notitle'}}">
<view wx:if="{{ title || desc }}" class="demo-block__heander">
<view wx:if="{{ title }}" class="demo-block__heander-title">{{ title }}</view>
<view wx:if="{{ desc }}" class="demo-block__heander-desc {{!title && 'demo-block_subtitle' }}"
>{{ desc }}</view
>
<!-- <slot name="title-right" /> -->
</view>
<view wx:for="{{ operList }}" wx:for-item="operItem" wx:key="oper" class="demo-block__oper">
<view wx:if="{{ operItem.title }}" class="demo-block__oper-subtitle">{{ operItem.title }}</view>
<view wx:for="{{ operItem.btns }}" wx:for-item="btnItem" wx:key="btn">
<t-button
t-class="demo-block__oper-btn"
size="large"
block
data-type="{{ btnItem.type }}"
bind:tap="clickHandle"
>
{{ btnItem.text }}
</t-button>
</view>
</view>
<view class="demo-block__slot {{padding ? 'with-padding' : ''}}">
<slot />
</view>
</view>

View File

@ -0,0 +1,42 @@
.demo-block {
margin: 48rpx 0 0;
line-height: 1.5;
font-size: 32rpx;
}
.demo-block__heander {
color: #000000;
margin: 16rpx 32rpx;
}
.demo-block__heander-title {
font-weight: 700;
}
.demo-block__heander-desc {
margin: 16rpx 0 32rpx;
font-size: 24rpx;
white-space: pre-line;
opacity: 0.4;
}
.demo-block__oper {
margin-top: 16rpx;
}
.demo-block__oper-subtitle {
font-size: 24rpx;
margin-bottom: 32rpx;
opacity: 0.4;
}
.demo-block__oper-btn {
margin: 0 0 32rpx 0;
height: 96rpx;
}
.demo-block__slot {
margin-top: 32rpx;
}
.demo-block__slot.with-padding {
margin: 0 32rpx;
}
.demo-block_notitle {
margin-top: 0px;
}
.demo-block_notitle .demo-block_subtitle {
margin-top: 32rpx;
}

View File

@ -0,0 +1,265 @@
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';
let ctx;
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
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: true
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
}
else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({ isUseNewCanvas });
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
}
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
}
else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,4 @@
<!-- 新的接口对其了H5 -->
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
<!-- 旧的 -->
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>

View File

@ -0,0 +1,4 @@
.ec-canvas {
width: 100%;
height: 100%;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,111 @@
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
}
else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
addEventListener() {
// noop
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}

View File

@ -0,0 +1,196 @@
// components/input-search-select/input-search-select.js
var myRequest = require("../../utils/api.js");
var utils = require("../../utils/utils.js");
Component({
/**
* 组件的属性列表
*/
properties: {
inputLabel:String,
value:null,
parentData:null,
index:Number
},
/**
* 组件的初始数据
*/
data: {
selectDraw:false,
HandlersData:[],
inputFouce:false,
searchName:'-1',
isScroll:false,
selectFlag:false,
},
/**
* 组件的方法列表
*/
methods: {
clearvalue(){
this.setData({
value:{dictName:''}
})
},
clickSelect(e){
let item = e.currentTarget.dataset.val.item
console.log(item)
this.setData({
selectDraw:false,
value:{
dictName: this.properties.index!=4?item.dictName:item.prodName
},
selectFlag:true
})
this.triggerEvent('setDist',{
index:this.properties.index,
val:{
value:item.dictId,
label:item.dictName,
item:item
}
})
},
getlableData(dictName) {
var that = this;
return new Promise((resole, reject) => {
if(that.data.index==4){
myRequest.myRequest('prodInfo/list', {
dictId:that.properties.parentData.value,
prodName:dictName
}, 'get').then(function (res) {
if (res.data.data && res.data.data.length != 0) {
that.setData({
proList: res.data.data
})
let HandlersData = res.data.data.map(item => {
return {
label: item.prodName,
value: item.prodId,
item:item
}
})
resole(HandlersData)
} else {
reject('暂无当前数据,请配置')
}
}).catch(function (res) {
console.log(res);
})
}else{
myRequest.myRequest('renovationDict/list', {
parentId:that.properties.parentData.value,
dictName
}, 'get').then(function (res) {
if (res.data.data.length) {
let HandlersData = res.data.data.map(item => {
return {
label: item.dictName,
value: item.dictId,
item: item
}
})
resole(HandlersData)
} else {
reject([])
}
}).catch(function (res) {
console.log(res);
})
}
})
},
clickHandler(e) {
e=e[0]
if(this.data.selectFlag){
this.setData({
selectFlag:false,
})
return
}
if(e.type=="change"){
this.triggerEvent('setDist',{
index:this.properties.index,
val:{
value:'',
label:e.detail.value
}
})
}
console.log(this.data.searchName,e.detail.value)
if(this.data.searchName!=e.detail.value){
if(this.properties?.parentData?.value){
this.getlableData(e.detail.value).then(res => {
console.log(111111111111)
this.setData({
selectDraw:true,
HandlersData: res,
searchName:e.detail.value
})
}).catch((error) => {
console.log(3)
this.setData({
selectDraw:false,
searchName:e.detail.value,
HandlersData: [],
})
})
}
}
},
focusHandle:utils.debounce(function (e) {
this.clickHandler(e)
}),
blurHandle(){
if( !this.data.isScroll){
this.setData({
selectDraw:false,
searchName:'-1',
HandlersData: [],
})
}
},
bindScrollStart(){
this.setData({
isScroll:true,
})
},
bindScrollEnd(e){
this.setData({
inputFouce:true,
isScroll:false
})
},
}
})

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"t-cell": "tdesign-miniprogram/cell/cell"
}
}

View File

@ -0,0 +1,25 @@
<view style="position: relative;">
<t-input label="{{inputLabel}}:" placeholder="请选择或输入" bind:focus="focusHandle" bind:change="focusHandle"
type="textarea"
hold-keyboard
style="height: 100px;"
focus="{{inputFouce}}"
bind:blur="blurHandle" clearable value="{{value.dictName}}" data-key="1" />
<view>
<scroll-view scroll-y class="selectCss"
binddragend="bindScrollEnd"
binddragstart="bindScrollStart"
enhanced
wx:if="{{selectDraw}}">
<view class="selectCell">
<t-cell wx:for="{{HandlersData}}" bind:tap="clickSelect" data-val="{{row}}" wx:for-item="row" title="{{row.label}}">
</t-cell>
</view>
</scroll-view>
<view class="arrow" wx:if="{{selectDraw}}"></view>
</view>
</view>

View File

@ -0,0 +1,50 @@
/* components/input-search-select/input-search-select.wxss */
/* components/input-search-select.wxss */
.selectCss{
position: absolute;
inset: 0px auto auto 0px;
z-index: 5;
top: 45px;
width: 95%;
overflow: hidden;
border-radius: 5px;
box-sizing: border-box;
max-height: 150px;
border-right: 0;
background: #fff;
border: 1px solid #e4e7ed;
background: #fff;
box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
}
.selectCell{
margin: 5px;
}
.arrow{
position: absolute;
top: 45px;
}
.arrow::after {
position: absolute;
width: 10px;
height: 10px;
z-index: 10;
content: " ";
top: -5px;
border: 0;
left: 75px;
transform: rotate(45deg);
background: #fff;
border: 1px solid #e4e7ed;
box-sizing: border-box;
border-right: 0;
border-bottom: 0;
}

1
components/pull-down-list/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare const itemHeight: number;

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/components/pull-down-list/index.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,UAAU,QAAS,CAAC","file":"index.d.ts","sourcesContent":["const itemHeight = 56 * 2;\n\nComponent({\n data: {\n childBoxHeight: 0,\n },\n externalClasses: ['t-class'],\n properties: {\n defaultOpen: {\n type: Boolean,\n value: false,\n },\n name: {\n type: String,\n value: '',\n },\n icon: {\n type: String,\n value: '',\n },\n childArr: {\n type: Array,\n value: [],\n observer(childArr: any[]) {\n this.setData({\n childBoxHeight: this.data.defaultOpen ? itemHeight * childArr.length : 0,\n });\n },\n },\n },\n methods: {\n switchHandle() {\n const { childArr, childBoxHeight } = this.data;\n this.setData({\n childBoxHeight: childBoxHeight > 0 ? 0 : childArr.length * itemHeight,\n });\n },\n tapChild(e: any) {\n this.triggerEvent('click', e.target.dataset);\n },\n },\n});\n"]}

View File

@ -0,0 +1,43 @@
const itemHeight = 56 * 2;
Component({
data: {
childBoxHeight: 0,
},
externalClasses: ['t-class'],
properties: {
defaultOpen: {
type: Boolean,
value: false,
},
name: {
type: String,
value: '',
},
icon: {
type: String,
value: '',
},
childArr: {
type: Array,
value: [],
observer(childArr) {
this.setData({
childBoxHeight: this.data.defaultOpen ? itemHeight * childArr.length : 0,
});
},
},
},
methods: {
switchHandle() {
const { childArr, childBoxHeight } = this.data;
this.setData({
childBoxHeight: childBoxHeight > 0 ? 0 : childArr.length * itemHeight,
});
},
tapChild(e) {
this.triggerEvent('click', e.target.dataset);
},
},
});
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../example/components/pull-down-list/index.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC;AAE1B,SAAS,CAAC;IACR,IAAI,EAAE;QACJ,cAAc,EAAE,CAAC;KAClB;IACD,eAAe,EAAE,CAAC,SAAS,CAAC;IAC5B,UAAU,EAAE;QACV,WAAW,EAAE;YACX,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,KAAK;SACb;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,EAAE;SACV;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,EAAE;SACV;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,EAAE;YACT,QAAQ,CAAC,QAAe;gBACtB,IAAI,CAAC,OAAO,CAAC;oBACX,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;iBACzE,CAAC,CAAC;YACL,CAAC;SACF;KACF;IACD,OAAO,EAAE;QACP,YAAY;YACV,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC;gBACX,cAAc,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,UAAU;aACtE,CAAC,CAAC;QACL,CAAC;QACD,QAAQ,CAAC,CAAM;YACb,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;KACF;CACF,CAAC,CAAC","file":"index.js","sourcesContent":["const itemHeight = 56 * 2;\n\nComponent({\n data: {\n childBoxHeight: 0,\n },\n externalClasses: ['t-class'],\n properties: {\n defaultOpen: {\n type: Boolean,\n value: false,\n },\n name: {\n type: String,\n value: '',\n },\n icon: {\n type: String,\n value: '',\n },\n childArr: {\n type: Array,\n value: [],\n observer(childArr: any[]) {\n this.setData({\n childBoxHeight: this.data.defaultOpen ? itemHeight * childArr.length : 0,\n });\n },\n },\n },\n methods: {\n switchHandle() {\n const { childArr, childBoxHeight } = this.data;\n this.setData({\n childBoxHeight: childBoxHeight > 0 ? 0 : childArr.length * itemHeight,\n });\n },\n tapChild(e: any) {\n this.triggerEvent('click', e.target.dataset);\n },\n },\n});\n"]}

View File

@ -0,0 +1,3 @@
{
"component": true
}

View File

@ -0,0 +1,12 @@
<view class="pullDownList t-class {{ childBoxHeight > 0 ? 'actived' : '' }}">
<view class="switchBox" catch:tap="switchHandle">
<view class="name">{{ name }}</view>
<t-icon name="{{icon}}" size="48rpx" color="#A6A6A6" t-class="icon" />
</view>
<view class="childBox" style="height: {{ childBoxHeight }}rpx">
<view class="child" wx:for="{{childArr}}" wx:key="name" data-item="{{item}}" bind:tap="tapChild">
{{ item.name }} {{ item.label }}
<t-icon name="chevron-right" color="#bbb" />
</view>
</view>
</view>

View File

@ -0,0 +1,49 @@
.pullDownList {
width: 100%;
box-sizing: border-box;
background-color: #fff;
border-radius: 8rpx;
margin-bottom: 24rpx;
overflow: hidden;
}
.pullDownList .switchBox {
height: 120rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 32rpx;
font-size: 32rpx;
line-height: 48rpx;
color: #333;
}
.pullDownList .name,
.pullDownList .icon {
transition: opacity 0.3s;
}
.pullDownList .name {
opacity: 0.9;
}
.pullDownList.actived .name {
opacity: 0.4;
}
.pullDownList.actived .icon {
opacity: 0.4;
}
.pullDownList .childBox {
transition: height 0.3s;
}
.pullDownList .childBox .child {
box-sizing: border-box;
border-bottom: 1rpx solid #e5e5e5;
height: 112rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 32rpx;
margin-right: 32rpx;
font-size: 32rpx;
opacity: 0.9;
}
.pullDownList .childBox .child:last-of-type {
border-bottom-color: transparent;
}

View File

@ -0,0 +1,250 @@
import { fetchData, stsFailContent } from '../utils/index';
let wifiConfigTimer = null;
let wifiConnectTimer = null;
class WeChat_EConnectWifi {
constructor(params) {
this.params = params;
// const { accessToken, deviceSerial, validateCode, customId } = params;
}
// 扫描二维码
scanDevice(accessToken) {
wx.scanCode({
success (res) {
console.log('扫描结果',res)
const result = res.result;
console.log(result);
const temp = result.split('\r');
console.log('temp', temp);
if (temp && temp.length > 0) {
// const res = temp[0];
const deviceSerial = temp[1];
const validateCode = temp[2];
console.log(temp, deviceSerial, validateCode);
wx.setStorage({
key: 'deviceSerial',
data: deviceSerial
});
wx.setStorage({
key: 'validateCode',
data: validateCode
});
}
}
})
}
searchDeviceInfo = (accessToken = '', deviceSerial = '') => {
const promise = new Promise((resolve, reject) => {
if (!accessToken || !deviceSerial) {
reject('searchDeviceInfo:fail:params error');
}
fetchData('/api/v3/device/searchDeviceInfo', '', {accessToken, deviceSerial}, 'POST' ,(res) => {
if (res) {
resolve(res);
} else {
reject('searchDeviceInfo:fail:request fail')
}
}, (err) => {
reject('searchDeviceInfo:fail:network error')
});
});
return promise
}
connectWifi = (deviceSerial = '', validateCode = '', accessToken = '', BSSID, SSID, wifiPassword) => {
const promise = new Promise((resolve, reject) => {
if (!accessToken || !deviceSerial || !validateCode || !BSSID || !SSID || !wifiPassword) {
reject('connectWifi:fail:params error');
}
const deviceSSID = 'SoftAP_' + deviceSerial;
const devicePassword = 'SoftAP_' + validateCode;
wx.startWifi({
success (res) {
console.log(res.errMsg);
wx.connectWifi({
SSID: deviceSSID,
password: devicePassword,
success (res) {
console.log('connectWifi success:', res);
if (res.errCode == 0 || res.errMsg == 'connectWifi:ok') {
// 兼容不同机型有些机型可以通过onWifiConnected识别是否连上目标wifi有些机型不可以,因此设置定时器
let timer = setTimeout(() => {
console.log('超时调用');
wifiConfig(SSID, BSSID, wifiPassword,accessToken);
clearTimeout(timer);
// 如果设备超时无响应将重试一次
// 存在设备超时无响应,此时将再次发送请求
let wifiConfigTimer = setTimeout(() => {
wifiConfig(SSID, BSSID, wifiPassword,accessToken);
clearTimeout(wifiConfigTimer);
}, 30000);
// 设置第二次超时时间,仍超时,则默认跳转至配置失败页面
// 设置响应超时时间为60s
wifiConnectTimer = setTimeout(() => {
clearTimeout(wifiConnectTimer);
reject('connectWifi:fail:connect deviceNetwork fail')
}, 31000);
}, 3000);
// 判断是否连接上目标网络
wx.onWifiConnected((result) => {
console.log('onWifiConnected',result.wifi.SSID);
if (deviceSSID === result.wifi.SSID) {
wifiConfig(SSID, BSSID, wifiPassword,accessToken);
clearTimeout(timer);
// 如果设备超时无响应将重试一次
// 存在设备超时无响应,此时将再次发送请求
let wifiConfigTimer = setTimeout(() => {
wifiConfig(SSID, BSSID, wifiPassword,accessToken);
clearTimeout(wifiConfigTimer);
}, 30000);
// 设置第二次超时时间,仍超时,则默认跳转至配置失败页面
// 设置响应超时时间为30s
wifiConnectTimer = setTimeout(() => {
clearTimeout(wifiConnectTimer);
reject('connectWifi:fail:connect deviceNetwork fail')
}, 31000);
}
});
}
},
fail(err) {
console.log(err);
// that.setData({
// pageLoading: false
// });
console.log('wifi connect fail');
// wx.navigateTo({
// url: '/packageD/pages/connectWifiFail/index?accessToken='+accessToken+'&validateCode='+validateCode+'&deviceSerial='+deviceSerial,
// })
reject('connectWifi:fail:connect deviceNetwork fail')
}
})
}
});
const wifiConfig = (SSID, BSSID, wifiPassword,accessToken) => {
console.log('正在给设备配置wifi');
wx.request({
url: 'http://192.168.8.1:8682/PreNetwork/WifiConfig',
method: 'PUT',
data: {
areaCode:"",
token: accessToken,
lbs_domain: 'open.ys7.com',
wifi_info:{
"bssid": BSSID,
"ssid": SSID,
"password":wifiPassword
},
token: ''
},
header: {
'content-type': 'text/plain'
},
success:(res) =>{
console.log('wifiConfig success:',res);
clearTimeout(wifiConfigTimer);
clearTimeout(wifiConnectTimer);
if (res && res.data ) {
if (wifiConfigTimer) {
clearTimeout(wifiConfigTimer);
}
console.log('wifi 配置接口返回',res);
// 现关闭连接的设备wifi,因为其无法发送网络请求
wx.startWifi({
success (res) {
console.log(res.errMsg);
wx.connectWifi({
SSID: SSID,
password: wifiPassword,
success (res) {
}
})
}
});
// 设备响应需要一定的时间
let timer = setTimeout(() => {
resolve()
clearTimeout(timer)
}, 10000);
} else {
// this.setData({
// pageLoading: false
// });
console.log('wifiConfig fail');
// wx.navigateTo({
// url: '/packageD/pages/connectWifiFail/index?accessToken='+accessToken+'&validateCode='+validateCode+'&deviceSerial='+deviceSerial,
// })
reject('connectWifi:fail:device config fail')
}
},
error:(err)=>{
console.log('wifiConfig fail:',err);
clearTimeout(wifiConfigTimer);
clearTimeout(wifiConnectTimer);
// this.setData({
// pageLoading: false
// });
console.log('wifiConfig fail');
// wx.navigateTo({
// url: '/packageD/pages/connectWifiFail/index?accessToken='+accessToken+'&validateCode='+validateCode+'&deviceSerial='+deviceSerial,
// })
reject('connectWifi:fail:device config fail')
}
})
}
});
return promise
}
// check network
checkNetWork = () => {
wx.getNetworkType({
success(res) {
const networkType = res.networkType;
if (!networkType || networkType === 'none') {
wx.showToast({
title: '当前网络异常',
icon: 'none',
duration: 2000,
});
return
}
}
})
}
}
export const EConnectWifi = (props) => {
const wechat_econnectWif_sdk = new WeChat_EConnectWifi(props)
return wechat_econnectWif_sdk;
}

90
lib/utils/index.js Normal file
View File

@ -0,0 +1,90 @@
export const isPromise = (obj) => {
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
};
export const getQueryString = (name, url) => {
var r = new RegExp("(\\?|#|&)" + name + "=(.*?)(#|&|$)"); var m = (url || window.location.href).match(r); return decodeURIComponent(m ? m[2] : '');
};
export const fetchData = (url, params='', data={}, method='GET' ,callback, errback, timeout = 60000) => {
const CONTENT_TYPE = 'application/x-www-form-urlencoded';
const HOST = 'https://open.ys7.com'; // http://10.10.34.51:8081 https://open.ys7.com
const OPEN_DOMAIN = ''; // /api/v3/console
const ACCESSTOKEN = data ? data.accessToken : '';
wx.request({
url: `${HOST}${OPEN_DOMAIN}${url}${params}`,
method: method,
data: data,
header: {
'content-type': CONTENT_TYPE,
'accessToken': ACCESSTOKEN
},
timeout: timeout,
success: (res) => {
console.log(res.data);
if (res.data) {
callback && callback(res.data)
} else {
wx.showToast({
title: '网络异常请稍后重试',
icon: 'error'
})
}
},
error:(err)=>{
console.log(err);
wx.showToast({
title: '网络异常请稍后重试',
icon: 'error'
});
errback && errback()
},
})
};
export const stsFailContent = (code) => {
let content = '';
switch (code) {
case 0:
break;
case 10001:
content = 'websocket请求参数错误';
break;
case 10002:
content = 'flv转封装失败';
break;
case 10003:
content = 'rtp转封装失败';
break;
case 10004:
content = 'rtmp读写错误 ';
break;
case 10005:
content = 'rtmp接收缓存溢出';
break;
case 6:
content = '连接sts服务失败';
break;
case 11:
content = '无效的房间号';
break;
case 14:
content = 'sts连接vtm失败';
break;
case 17:
content = '房间已满';
break;
case 18:
content = 'auth认证失败';
break;
case 35:
content = '房间号不存在';
break;
}
return content
}

View File

@ -0,0 +1,92 @@
---
title: ActionSheet 动作面板
description: 由用户操作后触发的一种特定的模态弹出框 ,呈现一组与当前情境相关的两个或多个选项。
spline: data
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-89%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-action-sheet": "tdesign-miniprogram/action-sheet/action-sheet",
}
```
## 代码演示
### 基础用法
{{ list }}
### 图标列表型
{{ icon-list }}
### 宫格型
{{ grid }}
### 宫格型-多页
{{ grid-multi }}
### 支持指令调用
```javascript
import ActionSheet, { ActionSheetTheme } from 'tdesign-miniprogram/action-sheet/index';
// 指令调用不同于组件引用不需要传入visible
const basicListOption: ActionSheetShowOption = {
theme: ActionSheetTheme.List,
selector: '#t-action-sheet',
items: [
{
label: '默认选项',
},
{
label: '失效选项',
disabled: true,
},
{
label: '警告选项',
color: '#e34d59',
},
],
};
const handler = ActionSheet.show(basicListOption);
```
指令调用的关闭如下
```javascript
handler.close();
```
## API
### ActionSheet Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
cancel-text | String | 取消 | 设置取消按钮的文本 | N
count | Number | 8 | 设置每页展示菜单的数量,仅当 type=grid 时有效 | N
items | Array | - | 必需。菜单项。TS 类型:`Array<string | ActionSheetItem>` `interface ActionSheetItem {label: string; color?: string; disabled?: boolean; icon?: string; }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/action-sheet/type.ts) | Y
show-cancel | Boolean | true | 是否显示取消按钮 | N
theme | String | list | 展示类型列表和表格形式展示。可选项list/grid | N
visible | Boolean | null | 必需。显示与隐藏 | Y
default-visible | Boolean | false | 必需。显示与隐藏。非受控属性 | Y
external-classes | Array | - | 组件类名,分别用于设置 组件外层元素、组件内容部分、取消按钮 等元素类名。`['t-class', 't-class-content', 't-class-cancel']` | N
### ActionSheet Events
名称 | 参数 | 描述
-- | -- | --
visible-change | `(visible: Boolean)` | 当浮层隐藏或显示时触发。
cancel | - | 点击取消按钮时触发
selected | `(selected: ActionSheetItem | String, index: Number)` | 选择菜单项时触发

View File

@ -0,0 +1,58 @@
import { SuperComponent } from '../common/src/index';
export default class ActionSheet extends SuperComponent {
static show: (options: import("./show").ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
externalClasses: string[];
properties: {
cancelText?: {
type: StringConstructor;
value?: string;
};
count?: {
type: NumberConstructor;
value?: number;
};
items: {
type: ArrayConstructor;
value?: (string | import("./type").ActionSheetItem)[];
};
showCancel?: {
type: BooleanConstructor;
value?: boolean;
};
theme?: {
type: StringConstructor;
value?: "list" | "grid";
};
visible: {
type: BooleanConstructor;
value?: boolean;
};
defaultVisible: {
type: BooleanConstructor;
value?: boolean;
};
};
data: {
prefix: string;
classPrefix: string;
gridThemeItems: any[];
currentSwiperIndex: number;
};
controlledProps: {
key: string;
event: string;
}[];
ready(): void;
methods: {
onSwiperChange(e: WechatMiniprogram.TouchEvent): void;
splitGridThemeActions(): void;
show(options: any): void;
memoInitialData(): void;
close(): void;
onPopupVisibleChange({ detail }: {
detail: any;
}): void;
onSelect(event: WechatMiniprogram.TouchEvent): void;
onCancel(): void;
};
}

View File

@ -0,0 +1,91 @@
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 { chunk } from '../common/utils';
import { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import { ActionSheetTheme, show } from './show';
import props from './props';
const { prefix } = config;
const name = `${prefix}-action-sheet`;
let ActionSheet = class ActionSheet extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-content`, `${prefix}-class-cancel`];
this.properties = Object.assign({}, props);
this.data = {
prefix,
classPrefix: name,
gridThemeItems: [],
currentSwiperIndex: 0,
};
this.controlledProps = [
{
key: 'visible',
event: 'visible-change',
},
];
this.methods = {
onSwiperChange(e) {
const { detail: { current }, } = e;
this.setData({
currentSwiperIndex: current,
});
},
splitGridThemeActions() {
if (this.data.theme !== ActionSheetTheme.Grid)
return;
this.setData({
gridThemeItems: chunk(this.data.items, this.data.count),
});
},
show(options) {
this.setData(Object.assign(Object.assign(Object.assign({}, this.initialData), options), { visible: true }));
this.splitGridThemeActions();
this.autoClose = true;
this._trigger('visible-change', { visible: true });
},
memoInitialData() {
this.initialData = Object.assign(Object.assign({}, this.properties), this.data);
},
close() {
this._trigger('visible-change', { visible: false });
},
onPopupVisibleChange({ detail }) {
if (!detail.visible) {
this._trigger('visible-change', { visible: false });
}
if (this.autoClose) {
this.setData({ visible: false });
this.autoClose = false;
}
},
onSelect(event) {
const { currentSwiperIndex, items, gridThemeItems, count, theme } = this.data;
const { index } = event.currentTarget.dataset;
const isSwiperMode = theme === ActionSheetTheme.Grid;
const item = isSwiperMode ? gridThemeItems[currentSwiperIndex][index] : items[index];
const realIndex = isSwiperMode ? index + currentSwiperIndex * count : index;
if (item) {
this.triggerEvent('selected', { selected: item, index: realIndex });
this._trigger('visible-change', { visible: false });
}
},
onCancel() {
this.triggerEvent('cancel');
},
};
}
ready() {
this.memoInitialData();
this.splitGridThemeActions();
}
};
ActionSheet.show = show;
ActionSheet = __decorate([
wxComponent()
], ActionSheet);
export default ActionSheet;

View File

@ -0,0 +1,12 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-popup": "../popup/popup",
"t-swiper": "../swiper/swiper",
"t-swiper-item": "../swiper/swiper-item",
"t-image": "../image/image",
"t-grid": "../grid/grid",
"t-grid-item": "../grid/grid-item"
}
}

View File

@ -0,0 +1,32 @@
<wxs src="./action-sheet.wxs" module="this" />
<import src="./template/action-sheet-list.wxml" />
<import src="./template/action-sheet-grid.wxml" />
<view id="{{classPrefix}}" class="{{classPrefix}} {{prefix}}-class">
<t-popup visible="{{visible}}" placement="bottom" bind:visible-change="onPopupVisibleChange">
<view class="{{classPrefix}}__content {{prefix}}-class-content">
<block wx:if="{{gridThemeItems.length}}">
<template is="grid" data="{{classPrefix, prefix, gridThemeItems, count, currentSwiperIndex}}" />
</block>
<block wx:elif="{{items && items.length}}">
<view class="{{classPrefix}}__list" wx:for="{{ items }}" wx:key="index">
<template
is="list"
data="{{index, classPrefix, listThemeItemClass: this.getListThemeItemClass({ item, prefix, classPrefix }), item}}"
/>
</view>
</block>
</view>
<slot />
<view wx:if="{{showCancel}}" class="{{classPrefix}}__footer {{classPrefix}}__safe">
<view class="{{classPrefix}}__gap-{{theme}}" />
<view
class="{{classPrefix}}__cancel {{prefix}}-class-cancel"
hover-class="{{classPrefix}}__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
</view>
</t-popup>
</view>

View File

@ -0,0 +1,19 @@
var getListThemeItemClass = function (props) {
var classPrefix = props.classPrefix;
var item = props.item;
var prefix = props.prefix;
var classList = [classPrefix + '__list-item'];
if (item.disabled) {
classList.push(prefix + '-is-disabled');
}
return classList.join(' ');
};
var isImage = function (name) {
return name.indexOf('/') !== -1;
};
module.exports = {
getListThemeItemClass: getListThemeItemClass,
isImage: isImage,
};

View File

@ -0,0 +1,134 @@
.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-action-sheet .flex-center {
display: flex;
align-items: center;
justify-content: center;
}
.t-action-sheet .ellipsis {
word-wrap: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.t-action-sheet__grid {
padding: 48rpx 0 16rpx 0;
}
.t-action-sheet__grid-item {
margin-bottom: 32rpx;
}
.t-action-sheet__list {
background-color: #fff;
border-bottom: 1rpx solid #f6f6f6;
}
.t-action-sheet__list:last-child {
border-bottom: none;
}
.t-action-sheet__list-item {
height: 96rpx;
display: flex;
align-items: center;
justify-content: center;
}
.t-action-sheet__list-item.t-is-disabled {
color: rgba(0, 0, 0, 0.26);
}
.t-action-sheet__list-item-text {
font-size: 32rpx;
word-wrap: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.t-action-sheet__list-item-icon {
margin-right: 16rpx;
}
.t-action-sheet__swiper-wrap {
position: relative;
background-color: #fff;
}
.t-action-sheet__square {
height: 148rpx;
margin-bottom: 32rpx;
}
.t-action-sheet__square-image {
width: 72rpx;
height: 72rpx;
padding: 10rpx;
}
.t-action-sheet__square-text {
width: 100%;
margin-top: 10rpx;
font-size: 28rpx;
color: rgba(0, 0, 0, 0.9);
text-align: center;
word-wrap: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.t-action-sheet__footer {
background-color: #fff;
}
.t-action-sheet__gap-list {
height: 16rpx;
background-color: #f3f3f3;
}
.t-action-sheet__gap-grid {
height: 1rpx;
background-color: #f3f3f3;
}
.t-action-sheet__cancel {
display: flex;
align-items: center;
justify-content: center;
height: 96rpx;
}
.t-action-sheet__dots {
position: absolute;
left: 50%;
bottom: 32rpx;
transform: translateX(-50%);
display: flex;
flex-direction: row;
}
.t-action-sheet__dots-item {
width: 16rpx;
height: 16rpx;
background-color: #dcdcdc;
border-radius: 50%;
margin: 0 16rpx;
transition: all 0.4s ease-in;
}
.t-action-sheet__dots-item.t-is-active {
background-color: #0052d9;
}
.t-action-sheet__safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}

View File

@ -0,0 +1,3 @@
import ActionSheet from './action-sheet';
export * from './show';
export default ActionSheet;

View File

@ -0,0 +1,3 @@
import ActionSheet from './action-sheet';
export * from './show';
export default ActionSheet;

View File

@ -0,0 +1,3 @@
import { TdActionSheetProps } from './type';
declare const props: TdActionSheetProps;
export default props;

View File

@ -0,0 +1,30 @@
const props = {
cancelText: {
type: String,
value: '取消',
},
count: {
type: Number,
value: 8,
},
items: {
type: Array,
},
showCancel: {
type: Boolean,
value: true,
},
theme: {
type: String,
value: 'list',
},
visible: {
type: Boolean,
value: null,
},
defaultVisible: {
type: Boolean,
value: false,
},
};
export default props;

View File

@ -0,0 +1,29 @@
/// <reference types="miniprogram-api-typings" />
/// <reference types="miniprogram-api-typings" />
export interface ActionSheetItem {
label: string;
color?: string;
disabled?: boolean;
icon?: string;
}
declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
export declare enum ActionSheetTheme {
List = "list",
Grid = "grid"
}
interface ActionSheetProps {
visible: boolean;
items: Array<string | ActionSheetItem>;
defaultVisible?: boolean;
cancelText?: string;
count?: number;
showCancel?: boolean;
theme?: ActionSheetTheme;
}
export interface ActionSheetShowOption extends Omit<ActionSheetProps, 'visible'> {
context?: Context;
selector?: string;
}
export declare const show: (options: ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
export declare const close: (options: ActionSheetShowOption) => void;
export {};

View File

@ -0,0 +1,33 @@
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { getInstance } from '../common/utils';
export var ActionSheetTheme;
(function (ActionSheetTheme) {
ActionSheetTheme["List"] = "list";
ActionSheetTheme["Grid"] = "grid";
})(ActionSheetTheme || (ActionSheetTheme = {}));
export const show = function (options) {
const _a = Object.assign({}, options), { context, selector = '#t-action-sheet' } = _a, otherOptions = __rest(_a, ["context", "selector"]);
const instance = getInstance(context, selector);
if (instance) {
instance.show(Object.assign({}, otherOptions));
return instance;
}
console.error('未找到组件,请确认 selector && context 是否正确');
};
export const close = function (options) {
const { context, selector = '#t-action-sheet' } = Object.assign({}, options);
const instance = getInstance(context, selector);
if (instance) {
instance.close();
}
};

View File

@ -0,0 +1,46 @@
<import src="./action-sheet-item.wxml" />
<template name="grid">
<block wx:if="{{gridThemeItems.length === 1}}">
<t-grid align="center" t-class="{{classPrefix}}__grid" column="{{count / 2}}" class="{{classPrefix}}__single-wrap">
<t-grid-item
t-class="{{classPrefix}}__grid-item"
class="{{classPrefix}}__square"
wx:for="{{gridThemeItems[0]}}"
wx:key="index"
bind:tap="onSelect"
data-index="{{index}}"
>
<template is="item" data="{{classPrefix, item}}" />
</t-grid-item>
</t-grid>
</block>
<block wx:elif="{{gridThemeItems.length > 1}}">
<view class="{{classPrefix}}__swiper-wrap">
<t-swiper height="{{456}}" autoplay="{{false}}" current="{{currentSwiperIndex}}" bindchange="onSwiperChange">
<t-swiper-item wx:for="{{gridThemeItems}}" wx:key="index">
<t-grid align="center" t-class="{{classPrefix}}__grid" column="{{count / 2}}">
<t-grid-item
t-class="{{classPrefix}}__grid-item"
class="{{classPrefix}}__square"
wx:for="{{item}}"
wx:key="index"
data-index="{{index}}"
bind:tap="onSelect"
>
<template is="item" data="{{classPrefix, item}}" />
</t-grid-item>
</t-grid>
</t-swiper-item>
</t-swiper>
<view class="{{classPrefix}}__nav">
<view class="{{classPrefix}}__dots">
<view
wx:for="{{gridThemeItems.length}}"
wx:key="index"
class="{{classPrefix}}__dots-item {{index === currentSwiperIndex ? prefix + '-is-active' : ''}}"
/>
</view>
</view>
</view>
</block>
</template>

View File

@ -0,0 +1,17 @@
<wxs src="../action-sheet.wxs" module="this" />
<template name="item">
<block>
<t-image
slot="image"
wx:if="{{ this.isImage(item.icon) }}"
lazy
class="{{classPrefix}}__square-image"
src="{{item.icon}}"
mode="aspectFill"
/>
<t-icon slot="image" wx:else name="{{item.icon}}" class="{{classPrefix}}__square-image" size="72rpx" />
</block>
<view slot="text" style="{{ item.color ? 'color: ' + item.color : '' }}" class="{{classPrefix}}__square-text">
{{item.label}}
</view>
</template>

View File

@ -0,0 +1,11 @@
<template name="list">
<view
data-index="{{index}}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{listThemeItemClass}}"
bind:tap="onSelect"
>
<t-icon wx:if="{{item.icon}}" name="{{item.icon}}" class="{{classPrefix}}__list-item-icon" size="48rpx"></t-icon>
<view class="{{classPrefix}}__list-item-text">{{item.label || item}}</view>
</view>
</template>

View File

@ -0,0 +1,35 @@
export interface TdActionSheetProps {
cancelText?: {
type: StringConstructor;
value?: string;
};
count?: {
type: NumberConstructor;
value?: number;
};
items: {
type: ArrayConstructor;
value?: Array<string | ActionSheetItem>;
};
showCancel?: {
type: BooleanConstructor;
value?: boolean;
};
theme?: {
type: StringConstructor;
value?: 'list' | 'grid';
};
visible: {
type: BooleanConstructor;
value?: boolean;
};
defaultVisible: {
type: BooleanConstructor;
value?: boolean;
};
}
export interface ActionSheetItem {
label: string;
color?: string;
disabled?: boolean;
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,80 @@
---
title: Avatar 头像
description: 用于展示用户头像信息,除了纯展示也可点击进入个人详情等操作。
spline: data
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-99%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-85%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-avatar-group": "tdesign-miniprogram/avatar/avatar-group"
}
```
### 主题定制
CSS 变量名|说明
--|--
--td-avatar-bg-color | 头像背景颜色;
--td-avatar-content-color | 头像内容(文字、图标)颜色;
--td-avatar-group-border-color | 组合头像边框颜色;
## 代码演示
### 基础头像
头像样式可为默认头像、微信头像圆形、方形、自定义文字
<img src="https://tdesign.gtimg.com/miniprogram/readme/avatar-2.png" width="375px" height="50%">
{{ shape }}
### 纯展示 从上往下
<img src="https://tdesign.gtimg.com/miniprogram/readme/avatar-1.png" width="375px" height="50%">
{{ exhibition }}
### 带操作 从下往上
{{ action }}
### 头像大小尺寸及消息提醒
<img src="https://tdesign.gtimg.com/miniprogram/readme/avatar-3.png" width="375px" height="50%">
{{ size }}
## API
### Avatar Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
alt | String | - | 头像替换文本,仅当图片加载失败时有效 | N
badge-props | Object | - | 头像右上角提示信息,继承 Badge 组件的全部特性。如小红点或者数字。TS 类型:`BadgeProps`[Badge API Documents](./badge?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
external-classes | Array | - | 组件类名,用于设置组件外层元素类名。`['t-class', 't-class-image', 't-class-icon', 't-class-alt', 't-class-content']` | N
hide-on-load-failed | Boolean | false | 加载失败时隐藏图片 | N
icon | String / Slot | - | 图标 | N
image | String | - | 图片地址 | N
shape | String | circle | 形状。可选项circle/round。TS 类型:`ShapeEnum ` `type ShapeEnum = 'circle' | 'round'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
size | String | - | 尺寸示例值small/medium/large/24px/38px 等,默认为 large | N
### Avatar Events
名称 | 参数 | 描述
-- | -- | --
error | \- | 图片加载失败时触发
### AvatarGroup Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
cascading | String | 'right-up' | 图片之间的层叠关系可选值左侧图片在上和右侧图片在上。可选项left-up/right-up。TS 类型:`CascadingValue` `type CascadingValue = 'left-up' | 'right-up'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
collapse-avatar | String / Slot | - | 头像数量超出时,会出现一个头像折叠元素。该元素内容可自定义。默认为 `+N`。示例:`+5``...`, `更多` | N
external-classes | Array | - | 组件类名,用于设置组件外层元素类名。`['t-class', 't-class-image', 't-class-content']` | N
max | Number | - | 能够同时显示的最多头像数量 | N
size | String | medium | 尺寸示例值small/medium/large/24px/38px 等。优先级低于 Avatar.size | N

View File

@ -0,0 +1,3 @@
import { TdAvatarGroupProps } from './type';
declare const props: TdAvatarGroupProps;
export default props;

View File

@ -0,0 +1,20 @@
const props = {
cascading: {
type: String,
value: 'right-up',
},
collapseAvatar: {
type: String,
},
externalClasses: {
type: Array,
},
max: {
type: Number,
},
size: {
type: String,
value: 'medium',
},
};
export default props;

View File

@ -0,0 +1,31 @@
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class AvatarGroup extends SuperComponent {
externalClasses: string[];
properties: import("./type").TdAvatarGroupProps;
data: {
prefix: string;
classPrefix: string;
hasChild: boolean;
length: number;
className: string;
borderSize: string;
};
options: {
multipleSlots: boolean;
};
relations: RelationsOptions;
ready(): void;
lifetimes: {
attached(): void;
};
methods: {
isINcludePX(size: any): boolean;
setClass(): void;
handleHasChild(children: any, hasChild: any): void;
handleChildSlot(max: any, children: any, f: any): void;
handleChildMax(max: any, children: any, isSlotElement: any): void;
handleChildSize(size: any, children: any): void;
handleChildCascading(cascading: any, children: any): void;
handleChildBorder(size: any, children: any): void;
};
}

View File

@ -0,0 +1,123 @@
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 avatarGroupProps from './avatar-group-props';
const { prefix } = config;
const name = `${prefix}-avatar-group`;
let AvatarGroup = class AvatarGroup extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-content`, `${prefix}-class-image`];
this.properties = avatarGroupProps;
this.data = {
prefix,
classPrefix: name,
hasChild: true,
length: 0,
className: '',
borderSize: '',
};
this.options = {
multipleSlots: true,
};
this.relations = {
'./avatar': {
type: 'descendant',
linked() {
this.children = this.getRelationNodes('./avatar');
},
},
};
this.lifetimes = {
attached() {
this.setClass();
},
};
this.methods = {
isINcludePX(size) {
return size.indexOf('px') > -1;
},
setClass() {
const { cascading, size } = this.properties;
const classList = [name, `${prefix}-class`];
const direction = cascading.split('-')[0];
if (this.isINcludePX(size)) {
classList.push(`${name}-offset-${direction}-medium`);
}
else {
classList.push(`${name}-offset-${direction}-${size}`);
}
this.setData({
className: classList.join(' '),
});
},
handleHasChild(children, hasChild) {
children.forEach((child) => {
child.updateIsChild(hasChild);
});
},
handleChildSlot(max, children, f) {
const query = this.createSelectorQuery();
const slotName = `.${this.data.classPrefix}__collapse--slot`;
query.select(slotName).boundingClientRect();
query.exec((res) => {
const isSlot = !!res[0].width;
f(max, children, isSlot);
});
},
handleChildMax(max, children, isSlotElement) {
const len = children.length;
if (!max || max > len)
return;
const slotElement = isSlotElement ? children.pop() : '';
const leftChildren = children.splice(max, len - max, isSlotElement && slotElement);
leftChildren.forEach((child) => {
child.updateShow();
});
},
handleChildSize(size, children) {
if (!size)
return;
children.forEach((child) => {
child.updateSize(size);
});
},
handleChildCascading(cascading, children) {
if (cascading === 'right-up')
return;
const defaultZIndex = 100;
children.forEach((child, index) => {
child.updateCascading(defaultZIndex - index * 10);
});
},
handleChildBorder(size, children) {
const borderSize = this.isINcludePX(size) ? 'medium' : size;
this.setData({
borderSize,
});
children.forEach((child) => {
child.updateBorder(borderSize);
});
},
};
}
ready() {
this.setData({
length: this.children.length,
});
this.handleHasChild(this.children, this.data.hasChild);
this.handleChildSlot(this.properties.max, this.children, this.handleChildMax);
this.handleChildSize(this.properties.size, this.children);
this.handleChildCascading(this.properties.cascading, this.children);
this.handleChildBorder(this.properties.size, this.children);
}
};
AvatarGroup = __decorate([
wxComponent()
], AvatarGroup);
export default AvatarGroup;

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"t-avatar": "./avatar"
}
}

View File

@ -0,0 +1,16 @@
<view class="{{className}}">
<slot />
<!-- 自定义折叠元素 -->
<view class="{{classPrefix}}__collapse--slot {{collapseAvatar ? prefix + '-is-hidden' : ''}}">
<slot name="collapseAvatar" />
</view>
<!-- 默认折叠元素 -->
<view class="{{classPrefix}}__collapse--default" wx:if="{{max && (max < length)}}">
<t-avatar
t-class-image="border--{{borderSize}} {{prefix}}-class-image"
t-class-content="{{prefix}}-class-content"
size="{{size}}"
>{{collapseAvatar || '+N'}}</t-avatar
>
</view>
</view>

View File

@ -0,0 +1,75 @@
.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-avatar-group-border-color: #fff;
}
.border--small {
border: 4rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--medium {
border: 6rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--large {
border: 8rpx solid var(--td-avatar-group-border-color, #fff);
}
.t-avatar-group {
display: inline-flex;
align-items: center;
}
.t-avatar-group-offset-left-small t-avatar:not(:first-child) {
margin-left: -4px;
}
.t-avatar-group-offset-left-medium t-avatar:not(:first-child) {
margin-left: -6px;
}
.t-avatar-group-offset-left-large t-avatar:not(:first-child) {
margin-left: -8px;
}
.t-avatar-group-offset-right-small t-avatar:not(:last-child) {
margin-right: -4px;
}
.t-avatar-group-offset-right-medium t-avatar:not(:last-child) {
margin-right: -6px;
}
.t-avatar-group-offset-right-large t-avatar:not(:last-child) {
margin-right: -8px;
}
.t-avatar-group__collapse--slot {
float: left;
}
.t-avatar-group__collapse--slot:not(:empty) + .t-avatar-group__collapse--default {
display: none;
float: left;
}
.t-avatar-group__collapse--slot:empty + .t-avatar-group__collapse--default {
display: block;
float: left;
}
.t-avatar-group .t-is-hidden {
display: none;
}

View File

@ -0,0 +1,25 @@
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class Avatar extends SuperComponent {
options: {
multipleSlots: boolean;
};
externalClasses: string[];
properties: import("./type").TdAvatarProps;
data: {
prefix: string;
classPrefix: string;
isShow: boolean;
zIndex: number;
isChild: boolean;
borderSize: string;
};
relations: RelationsOptions;
methods: {
updateIsChild(isChild: any): void;
updateShow(): void;
updateSize(size: any): void;
updateCascading(zIndex: any): void;
updateBorder(borderSize: any): void;
};
onLoadError(e: any): void;
}

View File

@ -0,0 +1,78 @@
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import avatarProps from './props';
const { prefix } = config;
const name = `${prefix}-avatar`;
let Avatar = class Avatar extends SuperComponent {
constructor() {
super(...arguments);
this.options = {
multipleSlots: true,
};
this.externalClasses = [
`${prefix}-class`,
`${prefix}-class-image`,
`${prefix}-class-icon`,
`${prefix}-class-alt`,
`${prefix}-class-content`,
];
this.properties = avatarProps;
this.data = {
prefix,
classPrefix: name,
isShow: true,
zIndex: 0,
isChild: false,
borderSize: '',
};
this.relations = {
'./avatar-group': {
type: 'ancestor',
linked(target) {
this.parent = target;
},
},
};
this.methods = {
updateIsChild(isChild) {
this.setData({
isChild,
});
},
updateShow() {
this.setData({
isShow: false,
});
},
updateSize(size) {
if (this.properties.size)
return;
this.setData({ size });
},
updateCascading(zIndex) {
this.setData({ zIndex });
},
updateBorder(borderSize) {
this.setData({ borderSize });
},
};
}
onLoadError(e) {
if (this.properties.hideOnLoadFailed) {
this.setData({
isShow: false,
});
}
this.triggerEvent('error', e.detail);
}
};
Avatar = __decorate([
wxComponent()
], Avatar);
export default Avatar;

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-badge": "../badge/badge",
"t-image": "../image/image"
}
}

View File

@ -0,0 +1,40 @@
<wxs src="./avatar.wxs" module="this" />
<view class="{{classPrefix}}__wrapper {{prefix}}-class" style="{{this.getStyles(isShow, zIndex)}}">
<view
class="{{this.getAvatarOuterClass(classPrefix, size, shape)}} border--{{borderSize}} {{prefix}}-class-image "
style="{{this.getAvatarSizePx(size)}}"
>
<t-image
wx:if="{{image}}"
class="{{prefix}}-image"
t-class-load="{{prefix}}-class-alt"
t-class="{{classPrefix}}__image"
src="{{image}}"
mode="aspectFill"
binderror="onLoadError"
loadFailed="{{alt}}"
/>
<view
wx:elif="{{icon}}"
class="{{classPrefix}}__icon {{this.getIconClass(classPrefix, size)}} {{prefix}}-class-icon"
>
<t-icon name="{{icon}}" />
</view>
<view wx:else class="{{classPrefix}}__text {{prefix}}-class-content">
<slot />
</view>
</view>
<t-badge
class="{{prefix}}-badge-host {{prefix}}-badge__{{shape === 'circle' ? 'circle' : 'round'}}"
wx:if="{{badgeProps.dot || badgeProps.count}}"
color="{{badgeProps.color}}"
count="{{badgeProps.count}}"
max-count="{{badgeProps.maxCount || 100}}"
dot="{{badgeProps.dot}}"
content="{{badgeProps.content}}"
size="{{badgeProps.size}}"
visible="{{badgeProps.visible}}"
offset="{{badgeProps.offset}}"
/>
</view>

View File

@ -0,0 +1,25 @@
module.exports = {
getAvatarOuterClass: function (classPrefix, size, shape) {
var isIncludePx = size.indexOf('px') > -1;
var classNames = [
classPrefix,
classPrefix + (shape === 'round' ? '--round' : '--circle'),
isIncludePx ? '' : 't-size-' + (size || 'medium').slice(0, 1),
];
return classNames.join(' ');
},
getAvatarSizePx: function (size = 'medium') {
var pxIndex = size.indexOf('px');
if (pxIndex > -1) {
return 'width:' + size + ';height:' + size + ';font-size:' + ((size.slice(0, pxIndex) / 8) * 3 + 2) + 'px;';
}
},
getStyles: function (isShow, zIndex) {
var styles = 'z-index:' + zIndex + ';';
return styles + (isShow ? '' : 'display: none;');
},
getIconClass: function (classPrefix, size) {
if (size.indexOf('px') > -1) return;
return classPrefix + '__icon--default-' + (size || 'medium').slice(0, 1);
},
};

View File

@ -0,0 +1,109 @@
.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-avatar-group-border-color: #fff;
}
.border--small {
border: 4rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--medium {
border: 6rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--large {
border: 8rpx solid var(--td-avatar-group-border-color, #fff);
}
page {
--td-avatar-bg-color: #d4e3fc;
--td-avatar-content-color: #0052d9;
}
.t-avatar {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.t-avatar__wrapper {
float: left;
position: relative;
background-color: var(--td-avatar-bg-color, #d4e3fc);
color: var(--td-avatar-content-color, #0052d9);
border-radius: 999rpx;
}
.t-avatar__wrapper .t-badge-host {
position: absolute;
}
.t-avatar__wrapper .t-badge__round {
top: -10%;
right: -10%;
}
.t-avatar__wrapper .t-badge__circle {
top: -5%;
right: -5%;
}
.t-avatar.t-size-l {
width: 128rpx;
height: 128rpx;
font-size: 52rpx;
}
.t-avatar.t-size-m {
width: 96rpx;
height: 96rpx;
font-size: 40rpx;
}
.t-avatar.t-size-s {
width: 64rpx;
height: 64rpx;
font-size: 28rpx;
}
.t-avatar .t-image,
.t-avatar__image {
width: 100%;
height: 100%;
}
.t-avatar--circle {
border-radius: 999rpx;
overflow: hidden;
}
.t-avatar--round {
border-radius: 10rpx;
overflow: hidden;
}
.t-avatar__text,
.t-avatar__icon {
font-size: inherit;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.t-avatar__text:empty,
.t-avatar__icon:empty {
width: 0;
height: 0;
}

View File

@ -0,0 +1,12 @@
page {
--td-avatar-group-border-color: #fff;
}
.border--small {
border: 4rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--medium {
border: 6rpx solid var(--td-avatar-group-border-color, #fff);
}
.border--large {
border: 8rpx solid var(--td-avatar-group-border-color, #fff);
}

View File

@ -0,0 +1,3 @@
import { TdAvatarProps } from './type';
declare const props: TdAvatarProps;
export default props;

View File

@ -0,0 +1,32 @@
const props = {
alt: {
type: String,
value: '',
},
badgeProps: {
type: Object,
},
externalClasses: {
type: Array,
},
hideOnLoadFailed: {
type: Boolean,
value: false,
},
icon: {
type: String,
},
image: {
type: String,
value: '',
},
shape: {
type: String,
value: 'circle',
},
size: {
type: String,
value: '',
},
};
export default props;

View File

@ -0,0 +1,59 @@
import { BadgeProps } from '../badge/index';
export interface TdAvatarProps {
alt?: {
type: StringConstructor;
value?: string;
};
badgeProps?: {
type: ObjectConstructor;
value?: BadgeProps;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class'];
};
hideOnLoadFailed?: {
type: BooleanConstructor;
value?: boolean;
};
icon?: {
type: StringConstructor;
value?: string;
};
image?: {
type: StringConstructor;
value?: string;
};
shape?: {
type: StringConstructor;
value?: ShapeEnum;
};
size?: {
type: StringConstructor;
value?: string;
};
}
export interface TdAvatarGroupProps {
cascading?: {
type: StringConstructor;
value?: CascadingValue;
};
collapseAvatar?: {
type: StringConstructor;
value?: string;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-image', 't-class-content'];
};
max?: {
type: NumberConstructor;
value?: number;
};
size?: {
type: StringConstructor;
value?: string;
};
}
export declare type ShapeEnum = 'circle' | 'round';
export declare type CascadingValue = 'left-up' | 'right-up';

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,43 @@
---
title: BackTop 返回顶部
description: 用于当页面过长往下滑动时,帮助用户快速回到页面顶部。
spline: navigation
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-100%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-back-top": "tdesign-miniprogram/back-top/back-top",
}
```
## 代码演示
<img src="https://tdesign.gtimg.com/miniprogram/readme/backtop-1.png" width="375px" height="50%">
### 基础返回顶部
{{ base }}
## API
### BackTop Props
| 名称 | 类型 | 默认值 | 说明 | 必传 |
| ---------------- | ------------- | --------- | ------------------------------------------------------------------------------------------------------- | ---- |
| external-classes | Array | - | 组件类名,分别用于设置外层元素、图标、文本内容等元素类名。`['t-class', 't-class-icon', 't-class-text']` | N |
| fixed | Boolean | true | 是否绝对定位固定到屏幕右下方 | N |
| icon | String / Slot | 'backtop' | 图标 | N |
| text | String | '' | 文案 | N |
| theme | String | round | 预设的样式类型。可选项round/half-round/round-dark/half-round-dark | N |
### BackTop Events
| 名称 | 参数 | 描述 |
| ------ | ---- | -------- |
| to-top | - | 点击触发 |

Some files were not shown because too many files have changed in this diff Show More