init
This commit is contained in:
31
miniprogram/.eslintrc.js
Normal file
31
miniprogram/.eslintrc.js
Normal 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: {},
|
||||
}
|
||||
9
miniprogram/LICENSE
Normal file
9
miniprogram/LICENSE
Normal file
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present TDesign
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
127
miniprogram/README.md
Normal file
127
miniprogram/README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
<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://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail">
|
||||
<img src="https://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/issues">
|
||||
<img src="https://img.shields.io/github/issues/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/Tencent/tdesign-miniprogram-starter-retail" 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 零售行业模版示例小程序
|
||||
|
||||
TDesign 零售模版示例小程序采用 [TDesign 企业级设计体系小程序解决方案](https://tdesign.tencent.com/miniprogram/overview) 进行搭建,依赖 [TDesign 微信小程序组件库](https://github.com/Tencent/tdesign-miniprogram),涵盖完整的基本零售场景需求。
|
||||
|
||||
## :high_brightness: 预览
|
||||
|
||||
<p>请使用微信扫描以下二维码:</p>
|
||||
|
||||
<img src="https://we-retail-static-1300977798.cos.ap-guangzhou.myqcloud.com/retail-mp/common/qrcode.jpeg" width = "200" height = "200" alt="模版小程序二维码" align=center />
|
||||
|
||||
## :pushpin: 项目介绍
|
||||
|
||||
### 1. 业务介绍
|
||||
|
||||
零售行业模版小程序是个经典的单店版电商小程序,涵盖了电商的黄金链路流程,从商品->购物车->结算->订单等。小程序总共包含 28 个完整的页面,涵盖首页,商品详情页,个人中心,售后流程等基础页面。采用 mock 数据进行展示,提供了完整的零售商品展示、交易与售后流程。页面详情:
|
||||
|
||||
<img src="https://tdesign.gtimg.com/miniprogram/template/retail/tdesign-starter-readmeV1.png" width = "650" height = "900" alt="模版小程序页面详情" align=center />
|
||||
|
||||
主要页面截图如下:
|
||||
|
||||
<p align="center">
|
||||
<img alt="example-home" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/home.png" />
|
||||
<img alt="example-sort" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v2/sort.png" />
|
||||
<img alt="example-cart" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/cart.png" />
|
||||
<img alt="example-user-center" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/user-center.png" />
|
||||
<img alt="example-goods-detail" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/goods-detail.png" />
|
||||
<img alt="example-pay" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/pay.png" />
|
||||
<img alt="example-order" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v1/order.png" />
|
||||
<img alt="example-order-detail" width="200" src="https://tdesign.gtimg.com/miniprogram/template/retail/example/v2/order.png" />
|
||||
</p>
|
||||
|
||||
### 2. 项目构成
|
||||
|
||||
零售行业模版小程序采用基础的 JavaScript + WXSS + ESLint 进行构建,降低了使用门槛。
|
||||
|
||||
项目目录结构如下:
|
||||
|
||||
```
|
||||
|-- tdesign-miniprogram-starter
|
||||
|-- README.md
|
||||
|-- app.js
|
||||
|-- app.json
|
||||
|-- app.wxss
|
||||
|-- components // 公共组件库
|
||||
|-- config // 基础配置
|
||||
|-- custom-tab-bar // 自定义 tabbar
|
||||
|-- model // mock 数据
|
||||
|-- pages
|
||||
| |-- cart // 购物车相关页面
|
||||
| |-- coupon // 优惠券相关页面
|
||||
| |-- goods // 商品相关页面
|
||||
| |-- home // 首页
|
||||
| |-- order // 订单售后相关页面
|
||||
| |-- promotion-detail // 营销活动页面
|
||||
| |-- usercenter // 个人中心及收货地址相关页面
|
||||
|-- services // 请求接口
|
||||
|-- style // 公共样式与iconfont
|
||||
|-- utils // 工具库
|
||||
```
|
||||
|
||||
### 3. 数据模拟
|
||||
|
||||
零售小程序采用真实的接口数据,模拟后端返回逻辑,在小程序展示完整的购物场景与购物体验逻辑。
|
||||
|
||||
### 4. 添加新页面
|
||||
|
||||
1. 在 `pages `目录下创建对应的页面文件夹
|
||||
2. 在 `app.json` 文件中的 ` "pages"` 数组中加上页面路径
|
||||
3. [可选] 在 `project.config.json` 文件的 `"miniprogram-list"` 下添加页面配置
|
||||
|
||||
## :hammer: 构建运行
|
||||
|
||||
1. `npm install`
|
||||
2. 小程序开发工具中引入工程
|
||||
3. 构建 npm
|
||||
|
||||
## :art: 代码风格控制
|
||||
|
||||
`eslint` `prettier`
|
||||
|
||||
## :iphone: 基础库版本
|
||||
|
||||
最低基础库版本`^2.6.5`
|
||||
|
||||
## :dart: 反馈
|
||||
|
||||
企业微信群
|
||||
TDesign 团队会及时在企业微信大群中同步发布版本、问题修复信息,也会有一些关于组件库建设的讨论,欢迎微信或企业微信扫码入群交流:
|
||||
|
||||
<img src="https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/site/doc/TDesign%20IM.png" width = "200" height = "200" alt="模版小程序页面详情" align=center />
|
||||
|
||||
邮件联系:tdesign@tencent.com
|
||||
|
||||
## :link: TDesign 其他技术栈实现
|
||||
|
||||
- 移动端 小程序 实现:[mobile-miniprogram](https://github.com/Tencent/tdesign-miniprogram)
|
||||
- 桌面端 Vue 2 实现:[web-vue](https://github.com/Tencent/tdesign-vue)
|
||||
- 桌面端 Vue 3 实现:[web-vue-next](https://github.com/Tencent/tdesign-vue-next)
|
||||
- 桌面端 React 实现:[web-react](https://github.com/Tencent/tdesign-react)
|
||||
|
||||
## :page_with_curl: 开源协议
|
||||
|
||||
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE)。
|
||||
23
miniprogram/app.js
Normal file
23
miniprogram/app.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import updateManager from './common/updateManager';
|
||||
const { config } = require('./config/index');
|
||||
|
||||
App({
|
||||
globalData: {
|
||||
config: {
|
||||
apiBaseUrl: config.apiBase
|
||||
}
|
||||
},
|
||||
onLaunch: function () {
|
||||
// 小程序启动时的初始化逻辑
|
||||
console.log('小程序启动');
|
||||
console.log('API基础URL:', this.globalData.config.apiBaseUrl);
|
||||
|
||||
// 初始化更新管理器
|
||||
// 微信在小程序每次启动(包括热启动)时自动检查更新
|
||||
updateManager();
|
||||
},
|
||||
onShow: function () {
|
||||
// 小程序显示时的逻辑
|
||||
console.log('小程序显示');
|
||||
},
|
||||
});
|
||||
111
miniprogram/app.json
Normal file
111
miniprogram/app.json
Normal file
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"pages": ["pages/home/home", "pages/category/index", "pages/cart/index", "pages/usercenter/index", "pages/login/index", "pages/points/index", "pages/network-test/index", "pages/help-center/index", "pages/error-log/index", "pages/user-agreement/index", "pages/privacy-policy/index", "pages/debug/payment-test", "pages/debug/comment-test", "pages/debug/comment-display-test",
|
||||
"pages/debug/simple-comment-test",
|
||||
"pages/debug/api-test",
|
||||
"pages/debug/hardcoded-comment-test",
|
||||
"pages/test-my-comments/index",
|
||||
"pages/test-comment-stats/index"],
|
||||
"subpackages": [
|
||||
{
|
||||
"root": "pages/user",
|
||||
"name": "user",
|
||||
"pages": ["person-info/index", "address/list/index", "address/edit/index", "name-edit/index", "phone-verify/index"]
|
||||
},
|
||||
{
|
||||
"root": "pages/goods",
|
||||
"name": "goods",
|
||||
"pages": [
|
||||
"list/index",
|
||||
"details/index",
|
||||
"search/index",
|
||||
"result/index",
|
||||
"comments/index",
|
||||
"comments/create/index"
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/order",
|
||||
"name": "order",
|
||||
"pages": [
|
||||
"order-confirm/index",
|
||||
"receipt/index",
|
||||
"pay-result/index",
|
||||
"order-list/index",
|
||||
"order-detail/index",
|
||||
"apply-service/index",
|
||||
"after-service-list/index",
|
||||
"after-service-detail/index",
|
||||
"fill-tracking-no/index",
|
||||
"delivery-detail/index",
|
||||
"invoice/index",
|
||||
"comment/index",
|
||||
"comment-list/index"
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/refund",
|
||||
"name": "refund",
|
||||
"pages": [
|
||||
"refund-list/index",
|
||||
"refund-detail/index",
|
||||
"refund-apply/index"
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/coupon",
|
||||
"name": "coupon",
|
||||
"pages": ["coupon-list/index", "coupon-detail/index", "coupon-activity-goods/index", "coupon-center/index"]
|
||||
},
|
||||
{
|
||||
"root": "pages/promotion",
|
||||
"name": "promotion",
|
||||
"pages": ["promotion-detail/index"]
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
"custom": true,
|
||||
"color": "#666666",
|
||||
"selectedColor": "#FF5F15",
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderStyle": "black",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/home/home",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/category/index",
|
||||
"text": "分类"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/cart/index",
|
||||
"text": "购物车"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/usercenter/index",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredPrivateInfos": ["chooseAddress","chooseLocation"],
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
"usingComponents": {},
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"navigationBarTitleText": "Weixin",
|
||||
"navigationBarTextStyle": "black"
|
||||
},
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "你的位置信息将用于小程序位置接口的效果展示"
|
||||
}
|
||||
},
|
||||
"networkTimeout": {
|
||||
"request": 60000,
|
||||
"downloadFile": 60000
|
||||
},
|
||||
"debug": false,
|
||||
"functionalPages": true
|
||||
}
|
||||
7
miniprogram/app.wxss
Normal file
7
miniprogram/app.wxss
Normal file
@@ -0,0 +1,7 @@
|
||||
@import 'style/iconfont.wxss';
|
||||
|
||||
@import 'style/theme.wxss';
|
||||
|
||||
.cell--noborder .t-cell::after {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
21
miniprogram/assets/logo.svg
Normal file
21
miniprogram/assets/logo.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- 背景圆形 -->
|
||||
<circle cx="80" cy="80" r="80" fill="url(#gradient)" />
|
||||
|
||||
<!-- 购物袋图标 -->
|
||||
<path d="M50 60 L110 60 L105 120 L55 120 Z" fill="white" opacity="0.9" />
|
||||
<path d="M65 60 L65 50 C65 42 72 35 80 35 C88 35 95 42 95 50 L95 60" stroke="white" stroke-width="4" fill="none" opacity="0.9" />
|
||||
|
||||
<!-- 装饰元素 -->
|
||||
<circle cx="70" cy="85" r="3" fill="white" opacity="0.7" />
|
||||
<circle cx="90" cy="85" r="3" fill="white" opacity="0.7" />
|
||||
<circle cx="80" cy="100" r="2" fill="white" opacity="0.5" />
|
||||
|
||||
<!-- 渐变定义 -->
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 919 B |
1
miniprogram/commitlint.config.js
Normal file
1
miniprogram/commitlint.config.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
||||
133
miniprogram/common/updateManager.js
Normal file
133
miniprogram/common/updateManager.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 小程序自动更新管理器
|
||||
* 基于微信官方UpdateManager API实现
|
||||
* 文档:https://developers.weixin.qq.com/miniprogram/dev/api/base/update/UpdateManager.html
|
||||
*/
|
||||
|
||||
let updateRetryCount = 0; // 更新重试次数
|
||||
const MAX_RETRY_COUNT = 3; // 最大重试次数
|
||||
|
||||
export default () => {
|
||||
// 检查是否支持UpdateManager
|
||||
if (!wx.canIUse('getUpdateManager')) {
|
||||
console.warn('当前微信版本过低,无法使用 UpdateManager');
|
||||
return;
|
||||
}
|
||||
|
||||
const updateManager = wx.getUpdateManager();
|
||||
|
||||
// 监听检查更新结果
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
console.log('检查更新结果:', res);
|
||||
|
||||
if (res.hasUpdate) {
|
||||
console.log('发现新版本,开始下载...');
|
||||
// 显示下载提示
|
||||
wx.showToast({
|
||||
title: '发现新版本,正在下载...',
|
||||
icon: 'loading',
|
||||
duration: 2000,
|
||||
mask: true
|
||||
});
|
||||
} else {
|
||||
console.log('当前已是最新版本');
|
||||
}
|
||||
});
|
||||
|
||||
// 监听新版本下载完成
|
||||
updateManager.onUpdateReady(function () {
|
||||
console.log('新版本下载完成,准备更新');
|
||||
|
||||
wx.hideToast(); // 隐藏下载提示
|
||||
|
||||
wx.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已准备就绪,立即重启应用以获得更好的体验?',
|
||||
confirmText: '立即更新',
|
||||
cancelText: '稍后更新',
|
||||
confirmColor: '#576B95',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
console.log('用户确认更新,开始应用新版本');
|
||||
// 显示更新中提示
|
||||
wx.showLoading({
|
||||
title: '更新中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
try {
|
||||
// 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
} catch (error) {
|
||||
console.error('应用更新失败:', error);
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: '更新失败,请稍后重试',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('用户选择稍后更新');
|
||||
// 可以在这里设置定时提醒或其他逻辑
|
||||
setTimeout(() => {
|
||||
wx.showToast({
|
||||
title: '建议及时更新以获得最佳体验',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}, 30000); // 30秒后提醒
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.error('显示更新弹窗失败:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 监听新版本下载失败
|
||||
updateManager.onUpdateFailed(function (error) {
|
||||
console.error('新版本下载失败:', error);
|
||||
updateRetryCount++;
|
||||
|
||||
wx.hideToast(); // 隐藏下载提示
|
||||
|
||||
if (updateRetryCount < MAX_RETRY_COUNT) {
|
||||
console.log(`第${updateRetryCount}次重试下载更新`);
|
||||
|
||||
wx.showModal({
|
||||
title: '下载失败',
|
||||
content: `新版本下载失败,是否重试?(${updateRetryCount}/${MAX_RETRY_COUNT})`,
|
||||
confirmText: '重试',
|
||||
cancelText: '取消',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 重新检查更新
|
||||
setTimeout(() => {
|
||||
console.log('重新检查更新...');
|
||||
// 这里可以添加重新检查更新的逻辑
|
||||
// 注意:微信会自动检查更新,开发者无需主动触发
|
||||
}, 2000);
|
||||
} else {
|
||||
console.log('用户取消重试');
|
||||
updateRetryCount = 0; // 重置重试次数
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('更新重试次数已达上限');
|
||||
updateRetryCount = 0; // 重置重试次数
|
||||
|
||||
wx.showModal({
|
||||
title: '更新失败',
|
||||
content: '新版本下载多次失败,请检查网络连接或稍后再试',
|
||||
showCancel: false,
|
||||
confirmText: '知道了',
|
||||
success() {
|
||||
console.log('用户确认更新失败提示');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log('UpdateManager 初始化完成');
|
||||
};
|
||||
BIN
miniprogram/components/.DS_Store
vendored
Normal file
BIN
miniprogram/components/.DS_Store
vendored
Normal file
Binary file not shown.
35
miniprogram/components/empty-state/index.js
Normal file
35
miniprogram/components/empty-state/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
Component({
|
||||
properties: {
|
||||
// 图标名称
|
||||
icon: {
|
||||
type: String,
|
||||
value: 'shop'
|
||||
},
|
||||
// 标题
|
||||
title: {
|
||||
type: String,
|
||||
value: '暂无商品'
|
||||
},
|
||||
// 描述文字
|
||||
description: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
// 是否显示操作按钮
|
||||
showAction: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 操作按钮文字
|
||||
actionText: {
|
||||
type: String,
|
||||
value: '刷新'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onActionTap() {
|
||||
this.triggerEvent('action');
|
||||
}
|
||||
}
|
||||
});
|
||||
7
miniprogram/components/empty-state/index.json
Normal file
7
miniprogram/components/empty-state/index.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-button": "tdesign-miniprogram/button/button"
|
||||
}
|
||||
}
|
||||
16
miniprogram/components/empty-state/index.wxml
Normal file
16
miniprogram/components/empty-state/index.wxml
Normal file
@@ -0,0 +1,16 @@
|
||||
<view class="empty-state wr-class">
|
||||
<view class="empty-state__icon">
|
||||
<t-icon name="{{icon || 'shop'}}" size="120rpx" color="#ddd" />
|
||||
</view>
|
||||
<view class="empty-state__title">{{title || '暂无商品'}}</view>
|
||||
<view class="empty-state__description" wx:if="{{description}}">{{description}}</view>
|
||||
<view class="empty-state__action" wx:if="{{showAction}}">
|
||||
<t-button
|
||||
variant="outline"
|
||||
size="medium"
|
||||
bind:tap="onActionTap"
|
||||
>
|
||||
{{actionText || '刷新'}}
|
||||
</t-button>
|
||||
</view>
|
||||
</view>
|
||||
32
miniprogram/components/empty-state/index.wxss
Normal file
32
miniprogram/components/empty-state/index.wxss
Normal file
@@ -0,0 +1,32 @@
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 40rpx;
|
||||
text-align: center;
|
||||
min-height: 400rpx;
|
||||
}
|
||||
|
||||
.empty-state__icon {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.empty-state__title {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
margin-bottom: 16rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.empty-state__description {
|
||||
font-size: 28rpx;
|
||||
color: #bbb;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 40rpx;
|
||||
max-width: 400rpx;
|
||||
}
|
||||
|
||||
.empty-state__action {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
36
miniprogram/components/filter-popup/index.js
Normal file
36
miniprogram/components/filter-popup/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
observer(show) {
|
||||
this.setData({ visible: show });
|
||||
},
|
||||
},
|
||||
closeBtn: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
data: { visible: false },
|
||||
|
||||
methods: {
|
||||
reset() {
|
||||
this.triggerEvent('reset');
|
||||
},
|
||||
confirm() {
|
||||
this.triggerEvent('confirm');
|
||||
},
|
||||
close() {
|
||||
this.triggerEvent('showFilterPopupClose');
|
||||
|
||||
this.setData({ visible: false });
|
||||
},
|
||||
},
|
||||
});
|
||||
6
miniprogram/components/filter-popup/index.json
Normal file
6
miniprogram/components/filter-popup/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-popup": "tdesign-miniprogram/popup/popup"
|
||||
}
|
||||
}
|
||||
18
miniprogram/components/filter-popup/index.wxml
Normal file
18
miniprogram/components/filter-popup/index.wxml
Normal file
@@ -0,0 +1,18 @@
|
||||
<t-popup
|
||||
visible="{{visible}}"
|
||||
placement="right"
|
||||
bind:visible-change="close"
|
||||
data-index="5"
|
||||
close-btn="{{closeBtn}}"
|
||||
>
|
||||
<view class="content">
|
||||
<slot name="filterSlot" />
|
||||
<view class="filter-btns-wrap">
|
||||
<view class="filter-btn btn-reset" bind:tap="reset">重置</view>
|
||||
<view class="filter-btn btn-confirm" bind:tap="confirm" data-index="5">
|
||||
确定
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
|
||||
39
miniprogram/components/filter-popup/index.wxss
Normal file
39
miniprogram/components/filter-popup/index.wxss
Normal file
@@ -0,0 +1,39 @@
|
||||
.content .filter-btns-wrap {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-radius: 10rpx 0 0 10rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.btn-reset {
|
||||
color: #fa4126;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
position: relative;
|
||||
border: 1rpx solid #fa4126;
|
||||
border-radius: 84rpx 0 0 84rpx;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
border-radius: 0 84rpx 84rpx 0;
|
||||
border: 1rpx solid #fa4126;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
color: #fff;
|
||||
background: #fa4126;
|
||||
}
|
||||
133
miniprogram/components/filter/index.js
Normal file
133
miniprogram/components/filter/index.js
Normal file
@@ -0,0 +1,133 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
overall: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
observer(overall) {
|
||||
this.setData({
|
||||
overall,
|
||||
});
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
observer(layout) {
|
||||
this.setData({
|
||||
layout,
|
||||
});
|
||||
},
|
||||
},
|
||||
sorts: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer(sorts) {
|
||||
this.setData({
|
||||
sorts,
|
||||
});
|
||||
},
|
||||
},
|
||||
prices: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(prices) {
|
||||
this.setData({
|
||||
prices,
|
||||
});
|
||||
},
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#FA550F',
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
layout: 1,
|
||||
overall: 1,
|
||||
sorts: '',
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChangeShowAction() {
|
||||
const { layout } = this.data;
|
||||
const nextLayout = layout === 1 ? 0 : 1;
|
||||
|
||||
console.log('[Filter] 布局切换:', {
|
||||
currentLayout: layout === 1 ? '列表' : '网格',
|
||||
nextLayout: nextLayout === 1 ? '列表' : '网格',
|
||||
timestamp: new Date().toLocaleString()
|
||||
});
|
||||
|
||||
this.triggerEvent('change', { ...this.properties, layout: nextLayout });
|
||||
},
|
||||
|
||||
handlePriseSort() {
|
||||
const { sorts } = this.data;
|
||||
const nextSort = sorts === 'desc' ? 'asc' : 'desc';
|
||||
|
||||
console.log('[Filter] 价格排序点击:', {
|
||||
currentSort: sorts || '默认',
|
||||
nextSort: nextSort,
|
||||
sortText: nextSort === 'asc' ? '价格从低到高' : '价格从高到低',
|
||||
timestamp: new Date().toLocaleString(),
|
||||
action: '用户点击价格排序按钮'
|
||||
});
|
||||
|
||||
const changeData = {
|
||||
...this.properties,
|
||||
overall: 0,
|
||||
sorts: nextSort,
|
||||
};
|
||||
|
||||
console.log('[Filter] 触发排序变化事件:', {
|
||||
eventData: changeData,
|
||||
timestamp: new Date().toLocaleString()
|
||||
});
|
||||
|
||||
this.triggerEvent('change', changeData);
|
||||
},
|
||||
|
||||
open() {
|
||||
this.triggerEvent('showFilterPopup', {
|
||||
show: true,
|
||||
});
|
||||
},
|
||||
|
||||
onOverallAction() {
|
||||
const { overall } = this.data;
|
||||
const nextOverall = overall === 1 ? 0 : 1;
|
||||
const nextData = {
|
||||
sorts: '',
|
||||
prices: [],
|
||||
};
|
||||
|
||||
console.log('[Filter] 综合排序点击:', {
|
||||
currentOverall: overall === 1 ? '综合排序' : '其他排序',
|
||||
nextOverall: nextOverall === 1 ? '综合排序' : '其他排序',
|
||||
resetData: nextData,
|
||||
timestamp: new Date().toLocaleString(),
|
||||
action: '用户点击综合排序,重置所有筛选条件'
|
||||
});
|
||||
|
||||
const changeData = {
|
||||
...this.properties,
|
||||
...nextData,
|
||||
overall: nextOverall,
|
||||
};
|
||||
|
||||
console.log('[Filter] 触发综合排序变化事件:', {
|
||||
eventData: changeData,
|
||||
timestamp: new Date().toLocaleString()
|
||||
});
|
||||
|
||||
this.triggerEvent('change', changeData);
|
||||
},
|
||||
},
|
||||
});
|
||||
6
miniprogram/components/filter/index.json
Normal file
6
miniprogram/components/filter/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
||||
37
miniprogram/components/filter/index.wxml
Normal file
37
miniprogram/components/filter/index.wxml
Normal file
@@ -0,0 +1,37 @@
|
||||
<!-- 过滤组件 -->
|
||||
<view class="wr-class filter-wrap">
|
||||
<view class="filter-left-content">
|
||||
<view class="filter-item {{overall === 1 ? 'filter-active-item' : ''}}" bindtap="onOverallAction">
|
||||
综合
|
||||
</view>
|
||||
<view class="filter-item" bind:tap="handlePriseSort">
|
||||
<text style="color: {{sorts !== '' ? color : '' }}">价格</text>
|
||||
<view class="filter-price">
|
||||
<t-icon
|
||||
prefix="wr"
|
||||
name="arrow_drop_up"
|
||||
size="18rpx"
|
||||
style="color:{{sorts === 'asc' ? color : '#bbb'}}"
|
||||
/>
|
||||
<t-icon
|
||||
prefix="wr"
|
||||
name="arrow_drop_down"
|
||||
size="18rpx"
|
||||
style="color:{{sorts === 'desc' ? color : '#bbb'}}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item {{prices.length ? 'filter-active-item' : ''}}" bindtap="open" data-index="5">
|
||||
筛选
|
||||
<t-icon
|
||||
name="filter"
|
||||
prefix="wr"
|
||||
color="#333"
|
||||
size="32rpx"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 筛选弹框 -->
|
||||
<slot name="filterPopup" />
|
||||
|
||||
50
miniprogram/components/filter/index.wxss
Normal file
50
miniprogram/components/filter/index.wxss
Normal file
@@ -0,0 +1,50 @@
|
||||
.filter-wrap {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.filter-right-content {
|
||||
height: 100%;
|
||||
flex-basis: 100rpx;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
|
||||
.filter-left-content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 2;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item .filter-price {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 6rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item .wr-filter {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-active-item {
|
||||
color: #fa550f;
|
||||
}
|
||||
159
miniprogram/components/goods-card/index.js
Normal file
159
miniprogram/components/goods-card/index.js
Normal file
@@ -0,0 +1,159 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
},
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
properties: {
|
||||
id: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer(id) {
|
||||
this.genIndependentID(id);
|
||||
if (this.properties.thresholds?.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
observer(data) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
let isValidityLinePrice = true;
|
||||
if (data.originPrice && data.price && data.originPrice < data.price) {
|
||||
isValidityLinePrice = false;
|
||||
}
|
||||
this.setData({ goods: data, isValidityLinePrice });
|
||||
},
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
value: '¥',
|
||||
},
|
||||
showCart: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
thresholds: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(thresholds) {
|
||||
if (thresholds && thresholds.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
} else {
|
||||
this.clearIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
independentID: '',
|
||||
goods: { id: '' },
|
||||
isValidityLinePrice: false,
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
attached() {
|
||||
// 组件实例被放到页面节点树后执行
|
||||
},
|
||||
ready() {
|
||||
this.init();
|
||||
},
|
||||
detached() {
|
||||
this.clear();
|
||||
},
|
||||
},
|
||||
|
||||
observers: {
|
||||
'goods.thumb': function(thumb) {
|
||||
// 图片URL变化监听
|
||||
}
|
||||
},
|
||||
|
||||
pageLifeTimes: {},
|
||||
|
||||
methods: {
|
||||
clickHandle() {
|
||||
this.triggerEvent('click', { goods: this.data.goods });
|
||||
},
|
||||
|
||||
clickThumbHandle() {
|
||||
this.triggerEvent('thumb', { goods: this.data.goods });
|
||||
},
|
||||
|
||||
addCartHandle(e) {
|
||||
const { id } = e.currentTarget;
|
||||
const { id: cardID } = e.currentTarget.dataset;
|
||||
this.triggerEvent('add-cart', {
|
||||
...e.detail,
|
||||
id,
|
||||
cardID,
|
||||
goods: this.data.goods,
|
||||
});
|
||||
},
|
||||
|
||||
handleImageError(e) {
|
||||
console.warn('商品卡片图片加载失败:', e.detail);
|
||||
// 可以在这里设置默认图片或其他错误处理逻辑
|
||||
},
|
||||
|
||||
genIndependentID(id) {
|
||||
let independentID;
|
||||
if (id) {
|
||||
independentID = id;
|
||||
} else {
|
||||
independentID = `goods-card-${~~(Math.random() * 10 ** 8)}`;
|
||||
}
|
||||
this.setData({ independentID });
|
||||
},
|
||||
|
||||
init() {
|
||||
const { thresholds, id } = this.properties;
|
||||
this.genIndependentID(id);
|
||||
if (thresholds && thresholds.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.clearIntersectionObserverHandle();
|
||||
},
|
||||
|
||||
intersectionObserverContext: null,
|
||||
|
||||
createIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext || !this.data.independentID) {
|
||||
return;
|
||||
}
|
||||
this.intersectionObserverContext = this.createIntersectionObserver({
|
||||
thresholds: this.properties.thresholds,
|
||||
}).relativeToViewport();
|
||||
|
||||
this.intersectionObserverContext.observe(
|
||||
`#${this.data.independentID}`,
|
||||
(res) => {
|
||||
this.intersectionObserverCB(res);
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
intersectionObserverCB() {
|
||||
this.triggerEvent('ob', {
|
||||
goods: this.data.goods,
|
||||
context: this.intersectionObserverContext,
|
||||
});
|
||||
},
|
||||
|
||||
clearIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext) {
|
||||
try {
|
||||
this.intersectionObserverContext.disconnect();
|
||||
} catch (e) {}
|
||||
this.intersectionObserverContext = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
8
miniprogram/components/goods-card/index.json
Normal file
8
miniprogram/components/goods-card/index.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"price": "/components/price/index",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-image": "/components/webp-image/index"
|
||||
}
|
||||
}
|
||||
72
miniprogram/components/goods-card/index.wxml
Normal file
72
miniprogram/components/goods-card/index.wxml
Normal file
@@ -0,0 +1,72 @@
|
||||
<view
|
||||
id="{{independentID}}"
|
||||
class="goods-card wr-class"
|
||||
bind:tap="clickHandle"
|
||||
data-goods="{{ goods }}"
|
||||
>
|
||||
<view class="goods-card__main">
|
||||
<view class="goods-card__thumb" bind:tap="clickThumbHandle">
|
||||
<t-image
|
||||
wx:if="{{ !!goods.thumb }}"
|
||||
t-class="goods-card__img"
|
||||
src="{{ goods.thumb }}"
|
||||
mode="aspectFill"
|
||||
lazy-load
|
||||
bind:error="handleImageError"
|
||||
/>
|
||||
<!-- 售罄遮罩 -->
|
||||
<view wx:if="{{ !goods.isStock }}" class="goods-card__soldout">
|
||||
<text class="goods-card__soldout-text">售罄</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-card__body">
|
||||
<view class="goods-card__upper">
|
||||
<view wx:if="{{ goods.title }}" class="goods-card__title">
|
||||
{{ goods.title }}
|
||||
</view>
|
||||
<view wx:if="{{ goods.specs }}" class="goods-card__specs">
|
||||
{{ goods.specs }}
|
||||
</view>
|
||||
<view wx:if="{{ goods.tags && !!goods.tags.length }}" class="goods-card__tags">
|
||||
<view
|
||||
wx:for="{{ goods.tags }}"
|
||||
wx:key="index"
|
||||
wx:for-item="tag"
|
||||
class="goods-card__tag"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
{{tag}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-card__down">
|
||||
<price
|
||||
wx:if="{{ goods.price }}"
|
||||
wr-class="spec-for-price"
|
||||
symbol-class="spec-for-symbol"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.price}}"
|
||||
/>
|
||||
<price
|
||||
wx:if="{{ goods.originPrice && isValidityLinePrice }}"
|
||||
wr-class="goods-card__origin-price"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.originPrice}}"
|
||||
type="delthrough"
|
||||
/>
|
||||
<t-icon
|
||||
wx:if="{{showCart}}"
|
||||
class="goods-card__add-cart"
|
||||
prefix="wr"
|
||||
name="cartAdd"
|
||||
id="{{independentID}}-cart"
|
||||
data-id="{{independentID}}"
|
||||
catchtap="addCartHandle"
|
||||
size="48rpx"
|
||||
color="#FA550F"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
166
miniprogram/components/goods-card/index.wxss
Normal file
166
miniprogram/components/goods-card/index.wxss
Normal file
@@ -0,0 +1,166 @@
|
||||
.goods-card {
|
||||
box-sizing: border-box;
|
||||
font-size: 24rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.goods-card__main {
|
||||
position: relative;
|
||||
display: flex;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
width: 333rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 16rpx;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.goods-card__thumb {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 333rpx;
|
||||
height: 333rpx;
|
||||
}
|
||||
|
||||
.goods-card__thumb:empty {
|
||||
display: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.goods-card__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-card__body {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
background: #fff;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
padding: 16rpx 16rpx 18rpx;
|
||||
flex-direction: column;
|
||||
width: 333rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.goods-card__upper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.goods-card__title {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
display: -webkit-box;
|
||||
height: 72rpx;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.goods-card__specs {
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
line-height: 32rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.goods-card__tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: 8rpx 0 0 0;
|
||||
}
|
||||
|
||||
.goods-card__tag {
|
||||
color: #fa4126;
|
||||
background: transparent;
|
||||
font-size: 20rpx;
|
||||
border: 1rpx solid #fa4126;
|
||||
padding: 0 8rpx;
|
||||
border-radius: 16rpx;
|
||||
line-height: 30rpx;
|
||||
margin: 0 8rpx 8rpx 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: keep-all;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.goods-card__down {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: baseline;
|
||||
line-height: 32rpx;
|
||||
margin: 8rpx 0 0 0;
|
||||
}
|
||||
|
||||
.goods-card__origin-price {
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
order: 2;
|
||||
color: #bbbbbb;
|
||||
font-size: 24rpx;
|
||||
margin: 0 0 0 8rpx;
|
||||
}
|
||||
|
||||
.goods-card__add-cart {
|
||||
order: 3;
|
||||
margin: auto 0 0 auto;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.spec-for-price {
|
||||
font-size: 36rpx;
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
order: 1;
|
||||
color: #fa4126;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.spec-for-symbol {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 售罄遮罩样式 */
|
||||
.goods-card__soldout {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
|
||||
.goods-card__soldout-text {
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
66
miniprogram/components/goods-list/index.js
Normal file
66
miniprogram/components/goods-list/index.js
Normal file
@@ -0,0 +1,66 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
properties: {
|
||||
goodsList: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer: (id) => {
|
||||
this.genIndependentID(id);
|
||||
},
|
||||
},
|
||||
showCart: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
thresholds: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
independentID: '',
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClickGoods(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('click', { ...e.detail, index });
|
||||
},
|
||||
|
||||
onAddCart(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('addcart', { ...e.detail, index });
|
||||
},
|
||||
|
||||
onClickGoodsThumb(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('thumb', { ...e.detail, index });
|
||||
},
|
||||
|
||||
init() {
|
||||
this.genIndependentID(this.id || '');
|
||||
},
|
||||
|
||||
genIndependentID(id) {
|
||||
if (id) {
|
||||
this.setData({ independentID: id });
|
||||
} else {
|
||||
this.setData({
|
||||
independentID: `goods-list-${~~(Math.random() * 10 ** 8)}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
6
miniprogram/components/goods-list/index.json
Normal file
6
miniprogram/components/goods-list/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"goods-card": "/components/goods-card/index"
|
||||
}
|
||||
}
|
||||
17
miniprogram/components/goods-list/index.wxml
Normal file
17
miniprogram/components/goods-list/index.wxml
Normal file
@@ -0,0 +1,17 @@
|
||||
<view class="goods-list-wrap wr-class" id="{{independentID}}">
|
||||
<block wx:for="{{goodsList}}" wx:for-item="item" wx:key="index">
|
||||
<goods-card
|
||||
id="{{independentID}}-gd-{{index}}"
|
||||
data="{{item}}"
|
||||
currency="{{item.currency || '¥'}}"
|
||||
thresholds="{{thresholds}}"
|
||||
show-cart="{{showCart}}"
|
||||
wr-class="goods-card-inside"
|
||||
data-index="{{index}}"
|
||||
bind:thumb="onClickGoodsThumb"
|
||||
bind:click="onClickGoods"
|
||||
bind:add-cart="onAddCart"
|
||||
/>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
14
miniprogram/components/goods-list/index.wxss
Normal file
14
miniprogram/components/goods-list/index.wxss
Normal file
@@ -0,0 +1,14 @@
|
||||
.goods-list-wrap {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 12rpx;
|
||||
background: #fff;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
/* 使商品卡按两列栅格排布 */
|
||||
.goods-card-inside {
|
||||
width: calc((100% - 12rpx) / 2);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
54
miniprogram/components/load-more/index.js
Normal file
54
miniprogram/components/load-more/index.js
Normal file
@@ -0,0 +1,54 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'wr-class--no-more'],
|
||||
|
||||
options: { multipleSlots: true },
|
||||
|
||||
properties: {
|
||||
status: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
value: '加载中...',
|
||||
},
|
||||
noMoreText: {
|
||||
type: String,
|
||||
value: '没有更多了',
|
||||
},
|
||||
failedText: {
|
||||
type: String,
|
||||
value: '加载失败,点击重试',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#BBBBBB',
|
||||
},
|
||||
failedColor: {
|
||||
type: String,
|
||||
value: '#FA550F',
|
||||
},
|
||||
size: {
|
||||
type: null,
|
||||
value: '40rpx',
|
||||
},
|
||||
loadingBackgroundColor: {
|
||||
type: String,
|
||||
value: '#F5F5F5',
|
||||
},
|
||||
listIsEmpty: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 点击处理 */
|
||||
tapHandle() {
|
||||
// 失败重试
|
||||
if (this.data.status === 3) {
|
||||
this.triggerEvent('retry');
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
7
miniprogram/components/load-more/index.json
Normal file
7
miniprogram/components/load-more/index.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-divider": "tdesign-miniprogram/divider/divider"
|
||||
}
|
||||
}
|
||||
34
miniprogram/components/load-more/index.wxml
Normal file
34
miniprogram/components/load-more/index.wxml
Normal file
@@ -0,0 +1,34 @@
|
||||
<view
|
||||
class="load-more wr-class"
|
||||
wx:if="{{!(listIsEmpty && (status === 0 || status === 2))}}"
|
||||
bindtap="tapHandle"
|
||||
>
|
||||
<!-- 加载中 -->
|
||||
|
||||
<t-loading
|
||||
t-class="t-class-loading"
|
||||
t-class-text="t-class-loading-text"
|
||||
t-class-indicator="t-class-indicator"
|
||||
loading="{{status === 1}}"
|
||||
text="加载中..."
|
||||
theme="circular"
|
||||
size="40rpx"
|
||||
/>
|
||||
|
||||
<!-- 已全部加载 -->
|
||||
<t-divider wx:if="{{status === 2}}" t-class="t-class-divider" t-class-content="t-class-divider-content">
|
||||
<text slot="content">{{noMoreText}}</text>
|
||||
</t-divider>
|
||||
|
||||
<!-- 加载失败 -->
|
||||
<view class="load-more__error" wx:if="{{status===3}}">
|
||||
加载失败
|
||||
<text class="load-more__refresh-btn" bind:tap="tapHandle">刷新</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view wx:if="{{listIsEmpty && (status === 0 || status === 2)}}" class="load-more__wrap">
|
||||
<slot name="empty" />
|
||||
</view>
|
||||
35
miniprogram/components/load-more/index.wxss
Normal file
35
miniprogram/components/load-more/index.wxss
Normal file
@@ -0,0 +1,35 @@
|
||||
.load-more {
|
||||
font-size: 24rpx;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
--td-loading-color: #fa4126;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading-text {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.t-class-divider-content {
|
||||
margin: 0 10rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
.load-more .t-class-indicator {
|
||||
color: #b9b9b9 !important;
|
||||
}
|
||||
|
||||
.load-more__error {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.load-more__refresh-btn {
|
||||
margin-left: 16rpx;
|
||||
color: #fa4126;
|
||||
}
|
||||
23
miniprogram/components/loading-content/index.js
Normal file
23
miniprogram/components/loading-content/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
properties: {
|
||||
position: {
|
||||
type: String,
|
||||
value: 'static',
|
||||
},
|
||||
noMask: Boolean,
|
||||
type: {
|
||||
type: String,
|
||||
value: 'circular',
|
||||
},
|
||||
vertical: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
value: '50rpx',
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
value: 'rgba(0, 0, 0, .6)',
|
||||
},
|
||||
},
|
||||
});
|
||||
6
miniprogram/components/loading-content/index.json
Normal file
6
miniprogram/components/loading-content/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading"
|
||||
}
|
||||
}
|
||||
11
miniprogram/components/loading-content/index.wxml
Normal file
11
miniprogram/components/loading-content/index.wxml
Normal file
@@ -0,0 +1,11 @@
|
||||
<view class="t-class loading-content {{position}}" style="{{(position === 'static' || noMask) ? 'visibility: hidden;' : ''}} background-color: {{backgroundColor}}">
|
||||
<t-loading
|
||||
t-class="loading"
|
||||
theme="{{type}}"
|
||||
layout="{{vertical}}"
|
||||
size="{{size}}"
|
||||
>
|
||||
<slot/>
|
||||
</t-loading>
|
||||
</view>
|
||||
|
||||
23
miniprogram/components/loading-content/index.wxss
Normal file
23
miniprogram/components/loading-content/index.wxss
Normal file
@@ -0,0 +1,23 @@
|
||||
.loading-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
position: relative;
|
||||
}
|
||||
.loading-content.absolute {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content.fixed {
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content .loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: visible;
|
||||
}
|
||||
71
miniprogram/components/price/index.js
Normal file
71
miniprogram/components/price/index.js
Normal file
@@ -0,0 +1,71 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'symbol-class', 'decimal-class'],
|
||||
useStore: [],
|
||||
properties: {
|
||||
priceUnit: {
|
||||
type: String,
|
||||
value: 'fen',
|
||||
}, // 价格单位,分 | 元, fen,yuan
|
||||
price: {
|
||||
type: null,
|
||||
value: '',
|
||||
observer(price) {
|
||||
this.format(price);
|
||||
},
|
||||
}, // 价格, 以分为单位
|
||||
type: {
|
||||
type: String,
|
||||
value: '', //
|
||||
}, // main 粗体, lighter 细体, mini 黑色, del 中划线, delthrough 中划线,包括货币符号
|
||||
symbol: {
|
||||
type: String,
|
||||
value: '¥', // '¥',
|
||||
}, // 货币符号,默认是人民币符号¥
|
||||
fill: Boolean, // 是否自动补齐两位小数
|
||||
decimalSmaller: Boolean, // 小数字号小一点
|
||||
lineThroughWidth: {
|
||||
type: null,
|
||||
value: '0.12em',
|
||||
}, // 划线价线条高度
|
||||
},
|
||||
|
||||
data: {
|
||||
pArr: ['0', ''], // 确保默认值
|
||||
},
|
||||
|
||||
methods: {
|
||||
format(price) {
|
||||
price = parseFloat(`${price}`);
|
||||
const pArr = ['0', '']; // 默认初始化
|
||||
if (!isNaN(price)) {
|
||||
const isMinus = price < 0;
|
||||
if (isMinus) {
|
||||
price = -price;
|
||||
}
|
||||
if (this.properties.priceUnit === 'yuan') {
|
||||
const priceSplit = price.toString().split('.');
|
||||
pArr[0] = priceSplit.length > 0 ? priceSplit[0] : '0';
|
||||
pArr[1] = !priceSplit[1]
|
||||
? '00'
|
||||
: priceSplit[1].length === 1
|
||||
? `${priceSplit[1]}0`
|
||||
: priceSplit[1].substring(0, 2);
|
||||
} else {
|
||||
price = Math.round(price * 10 ** 8) / 10 ** 8; // 恢复精度丢失
|
||||
price = Math.ceil(price); // 向上取整
|
||||
pArr[0] = price >= 100 ? `${price}`.slice(0, -2) : '0';
|
||||
pArr[1] = `${price + 100}`.slice(-2);
|
||||
}
|
||||
if (!this.properties.fill) {
|
||||
// 如果 fill 为 false, 不显示小数末尾的0
|
||||
if (pArr[1] === '00') pArr[1] = '';
|
||||
else if (pArr[1] && pArr[1].length > 1 && pArr[1][1] === '0') pArr[1] = pArr[1][0];
|
||||
}
|
||||
if (isMinus) {
|
||||
pArr[0] = `-${pArr[0]}`;
|
||||
}
|
||||
}
|
||||
this.setData({ pArr });
|
||||
},
|
||||
},
|
||||
});
|
||||
4
miniprogram/components/price/index.json
Normal file
4
miniprogram/components/price/index.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
21
miniprogram/components/price/index.wxml
Normal file
21
miniprogram/components/price/index.wxml
Normal file
@@ -0,0 +1,21 @@
|
||||
<wxs module="utils">
|
||||
var REGEXP = getRegExp('^\d+(\.\d+)?$');
|
||||
function addUnit(value) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
return REGEXP.test('' + value) ? value + 'rpx' : value;
|
||||
}
|
||||
module.exports = {
|
||||
addUnit: addUnit
|
||||
};
|
||||
</wxs>
|
||||
<view class="price {{type}} wr-class">
|
||||
<view wx:if="{{type === 'delthrough'}}" class="line" style="height:{{utils.addUnit(lineThroughWidth)}};" />
|
||||
<view class="symbol symbol-class">{{symbol}}</view>
|
||||
<view class="pprice">
|
||||
<view class="integer inline">{{pArr && pArr.length > 0 ? pArr[0] : '0'}}</view>
|
||||
<view wx:if="{{pArr && pArr.length > 1 && pArr[1]}}" class="decimal inline {{decimalSmaller ? 'smaller' : ''}} decimal-class">.{{pArr[1]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
66
miniprogram/components/price/index.wxss
Normal file
66
miniprogram/components/price/index.wxss
Normal file
@@ -0,0 +1,66 @@
|
||||
:host {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.inline {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.price {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.lighter {
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.mini {
|
||||
font-size: 24rpx;
|
||||
color: #5d5d5d;
|
||||
font-weight: 400;
|
||||
}
|
||||
.del .pprice {
|
||||
font-size: 32rpx;
|
||||
color: #9b9b9b;
|
||||
text-decoration: line-through;
|
||||
font-weight: 400;
|
||||
}
|
||||
.delthrough {
|
||||
position: relative;
|
||||
}
|
||||
.delthrough .line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
margin: 0;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.pprice {
|
||||
display: inline;
|
||||
margin: 0 0 0 4rpx;
|
||||
}
|
||||
.integer {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal.smaller {
|
||||
font-size: 0.8em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
98
miniprogram/components/promotion/ui-coupon-card/index.js
Normal file
98
miniprogram/components/promotion/ui-coupon-card/index.js
Normal file
@@ -0,0 +1,98 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
|
||||
externalClasses: ['coupon-class'],
|
||||
|
||||
properties: {
|
||||
mask: {
|
||||
type: Boolean,
|
||||
value: false, // 是否添加遮罩
|
||||
},
|
||||
superposable: {
|
||||
type: Boolean,
|
||||
value: false, // 是否可叠加
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
value: 0, // 优惠券类型:CouponType
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
value: '', // 优惠金额
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
value: '', // 优惠标签,优惠券名字标签,img
|
||||
},
|
||||
desc: {
|
||||
type: String,
|
||||
value: '', // 优惠金额描述,金额下方
|
||||
},
|
||||
title: {
|
||||
type: String, // 优惠券名称
|
||||
value: '',
|
||||
},
|
||||
timeLimit: {
|
||||
type: String, // 优惠券时限
|
||||
value: '',
|
||||
},
|
||||
ruleDesc: {
|
||||
type: String, // 优惠券适用规则描述
|
||||
value: '',
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
value: '¥', // 优惠货币
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
userCouponId: {
|
||||
type: Number,
|
||||
value: 0, // 用户优惠券ID
|
||||
},
|
||||
couponTemplateId: {
|
||||
type: Number,
|
||||
value: 0, // 优惠券模板ID
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
CouponType: {
|
||||
MJ_COUPON: 1,
|
||||
ZK_COUPON: 2,
|
||||
MJF_COUPON: 3,
|
||||
MYF_COUPON: 3, // 免邮券的另一种类型,与MJF_COUPON相同
|
||||
GIFT_COUPON: 4,
|
||||
MERCHANT_MJ_COUPON: 1, // 商家满减券,与MJ_COUPON相同
|
||||
MERCHANT_ZK_COUPON: 2, // 商家折扣券,与ZK_COUPON相同
|
||||
},
|
||||
theme: 'primary',
|
||||
},
|
||||
|
||||
observers: {
|
||||
status: function (value) {
|
||||
let theme = 'primary';
|
||||
// 已过期或已使用的券 颜色置灰
|
||||
if (value === 'useless' || value === 'disabled') {
|
||||
theme = 'weak';
|
||||
}
|
||||
|
||||
this.setData({ theme });
|
||||
},
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.setData({
|
||||
color: `color${this.properties.colorStyle}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-image": "/components/webp-image/index"
|
||||
}
|
||||
}
|
||||
63
miniprogram/components/promotion/ui-coupon-card/index.wxml
Normal file
63
miniprogram/components/promotion/ui-coupon-card/index.wxml
Normal file
@@ -0,0 +1,63 @@
|
||||
<wxs module="tools">
|
||||
function isBigValue(value) {
|
||||
if (!value) return false;
|
||||
var values = (value + '').split('.');
|
||||
if (values[1] && values[0].length >= 3) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function getBigValues(value) {
|
||||
if (!value) return ['0', ''];
|
||||
return (value + '').split('.');
|
||||
}
|
||||
module.exports = {
|
||||
isBigValue:isBigValue,
|
||||
getBigValues: getBigValues
|
||||
};
|
||||
</wxs>
|
||||
<view class="wr-coupon coupon-class theme-{{theme}}">
|
||||
<view class="wr-coupon__left">
|
||||
<view wx:if="{{type == CouponType.ZK_COUPON || type === CouponType.MERCHANT_ZK_COUPON}}">
|
||||
<text class="wr-coupon__left--value">{{value / 10}}</text>
|
||||
<text class="wr-coupon__left--unit">折</text>
|
||||
<view class="wr-coupon__left--desc">{{desc}}</view>
|
||||
</view>
|
||||
<view wx:if="{{type == CouponType.MJ_COUPON || type === CouponType.MERCHANT_MJ_COUPON}}">
|
||||
<text class="wr-coupon__left--value" wx:if="{{tools.isBigValue(value / 100)}}">
|
||||
<text class="wr-coupon__left--value-int">{{tools.getBigValues(value / 100) && tools.getBigValues(value / 100).length > 0 ? tools.getBigValues(value / 100)[0] : '0'}}</text>
|
||||
<text class="wr-coupon__left--value-decimal" wx:if="{{tools.getBigValues(value / 100) && tools.getBigValues(value / 100).length > 1}}">.{{tools.getBigValues(value / 100)[1]}}</text>
|
||||
</text>
|
||||
<text class="wr-coupon__left--value" wx:else>{{value / 100}}</text>
|
||||
<text class="wr-coupon__left--unit">元</text>
|
||||
<view class="wr-coupon__left--desc">{{desc}}</view>
|
||||
</view>
|
||||
<view wx:if="{{type === CouponType.MJF_COUPON || type === CouponType.MYF_COUPON}}">
|
||||
<text class="wr-coupon__left--value" style="font-family: PingFang SC; font-size: 44rpx">免邮</text>
|
||||
<view class="wr-coupon__left--desc">{{desc}}</view>
|
||||
</view>
|
||||
<view wx:if="{{type == CouponType.GIFT_COUPON}}">
|
||||
<t-image t-class="wr-coupon__left--image" src="{{image}}" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="wr-coupon__right">
|
||||
<view class="wr-coupon__right--title">
|
||||
<text class="coupon-title">{{title}}</text>
|
||||
<view class="coupon-time">{{timeLimit}}</view>
|
||||
<view class="coupon-desc">
|
||||
<view wx:if="{{ruleDesc}}">{{ruleDesc}}</view>
|
||||
</view>
|
||||
<!-- 显示用户优惠券ID,用于调试 -->
|
||||
<view class="coupon-debug-info" style="font-size: 20rpx; color: #999; margin-top: 8rpx;">
|
||||
用户券ID: {{userCouponId}} | 模板ID: {{couponTemplateId}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="wr-coupon__right--oper">
|
||||
<slot name="operator" />
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{status === 'useless' || status === 'disabled'}}" class="wr-coupon__seal seal-{{status}}}" />
|
||||
<view wx:if="{{mask}}" class="wr-coupon__mask" />
|
||||
<view wx:if="{{superposable}}" class="wr-coupon__tag">可叠加</view>
|
||||
</view>
|
||||
147
miniprogram/components/promotion/ui-coupon-card/index.wxss
Normal file
147
miniprogram/components/promotion/ui-coupon-card/index.wxss
Normal file
@@ -0,0 +1,147 @@
|
||||
.wr-coupon {
|
||||
display: flex;
|
||||
background-image: url('https://tdesign.gtimg.com/miniprogram/template/retail/coupon/coupon-bg-nocorners.png');
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
margin-bottom: 24rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.theme-weak.wr-coupon {
|
||||
background-image: url('https://tdesign.gtimg.com/miniprogram/template/retail/coupon/coupon-bg-grey2.png');
|
||||
}
|
||||
|
||||
.wr-coupon__left {
|
||||
width: 200rpx;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color: #fa4126;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.theme-weak .wr-coupon__left {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wr-coupon__left--value {
|
||||
font-size: 64rpx;
|
||||
line-height: 88rpx;
|
||||
font-weight: bold;
|
||||
font-family: 'DIN Alternate', cursive;
|
||||
}
|
||||
.wr-coupon__left--value-int {
|
||||
font-size: 48rpx;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
.wr-coupon__left--value-decimal {
|
||||
font-size: 36rpx;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
.wr-coupon__left--image {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
border-radius: 8px;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
.wr-coupon__left--unit {
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
.wr-coupon__left--desc {
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
color: #fa4126;
|
||||
}
|
||||
|
||||
.theme-weak .wr-coupon__left--desc {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.wr-coupon__right {
|
||||
flex-grow: 1;
|
||||
padding: 0 20rpx;
|
||||
height: 180rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.wr-coupon__right--title {
|
||||
display: flex;
|
||||
-webkit-display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
color: #999999;
|
||||
font-size: 24rpx;
|
||||
flex: 1;
|
||||
}
|
||||
.wr-coupon__right--title .coupon-title {
|
||||
max-width: 320rpx;
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
font-weight: bold;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
.wr-coupon__right--title .coupon-time {
|
||||
margin-top: 16rpx;
|
||||
/* // letter-spacing: -0.05em; */
|
||||
}
|
||||
.wr-coupon__right--title .coupon-desc {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.wr-coupon__right--title .coupon-arrow {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
.wr-coupon__right--oper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.wr-coupon__mask {
|
||||
width: 702rpx;
|
||||
height: 182rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #ffffff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.wr-coupon__tag {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: -24rpx;
|
||||
text-align: center;
|
||||
width: 106rpx;
|
||||
height: 28rpx;
|
||||
opacity: 0.9;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
color: #fa4126;
|
||||
border: 0.5px solid #fa4126;
|
||||
box-sizing: border-box;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.wr-coupon__seal {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.wr-coupon__seal.seal-useless {
|
||||
background-image: url('https://tdesign.gtimg.com/miniprogram/template/retail/coupon/seal-used.png');
|
||||
}
|
||||
|
||||
.wr-coupon__seal.seal-disabled {
|
||||
background-image: url('https://tdesign.gtimg.com/miniprogram/template/retail/coupon/coupon-expired.png');
|
||||
}
|
||||
79
miniprogram/components/swipeout/index.js
Normal file
79
miniprogram/components/swipeout/index.js
Normal file
@@ -0,0 +1,79 @@
|
||||
let ARRAY = [];
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
properties: {
|
||||
disabled: Boolean,
|
||||
leftWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
rightWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
asyncClose: Boolean,
|
||||
},
|
||||
attached() {
|
||||
ARRAY.push(this);
|
||||
},
|
||||
|
||||
detached() {
|
||||
ARRAY = ARRAY.filter((item) => item !== this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Component initial data
|
||||
*/
|
||||
data: {
|
||||
wrapperStyle: '',
|
||||
asyncClose: false,
|
||||
closed: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Component methods
|
||||
*/
|
||||
methods: {
|
||||
open(position) {
|
||||
this.setData({ closed: false });
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
},
|
||||
|
||||
close() {
|
||||
this.setData({ closed: true });
|
||||
},
|
||||
|
||||
closeOther() {
|
||||
ARRAY.filter((item) => item !== this).forEach((item) => item.close());
|
||||
},
|
||||
|
||||
noop() {
|
||||
return;
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
const { key: position = 'outside' } = event.currentTarget.dataset;
|
||||
this.triggerEvent('click', position);
|
||||
|
||||
if (this.data.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.data.asyncClose) {
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
4
miniprogram/components/swipeout/index.json
Normal file
4
miniprogram/components/swipeout/index.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
176
miniprogram/components/swipeout/index.wxml
Normal file
176
miniprogram/components/swipeout/index.wxml
Normal file
@@ -0,0 +1,176 @@
|
||||
<wxs module="swipe">
|
||||
var THRESHOLD = 0.3;
|
||||
var MIN_DISTANCE = 10;
|
||||
var owner;
|
||||
var state;
|
||||
|
||||
var getState = function(ownerInstance) {
|
||||
owner = ownerInstance;
|
||||
state = owner.getState();
|
||||
state.leftWidth = state.leftWidth || 0;
|
||||
state.rightWidth = state.rightWidth || 0;
|
||||
state.offset = state.offset || 0;
|
||||
state.startOffset = state.startOffset || 0;
|
||||
};
|
||||
|
||||
var initRightWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.rightWidth = newVal;
|
||||
if (state.offset < 0) {
|
||||
swipeMove(-state.rightWidth);
|
||||
}
|
||||
};
|
||||
|
||||
var initLeftWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.leftWidth = newVal;
|
||||
if (state.offset > 0) {
|
||||
swipeMove(state.leftWidth);
|
||||
}
|
||||
}
|
||||
|
||||
var resetTouchStatus = function() {
|
||||
state.direction = '';
|
||||
state.deltaX = 0;
|
||||
state.deltaY = 0;
|
||||
state.offsetX = 0;
|
||||
state.offsetY = 0;
|
||||
};
|
||||
|
||||
var touchMove = function(event) {
|
||||
var touchPoint = event.touches && event.touches[0];
|
||||
if (!touchPoint) return;
|
||||
state.deltaX = touchPoint.clientX - state.startX;
|
||||
state.deltaY = touchPoint.clientY - state.startY;
|
||||
state.offsetX = Math.abs(state.deltaX);
|
||||
state.offsetY = Math.abs(state.deltaY);
|
||||
state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
|
||||
};
|
||||
|
||||
var getDirection = function(x, y) {
|
||||
if (x > y && x > MIN_DISTANCE) {
|
||||
return 'horizontal';
|
||||
}
|
||||
if (y > x && y > MIN_DISTANCE) {
|
||||
return 'vertical';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var range = function(num, min, max) {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
};
|
||||
|
||||
var swipeMove = function(_offset = 0) {
|
||||
state.offset = range(
|
||||
_offset,
|
||||
-state.rightWidth,
|
||||
+state.leftWidth,
|
||||
);
|
||||
|
||||
var transform = 'translate3d(' + state.offset + 'px, 0, 0)';
|
||||
var transition = state.dragging
|
||||
? 'none'
|
||||
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
|
||||
owner.selectComponent('#wrapper').setStyle({
|
||||
'-webkit-transform': transform,
|
||||
'-webkit-transition': transition,
|
||||
'transform': transform,
|
||||
'transition': transition
|
||||
});
|
||||
};
|
||||
|
||||
var close = function() {
|
||||
swipeMove(0);
|
||||
};
|
||||
|
||||
var onCloseChange = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
if (newVal === oldVal) return;
|
||||
if (newVal) {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
var touchStart = function(event) {
|
||||
resetTouchStatus();
|
||||
state.startOffset = state.offset;
|
||||
var touchPoint = event.touches && event.touches[0];
|
||||
if (!touchPoint) return;
|
||||
state.startX = touchPoint.clientX;
|
||||
state.startY = touchPoint.clientY;
|
||||
owner.callMethod('closeOther');
|
||||
};
|
||||
|
||||
var startDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchStart(event);
|
||||
};
|
||||
|
||||
var onDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchMove(event);
|
||||
if (state.direction !== 'horizontal') {
|
||||
return;
|
||||
}
|
||||
state.dragging = true;
|
||||
swipeMove(state.startOffset + state.deltaX);
|
||||
};
|
||||
|
||||
var open = function(position) {
|
||||
var _offset = position === 'left' ? +state.leftWidth : -state.rightWidth;
|
||||
owner.callMethod('open', { position: position });
|
||||
swipeMove(_offset);
|
||||
};
|
||||
|
||||
var endDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.dragging = false;
|
||||
// 左/右侧有可滑动区域,且当前不是已open状态,且滑动幅度超过阈值时open左/右侧(滚动到该侧的最边上)
|
||||
if (+state.rightWidth > 0 && -state.startOffset < +state.rightWidth && -state.offset > +state.rightWidth * THRESHOLD) {
|
||||
open('right');
|
||||
} else if (+state.leftWidth > 0 && state.startOffset < +state.leftWidth && state.offset > +state.leftWidth * THRESHOLD) {
|
||||
open('left');
|
||||
} else {
|
||||
// 仅在有发生侧滑的情况下自动关闭(由js控制是否异步关闭)
|
||||
if (state.startOffset !== state.offset) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initLeftWidth: initLeftWidth,
|
||||
initRightWidth: initRightWidth,
|
||||
startDrag: startDrag,
|
||||
onDrag: onDrag,
|
||||
endDrag: endDrag,
|
||||
onCloseChange: onCloseChange
|
||||
};
|
||||
</wxs>
|
||||
|
||||
<view
|
||||
class="wr-class wr-swipeout"
|
||||
data-key="cell"
|
||||
capture-bind:tap="onClick"
|
||||
bindtouchstart="{{disabled || swipe.startDrag}}"
|
||||
capture-bind:touchmove="{{disabled || swipe.onDrag}}"
|
||||
bindtouchend="{{disabled || swipe.endDrag}}"
|
||||
bindtouchcancel="{{disabled || swipe.endDrag}}"
|
||||
closed="{{closed}}"
|
||||
change:closed="{{swipe.onCloseChange}}"
|
||||
leftWidth="{{leftWidth}}"
|
||||
rightWidth="{{rightWidth}}"
|
||||
change:leftWidth="{{swipe.initLeftWidth}}"
|
||||
change:rightWidth="{{swipe.initRightWidth}}"
|
||||
>
|
||||
<view id="wrapper">
|
||||
<view wx:if="{{ leftWidth }}" class="wr-swipeout__left" data-key="left" catch:tap="onClick">
|
||||
<slot name="left" />
|
||||
</view>
|
||||
<slot />
|
||||
<view wx:if="{{ rightWidth }}" class="wr-swipeout__right" data-key="right" catch:tap="onClick">
|
||||
<slot name="right" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
18
miniprogram/components/swipeout/index.wxss
Normal file
18
miniprogram/components/swipeout/index.wxss
Normal file
@@ -0,0 +1,18 @@
|
||||
.wr-swipeout {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-swipeout__left,
|
||||
.wr-swipeout__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.wr-swipeout__left {
|
||||
left: 0;
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
.wr-swipeout__right {
|
||||
right: 0;
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
88
miniprogram/components/webp-image/index.js
Normal file
88
miniprogram/components/webp-image/index.js
Normal file
@@ -0,0 +1,88 @@
|
||||
const systemInfo = wx.getSystemInfoSync();
|
||||
Component({
|
||||
externalClasses: ['t-class', 't-class-load'],
|
||||
properties: {
|
||||
loadFailed: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
loading: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
value: 'aspectFill',
|
||||
},
|
||||
webp: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
showMenuByLongpress: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
thumbHeight: 375,
|
||||
thumbWidth: 375,
|
||||
systemInfo,
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
const { mode } = this.properties;
|
||||
// 获取容器的真实宽高,设置图片的裁剪宽度
|
||||
this.getRect('.J-image').then((res) => {
|
||||
if (res) {
|
||||
const { width, height } = res;
|
||||
this.setData(
|
||||
mode === 'heightFix'
|
||||
? {
|
||||
thumbHeight: this.px2rpx(height) || 375,
|
||||
}
|
||||
: {
|
||||
thumbWidth: this.px2rpx(width) || 375,
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
px2rpx(px) {
|
||||
return (750 / (systemInfo.screenWidth || 375)) * px;
|
||||
},
|
||||
getRect(selector) {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.selectorQuery) {
|
||||
this.selectorQuery = this.createSelectorQuery();
|
||||
}
|
||||
this.selectorQuery.select(selector).boundingClientRect(resolve).exec();
|
||||
});
|
||||
},
|
||||
onLoad(e) {
|
||||
this.triggerEvent('load', e.detail);
|
||||
},
|
||||
onError(e) {
|
||||
this.triggerEvent('error', e.detail);
|
||||
},
|
||||
// 添加错误处理方法,防止组件报错
|
||||
handleError(e) {
|
||||
console.warn('[webp-image] 图片加载失败:', e.detail);
|
||||
this.triggerEvent('error', e.detail);
|
||||
},
|
||||
// 添加onError方法的别名,确保兼容性
|
||||
error(e) {
|
||||
console.warn('[webp-image] 图片错误事件:', e);
|
||||
this.onError(e);
|
||||
},
|
||||
},
|
||||
});
|
||||
6
miniprogram/components/webp-image/index.json
Normal file
6
miniprogram/components/webp-image/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-image": "tdesign-miniprogram/image/image"
|
||||
}
|
||||
}
|
||||
13
miniprogram/components/webp-image/index.wxml
Normal file
13
miniprogram/components/webp-image/index.wxml
Normal file
@@ -0,0 +1,13 @@
|
||||
<wxs src="./utils.wxs" module="Utils" />
|
||||
<t-image
|
||||
t-class="t-class J-image"
|
||||
t-class-load="t-class-load"
|
||||
src="{{Utils.getSrc({src, thumbWidth: thumbWidth || 0, thumbHeight: thumbHeight || 0, systemInfo, webp, mode})}}"
|
||||
mode="{{ mode }}"
|
||||
lazy="{{ lazyLoad }}"
|
||||
show-menu-by-longpress="{{showMenuByLongpress}}"
|
||||
error="{{loadFailed}}"
|
||||
loading="{{loading}}"
|
||||
binderror="onError"
|
||||
bindload="onLoad"
|
||||
/>
|
||||
0
miniprogram/components/webp-image/index.wxss
Normal file
0
miniprogram/components/webp-image/index.wxss
Normal file
153
miniprogram/components/webp-image/utils.wxs
Normal file
153
miniprogram/components/webp-image/utils.wxs
Normal file
@@ -0,0 +1,153 @@
|
||||
var isString = function (value) {
|
||||
return typeof value === 'string';
|
||||
};
|
||||
|
||||
var isNumber = function (value) {
|
||||
return typeof value === 'number';
|
||||
};
|
||||
|
||||
var getFileExt = function (src) {
|
||||
var fileUrl = src.split('?')[0];
|
||||
var splitUlr = fileUrl.split('/');
|
||||
var filepath = splitUlr[splitUlr.length - 1];
|
||||
return filepath.split('.')[1] || 'jpg';
|
||||
};
|
||||
|
||||
function isUrl(url) {
|
||||
// NOCC:ToolNameCheck(非敏感词)
|
||||
var urlReg = getRegExp(
|
||||
'/[(http(s)?)://(www.)?a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/',
|
||||
'ig',
|
||||
);
|
||||
|
||||
return urlReg.test(url);
|
||||
}
|
||||
|
||||
function rpx2px(rpx, screenWidth) {
|
||||
// px / systemWidth = rpx / 750
|
||||
var result = (rpx * (screenWidth || 375)) / 750;
|
||||
|
||||
return Math.round(result);
|
||||
}
|
||||
|
||||
function imageMogr(url, options) {
|
||||
if (!isString(url) || !url) return '';
|
||||
|
||||
if (
|
||||
url.indexOf('qlogo.cn') !== -1 ||
|
||||
url.indexOf('wxfile://') === 0 ||
|
||||
url.indexOf('http://tmp/wx') === 0 ||
|
||||
url.indexOf('imageMogr2') !== -1 ||
|
||||
url.indexOf('tral.cc') !== -1 ||
|
||||
url.indexOf('localhost') !== -1 ||
|
||||
url.indexOf('192.168.') !== -1 ||
|
||||
url.indexOf('127.0.0.1') !== -1
|
||||
) {
|
||||
//qlogo.cn域名、tral.cc域名、本地开发环境或者本地图片不做转换
|
||||
return url;
|
||||
} //强制转https
|
||||
|
||||
if (url.indexOf('http://') === 0) {
|
||||
url = url.replace('http://', 'https://');
|
||||
} else if (url.indexOf('//') === 0) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
|
||||
if (!options) return url;
|
||||
|
||||
var width = Math.ceil(options.width),
|
||||
height = Math.ceil(options.height),
|
||||
format = options.format,
|
||||
_optionsQuality = options.quality,
|
||||
quality = _optionsQuality === undefined ? 70 : _optionsQuality,
|
||||
_optionsStrip = options.strip,
|
||||
strip = _optionsStrip === undefined ? true : _optionsStrip,
|
||||
crop = options.crop;
|
||||
var isValidWidth = isNumber(width) && width > 0;
|
||||
var isValidHeight = isNumber(height) && height > 0;
|
||||
var imageMogrStr = '';
|
||||
var size = '';
|
||||
|
||||
if (isValidWidth && isValidHeight) {
|
||||
size = ''.concat(width, 'x').concat(height);
|
||||
} else if (isValidWidth) {
|
||||
size = ''.concat(width, 'x');
|
||||
} else if (isValidHeight) {
|
||||
size = 'x'.concat(height);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
//缩放或者裁剪
|
||||
imageMogrStr += '/'.concat(crop ? 'crop' : 'thumbnail', '/').concat(size);
|
||||
|
||||
if (crop) {
|
||||
//裁剪目前需求只有以图片中心为基准
|
||||
imageMogrStr += '/gravity/center';
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber(quality)) {
|
||||
//质量变换
|
||||
imageMogrStr += '/quality/'.concat(quality);
|
||||
}
|
||||
|
||||
if (strip) {
|
||||
//去除元信息
|
||||
imageMogrStr += '/strip';
|
||||
}
|
||||
|
||||
var ext = getFileExt(url);
|
||||
|
||||
// gif 图片不做格式转换,否则会损坏动图
|
||||
if (ext === 'gif') {
|
||||
imageMogrStr += '/cgif/1';
|
||||
} else if (format) {
|
||||
//格式转换
|
||||
imageMogrStr += '/format/'.concat(format);
|
||||
}
|
||||
|
||||
if (format === 'jpg' || (!format && (ext === 'jpg' || ext === 'jpeg'))) {
|
||||
//渐进式 jpg 加载
|
||||
imageMogrStr += '/interlace/1';
|
||||
}
|
||||
if (!imageMogrStr) return url;
|
||||
return ''
|
||||
.concat(url)
|
||||
.concat(url.indexOf('?') !== -1 ? '&' : '?', 'imageMogr2')
|
||||
.concat(imageMogrStr);
|
||||
}
|
||||
function getSrc(options) {
|
||||
if (!options.src) return '';
|
||||
|
||||
// 检查是否为本地开发环境,如果是则直接返回原始URL
|
||||
if (
|
||||
options.src.indexOf('localhost') !== -1 ||
|
||||
options.src.indexOf('192.168.') !== -1 ||
|
||||
options.src.indexOf('127.0.0.1') !== -1
|
||||
) {
|
||||
return options.src;
|
||||
}
|
||||
|
||||
if (options.thumbWidth || options.thumbHeight) {
|
||||
return imageMogr(options.src, {
|
||||
width:
|
||||
options.mode !== 'heightFix'
|
||||
? rpx2px(options.thumbWidth, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
height:
|
||||
options.mode !== 'widthFix'
|
||||
? rpx2px(options.thumbHeight, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
format: options.webp ? 'webp' : null,
|
||||
});
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageMogr: imageMogr,
|
||||
getSrc: getSrc,
|
||||
};
|
||||
88
miniprogram/config/eslintCheck.js
Normal file
88
miniprogram/config/eslintCheck.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/* eslint-disable prefer-template */
|
||||
/**
|
||||
* 工程代码pre-commit 检查工具
|
||||
* @date 2019.9.4
|
||||
|
||||
*/
|
||||
const { exec } = require('child_process');
|
||||
const chalk = require('chalk');
|
||||
const { CLIEngine } = require('eslint');
|
||||
const cli = new CLIEngine({});
|
||||
const { log } = console;
|
||||
|
||||
function getErrorLevel(number) {
|
||||
switch (number) {
|
||||
case 2:
|
||||
return 'error';
|
||||
case 1:
|
||||
return 'warn';
|
||||
default:
|
||||
}
|
||||
return 'undefined';
|
||||
}
|
||||
let pass = 0;
|
||||
exec('git diff --cached --name-only --diff-filter=ACM | grep -Ei "\\.ts$|\\.js$"', (error, stdout) => {
|
||||
if (stdout.length) {
|
||||
const array = stdout.split('\n');
|
||||
array.pop();
|
||||
const { results } = cli.executeOnFiles(array);
|
||||
let errorCount = 0;
|
||||
let warningCount = 0;
|
||||
results.forEach((result) => {
|
||||
errorCount += result.errorCount;
|
||||
warningCount += result.warningCount;
|
||||
if (result.messages.length > 0) {
|
||||
log('\n');
|
||||
log(result.filePath);
|
||||
result.messages.forEach((obj) => {
|
||||
const level = getErrorLevel(obj.severity);
|
||||
if (level === 'warn')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.yellow(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.red.bold(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t ' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error') pass = 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
if (warningCount > 0 || errorCount > 0) {
|
||||
log(
|
||||
'\n' +
|
||||
chalk.bgRed.bold(errorCount + warningCount + ' problems') +
|
||||
' (' +
|
||||
chalk.red.bold(errorCount) +
|
||||
' errors, ' +
|
||||
chalk.yellow(warningCount) +
|
||||
' warnings) \0',
|
||||
);
|
||||
}
|
||||
!pass && log(chalk.green.bold('~~ Done: 代码检验通过,提交成功 ~~'));
|
||||
process.exit(pass);
|
||||
}
|
||||
if (error !== null) {
|
||||
log(`exec error: ${error}`);
|
||||
}
|
||||
});
|
||||
20477
miniprogram/config/index.js
Normal file
20477
miniprogram/config/index.js
Normal file
File diff suppressed because it is too large
Load Diff
22
miniprogram/custom-tab-bar/data.js
Normal file
22
miniprogram/custom-tab-bar/data.js
Normal file
@@ -0,0 +1,22 @@
|
||||
export default [
|
||||
{
|
||||
icon: 'home',
|
||||
text: '首页',
|
||||
url: 'pages/home/home',
|
||||
},
|
||||
{
|
||||
icon: 'sort',
|
||||
text: '分类',
|
||||
url: 'pages/category/index',
|
||||
},
|
||||
{
|
||||
icon: 'cart',
|
||||
text: '购物车',
|
||||
url: 'pages/cart/index',
|
||||
},
|
||||
{
|
||||
icon: 'person',
|
||||
text: '个人中心',
|
||||
url: 'pages/usercenter/index',
|
||||
},
|
||||
];
|
||||
29
miniprogram/custom-tab-bar/index.js
Normal file
29
miniprogram/custom-tab-bar/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import TabMenu from './data';
|
||||
Component({
|
||||
data: {
|
||||
active: 0,
|
||||
list: TabMenu,
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.setData({ active: event.detail.value });
|
||||
wx.switchTab({
|
||||
url: this.data.list[event.detail.value].url.startsWith('/')
|
||||
? this.data.list[event.detail.value].url
|
||||
: `/${this.data.list[event.detail.value].url}`,
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
const page = getCurrentPages().pop();
|
||||
const route = page ? page.route.split('?')[0] : '';
|
||||
const active = this.data.list.findIndex(
|
||||
(item) =>
|
||||
(item.url.startsWith('/') ? item.url.substr(1) : item.url) ===
|
||||
`${route}`,
|
||||
);
|
||||
this.setData({ active });
|
||||
},
|
||||
},
|
||||
});
|
||||
8
miniprogram/custom-tab-bar/index.json
Normal file
8
miniprogram/custom-tab-bar/index.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-tab-bar": "tdesign-miniprogram/tab-bar/tab-bar",
|
||||
"t-tab-bar-item": "tdesign-miniprogram/tab-bar-item/tab-bar-item",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
||||
18
miniprogram/custom-tab-bar/index.wxml
Normal file
18
miniprogram/custom-tab-bar/index.wxml
Normal file
@@ -0,0 +1,18 @@
|
||||
<t-tab-bar
|
||||
value="{{active}}"
|
||||
bindchange="onChange"
|
||||
split="{{false}}"
|
||||
>
|
||||
<t-tab-bar-item
|
||||
wx:for="{{list}}"
|
||||
wx:for-item="item"
|
||||
wx:for-index="index"
|
||||
wx:key="index"
|
||||
>
|
||||
<view class="custom-tab-bar-wrapper">
|
||||
<t-icon prefix="wr" name="{{item.icon}}" size="48rpx" />
|
||||
<view class="text">{{ item.text }}</view>
|
||||
</view>
|
||||
</t-tab-bar-item>
|
||||
</t-tab-bar>
|
||||
|
||||
9
miniprogram/custom-tab-bar/index.wxss
Normal file
9
miniprogram/custom-tab-bar/index.wxss
Normal file
@@ -0,0 +1,9 @@
|
||||
.custom-tab-bar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-tab-bar-wrapper .text {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
5
miniprogram/jsconfig.json
Normal file
5
miniprogram/jsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
13
miniprogram/miniprogram_npm/dayjs/index.js
Normal file
13
miniprogram/miniprogram_npm/dayjs/index.js
Normal file
File diff suppressed because one or more lines are too long
1
miniprogram/miniprogram_npm/dayjs/index.js.map
Normal file
1
miniprogram/miniprogram_npm/dayjs/index.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
85
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/action-sheet.d.ts
vendored
Normal file
85
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/action-sheet.d.ts
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import { SuperComponent } from '../common/src/index';
|
||||
export default class ActionSheet extends SuperComponent {
|
||||
static show: (options: import("./show").ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
|
||||
behaviors: string[];
|
||||
externalClasses: string[];
|
||||
properties: {
|
||||
align?: {
|
||||
type: StringConstructor;
|
||||
value?: "left" | "center";
|
||||
};
|
||||
cancelText?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
count?: {
|
||||
type: NumberConstructor;
|
||||
value?: number;
|
||||
};
|
||||
description?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
items: {
|
||||
type: ArrayConstructor;
|
||||
value?: (string | import("./type").ActionSheetItem)[];
|
||||
required?: boolean;
|
||||
};
|
||||
popupProps?: {
|
||||
type: ObjectConstructor;
|
||||
value?: import("../popup").TdPopupProps;
|
||||
};
|
||||
showCancel?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
showOverlay?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
theme?: {
|
||||
type: StringConstructor;
|
||||
value?: "list" | "grid";
|
||||
};
|
||||
usingCustomNavbar?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
visible?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
defaultVisible?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
};
|
||||
data: {
|
||||
prefix: string;
|
||||
classPrefix: string;
|
||||
gridThemeItems: any[];
|
||||
currentSwiperIndex: number;
|
||||
defaultPopUpProps: {};
|
||||
defaultPopUpzIndex: number;
|
||||
};
|
||||
controlledProps: {
|
||||
key: string;
|
||||
event: string;
|
||||
}[];
|
||||
observers: {
|
||||
'visible, items'(visible: boolean): void;
|
||||
};
|
||||
methods: {
|
||||
init(): void;
|
||||
memoInitialData(): void;
|
||||
splitGridThemeActions(): void;
|
||||
show(options: any): void;
|
||||
close(): void;
|
||||
onPopupVisibleChange({ detail }: {
|
||||
detail: any;
|
||||
}): void;
|
||||
onSwiperChange(e: WechatMiniprogram.TouchEvent): void;
|
||||
onSelect(event: WechatMiniprogram.TouchEvent): void;
|
||||
onCancel(): void;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import{__decorate}from"tslib";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";import useCustomNavbar from"../mixins/using-custom-navbar";const{prefix:prefix}=config,name=`${prefix}-action-sheet`;let ActionSheet=class extends SuperComponent{constructor(){super(...arguments),this.behaviors=[useCustomNavbar],this.externalClasses=[`${prefix}-class`,`${prefix}-class-content`,`${prefix}-class-cancel`],this.properties=Object.assign({},props),this.data={prefix:prefix,classPrefix:name,gridThemeItems:[],currentSwiperIndex:0,defaultPopUpProps:{},defaultPopUpzIndex:11500},this.controlledProps=[{key:"visible",event:"visible-change"}],this.observers={"visible, items"(e){e&&this.init()}},this.methods={init(){this.memoInitialData(),this.splitGridThemeActions()},memoInitialData(){this.initialData=Object.assign(Object.assign({},this.properties),this.data)},splitGridThemeActions(){this.data.theme===ActionSheetTheme.Grid&&this.setData({gridThemeItems:chunk(this.data.items,this.data.count)})},show(e){this.setData(Object.assign(Object.assign(Object.assign({},this.initialData),e),{visible:!0})),this.splitGridThemeActions(),this.autoClose=!0,this._trigger("visible-change",{visible:!0})},close(){this.triggerEvent("close",{trigger:"command"}),this._trigger("visible-change",{visible:!1})},onPopupVisibleChange({detail:e}){e.visible||(this.triggerEvent("close",{trigger:"overlay"}),this._trigger("visible-change",{visible:!1})),this.autoClose&&(this.setData({visible:!1}),this.autoClose=!1)},onSwiperChange(e){const{current:t}=e.detail;this.setData({currentSwiperIndex:t})},onSelect(e){const{currentSwiperIndex:t,items:i,gridThemeItems:s,count:o,theme:r}=this.data,{index:n}=e.currentTarget.dataset,a=r===ActionSheetTheme.Grid,h=a?s[t][n]:i[n],c=a?n+t*o:n;h&&(this.triggerEvent("selected",{selected:h,index:c}),h.disabled||(this.triggerEvent("close",{trigger:"select"}),this._trigger("visible-change",{visible:!1})))},onCancel(){this.triggerEvent("cancel"),this.autoClose&&(this.setData({visible:!1}),this.autoClose=!1)}}}};ActionSheet.show=show,ActionSheet=__decorate([wxComponent()],ActionSheet);export default ActionSheet;
|
||||
@@ -0,0 +1 @@
|
||||
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-icon":"../icon/icon","t-popup":"../popup/popup","t-grid":"../grid/grid","t-grid-item":"../grid-item/grid-item"}}
|
||||
@@ -0,0 +1 @@
|
||||
<wxs src="./action-sheet.wxs" module="_this"/><wxs src="../common/utils.wxs" module="_"/><import src="./template/list.wxml"/><import src="./template/grid.wxml"/><view id="{{classPrefix}}" style="{{_._style([style, customStyle])}}" class="{{classPrefix}} class {{prefix}}-class"><t-popup visible="{{visible}}" placement="bottom" usingCustomNavbar="{{usingCustomNavbar}}" bind:visible-change="onPopupVisibleChange" show-overlay="{{showOverlay}}" z-index="{{ popupProps.zIndex || defaultPopUpzIndex }}" overlay-props="{{ popupProps.overlayProps || defaultPopUpProps }}"><view class="{{_.cls(classPrefix + '__content', [['grid', gridThemeItems.length]])}} {{prefix}}-class-content" tabindex="0"><view wx:if="{{description}}" tabindex="0" class="{{_.cls(classPrefix + '__description', [align])}}">{{description}}</view><block wx:if="{{gridThemeItems.length}}"><template is="grid" data="{{classPrefix, prefix, gridThemeItems, count, currentSwiperIndex}}"/></block><view wx:elif="{{items && items.length}}" class="{{classPrefix}}__list"><block wx:for="{{ items }}" wx:key="index"><template is="list" data="{{index, classPrefix, listThemeItemClass: _.cls(classPrefix + '__list-item', [align, [disabled, item.disabled]]), item}}"/></block></view></view><slot/><view wx:if="{{showCancel}}" class="{{classPrefix}}__footer"><view class="{{classPrefix}}__gap-{{theme}}"/><view class="{{classPrefix}}__cancel {{prefix}}-class-cancel" hover-class="{{classPrefix}}__cancel--hover" hover-stay-time="70" bind:tap="onCancel" aria-role="button">{{ cancelText || '取消' }}</view></view></t-popup></view>
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
@import '../common/style/index.wxss';.t-action-sheet__content{color:var(--td-action-sheet-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));border-top-left-radius:var(--td-action-sheet-border-radius,var(--td-radius-extra-large,24rpx));border-top-right-radius:var(--td-action-sheet-border-radius,var(--td-radius-extra-large,24rpx));background-color:var(--td-bg-color-container,var(--td-font-white-1,#fff));overflow:hidden}.t-action-sheet__content--grid{padding-top:16rpx}.t-action-sheet__content:focus{outline:0}.t-action-sheet__grid{padding-bottom:16rpx}.t-action-sheet__grid--swiper{padding-bottom:48rpx}.t-action-sheet__description{color:var(--td-action-sheet-description-color,var(--td-text-color-placeholder,var(--td-font-gray-3,rgba(0,0,0,.4))));line-height:44rpx;font-size:28rpx;text-align:var(--td-action-sheet-text-align,center);padding:24rpx 32rpx;position:relative}.t-action-sheet__description:focus{outline:0}.t-action-sheet__description::after{content:'';display:block;position:absolute;top:unset;bottom:0;left:unset;right:unset;background-color:var(--td-action-sheet-border-color,var(--td-border-level-1-color,var(--td-gray-color-3,#e7e7e7)))}.t-action-sheet__description::after{height:1px;left:0;right:0;transform:scaleY(.5)}.t-action-sheet__description--left{text-align:left}.t-action-sheet__description--left::after{left:32rpx}.t-action-sheet__list-item{display:flex;align-items:center;justify-content:center;position:relative;height:var(--td-action-sheet-list-item-height,112rpx);padding:0 32rpx}.t-action-sheet__list-item::after{content:'';display:block;position:absolute;top:unset;bottom:0;left:unset;right:unset;background-color:var(--td-action-sheet-border-color,var(--td-border-level-1-color,var(--td-gray-color-3,#e7e7e7)))}.t-action-sheet__list-item::after{height:1px;left:0;right:0;transform:scaleY(.5)}.t-action-sheet__list-item:focus{outline:0}.t-action-sheet__list-item--left{justify-content:start}.t-action-sheet__list-item--left::after{left:32rpx}.t-action-sheet__list-item--disabled{color:var(--td-action-sheet-list-item-disabled-color,var(--td-text-color-disabled,var(--td-font-gray-4,rgba(0,0,0,.26))))}.t-action-sheet__list-item-text{font-size:var(--td-font-size-m,32rpx);word-wrap:normal;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.t-action-sheet__list-item-icon{margin-right:16rpx}.t-action-sheet__list-item-icon--suffix{margin-left:auto}.t-action-sheet__swiper-wrap{margin-top:8rpx;position:relative}.t-action-sheet__footer{background-color:var(--td-bg-color-container,var(--td-font-white-1,#fff))}.t-action-sheet__gap-list{height:16rpx;background-color:var(--td-action-sheet-gap-color,var(--td-bg-color-page,var(--td-gray-color-1,#f3f3f3)))}.t-action-sheet__gap-grid{height:1rpx;background-color:var(--td-action-sheet-border-color,var(--td-border-level-1-color,var(--td-gray-color-3,#e7e7e7)))}.t-action-sheet__cancel{display:flex;align-items:center;justify-content:center;color:var(--td-action-sheet-cancel-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));height:var(--td-action-sheet-cancel-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 .4s ease-in}.t-action-sheet__dots-item.t-is-active{background-color:#0052d9}
|
||||
8
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/index.d.ts
vendored
Normal file
8
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/index.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
import { ActionSheetItem, ActionSheetTheme, ActionSheetShowOption } from './show';
|
||||
export { ActionSheetItem, ActionSheetTheme, ActionSheetShowOption };
|
||||
declare const _default: {
|
||||
show(options: ActionSheetShowOption): WechatMiniprogram.Component.TrivialInstance;
|
||||
close(options: ActionSheetShowOption): void;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1 @@
|
||||
import{show,close,ActionSheetTheme}from"./show";export{ActionSheetTheme};export default{show:e=>show(e),close:e=>close(e)};
|
||||
3
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/props.d.ts
vendored
Normal file
3
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/props.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { TdActionSheetProps } from './type';
|
||||
declare const props: TdActionSheetProps;
|
||||
export default props;
|
||||
@@ -0,0 +1 @@
|
||||
const props={align:{type:String,value:"center"},cancelText:{type:String,value:""},count:{type:Number,value:8},description:{type:String,value:""},items:{type:Array,required:!0},popupProps:{type:Object,value:{}},showCancel:{type:Boolean,value:!0},showOverlay:{type:Boolean,value:!0},theme:{type:String,value:"list"},usingCustomNavbar:{type:Boolean,value:!1},visible:{type:Boolean,value:null},defaultVisible:{type:Boolean,value:!1}};export default props;
|
||||
26
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/show.d.ts
vendored
Normal file
26
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/show.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
import { ActionSheetItem } from './type';
|
||||
export { ActionSheetItem };
|
||||
declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
|
||||
export declare enum ActionSheetTheme {
|
||||
List = "list",
|
||||
Grid = "grid"
|
||||
}
|
||||
interface ActionSheetProps {
|
||||
align: 'center' | 'left';
|
||||
cancelText?: string;
|
||||
count?: number;
|
||||
description: string;
|
||||
items: Array<string | ActionSheetItem>;
|
||||
showCancel?: boolean;
|
||||
theme?: ActionSheetTheme;
|
||||
visible: boolean;
|
||||
defaultVisible?: boolean;
|
||||
}
|
||||
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;
|
||||
@@ -0,0 +1 @@
|
||||
import{__rest}from"tslib";import{getInstance}from"../common/utils";export var ActionSheetTheme;!function(t){t.List="list",t.Grid="grid"}(ActionSheetTheme||(ActionSheetTheme={}));export const show=function(t){const e=Object.assign({},t),{context:o,selector:n="#t-action-sheet"}=e,c=__rest(e,["context","selector"]),s=getInstance(o,n);if(s)return s.show(Object.assign({},c)),s;console.error("未找到组件,请确认 selector && context 是否正确")};export const close=function(t){const{context:e,selector:o="#t-action-sheet"}=Object.assign({},t),n=getInstance(e,o);n&&n.close()};
|
||||
@@ -0,0 +1 @@
|
||||
<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}}" icon="{{ { name: item.icon, color: item.color } }}" text="{{item.label || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></block><block wx:elif="{{gridThemeItems.length > 1}}"><view class="{{classPrefix}}__swiper-wrap"><swiper style="height: 456rpx" autoplay="{{false}}" current="{{currentSwiperIndex}}" bindchange="onSwiperChange"><swiper-item wx:for="{{gridThemeItems}}" wx:key="index"><t-grid align="center" t-class="{{classPrefix}}__grid {{classPrefix}}__grid--swiper" 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" icon="{{ { name: item.icon, color: item.color } }}" text="{{item.label || ''}}" image="{{item.image || ''}}" style="--td-grid-item-text-color: {{item.color}}"></t-grid-item></t-grid></swiper-item></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>
|
||||
@@ -0,0 +1 @@
|
||||
<template name="list"><view data-index="{{index}}" style="{{ item.color ? 'color: ' + item.color : '' }}" class="{{listThemeItemClass}}" bind:tap="onSelect" aria-role="{{ariaRole || 'button'}}" aria-label="{{item.label || item}}" tabindex="0"><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><t-icon wx:if="{{item.suffixIcon}}" name="{{item.suffixIcon}}" class="{{classPrefix}}__list-item-icon {{classPrefix}}__list-item-icon--suffix" size="48rpx"></t-icon></view></template>
|
||||
59
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/type.d.ts
vendored
Normal file
59
miniprogram/miniprogram_npm/tdesign-miniprogram/action-sheet/type.d.ts
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { PopupProps } from '../popup/index';
|
||||
export interface TdActionSheetProps {
|
||||
align?: {
|
||||
type: StringConstructor;
|
||||
value?: 'center' | 'left';
|
||||
};
|
||||
cancelText?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
count?: {
|
||||
type: NumberConstructor;
|
||||
value?: number;
|
||||
};
|
||||
description?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
items: {
|
||||
type: ArrayConstructor;
|
||||
value?: Array<string | ActionSheetItem>;
|
||||
required?: boolean;
|
||||
};
|
||||
popupProps?: {
|
||||
type: ObjectConstructor;
|
||||
value?: PopupProps;
|
||||
};
|
||||
showCancel?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
showOverlay?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
theme?: {
|
||||
type: StringConstructor;
|
||||
value?: 'list' | 'grid';
|
||||
};
|
||||
usingCustomNavbar?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
visible?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
defaultVisible?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
}
|
||||
export interface ActionSheetItem {
|
||||
label: string;
|
||||
color?: string;
|
||||
disabled?: boolean;
|
||||
icon?: string;
|
||||
suffixIcon?: string;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export{};
|
||||
28
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/avatar-group.d.ts
vendored
Normal file
28
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/avatar-group.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
};
|
||||
options: {
|
||||
multipleSlots: boolean;
|
||||
};
|
||||
relations: RelationsOptions;
|
||||
lifetimes: {
|
||||
attached(): void;
|
||||
ready(): void;
|
||||
};
|
||||
observers: {
|
||||
'cascading, size'(): void;
|
||||
};
|
||||
methods: {
|
||||
setClass(): void;
|
||||
handleMax(): void;
|
||||
onCollapsedItemClick(e: WechatMiniprogram.CustomEvent): void;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import avatarGroupProps from"./props";const{prefix:prefix}=config,name=`${prefix}-avatar-group`;let AvatarGroup=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`,`${prefix}-class-content`,`${prefix}-class-image`],this.properties=avatarGroupProps,this.data={prefix:prefix,classPrefix:name,hasChild:!0,length:0,className:""},this.options={multipleSlots:!0},this.relations={"../avatar/avatar":{type:"descendant"}},this.lifetimes={attached(){this.setClass()},ready(){this.setData({length:this.$children.length}),this.handleMax()}},this.observers={"cascading, size"(){this.setClass()}},this.methods={setClass(){const{cascading:e,size:t}=this.properties,s=e.split("-")[0],a=[name,`${prefix}-class`,`${name}-offset-${s}`,`${name}-offset-${s}-${t.indexOf("px")>-1?"medium":t||"medium"}`];this.setData({className:a.join(" ")})},handleMax(){const{max:e}=this.data,t=this.$children.length;if(!e||e>t)return;this.$children.splice(e,t-e).forEach((e=>{e.hide()}))},onCollapsedItemClick(e){this.triggerEvent("collapsed-item-click",e.detail)}}}};AvatarGroup=__decorate([wxComponent()],AvatarGroup);export default AvatarGroup;
|
||||
@@ -0,0 +1 @@
|
||||
{"component":true,"styleIsolation":"shared","usingComponents":{"t-avatar":"../avatar/avatar"}}
|
||||
@@ -0,0 +1 @@
|
||||
<wxs src="../common/utils.wxs" module="_"/><view style="{{_._style([style, customStyle])}}" class="{{className}} class"><slot/><view class="{{classPrefix}}__collapse--slot"><slot name="collapse-avatar"/></view><view class="{{classPrefix}}__collapse--default" wx:if="{{max && (max < length)}}" bindtap="onCollapsedItemClick"><t-avatar t-class-image="{{prefix}}-avatar--border {{prefix}}-avatar--border-{{size}} {{prefix}}-class-image" t-class-content="{{prefix}}-class-content" size="{{size}}" shape="{{shape}}" icon="{{ collapseAvatar ? '' : 'user-add'}}" aria-role="none">{{collapseAvatar}}</t-avatar></view></view>
|
||||
File diff suppressed because one or more lines are too long
3
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/props.d.ts
vendored
Normal file
3
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/props.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { TdAvatarGroupProps } from './type';
|
||||
declare const props: TdAvatarGroupProps;
|
||||
export default props;
|
||||
@@ -0,0 +1 @@
|
||||
const props={cascading:{type:String,value:"left-up"},collapseAvatar:{type:String},max:{type:Number},shape:{type:String},size:{type:String,value:""}};export default props;
|
||||
24
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/type.d.ts
vendored
Normal file
24
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar-group/type.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ShapeEnum } from '../common/common';
|
||||
export interface TdAvatarGroupProps {
|
||||
cascading?: {
|
||||
type: StringConstructor;
|
||||
value?: CascadingValue;
|
||||
};
|
||||
collapseAvatar?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
max?: {
|
||||
type: NumberConstructor;
|
||||
value?: number;
|
||||
};
|
||||
shape?: {
|
||||
type: StringConstructor;
|
||||
value?: ShapeEnum;
|
||||
};
|
||||
size?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
}
|
||||
export declare type CascadingValue = 'left-up' | 'right-up';
|
||||
@@ -0,0 +1 @@
|
||||
export{};
|
||||
22
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/avatar.d.ts
vendored
Normal file
22
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/avatar.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="miniprogram-api-typings" />
|
||||
import { SuperComponent, RelationsOptions } from '../common/src/index';
|
||||
export default class Avatar extends SuperComponent {
|
||||
options: WechatMiniprogram.Component.ComponentOptions;
|
||||
externalClasses: string[];
|
||||
properties: import("./type").TdAvatarProps;
|
||||
data: {
|
||||
prefix: string;
|
||||
classPrefix: string;
|
||||
isShow: boolean;
|
||||
zIndex: number;
|
||||
systemInfo: WechatMiniprogram.WindowInfo | WechatMiniprogram.SystemInfo;
|
||||
};
|
||||
relations: RelationsOptions;
|
||||
observers: {
|
||||
icon(icon: any): void;
|
||||
};
|
||||
methods: {
|
||||
hide(): void;
|
||||
onLoadError(e: WechatMiniprogram.CustomEvent): void;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import avatarProps from"./props";import{setIcon,systemInfo}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-avatar`;let Avatar=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0},this.externalClasses=[`${prefix}-class`,`${prefix}-class-image`,`${prefix}-class-icon`,`${prefix}-class-alt`,`${prefix}-class-content`],this.properties=avatarProps,this.data={prefix:prefix,classPrefix:name,isShow:!0,zIndex:0,systemInfo:systemInfo},this.relations={"../avatar-group/avatar-group":{type:"ancestor",linked(t){this.parent=t,this.setData({shape:this.data.shape||t.data.shape||"circle",size:this.data.size||t.data.size,bordered:!0})}}},this.observers={icon(t){const s=setIcon("icon",t,"");this.setData(Object.assign({},s))}},this.methods={hide(){this.setData({isShow:!1})},onLoadError(t){this.properties.hideOnLoadFailed&&this.setData({isShow:!1}),this.triggerEvent("error",t.detail)}}}};Avatar=__decorate([wxComponent()],Avatar);export default Avatar;
|
||||
@@ -0,0 +1 @@
|
||||
{"component":true,"styleIsolation":"shared","usingComponents":{"t-icon":"../icon/icon","t-badge":"../badge/badge","t-image":"../image/image"}}
|
||||
@@ -0,0 +1 @@
|
||||
<import src="../common/template/icon.wxml"/><wxs src="../common/utils.wxs" module="_"/><wxs src="./avatar.wxs" module="_this"/><view class="{{classPrefix}}__wrapper class {{prefix}}-class" style="{{_._style([_this.getStyles(isShow), style, customStyle])}}"><t-badge color="{{badgeProps.color || ''}}" content="{{badgeProps.content || ''}}" count="{{badgeProps.count || 0}}" dot="{{badgeProps.dot || false}}" max-count="{{badgeProps.maxCount || 99}}" offset="{{badgeProps.offset || []}}" shape="{{badgeProps.shape || 'circle'}}" show-zero="{{badgeProps.showZero || false}}" size="{{badgeProps.size || 'medium'}}" t-class="{{badgeProps.tClass}}" t-class-content="{{badgeProps.tClassContent}}" t-class-count="{{badgeProps.tClassCount}}"><view class="{{_this.getClass(classPrefix, size || 'medium', shape, bordered)}} {{prefix}}-class-image" style="{{_this.getSize(size, systemInfo)}}" aria-label="{{ ariaLabel || alt ||'头像'}}" aria-role="{{ ariaRole || 'img'}}" aria-hidden="{{ ariaHidden }}"><t-image wx:if="{{image}}" t-class="{{prefix}}-image {{classPrefix}}__image" t-class-load="{{prefix}}-class-alt" style="{{imageProps && imageProps.style || ''}}" src="{{image}}" mode="{{imageProps && imageProps.mode || 'aspectFill'}}" lazy="{{imageProps && imageProps.lazy || false}}" loading="{{imageProps && imageProps.loading || 'default'}}" shape="{{imageProps && imageProps.shape || 'round'}}" webp="{{imageProps && imageProps.webp || false}}" error="{{alt || 'default'}}" bind:error="onLoadError"/><template wx:elif="{{iconName || _.isNoEmptyObj(iconData)}}" is="icon" data="{{tClass: classPrefix + '__icon ' + prefix + '-class-icon', name: iconName, ...iconData}}"/><view wx:else class="{{classPrefix}}__text {{prefix}}-class-content"><slot/></view></view></t-badge></view>
|
||||
@@ -0,0 +1,30 @@
|
||||
module.exports = {
|
||||
getClass: function (classPrefix, size, shape, bordered) {
|
||||
var hasPx = (size || '').indexOf('px') > -1;
|
||||
var borderSize = hasPx ? 'medium' : size;
|
||||
var classNames = [
|
||||
classPrefix,
|
||||
classPrefix + (shape === 'round' ? '--round' : '--circle'),
|
||||
bordered ? classPrefix + '--border' + ' ' + classPrefix + '--border-' + borderSize : '',
|
||||
hasPx ? '' : classPrefix + '--' + size,
|
||||
];
|
||||
return classNames.join(' ');
|
||||
},
|
||||
|
||||
getSize: function (size = 'medium', systemInfo) {
|
||||
var res = getRegExp('^([0-9]+)(px|rpx)$').exec(size);
|
||||
|
||||
if (res && res.length >= 3) {
|
||||
var px = res[1];
|
||||
if (res[2] === 'rpx') {
|
||||
px = Math.floor((systemInfo.windowWidth * res[1]) / 750);
|
||||
}
|
||||
|
||||
return 'width:' + size + ';height:' + size + ';font-size:' + ((px / 8) * 3 + 2) + 'px';
|
||||
}
|
||||
},
|
||||
|
||||
getStyles: function (isShow) {
|
||||
return isShow ? '' : 'display: none;';
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
@import '../common/style/index.wxss';.t-avatar{display:flex;align-items:center;justify-content:center;box-sizing:border-box;background-color:var(--td-avatar-bg-color,var(--td-brand-color-light-active,var(--td-primary-color-2,#d9e1ff)));color:var(--td-avatar-content-color,var(--td-brand-color,var(--td-primary-color-7,#0052d9)))}.t-avatar__wrapper{display:inline-flex;position:relative;vertical-align:top;margin-left:var(--td-avatar-margin-left,0)}.t-avatar--large{width:var(--td-avatar-large-width,128rpx);height:var(--td-avatar-large-width,128rpx);font-size:var(--td-avatar-text-large-font-size,var(--td-font-size-xl,40rpx))}.t-avatar--large .t-avatar__icon{font-size:var(--td-avatar-icon-large-font-size,64rpx)}.t-avatar--medium{width:var(--td-avatar-medium-width,96rpx);height:var(--td-avatar-medium-width,96rpx);font-size:var(--td-avatar-text-medium-font-size,var(--td-font-size-m,32rpx))}.t-avatar--medium .t-avatar__icon{font-size:var(--td-avatar-icon-medium-font-size,48rpx)}.t-avatar--small{width:var(--td-avatar-small-width,80rpx);height:var(--td-avatar-small-width,80rpx);font-size:var(--td-avatar-text-small-font-size,var(--td-font-size-base,28rpx))}.t-avatar--small .t-avatar__icon{font-size:var(--td-avatar-icon-small-font-size,40rpx)}.t-avatar .t-image,.t-avatar__image{width:100%;height:100%}.t-avatar--circle{border-radius:var(--td-avatar-circle-border-radius,var(--td-radius-circle,50%));overflow:hidden}.t-avatar--round{border-radius:var(--td-avatar-round-border-radius,var(--td-radius-default,12rpx));overflow:hidden}.t-avatar__icon,.t-avatar__text{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.t-avatar__icon:empty,.t-avatar__text:empty{width:0;height:0}.t-avatar--border{border-color:var(--td-avatar-border-color,#fff);border-style:solid}.t-avatar--border-small{border-width:var(--td-avatar-border-width-small,2rpx)}.t-avatar--border-medium{border-width:var(--td-avatar-border-width-medium,4rpx)}.t-avatar--border-large{border-width:var(--td-avatar-border-width-large,6rpx)}
|
||||
3
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/props.d.ts
vendored
Normal file
3
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/props.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { TdAvatarProps } from './type';
|
||||
declare const props: TdAvatarProps;
|
||||
export default props;
|
||||
@@ -0,0 +1 @@
|
||||
const props={alt:{type:String,value:""},badgeProps:{type:Object},bordered:{type:Boolean,value:!1},hideOnLoadFailed:{type:Boolean,value:!1},icon:{type:null},image:{type:String,value:""},imageProps:{type:Object},shape:{type:String},size:{type:String,value:""}};export default props;
|
||||
41
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/type.d.ts
vendored
Normal file
41
miniprogram/miniprogram_npm/tdesign-miniprogram/avatar/type.d.ts
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import { BadgeProps } from '../badge/index';
|
||||
import { ImageProps } from '../image/index';
|
||||
import { ShapeEnum } from '../common/common';
|
||||
export interface TdAvatarProps {
|
||||
alt?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
badgeProps?: {
|
||||
type: ObjectConstructor;
|
||||
value?: BadgeProps;
|
||||
};
|
||||
bordered?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
hideOnLoadFailed?: {
|
||||
type: BooleanConstructor;
|
||||
value?: boolean;
|
||||
};
|
||||
icon?: {
|
||||
type: null;
|
||||
value?: string | object;
|
||||
};
|
||||
image?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
imageProps?: {
|
||||
type: ObjectConstructor;
|
||||
value?: ImageProps;
|
||||
};
|
||||
shape?: {
|
||||
type: StringConstructor;
|
||||
value?: ShapeEnum;
|
||||
};
|
||||
size?: {
|
||||
type: StringConstructor;
|
||||
value?: string;
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user