st-comp 0.0.254 → 0.0.256

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