st-comp 0.0.253 → 0.0.255

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "st-comp",
3
3
  "public": true,
4
- "version": "0.0.253",
4
+ "version": "0.0.255",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -77,7 +77,7 @@ const handleFeedbackAction = async (action, messageIndex) => {
77
77
  type: 2,
78
78
  resTime: message.resTime,
79
79
  createTime: message.createTime,
80
- firstPackageTime: message.firstPackageTime
80
+ firstPackageTime: message.firstPackageTime,
81
81
  };
82
82
  await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
83
83
  ElMessage.success("感谢您的反馈!我们将持续跟踪并进行优化");
@@ -96,7 +96,7 @@ const handleFeedbackAction = async (action, messageIndex) => {
96
96
  type: null,
97
97
  resTime: message.resTime,
98
98
  createTime: message.createTime,
99
- firstPackageTime: message.firstPackageTime
99
+ firstPackageTime: message.firstPackageTime,
100
100
  };
101
101
  await stConfig.request.post("/alarm/deliversign/addVarietyAiHelperLog", params);
102
102
  }
@@ -144,7 +144,31 @@ const sendMessage = async () => {
144
144
  apiKey,
145
145
  value: content,
146
146
  callback: (type, data) => {
147
- if (type === "message") {
147
+ // 百炼应用错误
148
+ if (type === "error") {
149
+ isThinking.value = false;
150
+ isSending.value = false;
151
+
152
+ // 移除占位的AI消息
153
+ messages.value.pop();
154
+
155
+ // 添加错误提示消息
156
+ messages.value.push({
157
+ role: "assistant",
158
+ userContent: content,
159
+ content: `❌ ${data}`,
160
+ showFeedback: false,
161
+ hasFeedback: false,
162
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
163
+ resTime: new Date().getTime() - resTime,
164
+ firstPackageTime: 0,
165
+ });
166
+ handleFeedbackAction("default", messages.value.length - 1);
167
+ scrollToBottom();
168
+ return;
169
+ }
170
+ // 流式输出(正常)
171
+ else if (type === "message") {
148
172
  fullResponse += data;
149
173
  // 直接更新最后一条AI消息
150
174
  const lastMessage = messages.value[messages.value.length - 1];
@@ -156,12 +180,14 @@ const sendMessage = async () => {
156
180
  if (lastMessage.firstPackageTime === 0) {
157
181
  lastMessage.firstPackageTime = new Date().getTime() - resTime;
158
182
  }
159
- } else if (type === "finish") {
183
+ }
184
+ // 流式输出(完毕)
185
+ else if (type === "finish") {
160
186
  isThinking.value = false;
161
187
  isSending.value = false;
188
+ const lastMessage = messages.value[messages.value.length - 1];
162
189
 
163
190
  // 显示反馈按钮
164
- const lastMessage = messages.value[messages.value.length - 1];
165
191
  if (lastMessage && lastMessage.role === "assistant") {
166
192
  lastMessage.showFeedback = true;
167
193
  lastMessage.resTime = new Date().getTime() - resTime;
@@ -186,7 +212,7 @@ const sendMessage = async () => {
186
212
  messages.value.push({
187
213
  role: "assistant",
188
214
  userContent: content,
189
- content: "抱歉,AI服务响应异常,请稍后重试。",
215
+ content: "抱歉,AI服务响应异常,请稍后重试。",
190
216
  showFeedback: true,
191
217
  hasFeedback: false,
192
218
  createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
@@ -199,6 +225,29 @@ const sendMessage = async () => {
199
225
  isThinking.value = false;
200
226
  }
201
227
  };
228
+
229
+ // 处理键盘事件:Ctrl+Enter 换行,Enter 发送
230
+ const handleKeydown = (event) => {
231
+ if (event.key === "Enter") {
232
+ if (event.ctrlKey) {
233
+ // Ctrl + Enter: 插入换行符
234
+ event.preventDefault();
235
+ const textarea = event.target;
236
+ const start = textarea.selectionStart;
237
+ const end = textarea.selectionEnd;
238
+ inputMessage.value = inputMessage.value.substring(0, start) + "\n" + inputMessage.value.substring(end);
239
+ // 将光标移动到新插入的换行符之后
240
+ nextTick(() => {
241
+ textarea.selectionStart = textarea.selectionEnd = start + 1;
242
+ });
243
+ } else {
244
+ // 单独的 Enter: 发送消息
245
+ event.preventDefault();
246
+ sendMessage();
247
+ }
248
+ }
249
+ };
250
+
202
251
  // 滚动到底部
203
252
  const scrollToBottom = async () => {
204
253
  await nextTick();
@@ -317,12 +366,12 @@ defineExpose({
317
366
  type="textarea"
318
367
  :rows="4"
319
368
  :autosize="{ minRows: 2, maxRows: 4 }"
320
- placeholder="输入您想查询的品种条件..."
321
- @keydown.ctrl.enter="sendMessage"
369
+ placeholder="输入您想查询的品种条件... (Ctrl+Enter换行,Enter发送)"
370
+ @keydown="handleKeydown"
322
371
  />
323
372
  <div class="input-actions">
324
373
  <div class="input-hint">
325
- <span>Ctrl + Enter 发送</span>
374
+ <span>Enter 发送 | Ctrl + Enter 换行</span>
326
375
  </div>
327
376
  <el-button
328
377
  class="send-btn"
package/public/aiTools.js CHANGED
@@ -27,7 +27,7 @@ export const sendToBaiLianAppNonStreaming = async ({ appId, apiKey, value }) =>
27
27
  throw error;
28
28
  }
29
29
  };
30
- // 流式返回
30
+ // 流式返回 - 支持错误处理
31
31
  export const sendToBaiLianAppStreaming = async ({ appId, apiKey, value, callback }) => {
32
32
  try {
33
33
  const response = await fetch(`https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`, {
@@ -43,13 +43,17 @@ export const sendToBaiLianAppStreaming = async ({ appId, apiKey, value, callback
43
43
  "X-DashScope-SSE": "enable",
44
44
  },
45
45
  });
46
-
47
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
48
-
46
+
47
+ if (!response.ok) {
48
+ callback("error", `HTTP ${response.status}: ${response.statusText}`);
49
+ return;
50
+ }
51
+
49
52
  const reader = response.body.getReader();
50
53
  const decoder = new TextDecoder();
51
54
  let buffer = "";
52
-
55
+ let currentEvent = null; // 记录当前 event 类型
56
+
53
57
  while (true) {
54
58
  const { done, value } = await reader.read();
55
59
  if (done) {
@@ -60,28 +64,48 @@ export const sendToBaiLianAppStreaming = async ({ appId, apiKey, value, callback
60
64
  callback("finish", "");
61
65
  break;
62
66
  }
63
-
67
+
64
68
  buffer += decoder.decode(value, { stream: true });
65
-
69
+
66
70
  let newlineIndex;
67
71
  while ((newlineIndex = buffer.indexOf("\n")) !== -1) {
68
72
  const line = buffer.substring(0, newlineIndex).trim();
69
73
  buffer = buffer.substring(newlineIndex + 1);
70
-
74
+
75
+ // 处理 event: 行(错误类型)
76
+ if (line.startsWith("event:")) {
77
+ currentEvent = line.substring(6).trim();
78
+ continue;
79
+ }
80
+
81
+ // 处理 data: 行
71
82
  if (line.startsWith("data:")) {
72
- const data = line.substring(5).trim();
73
- if (data && data !== "[DONE]") {
83
+ const dataStr = line.substring(5).trim();
84
+
85
+ // 检查是否是错误响应
86
+ if (currentEvent === "error" || (dataStr && dataStr.startsWith("{"))) {
74
87
  try {
75
- const parsed = JSON.parse(data);
88
+ const parsed = JSON.parse(dataStr);
89
+
90
+ // 处理错误响应
91
+ if (parsed.code || parsed.message || currentEvent === "error") {
92
+ const errorMsg = parsed.message || parsed.code || "未知错误";
93
+ callback("error", `百炼服务端错误: ${errorMsg}`);
94
+ return; // 终止流式处理
95
+ }
96
+
97
+ // 正常响应:提取 text
76
98
  const text = parsed?.output?.text;
77
99
  if (text && callback) {
78
100
  callback("message", text);
79
101
  }
80
102
  } catch (e) {
81
- // 可能是部分数据,继续等待
82
- console.debug("等待完整数据...");
103
+ console.debug("JSON 解析失败:", dataStr);
83
104
  }
84
105
  }
106
+
107
+ // 重置 event 类型
108
+ currentEvent = null;
85
109
  }
86
110
  }
87
111
  }
@@ -92,18 +116,35 @@ export const sendToBaiLianAppStreaming = async ({ appId, apiKey, value, callback
92
116
  };
93
117
 
94
118
  // 辅助函数:处理缓冲区剩余数据
95
- function tryProcessBuffer(buffer, callback) {
119
+ const tryProcessBuffer = (buffer, callback) => {
96
120
  const lines = buffer.split("\n");
121
+ let currentEvent = null;
122
+
97
123
  for (const line of lines) {
124
+ if (line.startsWith("event:")) {
125
+ currentEvent = line.substring(6).trim();
126
+ continue;
127
+ }
128
+
98
129
  if (line.startsWith("data:")) {
99
- const data = line.substring(5).trim();
100
- if (data && data !== "[DONE]") {
130
+ const dataStr = line.substring(5).trim();
131
+ if (dataStr && dataStr !== "[DONE]") {
101
132
  try {
102
- const parsed = JSON.parse(data);
133
+ const parsed = JSON.parse(dataStr);
134
+
135
+ // 错误响应
136
+ if (currentEvent === "error" || parsed.code || parsed.message) {
137
+ const errorMsg = parsed.message || parsed.code || "未知错误";
138
+ callback("error", `百炼服务端错误: ${errorMsg}`);
139
+ return;
140
+ }
141
+
142
+ // 正常响应
103
143
  const text = parsed?.output?.text;
104
144
  if (text && callback) callback("message", text);
105
145
  } catch (e) {}
106
146
  }
147
+ currentEvent = null;
107
148
  }
108
149
  }
109
- }
150
+ };