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.
- package/es/VarietyAiHelper.cjs +5 -5
- package/es/VarietyAiHelper.js +339 -270
- package/es/aiTools.js +59 -18
- package/es/style.css +1 -1
- package/lib/aiTools.js +59 -18
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +83 -83
- package/lib/{index-28225e49.js → index-00866046.js} +3523 -3454
- package/lib/{python-b13b7faa.js → python-a25c0b5b.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/packages/VarietyAiHelper/index.vue +374 -335
- package/public/aiTools.js +59 -18
|
@@ -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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
132
|
+
messageList.value[messageIndex].hasFeedback = true;
|
|
86
133
|
break;
|
|
87
134
|
}
|
|
88
135
|
// 自动提交记录跟踪日志
|
|
89
136
|
case "default": {
|
|
90
|
-
const message =
|
|
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 =
|
|
154
|
+
const content = userInput.value.trim();
|
|
109
155
|
if (!content) return ElMessage.warning("请输入消息内容");
|
|
110
156
|
if (isSending.value) return;
|
|
111
157
|
|
|
112
158
|
// 记录用户消息
|
|
113
|
-
|
|
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
|
-
|
|
164
|
+
userInput.value = "";
|
|
119
165
|
await scrollToBottom();
|
|
120
166
|
|
|
121
167
|
// 创建AI消息占位符,记录对应的用户输入
|
|
122
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
}
|
|
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",
|
|
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
|
-
|
|
258
|
+
messageList.value.pop();
|
|
185
259
|
// 添加错误提示消息
|
|
186
|
-
|
|
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",
|
|
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
|
-
//
|
|
277
|
+
// 辅助函数: Ctrl+Enter 换行,Enter 发送
|
|
204
278
|
const handleKeydown = (event) => {
|
|
205
|
-
if (event.key ===
|
|
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
|
-
|
|
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
|
-
() =>
|
|
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="
|
|
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
|
|
341
|
+
v-for="(message, index) in messageList"
|
|
269
342
|
:key="index"
|
|
270
|
-
class="message
|
|
343
|
+
:class="message.role"
|
|
344
|
+
class="message-item"
|
|
271
345
|
>
|
|
272
|
-
<
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
<
|
|
289
|
-
<
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
>
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
>
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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 && !
|
|
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="
|
|
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
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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
|
-
|
|
488
|
-
|
|
499
|
+
&:hover {
|
|
500
|
+
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
|
501
|
+
}
|
|
489
502
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
673
|
+
&::placeholder {
|
|
674
|
+
color: #cbd5e0;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
544
678
|
|
|
545
|
-
|
|
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
|
-
|
|
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
|
-
.
|
|
569
|
-
font-size:
|
|
570
|
-
|
|
685
|
+
.input-hint {
|
|
686
|
+
font-size: 12px;
|
|
687
|
+
color: #9ca3af;
|
|
571
688
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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>
|