st-comp 0.0.252 → 0.0.254
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 -4
- package/es/VarietyAiHelper.js +372 -218
- package/es/style.css +1 -1
- package/lib/bundle.js +1 -1
- package/lib/bundle.umd.cjs +173 -172
- package/lib/{index-d57eff69.js → index-28225e49.js} +20226 -20073
- package/lib/{python-fe790c5a.js → python-b13b7faa.js} +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/packages/VarietyAiHelper/index.vue +343 -82
- package/src/pages/VarietySearch/index.vue +11 -7
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
3
|
import { ElMessage } from "element-plus";
|
|
4
|
-
import {
|
|
4
|
+
import { getUserData } from "st-func";
|
|
5
|
+
import { inject, ref, nextTick, watch, reactive } from "vue";
|
|
5
6
|
import { sendToBaiLianAppStreaming } from "../../public/aiTools";
|
|
6
7
|
import { UserFilled, Service, Promotion } from "@element-plus/icons-vue";
|
|
7
8
|
|
|
9
|
+
const stConfig = inject("stConfig");
|
|
10
|
+
const userData = reactive(getUserData());
|
|
8
11
|
const emit = defineEmits(["callBack"]);
|
|
9
12
|
const props = defineProps({
|
|
10
13
|
defaultMessage: {
|
|
@@ -14,114 +17,211 @@ const props = defineProps({
|
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
const visible = ref(false);
|
|
17
|
-
const isSending = ref(false);
|
|
18
|
-
const isThinking = ref(false);
|
|
20
|
+
const isSending = ref(false);
|
|
21
|
+
const isThinking = ref(false);
|
|
19
22
|
|
|
20
|
-
// 消息列表
|
|
21
23
|
const messageListRef = ref(null);
|
|
22
|
-
const messages = ref([
|
|
24
|
+
const messages = ref([
|
|
25
|
+
{
|
|
26
|
+
role: "assistant", // AI-assistant, 用户-user
|
|
27
|
+
content: props.defaultMessage,
|
|
28
|
+
userContent: null,
|
|
29
|
+
showFeedback: false, // 是否展示反馈按钮(默认信息不用展示)
|
|
30
|
+
hasFeedback: false, // 是否已进行过反馈
|
|
31
|
+
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 消息发起时间
|
|
32
|
+
resTime: 0, // 响应总耗时
|
|
33
|
+
firstPackageTime: 0, // 首包响应耗时
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
23
36
|
const inputMessage = ref("");
|
|
24
37
|
|
|
25
|
-
//
|
|
26
|
-
const
|
|
27
|
-
const
|
|
38
|
+
// 反馈弹窗相关
|
|
39
|
+
const feedbackDialogVisible = ref(false);
|
|
40
|
+
const feedbackContent = ref("");
|
|
41
|
+
const feedbackMessageIndex = ref({}); // 当前点击要反馈的message的索引
|
|
42
|
+
|
|
43
|
+
// 反馈弹窗相关函数处理
|
|
44
|
+
const handleFeedbackAction = async (action, messageIndex) => {
|
|
45
|
+
switch (action) {
|
|
46
|
+
// 窗口: 提交(满意)
|
|
47
|
+
case "satisfied": {
|
|
48
|
+
const message = messages.value[messageIndex];
|
|
49
|
+
const params = {
|
|
50
|
+
userName: userData.username,
|
|
51
|
+
userContent: message.userContent,
|
|
52
|
+
aiContent: message.content,
|
|
53
|
+
type: 1,
|
|
54
|
+
createTime: message.createTime,
|
|
55
|
+
resTime: message.resTime,
|
|
56
|
+
firstPackageTime: message.firstPackageTime,
|
|
57
|
+
};
|
|
58
|
+
await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
|
|
59
|
+
ElMessage.success("感谢您的评价!");
|
|
60
|
+
messages.value[messageIndex].hasFeedback = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
// 窗口: 打开
|
|
64
|
+
case "open": {
|
|
65
|
+
feedbackMessageIndex.value = messageIndex;
|
|
66
|
+
feedbackDialogVisible.value = true;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
// 窗口: 提交(不满意)
|
|
70
|
+
case "unsatisfied": {
|
|
71
|
+
const message = messages.value[messageIndex];
|
|
72
|
+
const params = {
|
|
73
|
+
userName: userData.username,
|
|
74
|
+
userContent: message.userContent,
|
|
75
|
+
userSuggestion: feedbackContent.value,
|
|
76
|
+
aiContent: message.content,
|
|
77
|
+
type: 2,
|
|
78
|
+
resTime: message.resTime,
|
|
79
|
+
createTime: message.createTime,
|
|
80
|
+
firstPackageTime: message.firstPackageTime
|
|
81
|
+
};
|
|
82
|
+
await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
|
|
83
|
+
ElMessage.success("感谢您的反馈!我们将持续跟踪并进行优化");
|
|
84
|
+
feedbackDialogVisible.value = false;
|
|
85
|
+
messages.value[messageIndex].hasFeedback = true;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
// 自动提交记录跟踪日志
|
|
89
|
+
case "default": {
|
|
90
|
+
const message = messages.value[messageIndex];
|
|
91
|
+
const params = {
|
|
92
|
+
userName: userData.username,
|
|
93
|
+
userContent: message.userContent,
|
|
94
|
+
userSuggestion: feedbackContent.value,
|
|
95
|
+
aiContent: message.content,
|
|
96
|
+
type: null,
|
|
97
|
+
resTime: message.resTime,
|
|
98
|
+
createTime: message.createTime,
|
|
99
|
+
firstPackageTime: message.firstPackageTime
|
|
100
|
+
};
|
|
101
|
+
await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
28
105
|
|
|
29
106
|
// 发送消息
|
|
30
107
|
const sendMessage = async () => {
|
|
31
|
-
// 校验输入内容是否为空
|
|
32
108
|
const content = inputMessage.value.trim();
|
|
33
109
|
if (!content) return ElMessage.warning("请输入消息内容");
|
|
34
|
-
// 校验是否正在处理消息
|
|
35
110
|
if (isSending.value) return;
|
|
36
111
|
|
|
37
112
|
// 记录用户消息
|
|
38
113
|
messages.value.push({
|
|
39
114
|
role: "user",
|
|
40
|
-
time: dayjs().format("HH:mm"),
|
|
41
115
|
content: content,
|
|
116
|
+
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
42
117
|
});
|
|
43
118
|
inputMessage.value = "";
|
|
44
119
|
await scrollToBottom();
|
|
45
120
|
|
|
46
|
-
//
|
|
47
|
-
|
|
121
|
+
// 创建AI消息占位符,记录对应的用户输入
|
|
122
|
+
messages.value.push({
|
|
48
123
|
role: "assistant",
|
|
49
|
-
time: dayjs().format("HH:mm"),
|
|
50
124
|
content: "",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
125
|
+
userContent: content,
|
|
126
|
+
showFeedback: false,
|
|
127
|
+
hasFeedback: false,
|
|
128
|
+
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
129
|
+
resTime: 0,
|
|
130
|
+
firstPackageTime: 0,
|
|
131
|
+
});
|
|
55
132
|
await scrollToBottom();
|
|
56
133
|
|
|
57
|
-
// 发送请求至百炼应用AI(流式)
|
|
58
134
|
isSending.value = true;
|
|
59
135
|
isThinking.value = true;
|
|
60
|
-
|
|
136
|
+
|
|
61
137
|
let fullResponse = "";
|
|
62
|
-
|
|
138
|
+
let resTime = new Date().getTime();
|
|
63
139
|
try {
|
|
64
140
|
const appId = "9e54d112acfe4531bd1fc4fee8827fef";
|
|
65
141
|
const apiKey = "sk-d995eb26a4334bdeb2ccb4cbfaf51de8";
|
|
66
|
-
|
|
67
142
|
await sendToBaiLianAppStreaming({
|
|
68
143
|
appId,
|
|
69
144
|
apiKey,
|
|
70
145
|
value: content,
|
|
71
146
|
callback: (type, data) => {
|
|
72
147
|
if (type === "message") {
|
|
73
|
-
// 实时更新消息内容
|
|
74
148
|
fullResponse += data;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
149
|
+
// 直接更新最后一条AI消息
|
|
150
|
+
const lastMessage = messages.value[messages.value.length - 1];
|
|
151
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
152
|
+
lastMessage.content = fullResponse;
|
|
78
153
|
scrollToBottom();
|
|
79
154
|
}
|
|
155
|
+
// 记录首包响应耗时
|
|
156
|
+
if (lastMessage.firstPackageTime === 0) {
|
|
157
|
+
lastMessage.firstPackageTime = new Date().getTime() - resTime;
|
|
158
|
+
}
|
|
80
159
|
} else if (type === "finish") {
|
|
81
|
-
// 流式传输完成
|
|
82
160
|
isThinking.value = false;
|
|
83
161
|
isSending.value = false;
|
|
84
|
-
|
|
162
|
+
|
|
163
|
+
// 显示反馈按钮
|
|
164
|
+
const lastMessage = messages.value[messages.value.length - 1];
|
|
165
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
166
|
+
lastMessage.showFeedback = true;
|
|
167
|
+
lastMessage.resTime = new Date().getTime() - resTime;
|
|
168
|
+
handleFeedbackAction("default", messages.value.length - 1);
|
|
169
|
+
}
|
|
170
|
+
|
|
85
171
|
// 触发回调
|
|
86
172
|
try {
|
|
87
|
-
// 尝试解析完整的响应为JSON
|
|
88
173
|
const jsonResponse = JSON.parse(fullResponse);
|
|
89
174
|
emit("callBack", jsonResponse);
|
|
90
175
|
} catch (error) {
|
|
91
|
-
// 如果不是JSON格式,直接返回文本
|
|
92
176
|
emit("callBack", fullResponse);
|
|
93
177
|
}
|
|
94
|
-
|
|
95
|
-
// 清空当前消息引用
|
|
96
|
-
currentAssistantMessage.value = null;
|
|
97
|
-
currentAssistantIndex.value = -1;
|
|
98
178
|
}
|
|
99
|
-
}
|
|
179
|
+
},
|
|
100
180
|
});
|
|
101
181
|
} catch (error) {
|
|
102
182
|
ElMessage.error(`AI响应异常: ${error}`);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// 如果出错,移除占位消息并显示错误
|
|
106
|
-
if (currentAssistantIndex.value !== -1) {
|
|
107
|
-
messages.value.splice(currentAssistantIndex.value, 1);
|
|
108
|
-
currentAssistantMessage.value = null;
|
|
109
|
-
currentAssistantIndex.value = -1;
|
|
110
|
-
}
|
|
111
|
-
|
|
183
|
+
// 移除占位的AI消息
|
|
184
|
+
messages.value.pop();
|
|
112
185
|
// 添加错误提示消息
|
|
113
186
|
messages.value.push({
|
|
114
187
|
role: "assistant",
|
|
115
|
-
|
|
188
|
+
userContent: content,
|
|
116
189
|
content: "抱歉,AI服务响应异常,请稍后重试。",
|
|
190
|
+
showFeedback: true,
|
|
191
|
+
hasFeedback: false,
|
|
192
|
+
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
|
193
|
+
resTime: new Date().getTime() - resTime,
|
|
194
|
+
firstPackageTime: 0,
|
|
117
195
|
});
|
|
196
|
+
handleFeedbackAction("default", messages.value.length - 1);
|
|
118
197
|
await scrollToBottom();
|
|
119
|
-
|
|
120
198
|
isSending.value = false;
|
|
121
199
|
isThinking.value = false;
|
|
122
200
|
}
|
|
123
201
|
};
|
|
124
202
|
|
|
203
|
+
// 处理键盘事件:Ctrl+Enter 换行,Enter 发送
|
|
204
|
+
const handleKeydown = (event) => {
|
|
205
|
+
if (event.key === 'Enter') {
|
|
206
|
+
if (event.ctrlKey) {
|
|
207
|
+
// Ctrl + Enter: 插入换行符
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
const textarea = event.target;
|
|
210
|
+
const start = textarea.selectionStart;
|
|
211
|
+
const end = textarea.selectionEnd;
|
|
212
|
+
inputMessage.value = inputMessage.value.substring(0, start) + '\n' + inputMessage.value.substring(end);
|
|
213
|
+
// 将光标移动到新插入的换行符之后
|
|
214
|
+
nextTick(() => {
|
|
215
|
+
textarea.selectionStart = textarea.selectionEnd = start + 1;
|
|
216
|
+
});
|
|
217
|
+
} else {
|
|
218
|
+
// 单独的 Enter: 发送消息
|
|
219
|
+
event.preventDefault();
|
|
220
|
+
sendMessage();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
125
225
|
// 滚动到底部
|
|
126
226
|
const scrollToBottom = async () => {
|
|
127
227
|
await nextTick();
|
|
@@ -130,14 +230,6 @@ const scrollToBottom = async () => {
|
|
|
130
230
|
}
|
|
131
231
|
};
|
|
132
232
|
|
|
133
|
-
onMounted(() => {
|
|
134
|
-
messages.value.push({
|
|
135
|
-
role: "assistant",
|
|
136
|
-
time: dayjs().format("HH:mm"),
|
|
137
|
-
content: props.defaultMessage,
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
233
|
watch(
|
|
142
234
|
() => messages.value,
|
|
143
235
|
() => {
|
|
@@ -145,11 +237,9 @@ watch(
|
|
|
145
237
|
},
|
|
146
238
|
{ deep: true },
|
|
147
239
|
);
|
|
148
|
-
|
|
149
240
|
defineExpose({
|
|
150
|
-
open: (
|
|
241
|
+
open: () => {
|
|
151
242
|
visible.value = true;
|
|
152
|
-
// 自动滚动到底部
|
|
153
243
|
nextTick(() => {
|
|
154
244
|
scrollToBottom();
|
|
155
245
|
});
|
|
@@ -170,7 +260,6 @@ defineExpose({
|
|
|
170
260
|
:modal-penetrable="true"
|
|
171
261
|
>
|
|
172
262
|
<div class="chat-container">
|
|
173
|
-
<!-- 消息列表 -->
|
|
174
263
|
<div
|
|
175
264
|
ref="messageListRef"
|
|
176
265
|
class="message-list"
|
|
@@ -178,26 +267,54 @@ defineExpose({
|
|
|
178
267
|
<div
|
|
179
268
|
v-for="(message, index) in messages"
|
|
180
269
|
:key="index"
|
|
181
|
-
class="message-item"
|
|
182
|
-
:class="message.role"
|
|
270
|
+
class="message-item-wrapper"
|
|
183
271
|
>
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
+
/>
|
|
282
|
+
</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>
|
|
310
|
+
</template>
|
|
311
|
+
</div>
|
|
312
|
+
</template>
|
|
313
|
+
</div>
|
|
196
314
|
</div>
|
|
197
315
|
|
|
198
|
-
<!-- AI 思考状态(仅在未开始接收流式消息时显示) -->
|
|
199
316
|
<div
|
|
200
|
-
v-if="isThinking && !
|
|
317
|
+
v-if="isThinking && !messages[messages.length - 1]?.content"
|
|
201
318
|
class="message-item assistant"
|
|
202
319
|
>
|
|
203
320
|
<div class="avatar">
|
|
@@ -215,7 +332,7 @@ defineExpose({
|
|
|
215
332
|
</div>
|
|
216
333
|
</div>
|
|
217
334
|
</div>
|
|
218
|
-
|
|
335
|
+
|
|
219
336
|
<div class="input-area">
|
|
220
337
|
<el-input
|
|
221
338
|
class="message-input"
|
|
@@ -223,12 +340,12 @@ defineExpose({
|
|
|
223
340
|
type="textarea"
|
|
224
341
|
:rows="4"
|
|
225
342
|
:autosize="{ minRows: 2, maxRows: 4 }"
|
|
226
|
-
placeholder="输入您想查询的品种条件..."
|
|
227
|
-
@keydown
|
|
343
|
+
placeholder="输入您想查询的品种条件... (Ctrl+Enter换行,Enter发送)"
|
|
344
|
+
@keydown="handleKeydown"
|
|
228
345
|
/>
|
|
229
346
|
<div class="input-actions">
|
|
230
347
|
<div class="input-hint">
|
|
231
|
-
<span>Ctrl + Enter
|
|
348
|
+
<span>Enter 发送 | Ctrl + Enter 换行</span>
|
|
232
349
|
</div>
|
|
233
350
|
<el-button
|
|
234
351
|
class="send-btn"
|
|
@@ -244,9 +361,38 @@ defineExpose({
|
|
|
244
361
|
</div>
|
|
245
362
|
</div>
|
|
246
363
|
</el-dialog>
|
|
364
|
+
|
|
365
|
+
<!-- 窗口: 反馈意见 -->
|
|
366
|
+
<el-dialog
|
|
367
|
+
v-model="feedbackDialogVisible"
|
|
368
|
+
title="📝 反馈意见"
|
|
369
|
+
width="400px"
|
|
370
|
+
>
|
|
371
|
+
<div class="feedback-dialog-content">
|
|
372
|
+
<div class="feedback-emoji">😟</div>
|
|
373
|
+
<p class="feedback-tip">很抱歉没能帮到您,请告诉我们哪里需要改进:</p>
|
|
374
|
+
<el-input
|
|
375
|
+
v-model="feedbackContent"
|
|
376
|
+
type="textarea"
|
|
377
|
+
:rows="4"
|
|
378
|
+
placeholder="[非必填]例如:回答不够准确、查询结果有误、界面体验不佳..."
|
|
379
|
+
/>
|
|
380
|
+
</div>
|
|
381
|
+
<template #footer>
|
|
382
|
+
<span class="dialog-footer">
|
|
383
|
+
<el-button @click="feedbackDialogVisible = false">取消</el-button>
|
|
384
|
+
<el-button
|
|
385
|
+
type="primary"
|
|
386
|
+
@click="handleFeedbackAction('unsatisfied', feedbackMessageIndex)"
|
|
387
|
+
>提交反馈</el-button
|
|
388
|
+
>
|
|
389
|
+
</span>
|
|
390
|
+
</template>
|
|
391
|
+
</el-dialog>
|
|
247
392
|
</template>
|
|
248
393
|
|
|
249
394
|
<style lang="scss" scoped>
|
|
395
|
+
/* 样式保持不变,和之前一样 */
|
|
250
396
|
.ai-dialog {
|
|
251
397
|
:deep(.el-dialog) {
|
|
252
398
|
border-radius: 24px;
|
|
@@ -280,12 +426,14 @@ defineExpose({
|
|
|
280
426
|
}
|
|
281
427
|
}
|
|
282
428
|
}
|
|
429
|
+
|
|
283
430
|
.chat-container {
|
|
284
431
|
display: flex;
|
|
285
432
|
flex-direction: column;
|
|
286
|
-
height:
|
|
433
|
+
height: 480px;
|
|
287
434
|
background: transparent;
|
|
288
435
|
}
|
|
436
|
+
|
|
289
437
|
.message-list {
|
|
290
438
|
flex: 1;
|
|
291
439
|
overflow-y: auto;
|
|
@@ -310,9 +458,13 @@ defineExpose({
|
|
|
310
458
|
}
|
|
311
459
|
}
|
|
312
460
|
}
|
|
461
|
+
|
|
462
|
+
.message-item-wrapper {
|
|
463
|
+
margin-bottom: 20px;
|
|
464
|
+
}
|
|
465
|
+
|
|
313
466
|
.message-item {
|
|
314
467
|
display: flex;
|
|
315
|
-
margin-bottom: 20px;
|
|
316
468
|
animation: fadeInUp 0.3s ease-out;
|
|
317
469
|
|
|
318
470
|
&.user {
|
|
@@ -332,7 +484,7 @@ defineExpose({
|
|
|
332
484
|
border-radius: 18px 18px 4px 18px;
|
|
333
485
|
}
|
|
334
486
|
|
|
335
|
-
.message-
|
|
487
|
+
.message-createTime {
|
|
336
488
|
text-align: right;
|
|
337
489
|
}
|
|
338
490
|
}
|
|
@@ -383,14 +535,80 @@ defineExpose({
|
|
|
383
535
|
white-space: pre-wrap;
|
|
384
536
|
}
|
|
385
537
|
|
|
386
|
-
.message-
|
|
538
|
+
.message-createTime {
|
|
387
539
|
font-size: 11px;
|
|
388
540
|
color: #9ca3af;
|
|
389
541
|
margin-top: 6px;
|
|
390
542
|
padding: 0 4px;
|
|
391
543
|
}
|
|
544
|
+
|
|
545
|
+
.feedback-buttons {
|
|
546
|
+
display: flex;
|
|
547
|
+
gap: 12px;
|
|
548
|
+
margin-top: 12px;
|
|
549
|
+
.feedback-btn {
|
|
550
|
+
display: flex;
|
|
551
|
+
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
|
+
}
|
|
567
|
+
|
|
568
|
+
.btn-text {
|
|
569
|
+
font-size: 13px;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
&:hover {
|
|
573
|
+
transform: translateY(-2px);
|
|
574
|
+
|
|
575
|
+
.btn-emoji {
|
|
576
|
+
transform: scale(1.1);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
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);
|
|
589
|
+
|
|
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);
|
|
601
|
+
|
|
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);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
392
609
|
}
|
|
393
610
|
}
|
|
611
|
+
|
|
394
612
|
.typing-indicator {
|
|
395
613
|
display: flex;
|
|
396
614
|
gap: 4px;
|
|
@@ -416,6 +634,7 @@ defineExpose({
|
|
|
416
634
|
}
|
|
417
635
|
}
|
|
418
636
|
}
|
|
637
|
+
|
|
419
638
|
.input-area {
|
|
420
639
|
padding: 16px 24px 24px;
|
|
421
640
|
border-top: 1px solid rgba(102, 126, 234, 0.1);
|
|
@@ -478,6 +697,36 @@ defineExpose({
|
|
|
478
697
|
}
|
|
479
698
|
}
|
|
480
699
|
}
|
|
700
|
+
|
|
701
|
+
.feedback-dialog-content {
|
|
702
|
+
text-align: center;
|
|
703
|
+
padding: 12px 0;
|
|
704
|
+
|
|
705
|
+
.feedback-emoji {
|
|
706
|
+
font-size: 48px;
|
|
707
|
+
margin-bottom: 16px;
|
|
708
|
+
animation: shake 0.5s ease-in-out;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.feedback-tip {
|
|
712
|
+
font-size: 14px;
|
|
713
|
+
color: #666;
|
|
714
|
+
margin-bottom: 20px;
|
|
715
|
+
line-height: 1.6;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
:deep(.el-textarea__inner) {
|
|
719
|
+
border-radius: 12px;
|
|
720
|
+
border: 1px solid rgba(102, 126, 234, 0.2);
|
|
721
|
+
font-size: 14px;
|
|
722
|
+
|
|
723
|
+
&:focus {
|
|
724
|
+
border-color: #667eea;
|
|
725
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
481
730
|
@keyframes fadeInUp {
|
|
482
731
|
from {
|
|
483
732
|
opacity: 0;
|
|
@@ -500,4 +749,16 @@ defineExpose({
|
|
|
500
749
|
opacity: 1;
|
|
501
750
|
}
|
|
502
751
|
}
|
|
752
|
+
@keyframes shake {
|
|
753
|
+
0%,
|
|
754
|
+
100% {
|
|
755
|
+
transform: translateX(0);
|
|
756
|
+
}
|
|
757
|
+
25% {
|
|
758
|
+
transform: translateX(-5px);
|
|
759
|
+
}
|
|
760
|
+
75% {
|
|
761
|
+
transform: translateX(5px);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
503
764
|
</style>
|
|
@@ -112,10 +112,14 @@ const actionState = (...args) => {
|
|
|
112
112
|
};
|
|
113
113
|
// 品种池参数解析助手的回调
|
|
114
114
|
const varietyAiHelperCallBack = (data) => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
if (typeof data === "string") {
|
|
116
|
+
return;
|
|
117
|
+
} else {
|
|
118
|
+
// 重置
|
|
119
|
+
varietySearchRef.value.reset();
|
|
120
|
+
// 参数合并
|
|
121
|
+
varietySearchData.value = { ...varietySearchData.value, ...data };
|
|
122
|
+
}
|
|
119
123
|
};
|
|
120
124
|
|
|
121
125
|
onMounted(async () => {
|
|
@@ -226,9 +230,9 @@ watch(
|
|
|
226
230
|
@actionState="actionState"
|
|
227
231
|
/>
|
|
228
232
|
<div>
|
|
229
|
-
<div style="font-size: 14px; display: flex
|
|
230
|
-
<pre style="flex: 1
|
|
231
|
-
<pre style="flex: 0.5
|
|
233
|
+
<div style="font-size: 14px; display: flex">
|
|
234
|
+
<pre style="flex: 1">前端组件参数: {{ varietySearchData }}</pre>
|
|
235
|
+
<pre style="flex: 0.5">后端接口参数: {{ apiParams }}</pre>
|
|
232
236
|
</div>
|
|
233
237
|
<el-table
|
|
234
238
|
ref="multipleTableRef"
|