Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions packages/pro-components/chat/chat-record/README.en-US.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: ChatRecord
description: A component for displaying chat conversation history with features like time grouping, scroll loading, and message interactions.
spline: base
isComponent: true
---

## Import

For global import, configure in `app.json` in the miniprogram root directory. For local import, configure in the `index.json` of the page or component where you need to import.

```json
"usingComponents": {
"t-chat-record": "tdesign-miniprogram/chat-record/chat-record"
}
```

## Usage

### 01 Component Types

#### Basic Type

Display a basic chat record list.

```xml
<t-chat-record records="{{records}}" />
```

#### With Time Grouping

Support automatic time grouping display based on time intervals.

```xml
<t-chat-record
records="{{records}}"
show-time-group="{{true}}"
time-group-interval="{{5}}"
/>
```

#### Scroll Load More

Support loading more history when scrolling to the top.

```xml
<t-chat-record
records="{{records}}"
loading="{{loading}}"
finished="{{finished}}"
bind:loadmore="handleLoadMore"
/>
```

#### Custom Message Rendering

Support custom message rendering through slots.

```xml
<t-chat-record records="{{records}}">
<view slot="message" slot-scope="record">
<!-- Custom message content -->
</view>
</t-chat-record>
```

## API

### ChatRecord Props

Name | Type | Default | Description | Required
-- | -- | -- | -- | --
style | Object | - | Style | N
custom-style | Object | - | Style, generally used for virtualized component node scenarios | N
records | Array | [] | Chat record data list. TS Type: `ChatRecordItem[]` | N
loading | Boolean | false | Whether to show loading state | N
finished | Boolean | false | Whether all data has been loaded | N
loading-text | String | Loading... | Loading prompt text | N
finished-text | String | No more data | Finished loading prompt text | N
empty-text | String | No chat records | Empty state prompt text | N
show-time-group | Boolean | true | Whether to show time grouping | N
time-group-interval | Number | 5 | Time grouping interval (minutes) | N
virtual-scroll | Boolean | false | Whether to enable virtual scrolling | N
scroll-view-height | String | 100vh | Scroll view height | N
auto-scroll-to-bottom | Boolean | true | Whether to auto scroll to bottom | N

### ChatRecord Events

Name | Parameters | Description
-- | -- | --
loadmore | - | Triggered when scrolling to the top, used to load more history
scroll | `(detail: ScrollDetail)` | Triggered when scrolling
message-click | `(detail: { record: ChatRecordItem })` | Triggered when clicking a message
message-long-press | `(detail: { record: ChatRecordItem })` | Triggered when long-pressing a message

### ChatRecord Slots

Name | Description
-- | --
empty | Custom empty state content
message | Custom message content, receives record parameter

### ChatRecord External Style Classes

Class Name | Description
-- | --
t-class | Root node style class
t-class-empty | Empty state style class
t-class-time | Time grouping style class
t-class-message | Message item style class
93 changes: 93 additions & 0 deletions packages/pro-components/chat/chat-record/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: ChatRecord 语音输入
description: 用于聊天场景的语音输入组件,支持语音转文字、录音时长控制等功能。
spline: base
isComponent: true
---

## 引入

全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。

```json
"usingComponents": {
"t-chat-record": "tdesign-miniprogram/chat-record/chat-record"
}
```

## 前置配置

### 1. 添加插件声明

在 `app.json` 中声明微信同声传译插件:

```json
{
"plugins": {
"WechatSI": {
"version": "0.3.6",
"provider": "wx069ba97219f66d99"

Check warning on line 29 in packages/pro-components/chat/chat-record/README.md

View workflow job for this annotation

GitHub Actions / run / Typos

"ba" should be "by" or "be".
}
}
}
```

### 2. 麦克风权限

使用语音输入需要用户授权麦克风权限。组件会自动处理授权流程,但开发者需要了解以下场景:

#### 首次使用
- 组件会自动调用 `wx.authorize` 申请麦克风权限
- 用户同意后即可正常使用

#### 用户拒绝授权
- 如果用户点击拒绝,会显示"请授权麦克风权限"提示
- 点击提示区域会引导用户前往设置页面开启权限

#### 权限问题排查

如果在小程序设置页面看不到麦克风权限选项:

1. **检查微信 App 权限**
- 进入手机系统设置 > 应用管理 > 微信
- 确保微信有麦克风权限

2. **检查小程序授权**
- 微信中下拉打开最近使用小程序列表
- 长按目标小程序 > 关于小程序 > 设置
- 查看是否有麦克风权限选项

3. **重新授权**
- 删除小程序后重新搜索进入
- 首次点击语音输入时会重新触发授权弹窗

4. **真机调试**
- 模拟器无法测试录音功能
- 必须使用真机预览或体验版测试

## API

### ChatRecord Props

名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
useSpeechNoAuthSlot | Boolean | false | 是否启用语音输入无权限时显示插槽 | N
useSpeechInputSlot | Boolean | false | 是否启用语音输入时显示插槽 | N
autoSendHeight| Number | 0 | 自动发送消息的高度 | N
speechInput | slot | false | 语音输入按钮插槽 | N
speechNoAuth | slot | false | 语音授权按钮插槽 | N


### ChatRecord Events

名称 | 参数 | 描述
-- | -- | --
recognize | msg: string | 识别到的文本内容

### ChatRecord Slots

名称 | 描述
-- | --
speechInput | 语音输入按钮插槽
speechNoAuth | 语音授权按钮插槽

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"component": true,
"styleIsolation": "shared",
"usingComponents": {
"t-navbar": "tdesign-miniprogram/navbar/navbar",
"t-chat-sender": "tdesign-miniprogram/chat-sender/chat-sender",
"t-chat-record": "tdesign-miniprogram/chat-record/chat-record"
}
}
97 changes: 97 additions & 0 deletions packages/pro-components/chat/chat-record/_example/base/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
Page({
/**
* 页面的初始数据
*/
data: {
query: '', // 输入框内容
placeholder: '请输入内容', // 输入框占位符
loading: false, // 发送按钮加载状态
showVoice: false, // 是否显示语音输入组件
},

/**
* 返回上一页
*/
navigateBack() {
wx.navigateBack({
delta: 1,
});
},

/**
* 处理输入框内容变化
*/
handleInput(e) {
this.setData({
query: e.detail.value,
});
},

/**
* 切换语音输入显示状态
*/
handleVoice() {
this.setData({
showVoice: !this.data.showVoice,
});
},

/**
* 语音识别回调
* @param {Object} e - 事件对象
*/
handleRecognize(e) {
const voiceMsg = e.detail.msg;
console.log('语音识别结果:', voiceMsg);

// 将语音识别结果设置到输入框中
this.setData({
query: voiceMsg,
showVoice: false, // 识别完成后隐藏语音输入组件
});

// 提示用户
wx.showToast({
title: '识别成功',
icon: 'success',
duration: 1500,
});
},

/**
* 发送消息
*/
handleSend() {
const { query, loading } = this.data;

// 如果正在加载或内容为空,不处理
if (loading || !query.trim()) {
if (!query.trim()) {
wx.showToast({
title: '请输入内容',
icon: 'none',
duration: 1500,
});
}
return;
}
// 设置加载状态
this.setData({
loading: true,
});

// 模拟发送请求
setTimeout(() => {
this.setData({
loading: false,
query: '', // 清空输入框
});

wx.showToast({
title: '发送成功',
icon: 'success',
duration: 1500,
});
}, 1000);
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<view class="demo-base-container">
<!-- 聊天发送器组件 - 文本输入模式 -->
<view class="chat-sender-demo-wrapper">
<view class="chat-sender-height-limit">
<view class="chat-sender-height-left-limit"> </view>
<view class="chat-sender-height-right-limit"> </view>
</view>
<!-- <view class="chat-sender-placeholder"> 文本输入模式:最大高度为132px </view> -->
<view class="chat-sender-wrapper">
<t-chat-sender
value="{{query}}"
loading="{{loading}}"
placeholder="{{placeholder}}"
inputMode="{{showVoice ? 'voice' : 'text'}}"
bind:send="onSend"
bind:keyboardheightchange="onKeyboardHeightChange"
>
<view slot="voice-input">
<t-chat-record useSpeechInputSlot useSpeechNoAuthSlot bind:recognize="onVoiceRecognize">
<view slot="speechInput" style="padding: 10px; background: #f0f0f0; border-radius: 8px"> 按住说话 </view>
<view slot="speechNoAuth" style="padding: 10px; background: #ffebee; border-radius: 8px; color: #d32f2f">
请授权麦克风权限
</view>
</t-chat-record>
</view>
<view slot="footer-prefix" class="demo-footer-prefix">
<view
style="
width: 40px;
height: 40px;
background-color: red;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
"
bind:tap="handleVoice"
>
<text style="color: white; font-size: 20px"> + </text>
</view>
</view>
</t-chat-sender>
</view>
</view>
</view>
Loading
Loading