first commit
This commit is contained in:
538
pages/text/text2.vue
Normal file
538
pages/text/text2.vue
Normal file
@@ -0,0 +1,538 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 连接状态卡片 -->
|
||||
<view class="status-card">
|
||||
<text class="status-label">连接状态</text>
|
||||
<view class="status-value" :class="connectionStatusClass">
|
||||
<text>{{ socketStore.getStatusText() }}</text>
|
||||
</view>
|
||||
<view class="status-info" v-if="socketStore.reconnectAttempts > 0">
|
||||
<text class="reconnect-info">重连次数: {{ socketStore.reconnectAttempts }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 配置区域 -->
|
||||
<view class="config-card">
|
||||
<text class="section-title">连接配置</text>
|
||||
<view class="input-group">
|
||||
<text class="input-label">Token</text>
|
||||
<input class="input-field" v-model="config.token" placeholder="请输入Token" />
|
||||
</view>
|
||||
<view class="input-group">
|
||||
<text class="input-label">Conversation ID</text>
|
||||
<input class="input-field" v-model="config.conversationId" placeholder="请输入会话ID(可选)" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 连接控制 -->
|
||||
<view class="control-card">
|
||||
<button class="btn btn-primary" :disabled="socketStore.isConnected || socketStore.isConnecting"
|
||||
@click="handleConnect">
|
||||
{{ socketStore.isConnecting ? '连接中...' : '连接' }}
|
||||
</button>
|
||||
<button class="btn btn-danger" :disabled="!socketStore.isConnected" @click="handleDisconnect">
|
||||
断开
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click="handleSendPing" :disabled="!socketStore.isConnected">
|
||||
Ping
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 发送消息区域 -->
|
||||
<view class="send-card">
|
||||
<text class="section-title">发送消息</text>
|
||||
<view class="send-input-wrapper">
|
||||
<textarea class="send-input" v-model="sendMessage" placeholder="输入要发送的消息(JSON格式)"
|
||||
:disabled="!socketStore.isConnected"></textarea>
|
||||
<view class="send-buttons">
|
||||
<button class="btn btn-primary btn-small"
|
||||
:disabled="!socketStore.isConnected || !sendMessage.trim()" @click="handleSend">
|
||||
发送
|
||||
</button>
|
||||
<button class="btn btn-outline btn-small" :disabled="!sendMessage.trim()" @click="formatJson">
|
||||
格式化
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 快捷消息 -->
|
||||
<view class="quick-messages">
|
||||
<text class="quick-label">快捷消息:</text>
|
||||
<view class="quick-btns">
|
||||
<button v-for="item in quickMessages" :key="item.label" class="quick-btn"
|
||||
:disabled="!socketStore.isConnected" @click="sendQuickMessage(item.data)">
|
||||
{{ item.label }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 日志区域 -->
|
||||
<view class="log-card">
|
||||
<view class="log-header">
|
||||
<view class="log-title-wrapper">
|
||||
<text class="section-title">日志</text>
|
||||
<text class="log-count">({{ socketStore.logs.length }})</text>
|
||||
</view>
|
||||
<view class="log-actions">
|
||||
<button class="btn btn-small btn-secondary" @click="socketStore.clearLogs">清空</button>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="log-list" scroll-y @scrolltoupper="loadMoreLogs">
|
||||
<view v-for="(log, index) in socketStore.logs" :key="index" class="log-item" :class="'log-' + log.type">
|
||||
<text class="log-time">{{ log.time }}</text>
|
||||
<text class="log-content">{{ log.content }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
watch
|
||||
} from 'vue'
|
||||
import {
|
||||
useSocketStore
|
||||
} from '@/stores/socket.js'
|
||||
import {
|
||||
getToken,
|
||||
getTaskCallId,
|
||||
getCurrentSessionId
|
||||
} from '@/utils/user-info.js'
|
||||
|
||||
// Store
|
||||
const socketStore = useSocketStore()
|
||||
|
||||
// 响应式数据
|
||||
const config = ref({
|
||||
token: getToken(),
|
||||
conversationId: getCurrentSessionId()
|
||||
})
|
||||
const sendMessage = ref('')
|
||||
const quickMessages = ref([{
|
||||
label: 'Ping',
|
||||
data: {
|
||||
ws_event: 'ping'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '认证',
|
||||
data: {
|
||||
ws_event: 'auth',
|
||||
data: {
|
||||
token: '',
|
||||
conversation_id: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '测试消息',
|
||||
data: {
|
||||
ws_event: 'message',
|
||||
data: {
|
||||
task_call_id: getTaskCallId(),
|
||||
token: getToken(),
|
||||
conversation_id: getCurrentSessionId()
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// 计算属性
|
||||
const connectionStatusClass = computed(() => {
|
||||
const status = socketStore.connectionStatus
|
||||
return {
|
||||
'status-connected': status === 'connected',
|
||||
'status-connecting': status === 'connecting',
|
||||
'status-error': status === 'error',
|
||||
'status-disconnected': status === 'disconnected'
|
||||
}
|
||||
})
|
||||
|
||||
// 方法
|
||||
const handleConnect = () => {
|
||||
if (!config.value.token) {
|
||||
uni.showToast({
|
||||
title: '请输入Token',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
socketStore.connect({
|
||||
token: config.value.token,
|
||||
conversationId: getCurrentSessionId()
|
||||
})
|
||||
}
|
||||
|
||||
const handleDisconnect = () => {
|
||||
socketStore.disconnect()
|
||||
}
|
||||
|
||||
const handleSendPing = async () => {
|
||||
try {
|
||||
await socketStore.sendPing()
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: '发送失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleSend = async () => {
|
||||
if (!sendMessage.value.trim()) return
|
||||
|
||||
try {
|
||||
const messageData = {
|
||||
ws_event: 'message',
|
||||
data: {
|
||||
task_call_id: getTaskCallId(),
|
||||
result: {
|
||||
tools: []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await socketStore.send(messageData)
|
||||
sendMessage.value = ''
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: '发送失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const sendQuickMessage = async (template) => {
|
||||
// console.log('getCurrentSessionId:', getCurrentSessionId())
|
||||
|
||||
const messageData = {
|
||||
ws_event: 'message',
|
||||
data: {
|
||||
task_call_id: getTaskCallId(),
|
||||
token: getToken(),
|
||||
conversation_id: getCurrentSessionId()
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await socketStore.send(messageData)
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: '发送失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const formatJson = () => {
|
||||
if (!sendMessage.value.trim()) return
|
||||
|
||||
try {
|
||||
const obj = JSON.parse(sendMessage.value)
|
||||
sendMessage.value = JSON.stringify(obj, null, 2)
|
||||
} catch {
|
||||
uni.showToast({
|
||||
title: '不是有效的JSON',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const loadMoreLogs = () => {
|
||||
// 预留扩展
|
||||
}
|
||||
watch(() => socketStore.isDisconnected, (newVal) => {
|
||||
if (newVal && socketStore.messageString) {
|
||||
console.log(socketStore.messageString);
|
||||
}
|
||||
})
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
socketStore.addLog('info', '=== Socket测试页面 ===')
|
||||
socketStore.addLog('info', '页面已加载')
|
||||
|
||||
if (socketStore.isConnected) {
|
||||
socketStore.addLog('info', '当前已处于连接状态')
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
socketStore.addLog('info', '页面卸载')
|
||||
// 注意:这里不主动断开连接,由App级别管理
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.status-card,
|
||||
.config-card,
|
||||
.control-card,
|
||||
.send-card,
|
||||
.log-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
display: inline-block;
|
||||
padding: 12rpx 32rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-connected {
|
||||
background-color: #e6f7e6;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.status-connecting {
|
||||
background-color: #fff7e6;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.status-disconnected {
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background-color: #fff1f0;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.reconnect-info {
|
||||
font-size: 24rpx;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 24rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 12rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
border: 2rpx solid #e8e8e8;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.control-card {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
text-align: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #ff4d4f;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #f0f0f0;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
color: #1890ff;
|
||||
border: 2rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
height: 64rpx;
|
||||
line-height: 64rpx;
|
||||
font-size: 26rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.btn[disabled] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.send-input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.send-input {
|
||||
border: 2rpx solid #e8e8e8;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 28rpx;
|
||||
min-height: 160rpx;
|
||||
background-color: #fafafa;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.send-buttons {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.quick-messages {
|
||||
margin-top: 24rpx;
|
||||
padding-top: 24rpx;
|
||||
border-top: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.quick-label {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
margin-bottom: 16rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.quick-btns {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.quick-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #f0f5ff;
|
||||
color: #1890ff;
|
||||
border-radius: 8rpx;
|
||||
font-size: 26rpx;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.quick-btn[disabled] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.log-title-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.log-title-wrapper .section-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.log-count {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.log-actions {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.log-list {
|
||||
max-height: 500rpx;
|
||||
background-color: #1e1e1e;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
display: flex;
|
||||
margin-bottom: 12rpx;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
color: #888;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.log-info .log-content {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.log-success .log-content {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.log-error .log-content {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.log-warn .log-content {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.log-send .log-content {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.log-receive .log-content {
|
||||
color: #52c41a;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user