Files
shop-platform/docs/websocket/test_uniapp_wechat.vue

755 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
Uniapp WebSocket 测试页面
用于在 Uniapp 项目中测试微信小程序的 WebSocket 功能
使用方法
1. Uniapp 项目的 pages 目录下创建 ws-test 目录
2. 将此文件保存为 ws-test.vue
3. pages.json 中注册该页面
4. 在微信开发者工具中运行项目并访问该页面
-->
<template>
<view class="container">
<view class="header">
<text class="title">WebSocket 测试</text>
<view class="status" :class="statusClass">
{{ connectionStatus }}
</view>
</view>
<view class="settings">
<view class="form-item">
<text class="label">服务器地址</text>
<input
class="input"
v-model="wsUrl"
placeholder="wss://your-domain.com/ws/aikefu"
/>
</view>
<view class="btn-group">
<button
class="btn btn-primary"
@click="connectWebSocket"
:disabled="connecting"
>
{{ connecting ? '连接中...' : '连接' }}
</button>
<button
class="btn btn-default"
@click="disconnectWebSocket"
:disabled="!connected"
>
断开连接
</button>
<button
class="btn btn-warn"
@click="reconnectWebSocket"
:disabled="connecting"
>
重连
</button>
</view>
</view>
<view class="message-area">
<scroll-view
class="message-list"
scroll-y="true"
:scroll-top="scrollTop"
@scroll="onScroll"
>
<view
v-for="(message, index) in messages"
:key="message.id"
class="message-item"
:class="message.type"
>
<view class="message-header">
<text class="sender">{{ message.sender }}</text>
<text class="time">{{ message.time }}</text>
</view>
<view class="message-content">
{{ formatMessage(message.content) }}
</view>
</view>
</scroll-view>
</view>
<view class="input-area">
<textarea
class="message-input"
v-model="inputMessage"
placeholder="输入要发送的消息..."
@confirm="sendCustomMessage"
></textarea>
<view class="btn-group">
<button class="btn btn-sm" @click="sendPing">Ping</button>
<button class="btn btn-sm" @click="sendTestMessage">测试消息</button>
<button class="btn btn-sm btn-primary" @click="sendCustomMessage">发送</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
wsUrl: 'wss://your-domain.com/ws/aikefu', // 替换为你的 WebSocket 服务器地址
connectionStatus: '未连接',
connected: false,
connecting: false,
socketTask: null,
messages: [],
inputMessage: '',
scrollTop: 0,
autoScroll: true
};
},
computed: {
statusClass() {
if (this.connecting) return 'status-connecting';
if (this.connected) return 'status-connected';
return 'status-disconnected';
}
},
onLoad() {
// 页面加载时自动连接
this.connectWebSocket();
},
onUnload() {
// 页面卸载时断开连接
this.closeWebSocket();
},
onHide() {
// 页面隐藏时断开连接
this.closeWebSocket();
},
methods: {
// 连接 WebSocket
connectWebSocket() {
if (this.connected || this.connecting) return;
this.connecting = true;
this.updateStatus('连接中...');
try {
// 创建 WebSocket 连接 (Uniapp API)
this.socketTask = uni.connectSocket({
url: this.wsUrl,
header: {
'content-type': 'application/json'
},
method: 'GET',
success: (res) => {
console.log('WebSocket 连接请求发送成功', res);
},
fail: (err) => {
console.error('WebSocket 连接请求发送失败', err);
this.connecting = false;
this.updateStatus('连接失败');
this.addMessage('系统', 'WebSocket 连接请求发送失败: ' + JSON.stringify(err), 'error');
}
});
// 监听 WebSocket 连接打开
this.socketTask.onOpen((res) => {
console.log('WebSocket 连接已打开', res);
this.connected = true;
this.connecting = false;
this.updateStatus('已连接');
this.addMessage('系统', 'WebSocket 连接已打开', 'system');
});
// 监听 WebSocket 接收到服务器的消息
this.socketTask.onMessage((res) => {
console.log('收到服务器消息', res.data);
this.addMessage('服务器', res.data, 'received');
});
// 监听 WebSocket 连接关闭
this.socketTask.onClose((res) => {
console.log('WebSocket 连接已关闭', res);
this.connected = false;
this.connecting = false;
this.updateStatus('已断开');
this.addMessage('系统', 'WebSocket 连接已关闭', 'system');
});
// 监听 WebSocket 错误
this.socketTask.onError((res) => {
console.error('WebSocket 连接发生错误', res);
this.connected = false;
this.connecting = false;
this.updateStatus('连接错误');
this.addMessage('系统', 'WebSocket 连接发生错误: ' + JSON.stringify(res), 'error');
});
} catch (error) {
console.error('WebSocket 连接异常', error);
this.connecting = false;
this.updateStatus('连接异常');
this.addMessage('系统', 'WebSocket 连接异常: ' + error.message, 'error');
}
},
// 断开 WebSocket 连接
disconnectWebSocket() {
if (!this.connected && !this.connecting) return;
this.closeWebSocket();
this.connected = false;
this.connecting = false;
this.updateStatus('已断开');
this.addMessage('系统', 'WebSocket 连接已手动断开', 'system');
},
// 关闭 WebSocket 连接(内部使用)
closeWebSocket() {
if (this.socketTask) {
try {
this.socketTask.close({
code: 1000,
reason: '用户主动断开连接'
});
} catch (error) {
console.error('关闭 WebSocket 连接失败', error);
}
this.socketTask = null;
}
},
// 重连 WebSocket
reconnectWebSocket() {
this.closeWebSocket();
this.connected = false;
this.connecting = false;
// 延迟 1 秒后重连
setTimeout(() => {
this.connectWebSocket();
}, 1000);
},
// 发送 Ping 消息
sendPing() {
this.sendMessage(JSON.stringify({ action: 'ping' }));
},
// 发送测试消息
sendTestMessage() {
this.sendMessage(JSON.stringify({
message: '你好,这是 Uniapp 测试消息!',
action: 'test',
timestamp: Date.now()
}));
},
// 发送自定义消息
sendCustomMessage() {
if (!this.inputMessage.trim()) {
uni.showToast({
title: '请输入消息内容',
icon: 'none'
});
return;
}
try {
// 尝试解析为 JSON
JSON.parse(this.inputMessage);
this.sendMessage(this.inputMessage);
} catch (error) {
// 不是 JSON包装为普通消息
this.sendMessage(JSON.stringify({
message: this.inputMessage,
action: 'chat'
}));
}
// 清空输入框
this.inputMessage = '';
},
// 发送消息(通用方法)
sendMessage(message) {
if (!this.connected || !this.socketTask) {
uni.showToast({
title: 'WebSocket 未连接',
icon: 'none'
});
this.updateStatus('已断开');
return;
}
try {
// 使用 Uniapp API 发送消息
this.socketTask.send({
data: message,
success: () => {
this.addMessage('我', message, 'sent');
},
fail: (err) => {
console.error('发送消息失败', err);
this.addMessage('系统', '发送消息失败: ' + JSON.stringify(err), 'error');
}
});
} catch (error) {
console.error('发送消息异常', error);
this.addMessage('系统', '发送消息异常: ' + error.message, 'error');
}
},
// 更新连接状态
updateStatus(status) {
this.connectionStatus = status;
},
// 添加消息到消息列表
addMessage(sender, content, type) {
const message = {
id: Date.now(),
sender,
content,
type,
time: this.formatTime(new Date())
};
this.messages.push(message);
// 自动滚动到底部
this.scrollToBottom();
},
// 滚动到底部
scrollToBottom() {
if (this.autoScroll) {
// 延迟执行以确保 DOM 已更新
this.$nextTick(() => {
uni.createSelectorQuery().in(this)
.select('.message-list')
.boundingClientRect((rect) => {
if (rect) {
this.scrollTop = rect.height;
}
})
.exec();
});
}
},
// 格式化时间
formatTime(date) {
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${hours}:${minutes}:${seconds}`;
},
// 格式化消息内容(美化 JSON
formatMessage(content) {
try {
const parsed = JSON.parse(content);
return JSON.stringify(parsed, null, 2);
} catch (error) {
return content;
}
},
// 处理滚动事件
onScroll(e) {
const { scrollTop, scrollHeight, clientHeight } = e.detail;
// 判断是否滚动到底部附近
this.autoScroll = scrollTop + clientHeight >= scrollHeight - 20;
}
}
};
</script>
<style scoped>
.container {
display: flex;
flex-direction: column;
height: 100vh;
padding: 20rpx;
background-color: #f5f5f5;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #eee;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.status {
padding: 8rpx 16rpx;
border-radius: 8rpx;
font-size: 24rpx;
font-weight: bold;
}
.status-connecting {
background-color: #fff3cd;
color: #856404;
}
.status-connected {
background-color: #d4edda;
color: #155724;
}
.status-disconnected {
background-color: #f8d7da;
color: #721c24;
}
.settings {
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 20rpx;
}
.form-item {
display: flex;
flex-direction: column;
margin-bottom: 20rpx;
}
.label {
font-size: 28rpx;
color: #666;
margin-bottom: 10rpx;
}
.input {
height: 80rpx;
padding: 0 20rpx;
border: 1rpx solid #ddd;
border-radius: 10rpx;
font-size: 28rpx;
background-color: #f9f9f9;
}
.btn-group {
display: flex;
justify-content: flex-start;
gap: 15rpx;
flex-wrap: wrap;
}
.btn {
flex: 1;
min-width: 150rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
border-radius: 10rpx;
font-size: 28rpx;
border: none;
}
.btn-primary {
background-color: #007aff;
color: #fff;
}
.btn-default {
background-color: #f5f5f5;
color: #333;
border: 1rpx solid #ddd;
}
.btn-warn {
background-color: #ff3b30;
color: #fff;
}
.btn-sm {
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
min-width: 100rpx;
}
.message-area {
flex: 1;
background-color: #fff;
border-radius: 10rpx;
margin-bottom: 20rpx;
overflow: hidden;
}
.message-list {
height: 100%;
padding: 20rpx;
}
.message-item {
margin-bottom: 20rpx;
padding: 15rpx;
border-radius: 10rpx;
max-width: 80%;
}
.message-item.sent {
align-self: flex-end;
margin-left: auto;
background-color: #d4edda;
border-right: 4rpx solid #28a745;
}
.message-item.received {
align-self: flex-start;
background-color: #e9ecef;
border-left: 4rpx solid #007bff;
}
.message-item.system {
align-self: center;
background-color: #fff3cd;
border-left: 4rpx solid #856404;
max-width: 90%;
}
.message-item.error {
align-self: center;
background-color: #f8d7da;
border-left: 4rpx solid #dc3545;
max-width: 90%;
}
.message-header {
display: flex;
justify-content: space-between;
margin-bottom: 10rpx;
font-size: 24rpx;
color: #666;
}
.message-content {
font-size: 28rpx;
line-height: 1.5;
word-break: break-all;
white-space: pre-wrap;
}
.input-area {
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
}
.message-input {
width: 100%;
min-height: 120rpx;
max-height: 200rpx;
padding: 20rpx;
margin-bottom: 20rpx;
border: 1rpx solid #ddd;
border-radius: 10rpx;
font-size: 28rpx;
background-color: #f9f9f9;
}
</style>
<script module="pages.json">
// 该模块仅用于示例,实际应在项目根目录的 pages.json 中配置
/*
{
"pages": [
{
"path": "pages/ws-test/ws-test",
"style": {
"navigationBarTitleText": "WebSocket 测试"
}
}
]
}
*/
</script>
<script module="README">
/*
# Uniapp WebSocket 测试页面使用说明
## 功能说明
用于在 Uniapp 项目中测试微信小程序的 WebSocket 功能,支持连接管理、消息发送和接收。
## 使用方法
### 1. 创建页面
将本文件保存为 `pages/ws-test/ws-test.vue`
### 2. 配置页面路由
在 `pages.json` 中添加以下配置:
```json
{
"pages": [
{
"path": "pages/ws-test/ws-test",
"style": {
"navigationBarTitleText": "WebSocket 测试"
}
}
]
}
```
### 3. 配置服务器地址
在 `ws-test.vue` 文件中修改 `wsUrl` 变量:
```javascript
data() {
return {
wsUrl: 'wss://your-domain.com/ws/aikefu', // 替换为你的 WebSocket 服务器地址
// ...
};
}
```
### 4. 运行测试
- 使用 HBuilderX 开发工具
- 选择 "运行" -> "运行到小程序模拟器" -> "微信开发者工具"
- 在微信开发者工具中访问该页面
## 注意事项
### 微信小程序限制
1. **域名配置**:需要在微信小程序管理后台配置合法域名
2. **协议支持**:仅支持 HTTPS/WSS 协议
3. **连接数限制**:最多同时存在 5 个 WebSocket 连接
### Uniapp API 特点
1. Uniapp 使用 `uni.connectSocket()` 替代微信小程序的 `wx.connectSocket()`
2. Uniapp 使用 `uni.createSelectorQuery()` 替代微信小程序的 `wx.createSelectorQuery()`
3. 页面生命周期钩子函数使用 Vue 组件的 `onLoad()`、`onUnload()`、`onHide()`
## 扩展功能
### 添加消息类型支持
可以根据业务需求扩展支持的消息类型:
```javascript
// 发送聊天消息
sendChatMessage() {
this.sendMessage(JSON.stringify({
action: 'chat',
message: this.inputMessage,
userId: 'user123',
timestamp: Date.now()
}));
}
// 发送指令消息
sendCommand(command, params) {
this.sendMessage(JSON.stringify({
action: 'command',
command,
params,
timestamp: Date.now()
}));
}
```
### 添加自动重连机制
可以实现更智能的自动重连机制:
```javascript
data() {
return {
// ...
reconnectAttempts: 0,
maxReconnectAttempts: 5,
reconnectDelay: 1000
};
},
methods: {
// 自动重连
autoReconnect() {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
this.addMessage('系统', '自动重连失败,已达到最大尝试次数', 'error');
return;
}
this.reconnectAttempts++;
this.addMessage('系统', `尝试自动重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`, 'system');
setTimeout(() => {
this.connectWebSocket();
}, this.reconnectDelay);
},
// 连接成功后重置重连计数
onConnectSuccess() {
this.reconnectAttempts = 0;
// ...
}
}
```
## 常见问题
### 1. 连接失败
**可能原因**
- 服务器地址错误
- 未配置合法域名
- 服务器未启动或网络不可达
- 使用了 HTTP 协议而不是 HTTPS
**解决方案**
- 检查服务器地址和端口
- 在微信小程序管理后台配置合法域名
- 确保服务器正常运行
- 切换到 WSS 协议
### 2. 消息发送失败
**可能原因**
- WebSocket 连接已关闭
- 消息格式不正确
- 网络中断
**解决方案**
- 检查连接状态,必要时重新连接
- 确保消息格式为 JSON 字符串
- 检查网络连接
### 3. 接收消息异常
**可能原因**
- 服务器返回格式错误
- 客户端解析错误
**解决方案**
- 检查服务器返回的消息格式
- 调试客户端解析逻辑
## 联系和支持
如果在使用过程中遇到问题,请联系开发人员或查看相关文档。
---
**更新时间**2025-12-19
**版本**1.0.0
**维护人员**WebSocket 开发团队
*/
</script>