Initial Commit

This commit is contained in:
syruan 2025-11-07 14:54:09 +08:00
commit 3c2c9c7b32
837 changed files with 11104 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# Windows
[Dd]esktop.ini
Thumbs.db
$RECYCLE.BIN/
# macOS
.DS_Store
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
# Node.js
node_modules/

347
PROJECT_GUIDE.md Normal file
View File

@ -0,0 +1,347 @@
# 安全工器具预警小程序 - 项目说明
## 📋 项目概述
这是一个基于微信小程序原生开发的**安全工器具预警管理系统**,主要用于施工过程中使用的安全工器具的管理、维保和预警。
### 核心功能
- ✅ 设备台账管理(查看、添加、编辑、删除)
- ✅ 多维度筛选和搜索
- ✅ 检测预警和提醒
- ✅ 统计分析
- ✅ 个人中心
## 🏗️ 技术栈
- **框架**:微信小程序原生开发
- **UI组件库**TDesign Miniprogram
- **开发语言**JavaScript + WXML + WXSS
- **基础库版本**3.6.3
## 📁 项目结构
```
miniprogram-1/
├── app.js # 小程序入口
├── app.json # 全局配置
├── app.wxss # 全局样式
├── project.config.json # 项目配置
├── pages/ # 页面目录
│ ├── index/ # 首页(工作台)
│ │ ├── index.wxml # 页面结构
│ │ ├── index.js # 页面逻辑
│ │ ├── index.wxss # 页面样式
│ │ └── index.json # 页面配置
│ │
│ ├── device/ # 设备管理模块
│ │ ├── list/ # 设备列表
│ │ ├── detail/ # 设备详情
│ │ └── add/ # 添加/编辑设备
│ │
│ ├── statistics/ # 统计分析模块
│ │ └── index/ # 统计首页
│ │
│ ├── warning/ # 预警中心模块
│ │ ├── list/ # 预警列表
│ │ └── settings/ # 预警设置
│ │
│ └── profile/ # 个人中心模块
│ └── index/ # 个人中心首页
├── components/ # 自定义组件
├── utils/ # 工具函数
├── assets/ # 静态资源
└── miniprogram_npm/ # npm包TDesign组件库
```
## 🎯 功能模块详解
### 1. 首页(工作台)
**路径**`pages/index/index`
**功能**
- 设备总览统计(总数、预警数、到期数)
- 预警提醒列表显示前3条
- 快捷入口(设备台账、添加设备、统计分析、扫码查询)
- 最近操作记录
**数据结构**
```javascript
{
totalDevices: 156, // 设备总数
warningDevices: 12, // 预警设备数
expiredDevices: 3, // 已到期设备数
warningList: [...], // 预警列表
recentList: [...] // 最近操作
}
```
### 2. 设备台账
**路径**`pages/device/list/list`
**功能**
- 设备列表展示
- 搜索功能(设备名称、编号、型号)
- 状态筛选(全部、正常、预警、已到期)
- 高级筛选(设备类型、使用单位)
- 跳转到设备详情
**数据结构**
```javascript
{
id: "设备ID",
deviceName: "设备名称",
deviceCode: "设备编号",
deviceType: "设备类型",
specification: "规格型号",
useUnit: "使用单位",
belongUnit: "所属单位",
lastInspectionDate: "上次检验日期",
nextInspectionDate: "下次检验日期",
status: "设备状态normal/warning/expired",
daysLeft: 7 // 距离到期天数
}
```
### 3. 设备详情
**路径**`pages/device/detail/detail`
**功能**
- 查看设备完整信息
- 编辑设备
- 删除设备
### 4. 添加/编辑设备
**路径**`pages/device/add/add`
**功能**
- 添加新设备
- 编辑现有设备
- 表单验证
- 日期选择器
- 下拉选择器
**必填字段**
- 设备名称
- 设备编号
- 使用单位
- 上次检验日期
- 下次检验日期
### 5. 统计分析
**路径**`pages/statistics/index/index`
**功能**
- 设备总览统计
- 预警率统计
- 设备类型分布(图表 - 待开发)
- 单位设备统计(图表 - 待开发)
### 6. 预警中心
**路径**`pages/warning/list/list`
**功能**
- 预警列表展示
- 按时间筛选全部、7天内、15天内、已到期
- 预警等级标识
- 跳转到设备详情
### 7. 预警设置
**路径**`pages/warning/settings/settings`
**功能**
- 设置提前预警天数
- 消息推送设置(待开发)
### 8. 个人中心
**路径**`pages/profile/index/index`
**功能**
- 用户信息展示
- 单位管理(待开发)
- 预警设置
- 数据导出(待开发)
- 关于我们
- 帮助中心(待开发)
## 🚀 快速开始
### 1. 环境准备
- 安装微信开发者工具
- Node.js 环境(用于 npm 包管理)
### 2. 安装依赖
```bash
# 在微信开发者工具中点击"工具" -> "构建 npm"
# 或者在命令行执行
npm install
```
### 3. 运行项目
1. 使用微信开发者工具打开项目目录
2. 点击"编译"按钮
3. 在模拟器或真机中预览
### 4. TabBar 图标配置(可选)
当前项目使用纯文字 TabBar。如需添加图标
1. 准备图标文件81px * 81pxPNG格式
2. 将图标放入 `assets/icons/` 目录
3. 在 `app.json` 中配置图标路径:
```json
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "assets/icons/home.png",
"selectedIconPath": "assets/icons/home-active.png"
}
```
所需图标:
- home.png / home-active.png
- device.png / device-active.png
- chart.png / chart-active.png
- warning.png / warning-active.png
- user.png / user-active.png
## 📊 数据管理
### 当前状态
项目目前使用**模拟数据Mock Data**,所有数据都在页面的 JS 文件中硬编码。
### 后续开发建议
#### 方案一:微信云开发(推荐)
```javascript
// 初始化云开发
wx.cloud.init({
env: 'your-env-id'
});
// 查询设备列表
const db = wx.cloud.database();
db.collection('devices').get({
success: res => {
console.log(res.data);
}
});
```
#### 方案二:本地存储
```javascript
// 保存数据
wx.setStorageSync('devices', deviceList);
// 读取数据
const devices = wx.getStorageSync('devices');
```
#### 方案三后端API
```javascript
// 请求后端接口
wx.request({
url: 'https://your-api.com/devices',
method: 'GET',
success: res => {
console.log(res.data);
}
});
```
## 🔧 待开发功能
### 高优先级
- [ ] 数据持久化云开发或后端API
- [ ] 用户登录和权限管理
- [ ] 消息推送(订阅消息)
- [ ] 扫码功能完善(生成设备二维码)
### 中优先级
- [ ] 统计图表(使用 echarts-for-weixin
- [ ] 数据导出Excel
- [ ] 批量导入设备
- [ ] 设备照片上传
### 低优先级
- [ ] 单位管理
- [ ] 操作日志
- [ ] 帮助文档
- [ ] 深色模式优化
## 🎨 UI组件使用
项目使用 TDesign Miniprogram 组件库,已在 `app.json` 中全局注册常用组件:
```javascript
// 已注册的组件
t-button // 按钮
t-icon // 图标
t-cell // 单元格
t-cell-group // 单元格组
t-tag // 标签
t-badge // 徽章
t-search // 搜索框
t-tabs // 标签页
t-tab-panel // 标签页面板
t-empty // 空状态
t-loading // 加载
t-dialog // 对话框
t-message // 消息
t-toast // 轻提示
t-input // 输入框
t-picker // 选择器
t-date-time-picker // 日期时间选择器
```
更多组件请参考:[TDesign 小程序文档](https://tdesign.tencent.com/miniprogram/overview)
## 📝 开发规范
### 命名规范
- 页面文件:小写字母,使用连字符(如:`device-list`
- 变量命名:驼峰命名法(如:`deviceList`
- 常量命名:大写字母+下划线(如:`MAX_COUNT`
### 代码注释
```javascript
// 单行注释
/**
* 多行注释
* @param {string} id - 设备ID
* @returns {Object} 设备信息
*/
```
### 样式规范
- 使用 rpx 作为尺寸单位(响应式)
- 颜色使用变量(参考 `app.wxss`
- 避免使用 !important
## 🐛 常见问题
### 1. 编译报错:找不到 TDesign 组件
**解决方案**:点击"工具" -> "构建 npm"
### 2. TabBar 不显示
**原因**:图标文件不存在
**解决方案**:参考上文"TabBar 图标配置"
### 3. 页面跳转失败
**检查**
- 页面路径是否正确
- 是否在 `app.json` 中注册
- TabBar 页面使用 `wx.switchTab`,非 TabBar 页面使用 `wx.navigateTo`
## 📞 联系方式
如有问题,请联系开发团队。
---
**版本**v1.0.0
**最后更新**2024-05-27

253
QUICKSTART.md Normal file
View File

@ -0,0 +1,253 @@
# 快速开始指南
## 🎯 项目已完成的工作
### ✅ 已完成
1. **项目结构搭建**
- 清理了所有 TDesign 示例页面
- 创建了核心功能页面结构
- 配置了底部导航栏TabBar
2. **核心页面开发**
- ✅ 首页(工作台)- 设备统计、预警提醒、快捷入口
- ✅ 设备列表 - 搜索、筛选、状态标识
- ✅ 设备详情 - 完整信息展示、编辑、删除
- ✅ 添加/编辑设备 - 表单录入、日期选择
- ✅ 统计分析 - 数据统计(图表待开发)
- ✅ 预警中心 - 预警列表、时间筛选
- ✅ 预警设置 - 预警天数设置
- ✅ 个人中心 - 用户信息、功能入口
3. **工具函数**
- ✅ `utils/deviceUtils.js` - 设备数据处理、日期计算、预警判断
- ✅ `utils/mockData.js` - 模拟数据生成
4. **UI组件**
- ✅ 全局注册 TDesign 常用组件
- ✅ 统一的样式风格
- ✅ 响应式布局
## 🚀 如何运行项目
### 步骤 1打开项目
1. 启动**微信开发者工具**
2. 选择"导入项目"
3. 选择项目目录:`/Users/syruan/WeChatProjects/miniprogram-1`
4. AppID 使用:`wx9d08fb2788d95136`(或使用测试号)
### 步骤 2构建 npm
1. 在微信开发者工具中,点击菜单栏:**工具 -> 构建 npm**
2. 等待构建完成(会生成 `miniprogram_npm` 目录)
### 步骤 3编译运行
1. 点击工具栏的"编译"按钮
2. 在模拟器中查看效果
3. 或点击"预览"在真机上测试
## 📱 功能演示
### 首页(工作台)
- 查看设备总数、预警数、到期数
- 查看最新的预警提醒前3条
- 使用快捷入口:
- 点击"设备台账"进入设备列表
- 点击"添加设备"添加新设备
- 点击"统计分析"查看统计数据
- 点击"扫码查询"扫描设备二维码(功能待完善)
### 设备台账
- 使用搜索框搜索设备(支持名称、编号、型号)
- 点击顶部标签筛选状态(全部、正常、预警、已到期)
- 点击右侧筛选图标进行高级筛选(设备类型、使用单位)
- 点击设备卡片查看详情
- 点击右下角"+"按钮添加新设备
### 设备详情
- 查看设备完整信息
- 点击"编辑设备"修改信息
- 点击"删除设备"删除设备(会弹出确认对话框)
### 添加/编辑设备
- 填写设备基本信息(名称、编号、规格型号等)
- 选择使用单位
- 选择检验日期
- 填写备注信息(可选)
- 点击"添加"或"保存"提交
### 统计分析
- 查看设备总数和预警率
- 查看设备类型统计列表
- 图表功能待开发(可集成 echarts-for-weixin
### 预警中心
- 切换标签查看不同时间范围的预警全部、7天内、15天内、已到期
- 点击预警项查看设备详情
### 预警设置
- 设置提前预警天数7天、15天、30天、60天、90天
### 个人中心
- 查看用户信息
- 访问预警设置
- 查看关于我们
## 🔧 当前使用的模拟数据
项目目前使用 `utils/mockData.js` 中的模拟数据,包含:
- 10 台设备的完整信息
- 不同状态的设备(正常、预警、已到期)
- 最近操作记录
- 设备类型和使用单位列表
**数据特点**
- 设备 ID 1绝缘手套即将到期预警状态
- 设备 ID 3安全带已到期
- 其他设备:正常或预警状态
## ⚠️ 已知问题
### 1. TabBar 图标缺失
**现象**:底部导航栏只显示文字,没有图标
**原因**:图标文件未创建
**解决方案**
- **临时方案**:当前已配置为纯文字 TabBar可以正常使用
- **完整方案**准备图标文件81px * 81pxPNG格式放入 `assets/icons/` 目录,然后在 `app.json` 中配置图标路径
所需图标:
```
assets/icons/
├── home.png # 首页图标(未选中)
├── home-active.png # 首页图标(选中)
├── device.png # 设备图标(未选中)
├── device-active.png # 设备图标(选中)
├── chart.png # 统计图标(未选中)
├── chart-active.png # 统计图标(选中)
├── warning.png # 预警图标(未选中)
├── warning-active.png # 预警图标(选中)
├── user.png # 我的图标(未选中)
└── user-active.png # 我的图标(选中)
```
### 2. 数据不持久化
**现象**:刷新页面后数据恢复到初始状态
**原因**:使用模拟数据,未实现数据持久化
**解决方案**:参考 `PROJECT_GUIDE.md` 中的"数据管理"章节,选择以下方案之一:
- 微信云开发(推荐)
- 本地存储wx.setStorageSync
- 后端 API
### 3. 部分功能待开发
以下功能显示"功能开发中"提示:
- 扫码查询(需要生成设备二维码)
- 统计图表(需要集成 echarts-for-weixin
- 数据导出
- 单位管理
- 帮助中心
- 消息推送
## 📝 下一步开发建议
### 优先级 1数据持久化
```javascript
// 方案一:使用本地存储(最简单)
// 在 utils/storage.js 中封装存储方法
function saveDevices(devices) {
wx.setStorageSync('devices', devices);
}
function getDevices() {
return wx.getStorageSync('devices') || [];
}
// 方案二:使用微信云开发(推荐)
// 1. 在微信开发者工具中开通云开发
// 2. 创建数据库集合 'devices'
// 3. 使用云数据库 API 进行 CRUD 操作
```
### 优先级 2用户登录
```javascript
// 使用微信登录
wx.login({
success: res => {
// 发送 res.code 到后端换取 openId, sessionKey, unionId
}
});
// 获取用户信息
wx.getUserProfile({
desc: '用于完善用户资料',
success: res => {
console.log(res.userInfo);
}
});
```
### 优先级 3消息推送
```javascript
// 订阅消息
wx.requestSubscribeMessage({
tmplIds: ['模板ID'],
success: res => {
// 订阅成功,可以发送模板消息
}
});
```
### 优先级 4统计图表
```bash
# 安装 echarts-for-weixin
npm install echarts-for-weixin --save
# 在页面中引入
import * as echarts from 'echarts-for-weixin';
```
## 🎨 自定义配置
### 修改主题色
编辑 `app.wxss`,修改以下变量:
```css
--td-brand-color: #0052D9; /* 主题色 */
--td-warning-color: #FF6B00; /* 预警色 */
--td-error-color: #E34D59; /* 错误色 */
```
### 修改预警天数阈值
编辑 `utils/deviceUtils.js`,修改 `getDeviceStatus` 函数的默认参数:
```javascript
function getDeviceStatus(daysLeft, warningDays = 30) {
// warningDays 默认为 30 天,可以修改为其他值
}
```
### 添加新的设备类型
编辑 `utils/mockData.js`,在 `getDeviceTypes` 函数中添加:
```javascript
function getDeviceTypes() {
return ['全部', '安全帽', '安全带', '新设备类型', ...];
}
```
## 📞 技术支持
如遇到问题,请检查:
1. 微信开发者工具版本是否最新
2. 是否已执行"构建 npm"
3. 基础库版本是否符合要求(>= 3.0.0
4. 查看控制台是否有错误信息
## 📚 相关文档
- [微信小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/)
- [TDesign 小程序组件库](https://tdesign.tencent.com/miniprogram/overview)
- [微信云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)
---
**祝开发顺利!** 🎉

1
app.d.ts vendored Normal file
View File

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

10
app.js Normal file
View File

@ -0,0 +1,10 @@
import gulpError from './utils/gulpError';
App({
onShow() {
if (gulpError !== 'gulpErrorPlaceHolder') {
wx.redirectTo({
url: `/pages/gulp-error/index?gulpError=${gulpError}`,
});
}
},
});

71
app.json Normal file
View File

@ -0,0 +1,71 @@
{
"darkmode": true,
"pages": [
"pages/index/index",
"pages/device/list/list",
"pages/device/detail/detail",
"pages/device/add/add",
"pages/statistics/index/index",
"pages/warning/list/list",
"pages/warning/settings/settings",
"pages/profile/index/index",
"pages/gulp-error/index"
],
"tabBar": {
"color": "#999999",
"selectedColor": "#0052D9",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/device/list/list",
"text": "设备"
},
{
"pagePath": "pages/statistics/index/index",
"text": "统计"
},
{
"pagePath": "pages/warning/list/list",
"text": "预警"
},
{
"pagePath": "pages/profile/index/index",
"text": "我的"
}
]
},
"themeLocation": "theme.json",
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button",
"t-icon": "tdesign-miniprogram/icon/icon",
"t-navbar": "tdesign-miniprogram/navbar/navbar",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
"t-tag": "tdesign-miniprogram/tag/tag",
"t-badge": "tdesign-miniprogram/badge/badge",
"t-search": "tdesign-miniprogram/search/search",
"t-tabs": "tdesign-miniprogram/tabs/tabs",
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"t-empty": "tdesign-miniprogram/empty/empty",
"t-loading": "tdesign-miniprogram/loading/loading",
"t-dialog": "tdesign-miniprogram/dialog/dialog",
"t-message": "tdesign-miniprogram/message/message",
"t-toast": "tdesign-miniprogram/toast/toast",
"t-input": "tdesign-miniprogram/input/input",
"t-picker": "tdesign-miniprogram/picker/picker",
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker"
},
"window": {
"navigationBarTitleText": "安全工器具预警",
"navigationBarBackgroundColor": "#0052D9",
"navigationBarTextStyle": "white",
"backgroundColor": "#F5F5F5"
},
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents"
}

386
app.wxss Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

24
assets/icons/README.md Normal file
View File

@ -0,0 +1,24 @@
# TabBar 图标说明
由于无法直接生成图片文件,请按以下方式准备图标:
## 方式一:使用 TDesign 图标(推荐)
可以从 TDesign 官网下载图标:
- home.png / home-active.png (首页图标)
- device.png / device-active.png (设备图标 - 可用 view-list)
- chart.png / chart-active.png (统计图标 - 可用 chart-bar)
- warning.png / warning-active.png (预警图标 - 可用 error-circle)
- user.png / user-active.png (我的图标 - 可用 user)
## 方式二:使用 iconfont
从 iconfont.cn 下载对应图标
## 方式三:临时方案
在 app.json 中暂时注释掉 tabBar 的 iconPath 和 selectedIconPath
使用纯文字的 TabBar不推荐但可以先运行起来
## 图标规格
- 尺寸81px * 81px
- 格式PNG
- 未选中状态:灰色 (#999999)
- 选中状态:蓝色 (#0052D9)

BIN
assets/icons/chart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

BIN
assets/icons/device.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

BIN
assets/icons/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

BIN
assets/icons/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

BIN
assets/icons/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

10
behaviors/skyline.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = Behavior({
data: {
skylineRender: false,
},
lifetimes: {
created() {
this.setData({ skylineRender: this.renderer === 'skyline' });
},
},
});

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

@ -0,0 +1 @@

View File

@ -0,0 +1,26 @@
Component({
options: {
multipleSlots: true,
},
properties: {
title: {
type: String,
value: '',
},
desc: {
type: String,
value: '',
},
operList: Array,
padding: {
type: Boolean,
value: false,
},
},
methods: {
clickHandle(e) {
const { type } = e.currentTarget.dataset;
this.triggerEvent('clickoper', type);
},
},
});

View File

@ -0,0 +1,4 @@
{
"component": true,
"styleIsolation": "apply-shared"
}

View File

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

View File

@ -0,0 +1,59 @@
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.demo-block {
margin: var(--td-spacer-4, 64rpx) 0 0;
}
.demo-block__header {
color: var(--bg-color-demo-title);
margin: 0 var(--td-spacer-2, 32rpx);
}
.demo-block__header-title {
font-weight: 700;
font-size: 36rpx;
line-height: 52rpx;
}
.demo-block__header-desc {
margin-top: var(--td-spacer, 16rpx);
font-size: var(--td-font-size-base, 28rpx);
white-space: pre-line;
color: var(--bg-color-demo-desc);
line-height: 22px;
}
.demo-block__oper {
margin-top: var(--td-spacer, 16rpx);
}
.demo-block__oper-subtitle {
font-size: var(--td-font-size-s, 24rpx);
margin-bottom: var(--td-spacer-2, 32rpx);
opacity: 0.4;
}
.demo-block__oper-btn {
margin: 0 0 var(--td-spacer-2, 32rpx) 0;
height: 96rpx;
}
.demo-block__slot {
margin-top: var(--td-spacer-2, 32rpx);
}
.demo-block__slot.with-padding {
margin-top: var(--td-spacer-2, 32rpx);
margin-left: var(--td-spacer-2, 32rpx);
margin-right: var(--td-spacer-2, 32rpx);
margin-bottom: 0;
}
.demo-block_notitle {
margin-top: 0px;
}
.demo-block_notitle .demo-block_subtitle {
margin-top: var(--td-spacer-3, 48rpx);
}

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

@ -0,0 +1 @@

View File

@ -0,0 +1,16 @@
Component({
options: {
multipleSlots: true,
},
properties: {
title: {
type: String,
},
desc: {
type: String,
},
notice: {
type: String,
},
},
});

View File

@ -0,0 +1,7 @@
{
"component": true,
"styleIsolation": "apply-shared",
"usingComponents": {
"t-notice-bar": "tdesign-miniprogram/notice-bar/notice-bar"
}
}

View File

@ -0,0 +1,8 @@
<block>
<t-notice-bar visible content="{{notice}}" />
<view class="demo-title">{{title}}</view>
<view class="demo-desc">
{{desc}}
<slot name="desc" />
</view>
</block>

View File

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

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

View File

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

View File

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

View File

@ -0,0 +1,12 @@
<view class="pullDownList t-class {{ childBoxHeight > 0 ? 'actived' : '' }}">
<view class="switchBox" aria-role="button" aria-expanded="{{!!childBoxHeight}}" catch:tap="switchHandle">
<view class="name">{{ name }}</view>
<t-icon name="{{icon}}" size="48rpx" color="#A6A6A6" t-class="icon" aria-hidden />
</view>
<view class="childBox" style="height: {{ childBoxHeight }}rpx" aria-hidden="{{childBoxHeight ? '' : true}}">
<view class="child" wx:for="{{childArr}}" wx:key="name" data-item="{{item}}" aria-role="button" bind:tap="tapChild">
{{ item.name }} {{ item.label }}
<t-icon name="chevron-right" color="var(--td-text-color-placeholder)" aria-hidden />
</view>
</view>
</view>

View File

@ -0,0 +1,50 @@
.pullDownList {
width: 100%;
box-sizing: border-box;
background-color: var(--td-bg-color-container);
border-radius: 8rpx;
margin-bottom: 24rpx;
overflow: hidden;
}
.pullDownList .switchBox {
height: 120rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 32rpx;
font-size: 32rpx;
line-height: 48rpx;
color: var(--td-text-color-secondary);
}
.pullDownList .name,
.pullDownList .icon {
transition: opacity 0.3s;
}
.pullDownList .name {
opacity: 0.9;
}
.pullDownList.actived .name {
opacity: 0.4;
}
.pullDownList.actived .icon {
opacity: 0.4;
}
.pullDownList .childBox {
transition: height 0.3s;
}
.pullDownList .childBox .child {
box-sizing: border-box;
border-bottom: 1rpx solid var(--td-component-stroke);
height: 112rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 32rpx;
margin-right: 32rpx;
font-size: 32rpx;
opacity: 0.9;
color: var(--td-text-color-primary);
}
.pullDownList .childBox .child:last-of-type {
border-bottom-color: transparent;
}

View File

@ -0,0 +1,60 @@
// components/privacy/privacy.js
Component({
/**
* 组件的属性列表
*/
properties: {
name: {
type: String,
value: '',
},
date: {
type: String,
value: '',
},
winStyle: {
type: Boolean,
value: false,
},
},
/**
* 组件的初始数据
*/
data: {
win: false,
privacy: false,
},
/**
* 组件的方法列表
*/
methods: {
showPrivacyDetail() {
this.setData({
win: false,
privacy: true,
});
},
privacyConfirm() {
this.setData({
privacy: false,
win: false,
});
wx.setStorageSync('TIMIShowPrivacy', true);
},
showPrivacyWin() {
this.setData({
win: true,
});
},
},
ready() {
const TIMIShowPrivacy = wx.getStorageSync('TIMIShowPrivacy');
if (!TIMIShowPrivacy) {
this.setData({
win: true,
});
}
},
});

View File

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

View File

@ -0,0 +1,39 @@
<view wx:if="{{privacy}}" class="privacy_wrap">
<view class="privacy_safe_area">
<view class="privacy_top">
<view class="privacy_title">{{name}}服务声明</view>
<view class="privacy_right">发布日期:{{date}}</view>
<view class="privacy_right">生效日期:{{date}}</view>
</view>
<view class="privacy_content">
<text class="privacy_bold">引言</text>
<text decode="{{true}}" class="privacy_normal"
>{{name}}是由深圳市腾讯计算机系统有限公司以下简称“我们”提供的产品我们的注册地为深圳市南山区粤海街道麻岭社区科技中一路腾讯大厦35层。</text
>
<text decode="{{true}}" class="privacy_bold"
>我们在此特别声明:\n1.本小程序产品功能的实现不涉及收集和处理用户(以下简称“您”)的任何个人信息。\n2.如果我们更新、改进或修改小程序产品功能,并因此导致我们需要处理您的个人信息的,我们将会依据适用法律的要求对本声明进行修订,并将修订后的内容通过弹框等形式通知您并获得您同意。</text
>
<text decode="{{true}}" class="privacy_normal">
3.如果您对本声明有任何疑问或建议,您可以通过以下方式与我们取得联系:\n1将问题发送至Dataprivacy@tencent.com;\n2通过https://kf.qq.com/与我们联系;\n3将您的问题邮寄至下列地址\n\n中国广东省深圳市南山区海天二路33号腾讯滨海大厦\n数据隐私保护部\n邮编518054\n\n我们将尽快审核所涉问题并在15个工作日或法律法规规定的期限内予以反馈。
</text>
</view>
<view class="footer">
<t-button class="t-design-button" theme="primary" bindtap="privacyConfirm">我已知晓</t-button>
</view>
</view>
</view>
<view wx:if="{{win}}" class="privacy_tips_win">
<view class="privacy_win_content {{winStyle?'privacy_middle':''}}">
<view class="privacy_tips_content"
>我们将严格按照<text class="privacy_url" bindtap="showPrivacyDetail">《{{name}}服务声明》</text
>向您提供服务,不会收集和处理您的个人信息。</view
>
<view class="privacy_tips_content"
>如您对<text class="privacy_url" bindtap="showPrivacyDetail">《{{name}}服务声明》</text
>有任何疑问或建议,可以通过声明内的联系方式向我们反馈。</view
>
<view class="footer">
<t-button class="t-design-button" theme="primary" bindtap="privacyConfirm">我已知晓</t-button>
</view>
</view>
</view>

View File

@ -0,0 +1,137 @@
/* components/privacy/privacy.wxss */
.privacy_wrap {
width: 100vw;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 99999;
background-color: #fff;
color: #222;
font-size: 24rpx;
}
.privacy_safe_area {
width: 750rpx;
height: 1180rpx;
position: absolute;
left: 0;
top: 50%;
transform: translate(0, -50%);
}
.privacy_top {
padding: 50rpx 40rpx;
position: relative;
overflow: hidden;
}
.privacy_btn_back::before {
content: '<<';
}
.privacy_title {
height: 100%;
font-size: 32rpx;
font-weight: 700;
text-align: center;
line-height: 60rpx;
}
.privacy_right {
height: 48rpx;
line-height: 48rpx;
text-align: right;
}
.privacy_content {
height: 790rpx;
padding: 0 40rpx;
overflow: auto;
line-height: 32rpx;
}
.privacy_bold {
font-weight: 700;
display: inline-block;
padding-bottom: 12rpx;
}
.privacy_normal {
text-indent: 2em;
display: inline-block;
padding-bottom: 12rpx;
}
.privacy_btn_confirm {
width: 150rpx;
height: 92rpx;
padding: 0 85rpx;
border-radius: 16rpx;
border: #ccc solid 2rpx;
background-color: #06c15f;
font-size: 32rpx;
text-align: center;
line-height: 92rpx;
color: #fff;
margin: 30rpx auto 0;
text-indent: 0;
}
.privacy_tips_win {
width: 100vw;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 99999;
background: rgba(0, 0, 0, 0.75);
color: #222;
font-size: 28rpx;
}
.privacy_win_content {
width: 100vw;
box-sizing: border-box;
overflow: hidden;
position: absolute;
left: 0;
bottom: 0;
background: #fff;
border-radius: 24rpx 24rpx 0 0;
padding: 50rpx 40rpx;
text-indent: 2em;
animation: privacy_up 0.2s forwards;
transform: translateY(100%);
}
@keyframes privacy_up {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(0);
}
}
.privacy_line {
display: inline-block;
vertical-align: middle;
}
.privacy_url {
color: #576b95;
text-indent: 0;
display: inline;
vertical-align: middle;
}
.privacy_tips_content {
line-height: 40rpx;
vertical-align: middle;
}
.privacy_middle {
width: 650rpx;
left: 50%;
bottom: 50%;
transform: translate(-50%, 50%);
border-radius: 24rpx;
animation: none;
}
.footer {
width: 100%;
margin-top: 30rpx;
display: flex;
justify-content: center;
align-items: center;
text-indent: 0;
}
.t-design-button {
width: 300rpx;
}

View 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;
};
}

View File

@ -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;

View File

@ -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"}}

View File

@ -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>

View File

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

View File

@ -0,0 +1 @@
@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}

View 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;

View File

@ -0,0 +1 @@
import{show,close,ActionSheetTheme}from"./show";export{ActionSheetTheme};export default{show:e=>show(e),close:e=>close(e)};

View File

@ -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;

View 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;

View File

@ -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()};

View File

@ -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>

View File

@ -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>

View File

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

View 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;
};
}

View File

@ -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;

View File

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

View File

@ -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

View File

@ -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;

View File

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

View 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;
};
}

View File

@ -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;

View File

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

View File

@ -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>

View File

@ -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;';
},
};

View File

@ -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)}

View File

@ -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;

View File

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

View File

@ -0,0 +1,26 @@
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class BackTop extends SuperComponent {
externalClasses: string[];
options: {
multipleSlots: boolean;
};
properties: import("./type").TdBackTopProps;
relations: RelationsOptions;
data: {
prefix: string;
classPrefix: string;
_icon: any;
hidden: boolean;
};
observers: {
icon(): void;
scrollTop(value: number): void;
};
lifetimes: {
ready(): void;
};
methods: {
setIcon(v: any): void;
toTop(): void;
};
}

View File

@ -0,0 +1 @@
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{calcIcon}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-back-top`;let BackTop=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`,`${prefix}-class-icon`,`${prefix}-class-text`],this.options={multipleSlots:!0},this.properties=props,this.relations={"../pull-down-refresh/pull-down-refresh":{type:"ancestor"}},this.data={prefix:prefix,classPrefix:name,_icon:null,hidden:!0},this.observers={icon(){this.setIcon()},scrollTop(o){const{visibilityHeight:t}=this.properties;this.setData({hidden:o<t})}},this.lifetimes={ready(){const{icon:o}=this.properties;this.setIcon(o)}},this.methods={setIcon(o){this.setData({_icon:calcIcon(o,"backtop")})},toTop(){var o;this.triggerEvent("to-top"),this.$parent?(null===(o=this.$parent)||void 0===o||o.setScrollTop(0),this.setData({hidden:!0})):wx.pageScrollTo({scrollTop:0,duration:300})}}}};BackTop=__decorate([wxComponent()],BackTop);export default BackTop;

View File

@ -0,0 +1 @@
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-icon":"../icon/icon"}}

View File

@ -0,0 +1 @@
<import src="../common/template/icon.wxml"/><wxs src="../common/utils.wxs" module="_"/><view style="{{_._style([style, customStyle])}}" class="class {{prefix}}-class {{_.cls(classPrefix, [['fixed', fixed], theme])}}" bindtap="toTop" aria-role="button" hidden="{{hidden}}"><view class="{{classPrefix}}__icon" aria-hidden><slot name="icon"/><template wx:if="{{_icon}}" is="icon" data="{{tClass: prefix + '-class-icon', ..._icon }}"/></view><view wx:if="{{!!text}}" class="{{classPrefix}}__text--{{theme}} {{prefix}}-class-text">{{text}}</view><slot/></view>

View File

@ -0,0 +1 @@
@import '../common/style/index.wxss';.t-back-top{display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:transparent;overflow:hidden;box-sizing:border-box;transition:height .2s;height:auto}.t-back-top--fixed{position:fixed;right:var(--td-spacer,16rpx);bottom:calc(var(--td-spacer-2,32rpx) + env(safe-area-inset-bottom))}.t-back-top--round,.t-back-top--round-dark{width:96rpx;height:96rpx;border-radius:var(--td-back-top-round-border-radius,var(--td-radius-circle,50%))}.t-back-top--half-round,.t-back-top--round{color:var(--td-back-top-round-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))));border:1rpx solid var(--td-back-top-round-border-color,var(--td-component-border,var(--td-gray-color-4,#dcdcdc)));background-color:var(--td-back-top-round-bg-color,var(--td-bg-color-container,var(--td-font-white-1,#fff)))}.t-back-top--half-round-dark,.t-back-top--round-dark{color:var(--td-back-top-round-dark-color,var(--td-text-color-anti,var(--td-font-white-1,#fff)));background-color:var(--td-back-top-round-dark-bg-color,var(--td-gray-color-13,#242424))}.t-back-top--half-round,.t-back-top--half-round-dark{width:120rpx;height:80rpx;border-radius:0;border-top-left-radius:var(--td-back-top-half-round-border-radius,var(--td-radius-round,999px));border-bottom-left-radius:var(--td-back-top-half-round-border-radius,var(--td-radius-round,999px));flex-direction:row;right:0}.t-back-top__text--half-round,.t-back-top__text--half-round-dark,.t-back-top__text--round,.t-back-top__text--round-dark{font-size:var(--td-font-size,20rpx);line-height:24rpx}.t-back-top__text--half-round,.t-back-top__text--half-round-dark{width:48rpx}.t-back-top__icon:not(:empty)+.t-back-top__text--half-round,.t-back-top__icon:not(:empty)+.t-back-top__text--half-round-dark{margin-left:8rpx}.t-back-top__icon{display:flex;justify-content:center;align-items:center;font-size:44rpx}

View File

@ -0,0 +1 @@
const props={fixed:{type:Boolean,value:!0},icon:{type:null,value:!0},scrollTop:{type:Number,value:0},style:{type:String,value:""},text:{type:String,value:""},theme:{type:String,value:"round"},visibilityHeight:{type:Number,value:200}};export default props;

View File

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

View File

@ -0,0 +1,21 @@
import { SuperComponent } from '../common/src/index';
import type { TdBadgeProps } from './type';
export interface BadgeProps extends TdBadgeProps {
}
export default class Badge extends SuperComponent {
options: {
multipleSlots: boolean;
};
externalClasses: string[];
properties: TdBadgeProps;
data: {
prefix: string;
classPrefix: string;
value: string;
labelID: string;
descriptionID: string;
};
lifetimes: {
ready(): void;
};
}

View File

@ -0,0 +1 @@
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{uniqueFactory}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-badge`,getUniqueID=uniqueFactory("badge");let Badge=class extends SuperComponent{constructor(){super(...arguments),this.options={multipleSlots:!0},this.externalClasses=[`${prefix}-class`,`${prefix}-class-count`,`${prefix}-class-content`],this.properties=props,this.data={prefix:prefix,classPrefix:name,value:"",labelID:"",descriptionID:""},this.lifetimes={ready(){const e=getUniqueID();this.setData({labelID:`${e}_label`,descriptionID:`${e}_description`})}}}};Badge=__decorate([wxComponent()],Badge);export default Badge;

View File

@ -0,0 +1 @@
{"component":true,"styleIsolation":"apply-shared","usingComponents":{}}

View File

@ -0,0 +1 @@
<wxs src="./badge.wxs" module="_this"/><wxs src="../common/utils.wxs" module="_"/><view style="{{_._style([style, customStyle])}}" class="{{_this.getBadgeOuterClass({shape})}} class {{prefix}}-class" aria-labelledby="{{labelID}}" aria-describedby="{{descriptionID}}" aria-role="{{ ariaRole || 'option'}}"><view id="{{labelID}}" class="{{classPrefix}}__content {{prefix}}-class-content" aria-hidden="true"><slot wx:if="{{!content}}" class="{{classPrefix}}__content-slot"/><text wx:else class="{{classPrefix}}__content-text">{{content}}</text></view><view aria-hidden="true" aria-label="{{ ariaLabel || _.getBadgeAriaLabel({dot, count, maxCount}) }}" wx:if="{{_this.isShowBadge({dot,count,showZero})}}" id="{{descriptionID}}" class="{{_this.getBadgeInnerClass({dot, size, shape, count})}} {{prefix}}-has-count {{prefix}}-class-count" style="{{_._style([_this.getBadgeStyles({color, offset})])}}" aria-hidden="true" aria-label="{{ ariaLabel || _.getBadgeAriaLabel({dot, count, maxCount}) }}">{{ _this.getBadgeValue({dot, count, maxCount}) }}</view><slot name="count"/></view>

View File

@ -0,0 +1,71 @@
var getBadgeValue = function (props) {
if (props.dot) {
return '';
}
if (isNaN(props.count) || isNaN(props.maxCount)) {
return props.count;
}
return parseInt(props.count) > props.maxCount ? props.maxCount + '+' : props.count;
};
var hasUnit = function (unit) {
return (
unit.indexOf('px') > 0 ||
unit.indexOf('rpx') > 0 ||
unit.indexOf('em') > 0 ||
unit.indexOf('rem') > 0 ||
unit.indexOf('%') > 0 ||
unit.indexOf('vh') > 0 ||
unit.indexOf('vm') > 0
);
};
var getBadgeStyles = function (props) {
var styleStr = '';
if (props.color) {
styleStr += 'background:' + props.color + ';';
}
if (props.offset[0]) {
styleStr +=
'left: calc(100% + ' + (hasUnit(props.offset[0].toString()) ? props.offset[0] : props.offset[0] + 'px') + ');';
}
if (props.offset[1]) {
styleStr += 'top:' + (hasUnit(props.offset[1].toString()) ? props.offset[1] : props.offset[1] + 'px') + ';';
}
return styleStr;
};
var getBadgeOuterClass = function (props) {
var baseClass = 't-badge';
var classNames = [baseClass, props.shape === 'ribbon' ? baseClass + '__ribbon-outer' : ''];
return classNames.join(' ');
};
var getBadgeInnerClass = function (props) {
var baseClass = 't-badge';
var classNames = [
baseClass + '--basic',
props.dot ? baseClass + '--dot' : '',
baseClass + '--' + props.size,
baseClass + '--' + props.shape,
!props.dot && props.count ? baseClass + '--count' : '',
];
return classNames.join(' ');
};
var isShowBadge = function (props) {
if (props.dot) {
return true;
}
if (!props.showZero && !isNaN(props.count) && parseInt(props.count) === 0) {
return false;
}
if (props.count == null) return false;
return true;
};
module.exports.getBadgeValue = getBadgeValue;
module.exports.getBadgeStyles = getBadgeStyles;
module.exports.getBadgeOuterClass = getBadgeOuterClass;
module.exports.getBadgeInnerClass = getBadgeInnerClass;
module.exports.isShowBadge = isShowBadge;

View File

@ -0,0 +1 @@
@import '../common/style/index.wxss';.t-badge{position:relative;display:inline-flex;align-items:start}.t-badge--basic{z-index:100;padding:0 var(--td-badge-basic-padding,8rpx);font-size:var(--td-badge-font-size,var(--td-font-size-xs,var(--td-font-size,20rpx)));color:var(--td-badge-text-color,var(--td-text-color-anti,var(--td-font-white-1,#fff)));background-color:var(--td-badge-bg-color,var(--td-error-color,var(--td-error-color-6,#d54941)));text-align:center;height:var(--td-badge-basic-height,32rpx);line-height:var(--td-badge-basic-height,32rpx);font-weight:var(--td-badge-font-weight,600);border-radius:var(--td-badge-border-radius,4rpx)}.t-badge--dot{height:var(--td-badge-dot-size,16rpx);border-radius:50%;min-width:var(--td-badge-dot-size,16rpx);padding:0}.t-badge--count{min-width:var(--td-badge-basic-width,32rpx);white-space:nowrap;box-sizing:border-box}.t-badge--circle{border-radius:calc(var(--td-badge-basic-height,32rpx)/ 2)}.t-badge__ribbon-outer{position:absolute;top:0;right:0}.t-badge--ribbon{position:relative;display:inline-block;transform-origin:center center;transform:translate(calc(50% - var(--td-badge-basic-height,32rpx) + 1rpx),calc(-50% + var(--td-badge-basic-height,32rpx) - 1rpx)) rotate(45deg);border-radius:0}.t-badge--ribbon::after,.t-badge--ribbon::before{content:'';position:absolute;width:0;height:0;bottom:0;border-bottom:var(--td-badge-basic-height,32rpx) solid var(--td-badge-bg-color,var(--td-error-color,var(--td-error-color-6,#d54941)));font-size:0}.t-badge--ribbon::before{left:calc(-1 * var(--td-badge-basic-height,32rpx) + 1rpx);border-left:var(--td-badge-basic-height,32rpx) solid transparent}.t-badge--ribbon::after{right:calc(-1 * var(--td-badge-basic-height,32rpx) + 1rpx);border-right:var(--td-badge-basic-height,32rpx) solid transparent}.t-badge--bubble{border-radius:var(--td-badge-bubble-border-radius,20rpx 20rpx 20rpx 1px)}.t-badge--large{font-size:var(--td-badge-large-font-size,var(--td-font-size-s,24rpx));height:var(--td-badge-large-height,40rpx);min-width:var(--td-badge-large-height,40rpx);line-height:var(--td-badge-large-height,40rpx);padding:0 var(--td-badge-large-padding,10rpx)}.t-badge--large.t-badge--circle{border-radius:calc(var(--td-badge-large-height,40rpx)/ 2)}.t-badge__content:not(:empty)+.t-has-count{transform-origin:center center;transform:translate(-50%,-50%);position:absolute;left:100%;top:0}.t-badge__content-text{display:block;line-height:48rpx;color:var(--td-badge-content-text-color,var(--td-text-color-primary,var(--td-font-gray-1,rgba(0,0,0,.9))))}

View File

@ -0,0 +1,3 @@
export * from './type';
export * from './props';
export * from './badge';

View File

@ -0,0 +1 @@
export*from"./type";export*from"./props";export*from"./badge";

View File

@ -0,0 +1 @@
const props={color:{type:String,value:""},content:{type:String,value:""},count:{type:null,value:0},dot:{type:Boolean,value:!1},externalClasses:{type:Array},maxCount:{type:Number,value:99},offset:{type:Array},shape:{type:String,value:"circle"},showZero:{type:Boolean,value:!1},size:{type:String,value:"medium"}};export default props;

View File

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

View File

@ -0,0 +1,36 @@
import { SuperComponent } from '../common/src/index';
import type { TdButtonProps } from './type';
export interface ButtonProps extends TdButtonProps {
}
export default class Button extends SuperComponent {
externalClasses: string[];
behaviors: string[];
properties: TdButtonProps;
options: {
multipleSlots: boolean;
};
data: {
prefix: string;
className: string;
classPrefix: string;
};
observers: {
'theme, size, plain, block, shape, disabled, loading, variant'(): void;
icon(icon: any): void;
};
lifetimes: {
attached(): void;
};
methods: {
setClass(): void;
getuserinfo(e: any): void;
contact(e: any): void;
getphonenumber(e: any): void;
error(e: any): void;
opensetting(e: any): void;
launchapp(e: any): void;
chooseavatar(e: any): void;
agreeprivacyauthorization(e: any): void;
handleTap(e: any): void;
};
}

View File

@ -0,0 +1 @@
import{__decorate}from"tslib";import{SuperComponent,wxComponent}from"../common/src/index";import config from"../common/config";import props from"./props";import{canIUseFormFieldButton}from"../common/version";import{calcIcon}from"../common/utils";const{prefix:prefix}=config,name=`${prefix}-button`;let Button=class extends SuperComponent{constructor(){super(...arguments),this.externalClasses=[`${prefix}-class`,`${prefix}-class-icon`,`${prefix}-class-loading`],this.behaviors=canIUseFormFieldButton()?["wx://form-field-button"]:[],this.properties=props,this.options={multipleSlots:!0},this.data={prefix:prefix,className:"",classPrefix:name},this.observers={"theme, size, plain, block, shape, disabled, loading, variant"(){this.setClass()},icon(t){this.setData({_icon:calcIcon(t,"")})}},this.lifetimes={attached(){this.setClass()}},this.methods={setClass(){const t=[name,`${prefix}-class`,`${name}--${this.data.variant||"base"}`,`${name}--${this.data.theme||"default"}`,`${name}--${this.data.shape||"rectangle"}`,`${name}--size-${this.data.size||"medium"}`];this.data.block&&t.push(`${name}--block`),this.data.disabled&&t.push(`${name}--disabled`),this.data.ghost&&t.push(`${name}--ghost`),this.setData({className:t.join(" ")})},getuserinfo(t){this.triggerEvent("getuserinfo",t.detail)},contact(t){this.triggerEvent("contact",t.detail)},getphonenumber(t){this.triggerEvent("getphonenumber",t.detail)},error(t){this.triggerEvent("error",t.detail)},opensetting(t){this.triggerEvent("opensetting",t.detail)},launchapp(t){this.triggerEvent("launchapp",t.detail)},chooseavatar(t){this.triggerEvent("chooseavatar",t.detail)},agreeprivacyauthorization(t){this.triggerEvent("agreeprivacyauthorization",t.detail)},handleTap(t){this.data.disabled||this.data.loading||this.triggerEvent("tap",t)}}}};Button=__decorate([wxComponent()],Button);export default Button;

View File

@ -0,0 +1 @@
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-icon":"../icon/icon","t-loading":"../loading/loading"}}

View File

@ -0,0 +1 @@
<import src="../common/template/icon.wxml"/><wxs src="../common/utils.wxs" module="_"/><button id="{{tId}}" style="{{_._style([style, customStyle])}}" data-custom="{{ customDataset }}" class="class {{className}}" form-type="{{disabled || loading ? '' : type}}" open-type="{{disabled || loading ? '' : openType}}" hover-stop-propagation="{{hoverStopPropagation}}" hover-start-time="{{hoverStartTime}}" hover-stay-time="{{hoverStayTime}}" lang="{{lang}}" session-from="{{sessionFrom}}" hover-class="{{disabled || loading ? '' : (hoverClass || classPrefix + '--hover')}}" send-message-title="{{sendMessageTitle}}" send-message-path="{{sendMessagePath}}" send-message-img="{{sendMessageImg}}" app-parameter="{{appParameter}}" show-message-card="{{showMessageCard}}" catch:tap="handleTap" bind:getuserinfo="getuserinfo" bind:contact="contact" bind:getphonenumber="getphonenumber" bind:error="error" bind:opensetting="opensetting" bind:launchapp="launchapp" bind:chooseavatar="chooseavatar" bind:agreeprivacyauthorization="agreeprivacyauthorization" aria-label="{{ariaLabel}}"><template wx:if="{{_icon}}" is="icon" data="{{tClass: classPrefix + '__icon ' + prefix + '-class-icon', ariaHidden: true, name: iconName, ..._icon}}"/><t-loading wx:if="{{loading}}" delay="{{loadingProps.delay || 0}}" duration="{{loadingProps.duration || 800}}" indicator="{{loadingProps.indicator || true}}" inheritColor="{{loadingProps.inheritColor || true}}" layout="{{loadingProps.layout || 'horizontal'}}" pause="{{loadingProps.pause || false}}" progress="{{loadingProps.progress || 0}}" reverse="{{loadingProps.reverse || false}}" size="{{loadingProps.size || '40rpx'}}" text="{{loadingProps.text || '' }}" theme="{{loadingProps.theme || 'circular'}}" loading t-class="{{classPrefix}}__loading {{classPrefix}}__loading--wrapper" t-class-indicator="{{classPrefix}}__loading--indicator {{prefix}}-class-loading"/><view class="{{classPrefix}}__content"><slot name="content"/><block wx:if="{{content}}">{{content}}</block><slot/></view><slot name="suffix"/></button>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
export * from './props';
export * from './type';
export * from './button';

View File

@ -0,0 +1 @@
export*from"./props";export*from"./type";export*from"./button";

View File

@ -0,0 +1 @@
const props={appParameter:{type:String,value:""},block:{type:Boolean,value:!1},content:{type:String},customDataset:{type:null},disabled:{type:null,value:void 0},ghost:{type:Boolean,value:!1},hoverClass:{type:String,value:""},hoverStartTime:{type:Number,value:20},hoverStayTime:{type:Number,value:70},hoverStopPropagation:{type:Boolean,value:!1},icon:{type:null},lang:{type:String},loading:{type:Boolean,value:!1},loadingProps:{type:Object},openType:{type:String},phoneNumberNoQuotaToast:{type:Boolean,value:!0},sendMessageImg:{type:String,value:"截图"},sendMessagePath:{type:String,value:"当前分享路径"},sendMessageTitle:{type:String,value:"当前标题"},sessionFrom:{type:String,value:""},shape:{type:String,value:"rectangle"},showMessageCard:{type:Boolean,value:!1},size:{type:String,value:"medium"},style:{type:String,value:""},tId:{type:String,value:""},theme:{type:String,value:"default"},type:{type:String},variant:{type:String,value:"base"}};export default props;

View File

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

View File

@ -0,0 +1 @@
<wxs src="../common/utils.wxs" module="_"/><template name="calendar-header"><view class="{{class}} {{classPrefix}} {{switchMode !== 'none' ? classPrefix + '__with-action' : ''}}" id="{{tId}}"><view class="{{classPrefix}}__action" wx:if="{{switchMode !== 'none'}}"><view wx:if="{{switchMode === 'year-month'}}" class="{{_.cls(classPrefix + '__icon', [['disabled', preYearBtnDisable]])}}" data-disabled="{{preYearBtnDisable}}" data-type="pre-year" bindtap="handleSwitchModeChange"><t-icon name="chevron-left-double"/></view><view class="{{_.cls(classPrefix + '__icon', [['disabled', prevMonthBtnDisable]])}}" data-disabled="{{prevMonthBtnDisable}}" data-type="pre-month" bindtap="handleSwitchModeChange"><t-icon name="chevron-left"/></view></view><view class="{{classPrefix}}__title">{{ title }}</view><view class="{{classPrefix}}__action" wx:if="{{switchMode !== 'none'}}"><view class="{{_.cls(classPrefix + '__icon', [['disabled', nextMonthBtnDisable]])}}" data-disabled="{{nextMonthBtnDisable}}" data-type="next-month" bindtap="handleSwitchModeChange"><t-icon name="chevron-right"/></view><view wx:if="{{switchMode === 'year-month'}}" class="{{_.cls(classPrefix + '__icon', [['disabled', nextYearBtnDisable]])}}" data-disabled="{{nextYearBtnDisable}}" data-type="next-year" bindtap="handleSwitchModeChange"><t-icon name="chevron-right-double"/></view></view></view></template>

View File

@ -0,0 +1,62 @@
/// <reference types="miniprogram-api-typings" />
import { SuperComponent } from '../common/src/index';
import { TdCalendarProps } from './type';
export interface CalendarProps extends TdCalendarProps {
}
export default class Calendar extends SuperComponent {
behaviors: string[];
externalClasses: string[];
options: WechatMiniprogram.Component.ComponentOptions;
properties: TdCalendarProps;
data: {
prefix: string;
classPrefix: string;
months: any[];
scrollIntoView: string;
innerConfirmBtn: {};
realLocalText: {};
currentMonth: {};
actionButtons: {
preYearBtnDisable: boolean;
prevMonthBtnDisable: boolean;
nextMonthBtnDisable: boolean;
nextYearBtnDisable: boolean;
};
};
controlledProps: {
key: string;
event: string;
}[];
lifetimes: {
created(): void;
ready(): void;
};
observers: {
type(v: any): void;
confirmBtn(v: any): void;
'firstDayOfWeek,minDate,maxDate'(firstDayOfWeek: any, minDate: any, maxDate: any): void;
value(v: any): void;
visible(v: any): void;
format(v: any): void;
};
methods: {
initialValue(): void;
scrollIntoView(): void;
getCurrentYearAndMonth(v: Date): {
year: number;
month: number;
};
updateActionButton(value: Date): void;
calcCurrentMonth(newValue?: any): void;
calcMonths(): void;
close(trigger: any): void;
onVisibleChange(): void;
handleClose(): void;
handleSelect(e: any): void;
onTplButtonTap(): void;
toTime(val: any): any;
onScroll(e: any): void;
getCurrentDate(): any;
handleSwitchModeChange(e: any): void;
};
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"component":true,"styleIsolation":"apply-shared","usingComponents":{"t-popup":"../popup/popup","t-button":"../button/button","t-icon":"../icon/icon"}}

View File

@ -0,0 +1 @@
<wxs src="./calendar.wxs" module="_this"/><wxs src="../common/utils.wxs" module="_"/><t-popup wx:if="{{usePopup}}" class="class" visible="{{visible}}" usingCustomNavbar="{{usingCustomNavbar}}" bind:visible-change="onVisibleChange" placement="bottom"><include src="./template.wxml"/></t-popup><block wx:else><include src="./template.wxml"/></block>

View File

@ -0,0 +1,44 @@
function getDateLabel(monthItem, dateItem) {
var weekdayText = ['日', '一', '二', '三', '四', '五', '六'];
var weekday = (monthItem.weekdayOfFirstDay + dateItem.day - 1) % 7;
var label = monthItem.month + 1 + '月' + dateItem.day + '日, 星期' + weekdayText[weekday];
if (dateItem.type === 'start') {
label = '开始日期:' + label;
}
if (dateItem.type === 'end') {
label = '结束日期:' + label;
}
if (isDateSelected(dateItem)) {
label = '已选中, ' + label;
}
if (dateItem.prefix) {
label += ', ' + dateItem.prefix;
}
if (dateItem.suffix) {
label += ', ' + dateItem.suffix;
}
return label;
}
function isDateSelected(dateItem) {
return ['start', 'end', 'selected', 'centre'].indexOf(dateItem.type) >= 0;
}
function getMonthTitle(year, month, pattern = '') {
// prettier-ignore
var REGEXP = getRegExp('\{year\}|\{month\}', 'g');
return pattern.replace(REGEXP, function (match) {
var replacements = {
'{year}': year,
'{month}': month < 10 ? '0' + month : month,
};
return replacements[match] || match;
});
}
module.exports = {
getDateLabel: getDateLabel,
isDateSelected: isDateSelected,
getMonthTitle: getMonthTitle,
};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
export * from './type';
export * from './calendar';

View File

@ -0,0 +1 @@
export*from"./type";export*from"./calendar";

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