@blueking/ai-ui-sdk 0.0.14 → 0.0.15-beta.2
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/dist/common/chart-helper.d.ts +1 -1
- package/dist/common/chart-helper.js +173 -0
- package/dist/common/util.d.ts +21 -0
- package/dist/common/util.js +143 -0
- package/dist/css/fonts/iconcool.eot +0 -0
- package/dist/css/fonts/iconcool.svg +53 -0
- package/dist/css/fonts/iconcool.ttf +0 -0
- package/dist/css/fonts/iconcool.woff +0 -0
- package/dist/css/iconcool.js +10 -0
- package/dist/css/style.css +43 -0
- package/dist/event/index.d.ts +4 -0
- package/dist/event/index.js +17 -0
- package/dist/hooks/use-chat.d.ts +843 -18
- package/dist/hooks/use-chat.js +533 -0
- package/dist/hooks/use-click-proxy.js +77 -0
- package/dist/hooks/use-http.d.ts +15 -0
- package/dist/hooks/use-http.js +48 -0
- package/dist/hooks/use-reference-doc.d.ts +1 -1
- package/dist/hooks/use-reference-doc.js +185 -0
- package/dist/hooks/use-style.js +11 -0
- package/dist/hooks/use-summary.d.ts +1 -1
- package/dist/hooks/use-summary.js +55 -0
- package/dist/hooks/use-think.js +135 -0
- package/dist/http/fetch/error-interceptor.d.ts +3 -0
- package/dist/http/fetch/error-interceptor.js +7 -0
- package/dist/http/fetch/index.d.ts +25 -0
- package/dist/http/fetch/index.js +182 -0
- package/dist/http/fetch/request-error.d.ts +6 -0
- package/dist/http/fetch/request-error.js +25 -0
- package/dist/http/fetch/success-interceptor.d.ts +3 -0
- package/dist/http/fetch/success-interceptor.js +92 -0
- package/dist/http/helper/knowledge.d.ts +43 -0
- package/dist/http/helper/knowledge.js +227 -0
- package/dist/http/helper/permission.d.ts +7 -0
- package/dist/http/helper/permission.js +28 -0
- package/dist/http/helper/session.d.ts +31 -0
- package/dist/http/helper/session.js +147 -0
- package/dist/http/helper/tool.d.ts +13 -0
- package/dist/http/helper/tool.js +49 -0
- package/dist/main.d.ts +13 -2
- package/dist/main.js +24 -239
- package/dist/types/enum.d.ts +39 -0
- package/dist/types/enum.js +105 -0
- package/dist/types/file.d.ts +13 -0
- package/dist/types/file.js +1 -0
- package/dist/types/knowledge.d.ts +133 -0
- package/dist/types/knowledge.js +1 -0
- package/dist/types/permission.d.ts +48 -0
- package/dist/types/permission.js +1 -0
- package/dist/types/{type.d.ts → session.d.ts} +84 -23
- package/dist/types/session.js +1 -0
- package/dist/types/tool.d.ts +60 -0
- package/dist/types/tool.js +1 -0
- package/package.json +3 -3
- package/dist/common/type-transform.d.ts +0 -7
@@ -0,0 +1,185 @@
|
|
1
|
+
import { onBeforeMount, onBeforeUnmount } from 'vue';
|
2
|
+
/**
|
3
|
+
* 获取引用资料的 HTML 内容
|
4
|
+
* @param documents
|
5
|
+
* @returns
|
6
|
+
*/ export const getHtmlContentFromDocuments = (documents)=>{
|
7
|
+
let htmlContent = `<section class="knowledge-head click-close"><svg class="ai-ui-sdk-wenzhang"><use href="#ai-ui-sdk-wenzhang"></use></svg>找到 ${documents.length} 篇资料参考<i class="ai-ui-sdk-icon ai-ui-sdk-angle-up"></i></section><ul class="knowledge-body">`;
|
8
|
+
documents.forEach((document1)=>{
|
9
|
+
const { path, file_path: filePath, display_name: displayName, preview_path: previewPath } = document1.metadata;
|
10
|
+
const title = displayName || filePath.split('/').pop();
|
11
|
+
htmlContent += `<li
|
12
|
+
class="knowledge-item"
|
13
|
+
>
|
14
|
+
<i class="ai-ui-sdk-icon ai-ui-sdk-zhishiku"></i>
|
15
|
+
<a href="${previewPath}" title="${title} (${previewPath})" target="_blank" class="knowledge-link g-flex-truncate">
|
16
|
+
${title}
|
17
|
+
</a>
|
18
|
+
<a href="${path}" title="预览原文" target="_blank" class="knowledge-link hover-show">
|
19
|
+
<i class="ai-ui-sdk-icon ai-ui-sdk-yanjing-kejian"></i>
|
20
|
+
</a>
|
21
|
+
</li>`;
|
22
|
+
});
|
23
|
+
htmlContent += '</ul>';
|
24
|
+
return htmlContent;
|
25
|
+
};
|
26
|
+
/**
|
27
|
+
* 移除引用资料的 HTML 内容
|
28
|
+
* @param content
|
29
|
+
* @returns
|
30
|
+
*/ export const removeReferenceDoc = (content)=>{
|
31
|
+
return content.replace(/<section class="knowledge-head click-close">[\s\S]*?<\/section>/, '').replace(/<ul class="knowledge-body">[\s\S]*?<\/ul>/, '').replace(/<section class="knowledge-tips">[\s\S]*?<\/section>/, '');
|
32
|
+
};
|
33
|
+
export const useReferenceDoc = ()=>{
|
34
|
+
let styleEle = null;
|
35
|
+
const addReferenceDocStyle = ()=>{
|
36
|
+
// 旧版知识样式
|
37
|
+
const oldStyle = `.knowledge-tips {
|
38
|
+
position: relative;
|
39
|
+
padding: 6px 8px;
|
40
|
+
margin-bottom: 14px;
|
41
|
+
line-height: 22px;
|
42
|
+
background: #f5f7fa;
|
43
|
+
border-radius: 4px;
|
44
|
+
|
45
|
+
&.closed {
|
46
|
+
.bkaidev-angle-up {
|
47
|
+
transform: rotate(180deg);
|
48
|
+
}
|
49
|
+
|
50
|
+
.knowledge-summary {
|
51
|
+
margin-bottom: 0;
|
52
|
+
}
|
53
|
+
|
54
|
+
.knowledge-link {
|
55
|
+
display: none;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
.bkaidev-angle-up {
|
60
|
+
position: absolute;
|
61
|
+
top: 4px;
|
62
|
+
right: 0px;
|
63
|
+
font-size: 22px;
|
64
|
+
color: #979ba5;
|
65
|
+
cursor: pointer;
|
66
|
+
}
|
67
|
+
|
68
|
+
.bkaidev-help-document {
|
69
|
+
margin-right: 4px;
|
70
|
+
font-size: 19px;
|
71
|
+
color: #3a84ff;
|
72
|
+
}
|
73
|
+
|
74
|
+
.knowledge-summary {
|
75
|
+
display: block;
|
76
|
+
margin-bottom: 4px;
|
77
|
+
color: #313238;
|
78
|
+
}
|
79
|
+
|
80
|
+
.knowledge-link {
|
81
|
+
display: block;
|
82
|
+
color: #3a84ff;
|
83
|
+
text-decoration: none;
|
84
|
+
cursor: pointer;
|
85
|
+
|
86
|
+
.bkaidev-cc-jump-link {
|
87
|
+
font-size: 14px;
|
88
|
+
}
|
89
|
+
|
90
|
+
&:last-child {
|
91
|
+
margin-bottom: 2px;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}`;
|
95
|
+
// 新版知识样式
|
96
|
+
const newStyle = `.knowledge-head {
|
97
|
+
display: flex;
|
98
|
+
align-items: center;
|
99
|
+
padding: 0 8px 0 6px;
|
100
|
+
margin-bottom: 8px;
|
101
|
+
line-height: 28px;
|
102
|
+
background: #F0F1F5;
|
103
|
+
border-radius: 4px;
|
104
|
+
font-size: 12px;
|
105
|
+
color: #313238;
|
106
|
+
cursor: pointer;
|
107
|
+
width: fit-content;
|
108
|
+
|
109
|
+
.ai-ui-sdk-wenzhang {
|
110
|
+
width: 14px;
|
111
|
+
height: 14px;
|
112
|
+
margin-right: 6px;
|
113
|
+
}
|
114
|
+
|
115
|
+
.ai-ui-sdk-angle-up {
|
116
|
+
font-size: 22px;
|
117
|
+
color: #4D4F56;
|
118
|
+
margin-left: 4px;
|
119
|
+
}
|
120
|
+
|
121
|
+
&.closed {
|
122
|
+
margin-bottom: 16px;
|
123
|
+
|
124
|
+
.ai-ui-sdk-angle-up {
|
125
|
+
transform: rotate(180deg);
|
126
|
+
}
|
127
|
+
|
128
|
+
&~ .knowledge-body {
|
129
|
+
display: none;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
&:hover {
|
134
|
+
background: #EAEBF0;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
.knowledge-body {
|
138
|
+
background: #F5F7FA;
|
139
|
+
padding: 16px 0 !important;
|
140
|
+
.knowledge-item {
|
141
|
+
padding-left: 10px;
|
142
|
+
display: flex;
|
143
|
+
align-items: center;
|
144
|
+
line-height: 28px;
|
145
|
+
.hover-show {
|
146
|
+
display: none;
|
147
|
+
}
|
148
|
+
a {
|
149
|
+
margin-right: 10px;
|
150
|
+
&:has(i) {
|
151
|
+
padding: 0 10px;
|
152
|
+
margin-right: 0;
|
153
|
+
text-decoration: none !important;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
.ai-ui-sdk-zhishiku {
|
157
|
+
color: #D66F6B;
|
158
|
+
font-size: 14px;
|
159
|
+
margin-right: 6px;
|
160
|
+
}
|
161
|
+
&:hover {
|
162
|
+
background: #EAEBF0;
|
163
|
+
.hover-show {
|
164
|
+
display: inline;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}`;
|
169
|
+
styleEle = document.createElement('style');
|
170
|
+
styleEle.textContent = oldStyle + newStyle;
|
171
|
+
document.head.appendChild(styleEle);
|
172
|
+
};
|
173
|
+
const removeReferenceDocStyle = ()=>{
|
174
|
+
if (styleEle) {
|
175
|
+
styleEle.remove();
|
176
|
+
styleEle = null;
|
177
|
+
}
|
178
|
+
};
|
179
|
+
onBeforeMount(()=>{
|
180
|
+
addReferenceDocStyle();
|
181
|
+
});
|
182
|
+
onBeforeUnmount(()=>{
|
183
|
+
removeReferenceDocStyle();
|
184
|
+
});
|
185
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { useReferenceDoc } from './use-reference-doc.js';
|
2
|
+
import { useThink } from './use-think.js';
|
3
|
+
import '../css/style.css';
|
4
|
+
import '../css/iconcool.js';
|
5
|
+
// ai 样式。注意:全局引入一次即可
|
6
|
+
export const useStyle = ()=>{
|
7
|
+
// 引用资料
|
8
|
+
useReferenceDoc();
|
9
|
+
// 思考
|
10
|
+
useThink();
|
11
|
+
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type { SummaryCallbacks } from '../types/
|
1
|
+
import type { SummaryCallbacks } from '../types/session';
|
2
2
|
export declare const useSummary: ({ handleStart, handleEnd, handleError, }?: SummaryCallbacks) => {
|
3
3
|
summary: ({ content, url, headers, model, }: {
|
4
4
|
content: string;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { SessionPromptRole } from '../types/enum.js';
|
2
|
+
import { removeReferenceDoc } from './use-reference-doc.js';
|
3
|
+
import { removeThink } from './use-think.js';
|
4
|
+
import { ChatHelper } from '../common/chart-helper.js';
|
5
|
+
// ai 总结
|
6
|
+
export const useSummary = ({ handleStart, handleEnd, handleError } = {})=>{
|
7
|
+
let summaryText = '';
|
8
|
+
const handleStartChat = ()=>{
|
9
|
+
summaryText = '';
|
10
|
+
return handleStart === null || handleStart === void 0 ? void 0 : handleStart();
|
11
|
+
};
|
12
|
+
const handleTextChat = (sessionCode, message, cover)=>{
|
13
|
+
if (cover || summaryText === '正在思考...') {
|
14
|
+
summaryText = message;
|
15
|
+
} else {
|
16
|
+
summaryText += message;
|
17
|
+
}
|
18
|
+
};
|
19
|
+
const handleEndChat = ()=>{
|
20
|
+
if (summaryText === '无话可说') {
|
21
|
+
summaryText = '';
|
22
|
+
}
|
23
|
+
return handleEnd === null || handleEnd === void 0 ? void 0 : handleEnd(summaryText);
|
24
|
+
};
|
25
|
+
const handleErrorChat = (sessionCode, message, code)=>{
|
26
|
+
return handleError === null || handleError === void 0 ? void 0 : handleError(message, code);
|
27
|
+
};
|
28
|
+
const chatHelper = new ChatHelper({
|
29
|
+
handleStart: handleStartChat,
|
30
|
+
handleText: handleTextChat,
|
31
|
+
handleEnd: handleEndChat,
|
32
|
+
handleError: handleErrorChat
|
33
|
+
});
|
34
|
+
const summary = ({ content, url, headers, model })=>{
|
35
|
+
const filterContent = removeThink(removeReferenceDoc(content));
|
36
|
+
const prompts = [
|
37
|
+
{
|
38
|
+
role: SessionPromptRole.User,
|
39
|
+
content: `你是一个总结大师,请帮助我对下面这段话进行总结。要求总结精炼,不超过 15 个字!且末尾没有标点符号!请注意:如果你无法总结,请回复“无话可说”!\n文字如下:\n${filterContent}`
|
40
|
+
}
|
41
|
+
];
|
42
|
+
chatHelper.stream({
|
43
|
+
sessionCode: 'summary',
|
44
|
+
url,
|
45
|
+
data: {
|
46
|
+
prompts,
|
47
|
+
model
|
48
|
+
},
|
49
|
+
headers
|
50
|
+
});
|
51
|
+
};
|
52
|
+
return {
|
53
|
+
summary
|
54
|
+
};
|
55
|
+
};
|
@@ -0,0 +1,135 @@
|
|
1
|
+
import { onBeforeMount, onBeforeUnmount } from 'vue';
|
2
|
+
import { durationFormatter } from '../common/util.js';
|
3
|
+
/**
|
4
|
+
* 获取思考的 HTML 内容
|
5
|
+
* @param chatContent 聊天内容
|
6
|
+
* @param content 思考内容
|
7
|
+
* @param elapsedTime 思考时间
|
8
|
+
* @returns 完整的 chatContent
|
9
|
+
*/ export const getHtmlContentFromThink = (chatContent, content, cover, elapsedTime)=>{
|
10
|
+
let htmlContent = chatContent === '内容正在生成中...' || cover ? '' : chatContent;
|
11
|
+
// 思考开始
|
12
|
+
if (!htmlContent.includes('<section class="think-head click-close">')) {
|
13
|
+
htmlContent += `<section class="think-head click-close">
|
14
|
+
<i class="ai-ui-sdk-icon ai-ui-sdk-sikao"></i>思考中...<i class="ai-ui-sdk-icon ai-ui-sdk-angle-up"></i>
|
15
|
+
</section>
|
16
|
+
<section class="think-body">
|
17
|
+
${content}
|
18
|
+
</section>`;
|
19
|
+
} else {
|
20
|
+
// 补充思考内容
|
21
|
+
const thinkBodyMatch = htmlContent.match(/<section class="think-body">([\s\S]*?)<\/section>/);
|
22
|
+
if (thinkBodyMatch) {
|
23
|
+
// 原有思考内容
|
24
|
+
const thinkContent = thinkBodyMatch[1];
|
25
|
+
// 在最后的换行符前面添加新的思考内容
|
26
|
+
const newThinkContent = thinkContent.replace(/\n$/g, `${content}\n`);
|
27
|
+
htmlContent = htmlContent.replace(thinkContent, newThinkContent);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
// 思考结束
|
31
|
+
if (elapsedTime) {
|
32
|
+
htmlContent = htmlContent.replace('思考中...', `已完成思考 (耗时:${durationFormatter(elapsedTime)})`);
|
33
|
+
}
|
34
|
+
return htmlContent;
|
35
|
+
};
|
36
|
+
/**
|
37
|
+
* 移除思考的 HTML 内容
|
38
|
+
* @param content
|
39
|
+
* @returns
|
40
|
+
*/ export const removeThink = (content)=>{
|
41
|
+
// 移除思考头部
|
42
|
+
const afterRemoveThinkHead = content.replace(/<section class="think-head click-close">[\s\S]*<\/section>/, '');
|
43
|
+
// 移除思考内容
|
44
|
+
let afterRemoveThinkBody = afterRemoveThinkHead.replace(/<section class="think-body">[\s\S]*<\/section>/, '');
|
45
|
+
// 如果内容只有思考,那就给ai传递思考内容
|
46
|
+
if (afterRemoveThinkBody.trim() === '') {
|
47
|
+
const thinkBodyMatch = content.match(/<section class="think-body">([\s\S]*?)<\/section>/);
|
48
|
+
if (thinkBodyMatch) {
|
49
|
+
[, afterRemoveThinkBody] = thinkBodyMatch;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return afterRemoveThinkBody;
|
53
|
+
};
|
54
|
+
/**
|
55
|
+
* 判断是否是思考中
|
56
|
+
* @param content
|
57
|
+
* @returns
|
58
|
+
*/ export const isThinking = (content)=>{
|
59
|
+
// 是否开始思考
|
60
|
+
const isStartThinking = content === '正在思考...';
|
61
|
+
// 判断是否空思考
|
62
|
+
const thinkBodyMatch = content.match(/<section class="think-body">([\s\S]*?)<\/section>$/);
|
63
|
+
const isEmptyThinking = thinkBodyMatch && thinkBodyMatch[1].trim() === '';
|
64
|
+
return isStartThinking || isEmptyThinking;
|
65
|
+
};
|
66
|
+
// 思考
|
67
|
+
export const useThink = ()=>{
|
68
|
+
let styleEle = null;
|
69
|
+
const addThinkStyle = ()=>{
|
70
|
+
const style = `.think-head {
|
71
|
+
display: flex;
|
72
|
+
align-items: center;
|
73
|
+
padding: 0 8px 0 6px;
|
74
|
+
margin-bottom: 8px;
|
75
|
+
line-height: 28px;
|
76
|
+
background: #F0F1F5;
|
77
|
+
border-radius: 4px;
|
78
|
+
font-size: 12px;
|
79
|
+
color: #313238;
|
80
|
+
cursor: pointer;
|
81
|
+
width: fit-content;
|
82
|
+
.ai-ui-sdk-sikao {
|
83
|
+
font-size: 14px;
|
84
|
+
color: #979ba5;
|
85
|
+
margin-right: 4px;
|
86
|
+
}
|
87
|
+
|
88
|
+
.ai-ui-sdk-angle-up {
|
89
|
+
font-size: 22px;
|
90
|
+
color: #4D4F56;
|
91
|
+
margin-left: 4px;
|
92
|
+
}
|
93
|
+
|
94
|
+
&.closed {
|
95
|
+
margin-bottom: 16px;
|
96
|
+
|
97
|
+
.ai-ui-sdk-angle-up {
|
98
|
+
transform: rotate(180deg);
|
99
|
+
}
|
100
|
+
|
101
|
+
&~ .think-body {
|
102
|
+
display: none;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
&:hover {
|
107
|
+
background: #EAEBF0;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
.think-body {
|
111
|
+
background: #F5F7FA;
|
112
|
+
color: #979BA5;
|
113
|
+
padding: 16px;
|
114
|
+
margin-bottom: 16px;
|
115
|
+
&~ .knowledge-head {
|
116
|
+
margin-bottom: 8px;
|
117
|
+
}
|
118
|
+
}`;
|
119
|
+
styleEle = document.createElement('style');
|
120
|
+
styleEle.textContent = style;
|
121
|
+
document.head.appendChild(styleEle);
|
122
|
+
};
|
123
|
+
const removeThinkStyle = ()=>{
|
124
|
+
if (styleEle) {
|
125
|
+
styleEle.remove();
|
126
|
+
styleEle = null;
|
127
|
+
}
|
128
|
+
};
|
129
|
+
onBeforeMount(()=>{
|
130
|
+
addThinkStyle();
|
131
|
+
});
|
132
|
+
onBeforeUnmount(()=>{
|
133
|
+
removeThinkStyle();
|
134
|
+
});
|
135
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
export interface IFetchConfig extends RequestInit {
|
2
|
+
requestType?: 'json' | 'formData';
|
3
|
+
responseType?: 'json' | 'text' | 'formData' | 'file' | 'blob';
|
4
|
+
globalError?: Boolean;
|
5
|
+
signal?: AbortSignal;
|
6
|
+
withoutSpace?: boolean;
|
7
|
+
noCheckPermission?: boolean;
|
8
|
+
}
|
9
|
+
type HttpMethod = <T>(url: string, payload?: any, config?: IFetchConfig) => Promise<T>;
|
10
|
+
interface IHttp {
|
11
|
+
get: HttpMethod;
|
12
|
+
post: HttpMethod;
|
13
|
+
put: HttpMethod;
|
14
|
+
delete: HttpMethod;
|
15
|
+
head: HttpMethod;
|
16
|
+
options: HttpMethod;
|
17
|
+
patch: HttpMethod;
|
18
|
+
}
|
19
|
+
declare const http: IHttp;
|
20
|
+
declare const withAbort: <R, T extends any[]>(fn: (signal: AbortSignal, ...args: T) => Promise<R>) => {
|
21
|
+
(...args: T): Promise<R>;
|
22
|
+
abort(): void | undefined;
|
23
|
+
};
|
24
|
+
export default http;
|
25
|
+
export { withAbort };
|
@@ -0,0 +1,182 @@
|
|
1
|
+
/* eslint-disable no-param-reassign */ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
2
|
+
try {
|
3
|
+
var info = gen[key](arg);
|
4
|
+
var value = info.value;
|
5
|
+
} catch (error) {
|
6
|
+
reject(error);
|
7
|
+
return;
|
8
|
+
}
|
9
|
+
if (info.done) {
|
10
|
+
resolve(value);
|
11
|
+
} else {
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
function _async_to_generator(fn) {
|
16
|
+
return function() {
|
17
|
+
var self = this, args = arguments;
|
18
|
+
return new Promise(function(resolve, reject) {
|
19
|
+
var gen = fn.apply(self, args);
|
20
|
+
function _next(value) {
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
22
|
+
}
|
23
|
+
function _throw(err) {
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
25
|
+
}
|
26
|
+
_next(undefined);
|
27
|
+
});
|
28
|
+
};
|
29
|
+
}
|
30
|
+
import errorInterceptor from './error-interceptor.js';
|
31
|
+
import RequestError from './request-error.js';
|
32
|
+
import successInterceptor from './success-interceptor.js';
|
33
|
+
import { deepMerge } from '../../common/util.js';
|
34
|
+
// Content-Type
|
35
|
+
const contentTypeMap = {
|
36
|
+
json: 'application/json',
|
37
|
+
text: 'text/plain',
|
38
|
+
formData: 'multipart/form-data'
|
39
|
+
};
|
40
|
+
const methodsWithoutData = [
|
41
|
+
'delete',
|
42
|
+
'get',
|
43
|
+
'head',
|
44
|
+
'options'
|
45
|
+
];
|
46
|
+
const methodsWithData = [
|
47
|
+
'post',
|
48
|
+
'put',
|
49
|
+
'patch'
|
50
|
+
];
|
51
|
+
const allMethods = [
|
52
|
+
...methodsWithoutData,
|
53
|
+
...methodsWithData
|
54
|
+
];
|
55
|
+
// 拼装发送请求配置
|
56
|
+
const getFetchConfig = (method, payload, config)=>{
|
57
|
+
const headers = {
|
58
|
+
'X-Requested-With': 'fetch'
|
59
|
+
};
|
60
|
+
if (config.requestType !== 'formData') {
|
61
|
+
headers['Content-Type'] = contentTypeMap[config.requestType] || 'application/json';
|
62
|
+
}
|
63
|
+
if (!config.withoutSpace) {
|
64
|
+
headers['X-SPACE-ID'] = localStorage.getItem('spaceId') || '';
|
65
|
+
}
|
66
|
+
// 合并配置
|
67
|
+
let fetchConfig = deepMerge({
|
68
|
+
method: method.toLocaleUpperCase(),
|
69
|
+
mode: 'cors',
|
70
|
+
cache: 'default',
|
71
|
+
credentials: 'include',
|
72
|
+
headers,
|
73
|
+
redirect: 'follow',
|
74
|
+
referrerPolicy: 'no-referrer-when-downgrade',
|
75
|
+
responseType: 'json',
|
76
|
+
globalError: true
|
77
|
+
}, config);
|
78
|
+
// merge payload
|
79
|
+
if (methodsWithData.includes(method)) {
|
80
|
+
fetchConfig = deepMerge(fetchConfig, {
|
81
|
+
body: config.requestType === 'formData' ? payload : JSON.stringify(payload)
|
82
|
+
});
|
83
|
+
} else {
|
84
|
+
fetchConfig = deepMerge(fetchConfig, payload);
|
85
|
+
}
|
86
|
+
return fetchConfig;
|
87
|
+
};
|
88
|
+
// 拼装发送请求 url
|
89
|
+
const getFetchUrl = (url, method, payload = {})=>{
|
90
|
+
try {
|
91
|
+
// 基础 url
|
92
|
+
const baseUrl = location.origin;
|
93
|
+
// 构造 url 对象
|
94
|
+
const urlObject = new URL(url, baseUrl);
|
95
|
+
// add path
|
96
|
+
const configPath = window.SITE_URL;
|
97
|
+
const subPath = configPath.endsWith('/') ? configPath.slice(0, -1) : configPath;
|
98
|
+
urlObject.pathname = subPath + urlObject.pathname;
|
99
|
+
// get 请求需要将参数拼接到url上
|
100
|
+
// if (methodsWithoutData.includes(method)) {
|
101
|
+
// urlObject.search = qs.stringify(payload);
|
102
|
+
// }
|
103
|
+
// if (methodsWithoutData.includes(method)) {
|
104
|
+
// Object.keys(payload).forEach((key) => {
|
105
|
+
// const value = payload[key];
|
106
|
+
// if (!['', undefined, null].includes(value)) {
|
107
|
+
// urlObject.searchParams.append(key, value);
|
108
|
+
// }
|
109
|
+
// });
|
110
|
+
// }
|
111
|
+
if (methodsWithoutData.includes(method)) {
|
112
|
+
const appendSearchParams = (key, value)=>{
|
113
|
+
if (![
|
114
|
+
'',
|
115
|
+
undefined,
|
116
|
+
null
|
117
|
+
].includes(value)) {
|
118
|
+
urlObject.searchParams.append(key, value);
|
119
|
+
}
|
120
|
+
};
|
121
|
+
// /api/cr/bkaidev/intelligence/code_review/mine_list/ 接口 status 参数需要 status=xx&&status=yy 此种方式接收
|
122
|
+
// 这里单独对此做处理,需要在参数中加上 noEncodeURI 标识,这种处理的缺陷是如果参数本身就有 noEncodeURI 就会出现问题,待处理
|
123
|
+
const isNoEncodURI = !!payload.noEncodeURI;
|
124
|
+
delete payload.noEncodeURI;
|
125
|
+
Object.keys(payload).forEach((key)=>{
|
126
|
+
const value = payload[key];
|
127
|
+
if (isNoEncodURI) {
|
128
|
+
if (Object.prototype.toString.call(value) === '[object Array]') {
|
129
|
+
value.forEach((item)=>{
|
130
|
+
appendSearchParams(key, item);
|
131
|
+
});
|
132
|
+
} else {
|
133
|
+
appendSearchParams(key, value);
|
134
|
+
}
|
135
|
+
} else {
|
136
|
+
appendSearchParams(key, value);
|
137
|
+
}
|
138
|
+
});
|
139
|
+
}
|
140
|
+
return urlObject.href;
|
141
|
+
} catch (error) {
|
142
|
+
throw new RequestError(-1, error.message);
|
143
|
+
}
|
144
|
+
};
|
145
|
+
// 在自定义对象 http 上添加各请求方法
|
146
|
+
const http = {};
|
147
|
+
allMethods.forEach((method)=>{
|
148
|
+
Object.defineProperty(http, method, {
|
149
|
+
get () {
|
150
|
+
return function() {
|
151
|
+
var _ref = _async_to_generator(function*(url, payload, config = {}) {
|
152
|
+
const fetchConfig = getFetchConfig(method, payload, config);
|
153
|
+
try {
|
154
|
+
const fetchUrl = getFetchUrl(url, method, payload);
|
155
|
+
const response = yield fetch(fetchUrl, fetchConfig);
|
156
|
+
return yield successInterceptor(response, fetchConfig);
|
157
|
+
} catch (err) {
|
158
|
+
return errorInterceptor(err, fetchConfig);
|
159
|
+
}
|
160
|
+
});
|
161
|
+
return function(url, payload) {
|
162
|
+
return _ref.apply(this, arguments);
|
163
|
+
};
|
164
|
+
}();
|
165
|
+
}
|
166
|
+
});
|
167
|
+
});
|
168
|
+
// 通过 withAbort 包装 http 方法,使其支持 abort
|
169
|
+
const withAbort = (fn)=>{
|
170
|
+
let controller = null;
|
171
|
+
const fnWithsignal = (...args)=>{
|
172
|
+
controller = new AbortController();
|
173
|
+
return fn(controller.signal, ...args);
|
174
|
+
};
|
175
|
+
fnWithsignal.abort = ()=>{
|
176
|
+
var _controller_abort;
|
177
|
+
return controller === null || controller === void 0 ? void 0 : (_controller_abort = controller.abort) === null || _controller_abort === void 0 ? void 0 : _controller_abort.call(controller);
|
178
|
+
};
|
179
|
+
return fnWithsignal;
|
180
|
+
};
|
181
|
+
export default http;
|
182
|
+
export { withAbort };
|
@@ -0,0 +1,25 @@
|
|
1
|
+
function _define_property(obj, key, value) {
|
2
|
+
if (key in obj) {
|
3
|
+
Object.defineProperty(obj, key, {
|
4
|
+
value: value,
|
5
|
+
enumerable: true,
|
6
|
+
configurable: true,
|
7
|
+
writable: true
|
8
|
+
});
|
9
|
+
} else {
|
10
|
+
obj[key] = value;
|
11
|
+
}
|
12
|
+
return obj;
|
13
|
+
}
|
14
|
+
class RequestError extends Error {
|
15
|
+
constructor(code, message, response){
|
16
|
+
super();
|
17
|
+
_define_property(this, "code", void 0);
|
18
|
+
_define_property(this, "message", void 0);
|
19
|
+
_define_property(this, "response", void 0);
|
20
|
+
this.code = code;
|
21
|
+
this.message = message;
|
22
|
+
this.response = response;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
export { RequestError as default };
|