ToolsLoadingCard.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <el-collapse v-model="activeCollapse" class="tools-collapse">
  3. <el-collapse-item :name="collapseKey" class="tools-collapse-item">
  4. <template #title>
  5. <div class="collapse-header">
  6. <el-tag :type="getRequestTagType()" size="small" class="type-tag">
  7. {{ toolData.requestType }}
  8. </el-tag>
  9. <span class="tool-name">{{ toolData.toolName || '未知工具' }}</span>
  10. </div>
  11. </template>
  12. <div class="collapse-content">
  13. <div v-if="toolData.data">
  14. <pre class="json-content">{{ formatData(toolData.data) }}</pre>
  15. </div>
  16. <el-empty v-else description="暂无数据" />
  17. </div>
  18. </el-collapse-item>
  19. </el-collapse>
  20. </template>
  21. <script setup lang="ts">
  22. import { ref, onMounted } from 'vue'
  23. type Props = {
  24. data: string
  25. }
  26. interface ToolData {
  27. requestType: string // request/response
  28. toolName: string // 工具名
  29. data: string // 参数或返回结果
  30. }
  31. const props = defineProps<Props>()
  32. const activeCollapse = ref<string[]>([])
  33. const collapseKey = ref('tool-collapse')
  34. const toolData = ref<ToolData>({
  35. requestType: '',
  36. toolName: '',
  37. data: ''
  38. })
  39. // 解析传入的数据
  40. onMounted(() => {
  41. try {
  42. const decodedData = decodeURIComponent(props.data)
  43. const lines = decodedData.trim().split('\n')
  44. if (lines.length >= 2) {
  45. toolData.value = {
  46. requestType: lines[0] || 'request',
  47. toolName: lines[1] || '未知工具',
  48. data: lines[2] || '' // 第三行为参数/结果,可能不存在
  49. }
  50. } else {
  51. toolData.value = {
  52. requestType: 'error',
  53. toolName: '数据格式错误',
  54. data: '应为2-3行格式:request/response、工具名、参数/结果'
  55. }
  56. }
  57. } catch (e) {
  58. console.error('解析工具数据失败:', e)
  59. toolData.value = {
  60. requestType: 'error',
  61. toolName: '数据解析失败',
  62. data: '解析错误'
  63. }
  64. }
  65. })
  66. // 获取请求类型标签类型
  67. const getRequestTagType = () => {
  68. const type = toolData.value.requestType.toLowerCase()
  69. switch (type) {
  70. case 'request':
  71. return 'primary'
  72. case 'response':
  73. return 'success'
  74. case 'error':
  75. return 'danger'
  76. default:
  77. return 'info'
  78. }
  79. }
  80. // 格式化数据显示
  81. const formatData = (data: string) => {
  82. try {
  83. // 尝试解析为JSON并格式化
  84. const parsed = JSON.parse(data)
  85. return JSON.stringify(parsed, null, 2)
  86. } catch {
  87. // 如果不是JSON,直接返回原始数据
  88. return data
  89. }
  90. }
  91. </script>
  92. <style scoped>
  93. .tools-collapse {
  94. border: 1px solid var(--el-border-color-light);
  95. border-radius: 6px;
  96. overflow: hidden;
  97. margin: 8px 0;
  98. }
  99. .tools-collapse-item {
  100. border: none;
  101. }
  102. .tools-collapse-item :deep(.el-collapse-item__header) {
  103. padding: 0;
  104. border: none;
  105. background: transparent;
  106. height: auto;
  107. min-height: 16px;
  108. position: relative;
  109. }
  110. .tools-collapse-item :deep(.el-collapse-item__content) {
  111. padding: 0;
  112. border: none;
  113. }
  114. /* 调整展开箭头位置 */
  115. :deep(.el-collapse-item__arrow) {
  116. margin-top: 8px;
  117. margin-bottom: 8px;
  118. }
  119. .collapse-header {
  120. padding: 2px 8px;
  121. width: 100%;
  122. display: flex;
  123. align-items: center;
  124. gap: 8px;
  125. line-height: 1;
  126. }
  127. .type-tag {
  128. font-size: 10px;
  129. flex-shrink: 0;
  130. padding: 1px 4px;
  131. line-height: 1;
  132. height: auto;
  133. }
  134. .tool-name {
  135. font-size: 12px;
  136. font-weight: 500;
  137. color: var(--el-text-color-primary);
  138. word-break: break-all;
  139. flex: 1;
  140. line-height: 1;
  141. padding: 0;
  142. margin: 0;
  143. }
  144. .collapse-content {
  145. padding: 4px 8px 4px 8px;
  146. border-top: 1px solid var(--el-border-color-lighter);
  147. }
  148. .json-content {
  149. background-color: var(--el-fill-color-light);
  150. border: 1px solid var(--el-border-color-light);
  151. border-radius: 3px;
  152. padding: 4px 6px;
  153. margin: 0;
  154. font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  155. font-size: 11px;
  156. line-height: 1.2;
  157. color: var(--el-text-color-primary);
  158. white-space: pre-wrap;
  159. word-break: break-all;
  160. overflow-x: auto;
  161. max-height: 120px;
  162. overflow-y: auto;
  163. }
  164. </style>