st-comp 0.0.255 → 0.0.257

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ import { UserFilled, Service, Promotion } from "@element-plus/icons-vue";
8
8
 
9
9
  const stConfig = inject("stConfig");
10
10
  const userData = reactive(getUserData());
11
+ const visible = ref(false);
11
12
  const emit = defineEmits(["callBack"]);
12
13
  const props = defineProps({
13
14
  defaultMessage: {
@@ -16,12 +17,13 @@ const props = defineProps({
16
17
  },
17
18
  });
18
19
 
19
- const visible = ref(false);
20
+ // loading状态
20
21
  const isSending = ref(false);
21
22
  const isThinking = ref(false);
22
23
 
24
+ // 消息队列
23
25
  const messageListRef = ref(null);
24
- const messages = ref([
26
+ const messageList = ref([
25
27
  {
26
28
  role: "assistant", // AI-assistant, 用户-user
27
29
  content: props.defaultMessage,
@@ -33,19 +35,64 @@ const messages = ref([
33
35
  firstPackageTime: 0, // 首包响应耗时
34
36
  },
35
37
  ]);
36
- const inputMessage = ref("");
37
38
 
38
- // 反馈弹窗相关
39
+ // 用户输入
40
+ const userInput = ref("");
41
+
42
+ // 反馈弹窗
39
43
  const feedbackDialogVisible = ref(false);
40
44
  const feedbackContent = ref("");
41
45
  const feedbackMessageIndex = ref({}); // 当前点击要反馈的message的索引
42
46
 
47
+ // 辅助函数:判断是否可JSON序列化
48
+ const isJSONSerializable = (str) => {
49
+ if (typeof str !== "string") return false;
50
+ try {
51
+ const parsed = JSON.parse(str);
52
+ return parsed !== null && typeof parsed === "object";
53
+ } catch {
54
+ return false;
55
+ }
56
+ };
57
+ // 辅助函数:解析并格式化JSON内容
58
+ const formatJSONContent = (content) => {
59
+ if (!isJSONSerializable(content)) return null;
60
+ try {
61
+ const jsonData = JSON.parse(content);
62
+ const { parsedConditions, ...webParams } = jsonData;
63
+ return {
64
+ parsedConditions: parsedConditions,
65
+ webParams,
66
+ };
67
+ } catch {
68
+ return null;
69
+ }
70
+ };
71
+ // 辅助函数:渲染JSON内容为HTML
72
+ const renderJSONContent = (jsonData) => {
73
+ if (!jsonData) return "";
74
+ let html = "";
75
+ // 渲染 parsedConditions
76
+ if (jsonData.parsedConditions?.length) {
77
+ html += '<div class="parsed-conditions">';
78
+ jsonData.parsedConditions.forEach((text) => {
79
+ html += `<div class="parsed-conditions-item">${text}</div>`;
80
+ });
81
+ html += "</div>";
82
+ }
83
+ // 渲染 webParams
84
+ // html += '<div class="web-params">';
85
+ // html += `<div>${JSON.stringify(jsonData.webParams)}</div>`;
86
+ // html += "</div>";
87
+ return html;
88
+ };
89
+
43
90
  // 反馈弹窗相关函数处理
44
91
  const handleFeedbackAction = async (action, messageIndex) => {
45
92
  switch (action) {
46
93
  // 窗口: 提交(满意)
47
94
  case "satisfied": {
48
- const message = messages.value[messageIndex];
95
+ const message = messageList.value[messageIndex];
49
96
  const params = {
50
97
  userName: userData.username,
51
98
  userContent: message.userContent,
@@ -54,10 +101,13 @@ const handleFeedbackAction = async (action, messageIndex) => {
54
101
  createTime: message.createTime,
55
102
  resTime: message.resTime,
56
103
  firstPackageTime: message.firstPackageTime,
104
+
105
+ isSolved: 1, // 是否解决
106
+ logOrigin: 1, // 日志来源
57
107
  };
58
108
  await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
59
109
  ElMessage.success("感谢您的评价!");
60
- messages.value[messageIndex].hasFeedback = true;
110
+ messageList.value[messageIndex].hasFeedback = true;
61
111
  break;
62
112
  }
63
113
  // 窗口: 打开
@@ -68,7 +118,7 @@ const handleFeedbackAction = async (action, messageIndex) => {
68
118
  }
69
119
  // 窗口: 提交(不满意)
70
120
  case "unsatisfied": {
71
- const message = messages.value[messageIndex];
121
+ const message = messageList.value[messageIndex];
72
122
  const params = {
73
123
  userName: userData.username,
74
124
  userContent: message.userContent,
@@ -78,16 +128,19 @@ const handleFeedbackAction = async (action, messageIndex) => {
78
128
  resTime: message.resTime,
79
129
  createTime: message.createTime,
80
130
  firstPackageTime: message.firstPackageTime,
131
+
132
+ isSolved: 0, // 是否解决
133
+ logOrigin: 1, // 日志来源
81
134
  };
82
135
  await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
83
136
  ElMessage.success("感谢您的反馈!我们将持续跟踪并进行优化");
84
137
  feedbackDialogVisible.value = false;
85
- messages.value[messageIndex].hasFeedback = true;
138
+ messageList.value[messageIndex].hasFeedback = true;
86
139
  break;
87
140
  }
88
141
  // 自动提交记录跟踪日志
89
142
  case "default": {
90
- const message = messages.value[messageIndex];
143
+ const message = messageList.value[messageIndex];
91
144
  const params = {
92
145
  userName: userData.username,
93
146
  userContent: message.userContent,
@@ -97,29 +150,31 @@ const handleFeedbackAction = async (action, messageIndex) => {
97
150
  resTime: message.resTime,
98
151
  createTime: message.createTime,
99
152
  firstPackageTime: message.firstPackageTime,
153
+
154
+ isSolved: 1, // 是否解决
155
+ logOrigin: 1, // 日志来源
100
156
  };
101
157
  await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
102
158
  }
103
159
  }
104
160
  };
105
-
106
161
  // 发送消息
107
162
  const sendMessage = async () => {
108
- const content = inputMessage.value.trim();
163
+ const content = userInput.value.trim();
109
164
  if (!content) return ElMessage.warning("请输入消息内容");
110
165
  if (isSending.value) return;
111
166
 
112
167
  // 记录用户消息
113
- messages.value.push({
168
+ messageList.value.push({
114
169
  role: "user",
115
170
  content: content,
116
171
  createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
117
172
  });
118
- inputMessage.value = "";
173
+ userInput.value = "";
119
174
  await scrollToBottom();
120
175
 
121
176
  // 创建AI消息占位符,记录对应的用户输入
122
- messages.value.push({
177
+ messageList.value.push({
123
178
  role: "assistant",
124
179
  content: "",
125
180
  userContent: content,
@@ -150,10 +205,10 @@ const sendMessage = async () => {
150
205
  isSending.value = false;
151
206
 
152
207
  // 移除占位的AI消息
153
- messages.value.pop();
208
+ messageList.value.pop();
154
209
 
155
210
  // 添加错误提示消息
156
- messages.value.push({
211
+ messageList.value.push({
157
212
  role: "assistant",
158
213
  userContent: content,
159
214
  content: `❌ ${data}`,
@@ -163,7 +218,7 @@ const sendMessage = async () => {
163
218
  resTime: new Date().getTime() - resTime,
164
219
  firstPackageTime: 0,
165
220
  });
166
- handleFeedbackAction("default", messages.value.length - 1);
221
+ handleFeedbackAction("default", messageList.value.length - 1);
167
222
  scrollToBottom();
168
223
  return;
169
224
  }
@@ -171,7 +226,7 @@ const sendMessage = async () => {
171
226
  else if (type === "message") {
172
227
  fullResponse += data;
173
228
  // 直接更新最后一条AI消息
174
- const lastMessage = messages.value[messages.value.length - 1];
229
+ const lastMessage = messageList.value[messageList.value.length - 1];
175
230
  if (lastMessage && lastMessage.role === "assistant") {
176
231
  lastMessage.content = fullResponse;
177
232
  scrollToBottom();
@@ -185,18 +240,21 @@ const sendMessage = async () => {
185
240
  else if (type === "finish") {
186
241
  isThinking.value = false;
187
242
  isSending.value = false;
188
- const lastMessage = messages.value[messages.value.length - 1];
243
+ const lastMessage = messageList.value[messageList.value.length - 1];
189
244
 
190
245
  // 显示反馈按钮
191
246
  if (lastMessage && lastMessage.role === "assistant") {
192
247
  lastMessage.showFeedback = true;
193
248
  lastMessage.resTime = new Date().getTime() - resTime;
194
- handleFeedbackAction("default", messages.value.length - 1);
249
+ handleFeedbackAction("default", messageList.value.length - 1);
195
250
  }
196
251
 
197
252
  // 触发回调
198
253
  try {
199
254
  const jsonResponse = JSON.parse(fullResponse);
255
+ // 切割掉parsedConditions, 这个字段仅做AI提炼展示使用
256
+ delete jsonResponse.parsedConditions;
257
+ console.log(jsonResponse)
200
258
  emit("callBack", jsonResponse);
201
259
  } catch (error) {
202
260
  emit("callBack", fullResponse);
@@ -207,9 +265,9 @@ const sendMessage = async () => {
207
265
  } catch (error) {
208
266
  ElMessage.error(`AI响应异常: ${error}`);
209
267
  // 移除占位的AI消息
210
- messages.value.pop();
268
+ messageList.value.pop();
211
269
  // 添加错误提示消息
212
- messages.value.push({
270
+ messageList.value.push({
213
271
  role: "assistant",
214
272
  userContent: content,
215
273
  content: "❌ 抱歉,AI服务响应异常,请稍后重试。",
@@ -219,14 +277,14 @@ const sendMessage = async () => {
219
277
  resTime: new Date().getTime() - resTime,
220
278
  firstPackageTime: 0,
221
279
  });
222
- handleFeedbackAction("default", messages.value.length - 1);
280
+ handleFeedbackAction("default", messageList.value.length - 1);
223
281
  await scrollToBottom();
224
282
  isSending.value = false;
225
283
  isThinking.value = false;
226
284
  }
227
285
  };
228
286
 
229
- // 处理键盘事件:Ctrl+Enter 换行,Enter 发送
287
+ // 辅助函数: Ctrl+Enter 换行,Enter 发送
230
288
  const handleKeydown = (event) => {
231
289
  if (event.key === "Enter") {
232
290
  if (event.ctrlKey) {
@@ -235,7 +293,7 @@ const handleKeydown = (event) => {
235
293
  const textarea = event.target;
236
294
  const start = textarea.selectionStart;
237
295
  const end = textarea.selectionEnd;
238
- inputMessage.value = inputMessage.value.substring(0, start) + "\n" + inputMessage.value.substring(end);
296
+ userInput.value = userInput.value.substring(0, start) + "\n" + userInput.value.substring(end);
239
297
  // 将光标移动到新插入的换行符之后
240
298
  nextTick(() => {
241
299
  textarea.selectionStart = textarea.selectionEnd = start + 1;
@@ -247,8 +305,7 @@ const handleKeydown = (event) => {
247
305
  }
248
306
  }
249
307
  };
250
-
251
- // 滚动到底部
308
+ // 辅助函数: 滚动到底部
252
309
  const scrollToBottom = async () => {
253
310
  await nextTick();
254
311
  if (messageListRef.value) {
@@ -257,7 +314,7 @@ const scrollToBottom = async () => {
257
314
  };
258
315
 
259
316
  watch(
260
- () => messages.value,
317
+ () => messageList.value,
261
318
  () => {
262
319
  scrollToBottom();
263
320
  },
@@ -285,62 +342,72 @@ defineExpose({
285
342
  :modal="false"
286
343
  :modal-penetrable="true"
287
344
  >
288
- <div class="chat-container">
345
+ <div class="ai-dialog-body">
289
346
  <div
290
347
  ref="messageListRef"
291
348
  class="message-list"
292
349
  >
293
350
  <div
294
- v-for="(message, index) in messages"
351
+ v-for="(message, index) in messageList"
295
352
  :key="index"
296
- class="message-item-wrapper"
353
+ :class="message.role"
354
+ class="message-item"
297
355
  >
298
- <div
299
- class="message-item"
300
- :class="message.role"
301
- >
302
- <template v-if="message.content">
303
- <div class="avatar">
304
- <el-avatar
305
- :size="32"
306
- :icon="message.role === 'user' ? UserFilled : Service"
307
- />
356
+ <template v-if="message.content">
357
+ <!-- 消息头像 -->
358
+ <div class="avatar">
359
+ <el-avatar
360
+ :size="32"
361
+ :icon="message.role === 'user' ? UserFilled : Service"
362
+ />
363
+ </div>
364
+ <div class="message-content">
365
+ <!-- 判断是否为可JSON序列化的数据 -->
366
+ <div
367
+ v-if="isJSONSerializable(message.content)"
368
+ class="message-json"
369
+ v-html="renderJSONContent(formatJSONContent(message.content))"
370
+ ></div>
371
+ <!-- 普通文本展示 -->
372
+ <div
373
+ v-else
374
+ class="message-text"
375
+ >
376
+ {{ message.content }}
308
377
  </div>
309
- <div class="message-content">
310
- <div class="message-text">{{ message.content }}</div>
311
- <div class="message-createTime">{{ message.createTime }}</div>
312
- <!-- 反馈按钮(仅AI侧展示) -->
313
- <template v-if="message.role === 'assistant'">
314
- <template v-if="message.showFeedback && !message.hasFeedback">
315
- <div class="message-createTime">请问对本轮查询结果是否满意?</div>
316
- <div class="feedback-buttons">
317
- <button
318
- class="feedback-btn satisfied-btn"
319
- @click="handleFeedbackAction('satisfied', index)"
320
- >
321
- <span class="btn-emoji">👍</span>
322
- <span class="btn-text">满意</span>
323
- </button>
324
- <button
325
- class="feedback-btn unsatisfied-btn"
326
- @click="handleFeedbackAction('open', index)"
327
- >
328
- <span class="btn-emoji">👎</span>
329
- <span class="btn-text">不满意</span>
330
- </button>
331
- </div>
332
- </template>
333
- <template v-if="message.showFeedback && message.hasFeedback">
334
- <div class="message-createTime">感谢您进行的评价反馈</div>
335
- </template>
378
+ <div class="message-createTime">{{ message.createTime }}</div>
379
+ <!-- 反馈按钮(仅AI侧展示) -->
380
+ <template v-if="message.role === 'assistant'">
381
+ <template v-if="message.showFeedback && !message.hasFeedback">
382
+ <div class="message-createTime">请问对本轮查询结果是否满意?</div>
383
+ <div class="feedback-buttons">
384
+ <button
385
+ class="feedback-btn satisfied-btn"
386
+ @click="handleFeedbackAction('satisfied', index)"
387
+ >
388
+ <span class="btn-emoji">👍</span>
389
+ <span class="btn-text">满意</span>
390
+ </button>
391
+ <button
392
+ class="feedback-btn unsatisfied-btn"
393
+ @click="handleFeedbackAction('open', index)"
394
+ >
395
+ <span class="btn-emoji">👎</span>
396
+ <span class="btn-text">不满意</span>
397
+ </button>
398
+ </div>
336
399
  </template>
337
- </div>
338
- </template>
339
- </div>
400
+ <template v-if="message.showFeedback && message.hasFeedback">
401
+ <div class="message-createTime">感谢您进行的评价反馈</div>
402
+ </template>
403
+ </template>
404
+ </div>
405
+ </template>
340
406
  </div>
341
407
 
408
+ <!-- AI首包响应思考Loading -->
342
409
  <div
343
- v-if="isThinking && !messages[messages.length - 1]?.content"
410
+ v-if="isThinking && !messageList[messageList.length - 1]?.content"
344
411
  class="message-item assistant"
345
412
  >
346
413
  <div class="avatar">
@@ -362,7 +429,7 @@ defineExpose({
362
429
  <div class="input-area">
363
430
  <el-input
364
431
  class="message-input"
365
- v-model="inputMessage"
432
+ v-model="userInput"
366
433
  type="textarea"
367
434
  :rows="4"
368
435
  :autosize="{ minRows: 2, maxRows: 4 }"
@@ -418,223 +485,245 @@ defineExpose({
418
485
  </template>
419
486
 
420
487
  <style lang="scss" scoped>
421
- /* 样式保持不变,和之前一样 */
422
488
  .ai-dialog {
423
- :deep(.el-dialog) {
424
- border-radius: 24px;
425
- background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
426
- box-shadow: 0 20px 35px -12px rgba(0, 0, 0, 0.15);
427
- overflow: hidden;
428
-
429
- .el-dialog__header {
430
- padding: 20px 24px 12px;
431
- margin: 0;
432
- border-bottom: 1px solid rgba(102, 126, 234, 0.1);
433
- background: rgba(255, 255, 255, 0.8);
434
- backdrop-filter: blur(10px);
435
-
436
- .el-dialog__title {
437
- font-size: 18px;
438
- font-weight: 600;
439
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
440
- background-clip: text;
441
- -webkit-background-clip: text;
442
- -webkit-text-fill-color: transparent;
489
+ .ai-dialog-body {
490
+ display: flex;
491
+ flex-direction: column;
492
+ height: 480px;
493
+ background: transparent;
494
+ .message-list {
495
+ flex: 1;
496
+ overflow-y: auto;
497
+ padding: 20px 24px;
498
+ &::-webkit-scrollbar {
499
+ width: 6px;
443
500
  }
444
- }
445
-
446
- .el-dialog__body {
447
- padding: 0;
448
- }
449
-
450
- .el-dialog__footer {
451
- display: none;
452
- }
453
- }
454
- }
455
-
456
- .chat-container {
457
- display: flex;
458
- flex-direction: column;
459
- height: 480px;
460
- background: transparent;
461
- }
462
-
463
- .message-list {
464
- flex: 1;
465
- overflow-y: auto;
466
- padding: 20px 24px;
467
- scroll-behavior: smooth;
468
-
469
- &::-webkit-scrollbar {
470
- width: 6px;
471
- }
472
-
473
- &::-webkit-scrollbar-track {
474
- background: rgba(0, 0, 0, 0.05);
475
- border-radius: 3px;
476
- }
477
-
478
- &::-webkit-scrollbar-thumb {
479
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
480
- border-radius: 3px;
481
-
482
- &:hover {
483
- background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
484
- }
485
- }
486
- }
487
-
488
- .message-item-wrapper {
489
- margin-bottom: 20px;
490
- }
491
-
492
- .message-item {
493
- display: flex;
494
- animation: fadeInUp 0.3s ease-out;
495
-
496
- &.user {
497
- flex-direction: row-reverse;
498
-
499
- .avatar {
500
- margin-left: 12px;
501
- margin-right: 0;
502
- }
503
-
504
- .message-content {
505
- align-items: flex-end;
506
-
507
- .message-text {
508
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
509
- color: white;
510
- border-radius: 18px 18px 4px 18px;
501
+ &::-webkit-scrollbar-track {
502
+ background: rgba(0, 0, 0, 0.05);
503
+ border-radius: 3px;
511
504
  }
505
+ &::-webkit-scrollbar-thumb {
506
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
507
+ border-radius: 3px;
512
508
 
513
- .message-createTime {
514
- text-align: right;
509
+ &:hover {
510
+ background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
511
+ }
515
512
  }
516
- }
517
- }
518
-
519
- &.assistant {
520
- .avatar {
521
- margin-right: 12px;
522
- }
523
-
524
- .message-content {
525
- align-items: flex-start;
526
-
527
- .message-text {
528
- background: white;
529
- color: #2c3e50;
530
- border-radius: 18px 18px 18px 4px;
531
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
532
- border: 1px solid rgba(102, 126, 234, 0.1);
513
+ // 消息公共样式
514
+ .message-item {
515
+ display: flex;
516
+ animation: fadeInUp 0.3s ease-out;
517
+ margin-bottom: 20px;
518
+ .avatar {
519
+ flex-shrink: 0;
520
+ :deep(.el-avatar) {
521
+ background: linear-gradient(135deg, #f0f2ff 0%, #e8ecff 100%);
522
+ color: #667eea;
523
+ svg {
524
+ width: 18px;
525
+ height: 18px;
526
+ }
527
+ }
528
+ }
529
+ .message-content {
530
+ display: flex;
531
+ flex-direction: column;
532
+ max-width: 70%;
533
+ .message-json,
534
+ .message-text {
535
+ padding: 10px 16px;
536
+ font-size: 14px;
537
+ line-height: 1.5;
538
+ word-wrap: break-word;
539
+ white-space: pre-wrap;
540
+ }
541
+ .message-createTime {
542
+ font-size: 11px;
543
+ color: #9ca3af;
544
+ margin-top: 6px;
545
+ }
546
+ .feedback-buttons {
547
+ display: flex;
548
+ gap: 12px;
549
+ margin-top: 12px;
550
+ .feedback-btn {
551
+ display: flex;
552
+ align-items: center;
553
+ gap: 6px;
554
+ padding: 4px 10px;
555
+ border: none;
556
+ border-radius: 20px;
557
+ font-size: 13px;
558
+ font-weight: 500;
559
+ cursor: pointer;
560
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
561
+ background: rgba(255, 255, 255, 0.9);
562
+ backdrop-filter: blur(10px);
563
+
564
+ .btn-emoji {
565
+ font-size: 16px;
566
+ transition: transform 0.2s ease;
567
+ }
568
+ .btn-text {
569
+ font-size: 13px;
570
+ }
571
+ &:hover {
572
+ transform: translateY(-2px);
573
+ .btn-emoji {
574
+ transform: scale(1.1);
575
+ }
576
+ }
577
+ &:active {
578
+ transform: translateY(0);
579
+ }
580
+ }
581
+ .satisfied-btn {
582
+ background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
583
+ color: #1890ff;
584
+ border: 1px solid rgba(24, 144, 255, 0.2);
585
+ box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1);
586
+
587
+ &:hover {
588
+ background: linear-gradient(135deg, #e6f7ff 0%, #bae7ff 100%);
589
+ border-color: #1890ff;
590
+ box-shadow: 0 4px 12px rgba(24, 144, 255, 0.2);
591
+ }
592
+ }
593
+ .unsatisfied-btn {
594
+ background: linear-gradient(135deg, #fff1f0 0%, #ffe7e5 100%);
595
+ color: #ff4d4f;
596
+ border: 1px solid rgba(255, 77, 79, 0.2);
597
+ box-shadow: 0 2px 8px rgba(255, 77, 79, 0.1);
598
+
599
+ &:hover {
600
+ background: linear-gradient(135deg, #ffe7e5 0%, #ffccc7 100%);
601
+ border-color: #ff4d4f;
602
+ box-shadow: 0 4px 12px rgba(255, 77, 79, 0.2);
603
+ }
604
+ }
605
+ }
606
+ }
533
607
  }
534
- }
535
- }
536
-
537
- .avatar {
538
- flex-shrink: 0;
539
-
540
- :deep(.el-avatar) {
541
- background: linear-gradient(135deg, #f0f2ff 0%, #e8ecff 100%);
542
- color: #667eea;
543
-
544
- svg {
545
- width: 18px;
546
- height: 18px;
608
+ // 用户消息
609
+ .user {
610
+ flex-direction: row-reverse;
611
+ .avatar {
612
+ margin-left: 12px;
613
+ margin-right: 0;
614
+ }
615
+ .message-content {
616
+ align-items: flex-end;
617
+ .message-text {
618
+ color: white;
619
+ border-radius: 18px 18px 4px 18px;
620
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
621
+ }
622
+ .message-createTime {
623
+ text-align: right;
624
+ }
625
+ }
626
+ }
627
+ // AI消息
628
+ .assistant {
629
+ .avatar {
630
+ margin-right: 12px;
631
+ }
632
+ .message-content {
633
+ align-items: flex-start;
634
+ .message-text {
635
+ background: white;
636
+ color: #2c3e50;
637
+ border-radius: 18px 18px 18px 4px;
638
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
639
+ border: 1px solid rgba(102, 126, 234, 0.1);
640
+ }
641
+ .message-json {
642
+ width: 100%;
643
+ background: white;
644
+ color: #2c3e50;
645
+ border-radius: 18px 18px 18px 4px;
646
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
647
+ border: 1px solid rgba(102, 126, 234, 0.1);
648
+ :deep(.parsed-conditions) {
649
+ margin-top: 10px;
650
+ .parsed-conditions-item {
651
+ text-align: center;
652
+ color: #f56c6c;
653
+ margin-bottom: 10px;
654
+ padding: 2px;
655
+ background-color: rgb(253, 226, 226);
656
+ border-radius: 4px;
657
+ }
658
+ }
659
+ }
660
+ }
547
661
  }
548
662
  }
549
- }
663
+ .input-area {
664
+ padding: 16px 24px 24px;
665
+ border-top: 1px solid rgba(102, 126, 234, 0.1);
666
+ background: rgba(255, 255, 255, 0.9);
667
+ backdrop-filter: blur(10px);
550
668
 
551
- .message-content {
552
- display: flex;
553
- flex-direction: column;
554
- max-width: 70%;
555
-
556
- .message-text {
557
- padding: 10px 16px;
558
- font-size: 14px;
559
- line-height: 1.5;
560
- word-wrap: break-word;
561
- white-space: pre-wrap;
562
- }
669
+ .message-input {
670
+ :deep(.el-textarea__inner) {
671
+ border-radius: 16px;
672
+ border: 1px solid rgba(102, 126, 234, 0.2);
673
+ background: #ffffff;
674
+ font-size: 14px;
675
+ padding: 12px 16px;
676
+ transition: all 0.3s ease;
677
+
678
+ &:focus {
679
+ border-color: #667eea;
680
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
681
+ }
563
682
 
564
- .message-createTime {
565
- font-size: 11px;
566
- color: #9ca3af;
567
- margin-top: 6px;
568
- padding: 0 4px;
569
- }
683
+ &::placeholder {
684
+ color: #cbd5e0;
685
+ }
686
+ }
687
+ }
570
688
 
571
- .feedback-buttons {
572
- display: flex;
573
- gap: 12px;
574
- margin-top: 12px;
575
- .feedback-btn {
689
+ .input-actions {
576
690
  display: flex;
691
+ justify-content: space-between;
577
692
  align-items: center;
578
- gap: 6px;
579
- padding: 4px 10px;
580
- border: none;
581
- border-radius: 20px;
582
- font-size: 13px;
583
- font-weight: 500;
584
- cursor: pointer;
585
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
586
- background: rgba(255, 255, 255, 0.9);
587
- backdrop-filter: blur(10px);
588
-
589
- .btn-emoji {
590
- font-size: 16px;
591
- transition: transform 0.2s ease;
592
- }
693
+ margin-top: 12px;
593
694
 
594
- .btn-text {
595
- font-size: 13px;
596
- }
597
-
598
- &:hover {
599
- transform: translateY(-2px);
695
+ .input-hint {
696
+ font-size: 12px;
697
+ color: #9ca3af;
600
698
 
601
- .btn-emoji {
602
- transform: scale(1.1);
699
+ span {
700
+ background: rgba(102, 126, 234, 0.1);
701
+ padding: 4px 8px;
702
+ border-radius: 12px;
703
+ font-size: 11px;
603
704
  }
604
705
  }
605
706
 
606
- &:active {
607
- transform: translateY(0);
608
- }
609
- }
610
- .satisfied-btn {
611
- background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
612
- color: #1890ff;
613
- border: 1px solid rgba(24, 144, 255, 0.2);
614
- box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1);
707
+ .send-btn {
708
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
709
+ border: none;
710
+ padding: 8px 20px;
711
+ font-weight: 500;
712
+ transition: all 0.3s ease;
615
713
 
616
- &:hover {
617
- background: linear-gradient(135deg, #e6f7ff 0%, #bae7ff 100%);
618
- border-color: #1890ff;
619
- box-shadow: 0 4px 12px rgba(24, 144, 255, 0.2);
620
- }
621
- }
622
- .unsatisfied-btn {
623
- background: linear-gradient(135deg, #fff1f0 0%, #ffe7e5 100%);
624
- color: #ff4d4f;
625
- border: 1px solid rgba(255, 77, 79, 0.2);
626
- box-shadow: 0 2px 8px rgba(255, 77, 79, 0.1);
714
+ &:hover {
715
+ transform: translateY(-2px);
716
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
717
+ }
627
718
 
628
- &:hover {
629
- background: linear-gradient(135deg, #ffe7e5 0%, #ffccc7 100%);
630
- border-color: #ff4d4f;
631
- box-shadow: 0 4px 12px rgba(255, 77, 79, 0.2);
719
+ &:active {
720
+ transform: translateY(0);
721
+ }
632
722
  }
633
723
  }
634
724
  }
635
725
  }
636
726
  }
637
-
638
727
  .typing-indicator {
639
728
  display: flex;
640
729
  gap: 4px;
@@ -654,76 +743,11 @@ defineExpose({
654
743
  &:nth-child(1) {
655
744
  animation-delay: -0.32s;
656
745
  }
657
-
658
746
  &:nth-child(2) {
659
747
  animation-delay: -0.16s;
660
748
  }
661
749
  }
662
750
  }
663
-
664
- .input-area {
665
- padding: 16px 24px 24px;
666
- border-top: 1px solid rgba(102, 126, 234, 0.1);
667
- background: rgba(255, 255, 255, 0.9);
668
- backdrop-filter: blur(10px);
669
-
670
- .message-input {
671
- :deep(.el-textarea__inner) {
672
- border-radius: 16px;
673
- border: 1px solid rgba(102, 126, 234, 0.2);
674
- background: #ffffff;
675
- font-size: 14px;
676
- padding: 12px 16px;
677
- transition: all 0.3s ease;
678
-
679
- &:focus {
680
- border-color: #667eea;
681
- box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
682
- }
683
-
684
- &::placeholder {
685
- color: #cbd5e0;
686
- }
687
- }
688
- }
689
-
690
- .input-actions {
691
- display: flex;
692
- justify-content: space-between;
693
- align-items: center;
694
- margin-top: 12px;
695
-
696
- .input-hint {
697
- font-size: 12px;
698
- color: #9ca3af;
699
-
700
- span {
701
- background: rgba(102, 126, 234, 0.1);
702
- padding: 4px 8px;
703
- border-radius: 12px;
704
- font-size: 11px;
705
- }
706
- }
707
-
708
- .send-btn {
709
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
710
- border: none;
711
- padding: 8px 20px;
712
- font-weight: 500;
713
- transition: all 0.3s ease;
714
-
715
- &:hover {
716
- transform: translateY(-2px);
717
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
718
- }
719
-
720
- &:active {
721
- transform: translateY(0);
722
- }
723
- }
724
- }
725
- }
726
-
727
751
  .feedback-dialog-content {
728
752
  text-align: center;
729
753
  padding: 12px 0;
@@ -752,7 +776,6 @@ defineExpose({
752
776
  }
753
777
  }
754
778
  }
755
-
756
779
  @keyframes fadeInUp {
757
780
  from {
758
781
  opacity: 0;