简单渲染wyxd,未整合

This commit is contained in:
2026-07-24 09:18:10 +08:00
parent 9ace485cbd
commit dc4f6b2132
11 changed files with 7420 additions and 1435 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

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