af-mobile-client-vue3 1.6.19 → 1.6.21
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/.env +11 -11
- package/package.json +121 -121
- package/src/api/user/index.ts +50 -50
- package/src/components/common/MateChat/apiService.ts +310 -310
- package/src/components/data/OtherCharge/OtherChargeGroupModal.vue +542 -542
- package/src/components/data/UserDetail/api.ts +24 -24
- package/src/components/data/UserDetail/index.vue +660 -660
- package/src/components/data/XFormGroup/doc/UserForm.vue +102 -102
- package/src/components/data/step/index.vue +1975 -1975
- package/src/router/invoiceRoutes.ts +37 -37
- package/src/services/api/Login.ts +6 -6
- package/src/services/v3Api.ts +170 -170
- package/src/stores/modules/user.ts +441 -441
- package/src/types/platform.ts +194 -194
- package/src/utils/Storage.ts +124 -124
- package/src/utils/http/index.ts +228 -228
- package/src/utils/login/loginVerify.ts +317 -317
- package/src/views/SafeInspection/SecurityCertificate/AddDevice/index.vue +662 -661
- package/src/views/SafeInspection/SecurityCertificate/OverallHiddenDangers/index.vue +376 -376
- package/src/views/SafeInspection/SecurityCertificate/contractSign/index.vue +80 -80
- package/src/views/SafeInspection/SecurityCertificate/photoSignature/SignatureComponent/SignatureComponent.vue +285 -285
- package/src/views/SafeInspection/SecurityCertificate/photoSignature/index.vue +258 -258
- package/src/views/SafeInspection/SecurityCertificate/photoSignature/slots/QinHuaSignature.vue +82 -82
- package/src/views/SafeInspection/SecurityCertificate/slots/GasDevice.vue +132 -132
- package/src/views/SafeInspection/SecurityCertificate/userInfo/index.vue +1 -0
- package/src/views/SafeInspection/SecurityCertificate/userInfo/upaddress.vue +239 -239
- package/src/views/SafeInspection/SecurityFormItem/XMultiSelect/index.vue +194 -194
- package/src/views/SafeInspection/SecurityFormItem/XSignature/index.vue +68 -68
- package/src/views/SafeInspection/SecurityFormItem/index.vue +418 -418
- package/src/views/component/UserDetailView/UserDetailPage.vue +78 -78
- package/src/views/component/UserDetailView/index.vue +234 -234
- package/src/views/external/index.vue +158 -158
- package/src/views/user/employeeBinding/index.vue +392 -392
- package/src/views/user/register/index.vue +995 -995
- package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -21
- package/src/views/userRecords/CardReplacementRecords.vue +21 -21
- package/src/views/userRecords/ChangeRecords.vue +19 -19
- package/src/views/userRecords/CommandViewRecords.vue +20 -20
- package/src/views/userRecords/GasCompensationRecords.vue +20 -20
- package/src/views/userRecords/GasPurchaseRecords.vue +19 -19
- package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -21
- package/src/views/userRecords/MeterRecords.vue +20 -20
- package/src/views/userRecords/OperateRecords.vue +51 -51
- package/src/views/userRecords/OtherChargeRecords.vue +19 -19
- package/src/views/userRecords/PaymentRecords.vue +114 -114
- package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -19
- package/src/views/userRecords/RepairRecords.vue +19 -19
- package/src/views/userRecords/ReplacementRecords.vue +19 -19
- package/src/views/userRecords/SafetyRecords.vue +19 -19
- package/src/views/userRecords/TransactionRecords.vue +21 -21
- package/src/views/userRecords/TransferGasRecords.vue +19 -19
- package/src/views/userRecords/TransferRecords.vue +19 -19
- package/vite.config.ts +121 -121
- package/certs/127.0.0.1+2-key.pem +0 -28
- package/certs/127.0.0.1+2.pem +0 -27
- package/mock/modules/prose.mock.ts.timestamp-1758877157774.mjs +0 -53
- package/mock/modules/user.mock.ts.timestamp-1758877157774.mjs +0 -97
|
@@ -1,310 +1,310 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ChatBizResult,
|
|
3
|
-
ChatCompletionsRequest,
|
|
4
|
-
ChatCompletionsResponse,
|
|
5
|
-
ChatStreamCallbacks,
|
|
6
|
-
GetHistoriesRequest,
|
|
7
|
-
GetHistoriesResponse,
|
|
8
|
-
GetPaginationRecordsRequest,
|
|
9
|
-
GetPaginationRecordsResponse,
|
|
10
|
-
} from '@af-mobile-client-vue3/components/common/MateChat/types'
|
|
11
|
-
import type { AxiosInstance } from 'axios'
|
|
12
|
-
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
13
|
-
import axios from 'axios'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 创建独立的 axios 实例,不经过拦截器
|
|
17
|
-
*/
|
|
18
|
-
const chatAxiosInstance: AxiosInstance = axios.create({
|
|
19
|
-
baseURL: import.meta.env.VITE_APP_API_BASE_URL || '',
|
|
20
|
-
timeout: 20000,
|
|
21
|
-
headers: {
|
|
22
|
-
'Content-Type': 'application/json',
|
|
23
|
-
},
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 生成 outLinkUid:用户类型 + 用户ID
|
|
28
|
-
* @returns outLinkUid 字符串,格式:用户类型_用户ID
|
|
29
|
-
*/
|
|
30
|
-
export function generateOutLinkUid(): string {
|
|
31
|
-
const userStore = useUserStore()
|
|
32
|
-
const userInfo = userStore.getUserInfo()
|
|
33
|
-
const userType = userStore.getUserType()
|
|
34
|
-
|
|
35
|
-
// 用户类型:SYSTEM 或 EXTERNAL,如果为 null 则默认为 SYSTEM
|
|
36
|
-
const type = userType || 'SYSTEM'
|
|
37
|
-
// 用户ID
|
|
38
|
-
const userId = userInfo?.id || ''
|
|
39
|
-
// 兼容旧版af-system 返回 userinfoid 都一样的问题
|
|
40
|
-
if (type === 'EXTERNAL' && userInfo?.nickname) {
|
|
41
|
-
return `EXTERNAL_${userInfo?.nickname}`
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return `${type}_${userId}`
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 获取用户平台 OpenID
|
|
49
|
-
* @returns OpenID
|
|
50
|
-
*/
|
|
51
|
-
export function getOpenId(): string {
|
|
52
|
-
const userStore = useUserStore()
|
|
53
|
-
const userInfo = userStore.getUserInfo()
|
|
54
|
-
if (userInfo.platformUserId) {
|
|
55
|
-
return userInfo.platformUserId
|
|
56
|
-
}
|
|
57
|
-
return null
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* 发送聊天请求
|
|
62
|
-
* @param content 用户输入的内容
|
|
63
|
-
* @param appId FastGPT 应用 ID
|
|
64
|
-
* @param appKey FastGPT API Key
|
|
65
|
-
* @param chatId 会话 ID
|
|
66
|
-
* @returns Promise<ChatCompletionsResponse>
|
|
67
|
-
*/
|
|
68
|
-
export function chatCompletions(
|
|
69
|
-
content: string,
|
|
70
|
-
appId: string,
|
|
71
|
-
appKey: string,
|
|
72
|
-
chatId: string,
|
|
73
|
-
): Promise<ChatCompletionsResponse> {
|
|
74
|
-
const requestData: ChatCompletionsRequest = {
|
|
75
|
-
chatId,
|
|
76
|
-
stream: false,
|
|
77
|
-
detail: false,
|
|
78
|
-
variables: {
|
|
79
|
-
openid: getOpenId(),
|
|
80
|
-
// openid: 'oUx6l5gyHp3JNt9465QCKZOgjB9E',
|
|
81
|
-
},
|
|
82
|
-
messages: [
|
|
83
|
-
{
|
|
84
|
-
role: 'user',
|
|
85
|
-
content,
|
|
86
|
-
},
|
|
87
|
-
],
|
|
88
|
-
customUid: generateOutLinkUid(),
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return chatAxiosInstance.post<ChatCompletionsResponse>(
|
|
92
|
-
'/fastApi/v1/chat/completions',
|
|
93
|
-
requestData,
|
|
94
|
-
{
|
|
95
|
-
headers: {
|
|
96
|
-
Authorization: `Bearer ${appKey}`,
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
).then(response => response.data)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* 封装后的业务聊天请求
|
|
104
|
-
* - 负责从大模型返回中解析出业务含义(普通回复 / 转人工)
|
|
105
|
-
* - UI 层只需要根据 type 决定渲染哪种气泡
|
|
106
|
-
* @param content 用户输入的内容
|
|
107
|
-
* @param appId FastGPT 应用 ID
|
|
108
|
-
* @param appKey FastGPT API Key
|
|
109
|
-
* @param chatId 会话 ID
|
|
110
|
-
*/
|
|
111
|
-
export async function chatBiz(
|
|
112
|
-
content: string,
|
|
113
|
-
appId: string,
|
|
114
|
-
appKey: string,
|
|
115
|
-
chatId: string,
|
|
116
|
-
): Promise<ChatBizResult> {
|
|
117
|
-
const response = await chatCompletions(content, appId, appKey, chatId)
|
|
118
|
-
|
|
119
|
-
if (!response.choices || response.choices.length === 0) {
|
|
120
|
-
throw new Error('响应数据格式错误')
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const text = response.choices[0].message.content
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const parsed = JSON.parse(text) as { msgType?: string }
|
|
127
|
-
if (parsed.msgType === 'transfer') {
|
|
128
|
-
return {
|
|
129
|
-
type: 'transfer',
|
|
130
|
-
content: text,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
// 忽略解析错误,按普通文本处理
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
type: 'normal',
|
|
140
|
-
content: text,
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* 使用 FastGPT /v1/chat/completions 的 stream=true 进行流式对话
|
|
146
|
-
* 参考官方文档: https://doc.fastgpt.io/docs/introduction/development/openapi/chat
|
|
147
|
-
* @param content 用户输入的内容
|
|
148
|
-
* @param appId FastGPT 应用 ID
|
|
149
|
-
* @param appKey FastGPT API Key
|
|
150
|
-
* @param chatId 会话 ID
|
|
151
|
-
* @param callbacks 流式回调函数
|
|
152
|
-
*/
|
|
153
|
-
export async function chatCompletionsStream(
|
|
154
|
-
content: string,
|
|
155
|
-
appId: string,
|
|
156
|
-
appKey: string,
|
|
157
|
-
chatId: string,
|
|
158
|
-
callbacks: ChatStreamCallbacks,
|
|
159
|
-
): Promise<void> {
|
|
160
|
-
const { onMessage, onComplete, onError } = callbacks
|
|
161
|
-
|
|
162
|
-
const requestData: ChatCompletionsRequest = {
|
|
163
|
-
chatId,
|
|
164
|
-
stream: true,
|
|
165
|
-
detail: false,
|
|
166
|
-
variables: {
|
|
167
|
-
openid: getOpenId(),
|
|
168
|
-
// openid: 'oYt6WtxACKSH4XmIe0E3jUvx70U0',
|
|
169
|
-
},
|
|
170
|
-
messages: [
|
|
171
|
-
{
|
|
172
|
-
role: 'user',
|
|
173
|
-
content,
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
customUid: generateOutLinkUid(),
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const baseUrl = import.meta.env.VITE_APP_API_BASE_URL || ''
|
|
181
|
-
const res = await fetch(`${baseUrl}/fastApi/v1/chat/completions`, {
|
|
182
|
-
method: 'POST',
|
|
183
|
-
headers: {
|
|
184
|
-
'Content-Type': 'application/json',
|
|
185
|
-
'Authorization': `Bearer ${appKey}`,
|
|
186
|
-
},
|
|
187
|
-
body: JSON.stringify(requestData),
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
if (!res.ok || !res.body) {
|
|
191
|
-
throw new Error(`请求失败: ${res.status}`)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const reader = res.body.getReader()
|
|
195
|
-
const decoder = new TextDecoder('utf-8')
|
|
196
|
-
let buffer = ''
|
|
197
|
-
|
|
198
|
-
while (true) {
|
|
199
|
-
const { done, value } = await reader.read()
|
|
200
|
-
if (done)
|
|
201
|
-
break
|
|
202
|
-
|
|
203
|
-
buffer += decoder.decode(value, { stream: true })
|
|
204
|
-
const lines = buffer.split('\n')
|
|
205
|
-
buffer = lines.pop() ?? ''
|
|
206
|
-
|
|
207
|
-
for (const rawLine of lines) {
|
|
208
|
-
const line = rawLine.trim()
|
|
209
|
-
if (!line.startsWith('data:'))
|
|
210
|
-
continue
|
|
211
|
-
|
|
212
|
-
const dataStr = line.slice(5).trim()
|
|
213
|
-
if (!dataStr || dataStr === '[DONE]') {
|
|
214
|
-
onComplete?.()
|
|
215
|
-
return
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
try {
|
|
219
|
-
const json = JSON.parse(dataStr) as {
|
|
220
|
-
choices?: Array<{ delta?: { content?: string } }>
|
|
221
|
-
}
|
|
222
|
-
const delta = json.choices?.[0]?.delta
|
|
223
|
-
const chunkText = delta?.content || ''
|
|
224
|
-
if (chunkText) {
|
|
225
|
-
onMessage?.(chunkText)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
catch (e) {
|
|
229
|
-
console.error('解析数据失败', e, dataStr)
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
onComplete?.()
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
console.error('FastGPT 流式请求异常', error)
|
|
238
|
-
onError?.(error)
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* 获取历史会话列表
|
|
244
|
-
* @param appId FastGPT 应用 ID
|
|
245
|
-
* @param appKey FastGPT API Key
|
|
246
|
-
* @param offset 偏移量
|
|
247
|
-
* @param pageSize 每页数量
|
|
248
|
-
* @returns Promise<GetHistoriesResponse>
|
|
249
|
-
*/
|
|
250
|
-
export function getHistories(
|
|
251
|
-
appId: string,
|
|
252
|
-
appKey: string,
|
|
253
|
-
offset: number = 0,
|
|
254
|
-
pageSize: number = 5,
|
|
255
|
-
): Promise<GetHistoriesResponse> {
|
|
256
|
-
const requestData: GetHistoriesRequest = {
|
|
257
|
-
appId,
|
|
258
|
-
outLinkUid: generateOutLinkUid(),
|
|
259
|
-
offset,
|
|
260
|
-
pageSize,
|
|
261
|
-
source: 'api',
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return chatAxiosInstance.post<GetHistoriesResponse>(
|
|
265
|
-
'/fastApi/core/chat/getHistories',
|
|
266
|
-
requestData,
|
|
267
|
-
{
|
|
268
|
-
headers: {
|
|
269
|
-
Authorization: `Bearer ${appKey}`,
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
).then(response => response.data)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* 获取历史会话记录
|
|
277
|
-
* @param appId FastGPT 应用 ID
|
|
278
|
-
* @param appKey FastGPT API Key
|
|
279
|
-
* @param chatId 会话 ID
|
|
280
|
-
* @param offset 偏移量
|
|
281
|
-
* @param pageSize 每页数量
|
|
282
|
-
* @param loadCustomFeedbacks 是否加载自定义反馈
|
|
283
|
-
* @returns Promise<GetPaginationRecordsResponse>
|
|
284
|
-
*/
|
|
285
|
-
export function getPaginationRecords(
|
|
286
|
-
appId: string,
|
|
287
|
-
appKey: string,
|
|
288
|
-
chatId: string,
|
|
289
|
-
offset: number = 0,
|
|
290
|
-
pageSize: number = 10,
|
|
291
|
-
loadCustomFeedbacks: boolean = true,
|
|
292
|
-
): Promise<GetPaginationRecordsResponse> {
|
|
293
|
-
const requestData: GetPaginationRecordsRequest = {
|
|
294
|
-
appId,
|
|
295
|
-
chatId,
|
|
296
|
-
offset,
|
|
297
|
-
pageSize,
|
|
298
|
-
loadCustomFeedbacks,
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return chatAxiosInstance.post<GetPaginationRecordsResponse>(
|
|
302
|
-
'/fastApi/core/chat/getPaginationRecords',
|
|
303
|
-
requestData,
|
|
304
|
-
{
|
|
305
|
-
headers: {
|
|
306
|
-
Authorization: `Bearer ${appKey}`,
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
|
-
).then(response => response.data)
|
|
310
|
-
}
|
|
1
|
+
import type {
|
|
2
|
+
ChatBizResult,
|
|
3
|
+
ChatCompletionsRequest,
|
|
4
|
+
ChatCompletionsResponse,
|
|
5
|
+
ChatStreamCallbacks,
|
|
6
|
+
GetHistoriesRequest,
|
|
7
|
+
GetHistoriesResponse,
|
|
8
|
+
GetPaginationRecordsRequest,
|
|
9
|
+
GetPaginationRecordsResponse,
|
|
10
|
+
} from '@af-mobile-client-vue3/components/common/MateChat/types'
|
|
11
|
+
import type { AxiosInstance } from 'axios'
|
|
12
|
+
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
13
|
+
import axios from 'axios'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 创建独立的 axios 实例,不经过拦截器
|
|
17
|
+
*/
|
|
18
|
+
const chatAxiosInstance: AxiosInstance = axios.create({
|
|
19
|
+
baseURL: import.meta.env.VITE_APP_API_BASE_URL || '',
|
|
20
|
+
timeout: 20000,
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 生成 outLinkUid:用户类型 + 用户ID
|
|
28
|
+
* @returns outLinkUid 字符串,格式:用户类型_用户ID
|
|
29
|
+
*/
|
|
30
|
+
export function generateOutLinkUid(): string {
|
|
31
|
+
const userStore = useUserStore()
|
|
32
|
+
const userInfo = userStore.getUserInfo()
|
|
33
|
+
const userType = userStore.getUserType()
|
|
34
|
+
|
|
35
|
+
// 用户类型:SYSTEM 或 EXTERNAL,如果为 null 则默认为 SYSTEM
|
|
36
|
+
const type = userType || 'SYSTEM'
|
|
37
|
+
// 用户ID
|
|
38
|
+
const userId = userInfo?.id || ''
|
|
39
|
+
// 兼容旧版af-system 返回 userinfoid 都一样的问题
|
|
40
|
+
if (type === 'EXTERNAL' && userInfo?.nickname) {
|
|
41
|
+
return `EXTERNAL_${userInfo?.nickname}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return `${type}_${userId}`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 获取用户平台 OpenID
|
|
49
|
+
* @returns OpenID
|
|
50
|
+
*/
|
|
51
|
+
export function getOpenId(): string {
|
|
52
|
+
const userStore = useUserStore()
|
|
53
|
+
const userInfo = userStore.getUserInfo()
|
|
54
|
+
if (userInfo.platformUserId) {
|
|
55
|
+
return userInfo.platformUserId
|
|
56
|
+
}
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 发送聊天请求
|
|
62
|
+
* @param content 用户输入的内容
|
|
63
|
+
* @param appId FastGPT 应用 ID
|
|
64
|
+
* @param appKey FastGPT API Key
|
|
65
|
+
* @param chatId 会话 ID
|
|
66
|
+
* @returns Promise<ChatCompletionsResponse>
|
|
67
|
+
*/
|
|
68
|
+
export function chatCompletions(
|
|
69
|
+
content: string,
|
|
70
|
+
appId: string,
|
|
71
|
+
appKey: string,
|
|
72
|
+
chatId: string,
|
|
73
|
+
): Promise<ChatCompletionsResponse> {
|
|
74
|
+
const requestData: ChatCompletionsRequest = {
|
|
75
|
+
chatId,
|
|
76
|
+
stream: false,
|
|
77
|
+
detail: false,
|
|
78
|
+
variables: {
|
|
79
|
+
openid: getOpenId(),
|
|
80
|
+
// openid: 'oUx6l5gyHp3JNt9465QCKZOgjB9E',
|
|
81
|
+
},
|
|
82
|
+
messages: [
|
|
83
|
+
{
|
|
84
|
+
role: 'user',
|
|
85
|
+
content,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
customUid: generateOutLinkUid(),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return chatAxiosInstance.post<ChatCompletionsResponse>(
|
|
92
|
+
'/fastApi/v1/chat/completions',
|
|
93
|
+
requestData,
|
|
94
|
+
{
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${appKey}`,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
).then(response => response.data)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 封装后的业务聊天请求
|
|
104
|
+
* - 负责从大模型返回中解析出业务含义(普通回复 / 转人工)
|
|
105
|
+
* - UI 层只需要根据 type 决定渲染哪种气泡
|
|
106
|
+
* @param content 用户输入的内容
|
|
107
|
+
* @param appId FastGPT 应用 ID
|
|
108
|
+
* @param appKey FastGPT API Key
|
|
109
|
+
* @param chatId 会话 ID
|
|
110
|
+
*/
|
|
111
|
+
export async function chatBiz(
|
|
112
|
+
content: string,
|
|
113
|
+
appId: string,
|
|
114
|
+
appKey: string,
|
|
115
|
+
chatId: string,
|
|
116
|
+
): Promise<ChatBizResult> {
|
|
117
|
+
const response = await chatCompletions(content, appId, appKey, chatId)
|
|
118
|
+
|
|
119
|
+
if (!response.choices || response.choices.length === 0) {
|
|
120
|
+
throw new Error('响应数据格式错误')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const text = response.choices[0].message.content
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const parsed = JSON.parse(text) as { msgType?: string }
|
|
127
|
+
if (parsed.msgType === 'transfer') {
|
|
128
|
+
return {
|
|
129
|
+
type: 'transfer',
|
|
130
|
+
content: text,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// 忽略解析错误,按普通文本处理
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
type: 'normal',
|
|
140
|
+
content: text,
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 使用 FastGPT /v1/chat/completions 的 stream=true 进行流式对话
|
|
146
|
+
* 参考官方文档: https://doc.fastgpt.io/docs/introduction/development/openapi/chat
|
|
147
|
+
* @param content 用户输入的内容
|
|
148
|
+
* @param appId FastGPT 应用 ID
|
|
149
|
+
* @param appKey FastGPT API Key
|
|
150
|
+
* @param chatId 会话 ID
|
|
151
|
+
* @param callbacks 流式回调函数
|
|
152
|
+
*/
|
|
153
|
+
export async function chatCompletionsStream(
|
|
154
|
+
content: string,
|
|
155
|
+
appId: string,
|
|
156
|
+
appKey: string,
|
|
157
|
+
chatId: string,
|
|
158
|
+
callbacks: ChatStreamCallbacks,
|
|
159
|
+
): Promise<void> {
|
|
160
|
+
const { onMessage, onComplete, onError } = callbacks
|
|
161
|
+
|
|
162
|
+
const requestData: ChatCompletionsRequest = {
|
|
163
|
+
chatId,
|
|
164
|
+
stream: true,
|
|
165
|
+
detail: false,
|
|
166
|
+
variables: {
|
|
167
|
+
openid: getOpenId(),
|
|
168
|
+
// openid: 'oYt6WtxACKSH4XmIe0E3jUvx70U0',
|
|
169
|
+
},
|
|
170
|
+
messages: [
|
|
171
|
+
{
|
|
172
|
+
role: 'user',
|
|
173
|
+
content,
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
customUid: generateOutLinkUid(),
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const baseUrl = import.meta.env.VITE_APP_API_BASE_URL || ''
|
|
181
|
+
const res = await fetch(`${baseUrl}/fastApi/v1/chat/completions`, {
|
|
182
|
+
method: 'POST',
|
|
183
|
+
headers: {
|
|
184
|
+
'Content-Type': 'application/json',
|
|
185
|
+
'Authorization': `Bearer ${appKey}`,
|
|
186
|
+
},
|
|
187
|
+
body: JSON.stringify(requestData),
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
if (!res.ok || !res.body) {
|
|
191
|
+
throw new Error(`请求失败: ${res.status}`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const reader = res.body.getReader()
|
|
195
|
+
const decoder = new TextDecoder('utf-8')
|
|
196
|
+
let buffer = ''
|
|
197
|
+
|
|
198
|
+
while (true) {
|
|
199
|
+
const { done, value } = await reader.read()
|
|
200
|
+
if (done)
|
|
201
|
+
break
|
|
202
|
+
|
|
203
|
+
buffer += decoder.decode(value, { stream: true })
|
|
204
|
+
const lines = buffer.split('\n')
|
|
205
|
+
buffer = lines.pop() ?? ''
|
|
206
|
+
|
|
207
|
+
for (const rawLine of lines) {
|
|
208
|
+
const line = rawLine.trim()
|
|
209
|
+
if (!line.startsWith('data:'))
|
|
210
|
+
continue
|
|
211
|
+
|
|
212
|
+
const dataStr = line.slice(5).trim()
|
|
213
|
+
if (!dataStr || dataStr === '[DONE]') {
|
|
214
|
+
onComplete?.()
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const json = JSON.parse(dataStr) as {
|
|
220
|
+
choices?: Array<{ delta?: { content?: string } }>
|
|
221
|
+
}
|
|
222
|
+
const delta = json.choices?.[0]?.delta
|
|
223
|
+
const chunkText = delta?.content || ''
|
|
224
|
+
if (chunkText) {
|
|
225
|
+
onMessage?.(chunkText)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
console.error('解析数据失败', e, dataStr)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
onComplete?.()
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.error('FastGPT 流式请求异常', error)
|
|
238
|
+
onError?.(error)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* 获取历史会话列表
|
|
244
|
+
* @param appId FastGPT 应用 ID
|
|
245
|
+
* @param appKey FastGPT API Key
|
|
246
|
+
* @param offset 偏移量
|
|
247
|
+
* @param pageSize 每页数量
|
|
248
|
+
* @returns Promise<GetHistoriesResponse>
|
|
249
|
+
*/
|
|
250
|
+
export function getHistories(
|
|
251
|
+
appId: string,
|
|
252
|
+
appKey: string,
|
|
253
|
+
offset: number = 0,
|
|
254
|
+
pageSize: number = 5,
|
|
255
|
+
): Promise<GetHistoriesResponse> {
|
|
256
|
+
const requestData: GetHistoriesRequest = {
|
|
257
|
+
appId,
|
|
258
|
+
outLinkUid: generateOutLinkUid(),
|
|
259
|
+
offset,
|
|
260
|
+
pageSize,
|
|
261
|
+
source: 'api',
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return chatAxiosInstance.post<GetHistoriesResponse>(
|
|
265
|
+
'/fastApi/core/chat/getHistories',
|
|
266
|
+
requestData,
|
|
267
|
+
{
|
|
268
|
+
headers: {
|
|
269
|
+
Authorization: `Bearer ${appKey}`,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
).then(response => response.data)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* 获取历史会话记录
|
|
277
|
+
* @param appId FastGPT 应用 ID
|
|
278
|
+
* @param appKey FastGPT API Key
|
|
279
|
+
* @param chatId 会话 ID
|
|
280
|
+
* @param offset 偏移量
|
|
281
|
+
* @param pageSize 每页数量
|
|
282
|
+
* @param loadCustomFeedbacks 是否加载自定义反馈
|
|
283
|
+
* @returns Promise<GetPaginationRecordsResponse>
|
|
284
|
+
*/
|
|
285
|
+
export function getPaginationRecords(
|
|
286
|
+
appId: string,
|
|
287
|
+
appKey: string,
|
|
288
|
+
chatId: string,
|
|
289
|
+
offset: number = 0,
|
|
290
|
+
pageSize: number = 10,
|
|
291
|
+
loadCustomFeedbacks: boolean = true,
|
|
292
|
+
): Promise<GetPaginationRecordsResponse> {
|
|
293
|
+
const requestData: GetPaginationRecordsRequest = {
|
|
294
|
+
appId,
|
|
295
|
+
chatId,
|
|
296
|
+
offset,
|
|
297
|
+
pageSize,
|
|
298
|
+
loadCustomFeedbacks,
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return chatAxiosInstance.post<GetPaginationRecordsResponse>(
|
|
302
|
+
'/fastApi/core/chat/getPaginationRecords',
|
|
303
|
+
requestData,
|
|
304
|
+
{
|
|
305
|
+
headers: {
|
|
306
|
+
Authorization: `Bearer ${appKey}`,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
).then(response => response.data)
|
|
310
|
+
}
|