@ai-group/chat-sdk 3.0.1-alpha.4 → 3.0.1-alpha.6
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/cjs/components/XAdkProvider/XAdkProvider.stories.js +1 -1
- package/dist/cjs/components/XAdkProvider/XAdkProvider.stories.js.map +1 -1
- package/dist/cjs/components/XAdkSender/FileGallery.js +148 -85
- package/dist/cjs/components/XAdkSender/FileGallery.js.map +3 -3
- package/dist/cjs/components/XAdkSender/index.d.ts +2 -2
- package/dist/cjs/components/XAdkSender/index.js +126 -94
- package/dist/cjs/components/XAdkSender/index.js.map +2 -2
- package/dist/esm/components/XAdkProvider/XAdkProvider.stories.js +1 -1
- package/dist/esm/components/XAdkProvider/XAdkProvider.stories.js.map +1 -1
- package/dist/esm/components/XAdkSender/FileGallery.js +225 -114
- package/dist/esm/components/XAdkSender/FileGallery.js.map +1 -1
- package/dist/esm/components/XAdkSender/index.d.ts +2 -2
- package/dist/esm/components/XAdkSender/index.js +44 -44
- package/dist/esm/components/XAdkSender/index.js.map +1 -1
- package/dist/umd/chat-sdk.min.js +1 -1
- package/package.json +1 -1
|
@@ -51,7 +51,19 @@ var XAdkSender = ({
|
|
|
51
51
|
onStop,
|
|
52
52
|
onFilesChange,
|
|
53
53
|
maxFileSize = 10,
|
|
54
|
-
allowedFileTypes = [
|
|
54
|
+
allowedFileTypes = [
|
|
55
|
+
"image/*",
|
|
56
|
+
"audio/*",
|
|
57
|
+
"video/*",
|
|
58
|
+
"application/pdf",
|
|
59
|
+
"text/plain",
|
|
60
|
+
".doc",
|
|
61
|
+
".docx",
|
|
62
|
+
".xls",
|
|
63
|
+
".xlsx",
|
|
64
|
+
".ppt",
|
|
65
|
+
".pptx"
|
|
66
|
+
],
|
|
55
67
|
maxFiles = 5,
|
|
56
68
|
suffix,
|
|
57
69
|
header,
|
|
@@ -99,75 +111,90 @@ var XAdkSender = ({
|
|
|
99
111
|
const ext = filename.split(".").pop();
|
|
100
112
|
return ext ? ext.toLowerCase() : "";
|
|
101
113
|
};
|
|
102
|
-
const handleFileSelect = (0, import_react.useCallback)(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
const handleFileSelect = (0, import_react.useCallback)(
|
|
115
|
+
(selectedFiles) => {
|
|
116
|
+
const fileArray = Array.from(selectedFiles);
|
|
117
|
+
const validFiles = [];
|
|
118
|
+
fileArray.forEach((file) => {
|
|
119
|
+
const validation = validateFile(file);
|
|
120
|
+
if (validation.valid) {
|
|
121
|
+
validFiles.push({
|
|
122
|
+
id: generateId(),
|
|
123
|
+
uid: generateId(),
|
|
124
|
+
name: file.name,
|
|
125
|
+
size: file.size,
|
|
126
|
+
type: file.type,
|
|
127
|
+
file,
|
|
128
|
+
progress: 0,
|
|
129
|
+
status: "pending",
|
|
130
|
+
response: null
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
import_antd.message.error(validation.message);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (validFiles.length > 0) {
|
|
137
|
+
setFiles((prev) => [...prev, ...validFiles]);
|
|
138
|
+
uploadFiles(validFiles);
|
|
121
139
|
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
uploadFiles(validFiles);
|
|
126
|
-
}
|
|
127
|
-
}, [files.length, maxFiles, maxFileSize, allowedFileTypes]);
|
|
140
|
+
},
|
|
141
|
+
[files.length, maxFiles, maxFileSize, allowedFileTypes]
|
|
142
|
+
);
|
|
128
143
|
const uploadFiles = async (fileList) => {
|
|
129
144
|
for (const localFile of fileList) {
|
|
130
|
-
setFiles(
|
|
131
|
-
(
|
|
132
|
-
|
|
145
|
+
setFiles(
|
|
146
|
+
(prev) => prev.map(
|
|
147
|
+
(f) => f.id === localFile.id ? { ...f, status: "uploading" } : f
|
|
148
|
+
)
|
|
149
|
+
);
|
|
133
150
|
try {
|
|
134
151
|
await uploadRequest({
|
|
135
152
|
file: localFile.file,
|
|
136
153
|
onProgress: (e) => {
|
|
137
|
-
setFiles(
|
|
138
|
-
(
|
|
139
|
-
|
|
154
|
+
setFiles(
|
|
155
|
+
(prev) => prev.map(
|
|
156
|
+
(f) => f.id === localFile.id ? { ...f, progress: e.percent } : f
|
|
157
|
+
)
|
|
158
|
+
);
|
|
140
159
|
},
|
|
141
160
|
onSuccess: (response) => {
|
|
142
|
-
setFiles(
|
|
143
|
-
(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
161
|
+
setFiles(
|
|
162
|
+
(prev) => prev.map(
|
|
163
|
+
(f) => f.id === localFile.id ? {
|
|
164
|
+
...f,
|
|
165
|
+
status: "success",
|
|
166
|
+
progress: 100,
|
|
167
|
+
response
|
|
168
|
+
} : f
|
|
169
|
+
)
|
|
170
|
+
);
|
|
150
171
|
},
|
|
151
172
|
onError: (error) => {
|
|
152
|
-
setFiles(
|
|
153
|
-
(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
173
|
+
setFiles(
|
|
174
|
+
(prev) => prev.map(
|
|
175
|
+
(f) => f.id === localFile.id ? {
|
|
176
|
+
...f,
|
|
177
|
+
status: "error",
|
|
178
|
+
errorMessage: error.message || "上传失败"
|
|
179
|
+
} : f
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
import_antd.message.error(
|
|
183
|
+
`${localFile.name} 上传失败: ${error.message || "未知错误"}`
|
|
184
|
+
);
|
|
160
185
|
}
|
|
161
186
|
});
|
|
162
187
|
} catch (error) {
|
|
163
188
|
console.error("上传处理错误:", error);
|
|
164
|
-
setFiles(
|
|
165
|
-
(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
setFiles(
|
|
190
|
+
(prev) => prev.map(
|
|
191
|
+
(f) => f.id === localFile.id ? {
|
|
192
|
+
...f,
|
|
193
|
+
status: "error",
|
|
194
|
+
errorMessage: error instanceof Error ? error.message : "上传处理失败"
|
|
195
|
+
} : f
|
|
196
|
+
)
|
|
197
|
+
);
|
|
171
198
|
import_antd.message.error(`${localFile.name} 上传失败`);
|
|
172
199
|
}
|
|
173
200
|
}
|
|
@@ -177,9 +204,9 @@ var XAdkSender = ({
|
|
|
177
204
|
let progress = 0;
|
|
178
205
|
const interval = setInterval(() => {
|
|
179
206
|
progress += 10;
|
|
180
|
-
setFiles(
|
|
181
|
-
(f) => f.id === localFile.id ? { ...f, progress } : f
|
|
182
|
-
)
|
|
207
|
+
setFiles(
|
|
208
|
+
(prev) => prev.map((f) => f.id === localFile.id ? { ...f, progress } : f)
|
|
209
|
+
);
|
|
183
210
|
if (progress >= 100) {
|
|
184
211
|
clearInterval(interval);
|
|
185
212
|
setTimeout(() => {
|
|
@@ -192,14 +219,16 @@ var XAdkSender = ({
|
|
|
192
219
|
fileType: getFileExtension(localFile.name)
|
|
193
220
|
}
|
|
194
221
|
};
|
|
195
|
-
setFiles(
|
|
196
|
-
(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
setFiles(
|
|
223
|
+
(prev) => prev.map(
|
|
224
|
+
(f) => f.id === localFile.id ? {
|
|
225
|
+
...f,
|
|
226
|
+
status: "success",
|
|
227
|
+
progress: 100,
|
|
228
|
+
response: mockResponse
|
|
229
|
+
} : f
|
|
230
|
+
)
|
|
231
|
+
);
|
|
203
232
|
}, 300);
|
|
204
233
|
}
|
|
205
234
|
}, 100);
|
|
@@ -213,28 +242,37 @@ var XAdkSender = ({
|
|
|
213
242
|
fileInputRef.current.click();
|
|
214
243
|
}
|
|
215
244
|
};
|
|
216
|
-
const handleDragOver = (0, import_react.useCallback)(
|
|
217
|
-
e
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
245
|
+
const handleDragOver = (0, import_react.useCallback)(
|
|
246
|
+
(e) => {
|
|
247
|
+
e.preventDefault();
|
|
248
|
+
e.stopPropagation();
|
|
249
|
+
if (allowUpload) {
|
|
250
|
+
setIsDragOver(true);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
[allowUpload]
|
|
254
|
+
);
|
|
255
|
+
const handleDragLeave = (0, import_react.useCallback)(
|
|
256
|
+
(e) => {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
e.stopPropagation();
|
|
259
|
+
if (allowUpload) {
|
|
260
|
+
setIsDragOver(false);
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
[allowUpload]
|
|
264
|
+
);
|
|
265
|
+
const handleDrop = (0, import_react.useCallback)(
|
|
266
|
+
(e) => {
|
|
267
|
+
e.preventDefault();
|
|
268
|
+
e.stopPropagation();
|
|
227
269
|
setIsDragOver(false);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (allowUpload && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
235
|
-
handleFileSelect(Array.from(e.dataTransfer.files));
|
|
236
|
-
}
|
|
237
|
-
}, [allowUpload, handleFileSelect]);
|
|
270
|
+
if (allowUpload && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
271
|
+
handleFileSelect(Array.from(e.dataTransfer.files));
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
[allowUpload, handleFileSelect]
|
|
275
|
+
);
|
|
238
276
|
const handleSubmit = () => {
|
|
239
277
|
if (!value.trim() && files.length === 0) {
|
|
240
278
|
import_antd.message.warning("请输入消息或选择文件");
|
|
@@ -304,13 +342,7 @@ var XAdkSender = ({
|
|
|
304
342
|
const renderFileList = () => {
|
|
305
343
|
if (files.length === 0)
|
|
306
344
|
return null;
|
|
307
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
308
|
-
import_FileGallery.default,
|
|
309
|
-
{
|
|
310
|
-
files,
|
|
311
|
-
onRemove: handleRemoveFile
|
|
312
|
-
}
|
|
313
|
-
);
|
|
345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FileGallery.default, { files, onRemove: handleRemoveFile });
|
|
314
346
|
};
|
|
315
347
|
const containerClass = `${styles.container} ${isDragOver ? "drag-over" : ""}`;
|
|
316
348
|
const uploading = files.some((f) => f.status === "uploading");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/XAdkSender/index.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useState, useRef, useCallback } from 'react';\nimport {\n Popconfirm, \n message, \n Progress,\n Tooltip,\n Input,\n Modal,\n} from 'antd';\nimport { \n ClearOutlined, \n LoadingOutlined, \n ArrowUpOutlined,\n PaperClipOutlined,\n CloseOutlined,\n} from '@ant-design/icons';\nimport { XAdkSenderProps, ServerFile, LocalFile, ActionsComponents } from '../../types/XAdkSender';\nimport { useStyles } from './styles';\nimport FileGallery from './FileGallery';\n\n\nconst XAdkSender: React.FC<XAdkSenderProps> = ({\n clearBtnShow = true,\n allowUpload = false,\n loading = false,\n disabled = false,\n uploadRequest = () => {},\n onClear,\n onChange,\n onSubmit,\n onStop,\n onFilesChange,\n maxFileSize = 10,\n allowedFileTypes = ['image/*', 'application/pdf', 'text/plain'],\n maxFiles = 5,\n suffix,\n header,\n prefix,\n footer,\n}) => {\n const styles = useStyles();\n const [value, setValue] = useState<string>('');\n const [files, setFiles] = useState<LocalFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadRef = useRef<any>(null);\n \n // 生成唯一ID\n const generateId = () => {\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\n };\n \n \n // 检查文件类型\n const checkFileType = (file: File): boolean => {\n if (!allowedFileTypes.length) return true;\n \n return allowedFileTypes.some(type => {\n if (type.includes('/*')) {\n const mainType = type.split('/')[0];\n return file.type.startsWith(mainType);\n }\n return file.type === type;\n });\n };\n \n // 检查文件大小\n const checkFileSize = (file: File): boolean => {\n const maxSize = maxFileSize * 1024 * 1024;\n return file.size <= maxSize;\n };\n \n // 验证文件\n const validateFile = (file: File): { valid: boolean; message?: string } => {\n if (files.length >= maxFiles) {\n return { valid: false, message: `最多只能上传 ${maxFiles} 个文件` };\n }\n \n if (!checkFileSize(file)) {\n return { valid: false, message: `文件大小不能超过 ${maxFileSize}MB` };\n }\n \n if (!checkFileType(file)) {\n return { valid: false, message: '不支持的文件类型' };\n }\n \n return { valid: true };\n };\n\n // 获取文件扩展名\n const getFileExtension = (filename: string): string => {\n const ext = filename.split('.').pop();\n return ext ? ext.toLowerCase() : '';\n };\n\n // 处理文件选择\n const handleFileSelect = useCallback((selectedFiles: File[]) => {\n const fileArray = Array.from(selectedFiles);\n const validFiles: LocalFile[] = [];\n \n fileArray.forEach(file => {\n const validation = validateFile(file);\n if (validation.valid) {\n validFiles.push({\n id: generateId(),\n uid: generateId(),\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n progress: 0,\n status: 'pending',\n response: null\n });\n } else {\n message.error(validation.message);\n }\n });\n \n if (validFiles.length > 0) {\n setFiles(prev => [...prev, ...validFiles]);\n uploadFiles(validFiles);\n }\n }, [files.length, maxFiles, maxFileSize, allowedFileTypes]);\n\n // 上传文件\n const uploadFiles = async (fileList: LocalFile[]) => {\n for (const localFile of fileList) {\n // 开始上传\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { ...f, status: 'uploading' } : f\n ));\n \n try {\n await uploadRequest({\n file: localFile.file,\n onProgress: (e) => {\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { ...f, progress: e.percent } : f\n ));\n },\n onSuccess: (response) => {\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { \n ...f, \n status: 'success', \n progress: 100,\n response \n } : f\n ));\n },\n onError: (error) => {\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { \n ...f, \n status: 'error',\n errorMessage: error.message || '上传失败'\n } : f\n ));\n message.error(`${localFile.name} 上传失败: ${error.message || '未知错误'}`);\n }\n });\n } catch (error) {\n console.error('上传处理错误:', error);\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { \n ...f, \n status: 'error',\n errorMessage: error instanceof Error ? error.message : '上传处理失败'\n } : f\n ));\n message.error(`${localFile.name} 上传失败`);\n }\n }\n };\n\n // 模拟上传过程\n const simulateUpload = async (uploadFilesList: LocalFile[]) => {\n uploadFilesList.forEach(localFile => {\n let progress = 0;\n const interval = setInterval(() => {\n progress += 10;\n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { ...f, progress } : f\n ));\n \n if (progress >= 100) {\n clearInterval(interval);\n setTimeout(() => {\n // 模拟服务器响应\n const mockResponse = {\n code: 200,\n data: {\n fileId: Math.floor(Math.random() * 1000) + 1,\n tempUrl: `https://example.com/uploads/${localFile.name}`,\n fileName: localFile.name,\n fileType: getFileExtension(localFile.name)\n }\n };\n \n setFiles(prev => prev.map(f => \n f.id === localFile.id ? { \n ...f, \n status: 'success', \n progress: 100,\n response: mockResponse\n } : f\n ));\n }, 300);\n }\n }, 100);\n });\n };\n \n // 删除文件\n const handleRemoveFile = (id: string) => {\n setFiles(prev => prev.filter(file => file.id !== id));\n };\n \n // 触发文件选择\n const triggerFileSelect = () => {\n if (fileInputRef.current) {\n fileInputRef.current.click();\n }\n };\n \n // 处理拖拽事件\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(true);\n }\n }, [allowUpload]);\n \n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(false);\n }\n }, [allowUpload]);\n \n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n \n if (allowUpload && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n handleFileSelect(Array.from(e.dataTransfer.files));\n }\n }, [allowUpload, handleFileSelect]);\n \n // 处理提交\n const handleSubmit = () => {\n if (!value.trim() && files.length === 0) {\n message.warning('请输入消息或选择文件');\n return;\n }\n\n const successFiles = files.filter(file => file.status === 'success');\n const uploadingFiles = files.filter(file => file.status === 'uploading');\n \n if (uploadingFiles.length > 0) {\n Modal.confirm({\n title: '文件上传中',\n content: `还有 ${uploadingFiles.length} 个文件正在上传,是否继续发送?`,\n okText: '发送已完成的',\n cancelText: '等待全部完成',\n onOk: () => {\n const formattedFiles = formatFilesForServer(successFiles);\n if (onSubmit) {\n onSubmit({ \n text: value, \n files: formattedFiles \n });\n }\n\n setValue('');\n setFiles(prev => prev.filter(f => f.status !== 'success'));\n },\n onCancel: () => {\n message.info('请等待文件上传完成后再发送');\n },\n });\n } else {\n const formattedFiles = formatFilesForServer(successFiles);\n \n if (onSubmit) {\n onSubmit({ \n text: value, \n files: formattedFiles \n });\n }\n \n setValue('');\n setFiles(prev => prev.filter(f => f.status !== 'success'));\n }\n };\n\n // 格式化文件列表为服务端格式\n const formatFilesForServer = (fileList: LocalFile[]): ServerFile[] => {\n return fileList\n .filter(file => file.status === 'success' && file.response?.data)\n .map(file => {\n const responseData = file.response.data;\n \n return {\n fileName: file.name,\n fileId: responseData.fileId || responseData.id || 0,\n tempUrl: responseData.tempUrl || responseData.url || '',\n type: responseData.fileType || getFileExtension(file.name),\n mimeType: file.type\n };\n });\n };\n \n // 处理输入框变化\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n setValue(newValue);\n onChange?.(newValue);\n };\n \n // 处理回车键\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n \n // 渲染文件列表 - 使用新的 FileGallery 组件\n const renderFileList = () => {\n if (files.length === 0) return null;\n\n return (\n <FileGallery\n files={files}\n onRemove={handleRemoveFile}\n />\n );\n };\n \n const containerClass = `${styles.container} ${isDragOver ? 'drag-over' : ''}`;\n const uploading = files.some(f => f.status === 'uploading');\n const isDisabled = disabled || uploading || loading;\n\n // 定义按钮组件\n const SendButton = (props: any) => (\n <Tooltip title={loading ? \"停止生成\" : \"发送消息\"}>\n <button\n className={`${styles.iconButton} ${styles.sendButton} ${loading ? 'stop' : ''}`}\n onClick={loading ? onStop : handleSubmit}\n disabled={uploading || disabled}\n aria-label={loading ? \"停止生成\" : \"发送消息\"}\n {...props}\n >\n {loading ? <LoadingOutlined /> : <ArrowUpOutlined />}\n </button>\n </Tooltip>\n );\n\n const UploadButton = (props: any) => (\n <Tooltip title=\"上传文件\">\n <button\n className={`${styles.iconButton} ${styles.uploadButton}`}\n onClick={triggerFileSelect}\n disabled={isDisabled}\n aria-label=\"上传文件\"\n {...props}\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n );\n\n const ClearButton = (props: any) => (\n <Popconfirm\n title=\"确定要清空聊天记录吗?\"\n onConfirm={onClear}\n placement=\"top\"\n okText=\"确定\"\n cancelText=\"取消\"\n disabled={isDisabled}\n >\n <button\n className={`${styles.iconButton} ${styles.clearButton}`}\n disabled={isDisabled}\n aria-label=\"清空聊天记录\"\n {...props}\n >\n <ClearOutlined />\n </button>\n </Popconfirm>\n );\n\n const actionsComponents: ActionsComponents = {\n SendButton,\n UploadButton,\n ClearButton,\n };\n\n // 渲染插槽内容\n const renderSlot = (\n slot: React.ReactNode | false | ((oriNode: React.ReactNode, info: { components: ActionsComponents }) => React.ReactNode | false) | undefined,\n oriNode: React.ReactNode\n ): React.ReactNode | null => {\n if (slot === false) return null;\n if (slot === undefined) return oriNode;\n if (typeof slot === 'function') {\n const result = slot(oriNode, { components: actionsComponents });\n return result === false ? null : result;\n }\n return slot;\n };\n\n // 默认的后缀内容(操作按钮组)\n const defaultSuffix = (\n <div className={styles.buttonGroup}>\n {allowUpload && <UploadButton />}\n <SendButton />\n </div>\n );\n\n return (\n <div\n ref={containerRef}\n className={containerClass}\n onDragOver={allowUpload ? handleDragOver : undefined}\n onDragLeave={allowUpload ? handleDragLeave : undefined}\n onDrop={allowUpload ? handleDrop : undefined}\n >\n {/* 头部插槽 */}\n {renderSlot(header, false)}\n\n {allowUpload && files.length > 0 && renderFileList()}\n\n {/* 隐藏的原生 file input */}\n {allowUpload && (\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept={allowedFileTypes.join(',')}\n style={{ display: 'none' }}\n onChange={(e) => {\n if (e.target.files) {\n handleFileSelect(Array.from(e.target.files));\n e.target.value = '';\n }\n }}\n />\n )}\n\n <div className={styles.mainArea}>\n <div className={styles.senderWrap}>\n {/* 清除按钮 */}\n {clearBtnShow && <ClearButton />}\n\n <div className={styles.inputAndButtons}>\n {/* 前缀插槽 */}\n {renderSlot(prefix, false)}\n\n <div className={styles.textAreaWrapper}>\n <Input.TextArea\n className={styles.textArea}\n value={value}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder=\"请输入消息...\"\n disabled={isDisabled}\n autoSize={{ minRows: 1, maxRows: 4 }}\n style={{\n border: 'none',\n boxShadow: 'none',\n outline: 'none',\n padding: 0,\n }}\n />\n </div>\n\n {/* 后缀插槽(默认显示操作按钮) */}\n {renderSlot(suffix, defaultSuffix)}\n </div>\n </div>\n\n {/* 底部插槽(默认显示提示文字) */}\n {renderSlot(\n footer,\n <div className={styles.tip}>\n 内容由AI生成,无法确保真实准确,仅供参考\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default XAdkSender;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqD;AACrD,
|
|
4
|
+
"sourcesContent": ["import React, { useState, useRef, useCallback } from \"react\";\nimport { Popconfirm, message, Progress, Tooltip, Input, Modal } from \"antd\";\nimport {\n ClearOutlined,\n LoadingOutlined,\n ArrowUpOutlined,\n PaperClipOutlined,\n CloseOutlined,\n} from \"@ant-design/icons\";\nimport {\n XAdkSenderProps,\n ServerFile,\n LocalFile,\n ActionsComponents,\n} from \"../../types/XAdkSender\";\nimport { useStyles } from \"./styles\";\nimport FileGallery from \"./FileGallery\";\n\nconst XAdkSender: React.FC<XAdkSenderProps> = ({\n clearBtnShow = true,\n allowUpload = false,\n loading = false,\n disabled = false,\n uploadRequest = () => {},\n onClear,\n onChange,\n onSubmit,\n onStop,\n onFilesChange,\n maxFileSize = 10,\n allowedFileTypes = [\n \"image/*\",\n \"audio/*\",\n \"video/*\",\n \"application/pdf\",\n \"text/plain\",\n \".doc\",\n \".docx\",\n \".xls\",\n \".xlsx\",\n \".ppt\",\n \".pptx\",\n ],\n maxFiles = 5,\n suffix,\n header,\n prefix,\n footer,\n}) => {\n const styles = useStyles();\n const [value, setValue] = useState<string>(\"\");\n const [files, setFiles] = useState<LocalFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadRef = useRef<any>(null);\n\n // 生成唯一ID\n const generateId = () => {\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\n };\n\n // 检查文件类型\n const checkFileType = (file: File): boolean => {\n if (!allowedFileTypes.length) return true;\n\n return allowedFileTypes.some((type) => {\n if (type.includes(\"/*\")) {\n const mainType = type.split(\"/\")[0];\n return file.type.startsWith(mainType);\n }\n return file.type === type;\n });\n };\n\n // 检查文件大小\n const checkFileSize = (file: File): boolean => {\n const maxSize = maxFileSize * 1024 * 1024;\n return file.size <= maxSize;\n };\n\n // 验证文件\n const validateFile = (file: File): { valid: boolean; message?: string } => {\n if (files.length >= maxFiles) {\n return { valid: false, message: `最多只能上传 ${maxFiles} 个文件` };\n }\n\n if (!checkFileSize(file)) {\n return { valid: false, message: `文件大小不能超过 ${maxFileSize}MB` };\n }\n\n if (!checkFileType(file)) {\n return { valid: false, message: \"不支持的文件类型\" };\n }\n\n return { valid: true };\n };\n\n // 获取文件扩展名\n const getFileExtension = (filename: string): string => {\n const ext = filename.split(\".\").pop();\n return ext ? ext.toLowerCase() : \"\";\n };\n\n // 处理文件选择\n const handleFileSelect = useCallback(\n (selectedFiles: File[]) => {\n const fileArray = Array.from(selectedFiles);\n const validFiles: LocalFile[] = [];\n\n fileArray.forEach((file) => {\n const validation = validateFile(file);\n if (validation.valid) {\n validFiles.push({\n id: generateId(),\n uid: generateId(),\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n progress: 0,\n status: \"pending\",\n response: null,\n });\n } else {\n message.error(validation.message);\n }\n });\n\n if (validFiles.length > 0) {\n setFiles((prev) => [...prev, ...validFiles]);\n uploadFiles(validFiles);\n }\n },\n [files.length, maxFiles, maxFileSize, allowedFileTypes],\n );\n\n // 上传文件\n const uploadFiles = async (fileList: LocalFile[]) => {\n for (const localFile of fileList) {\n // 开始上传\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, status: \"uploading\" } : f,\n ),\n );\n\n try {\n await uploadRequest({\n file: localFile.file,\n onProgress: (e) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, progress: e.percent } : f,\n ),\n );\n },\n onSuccess: (response) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"success\",\n progress: 100,\n response,\n }\n : f,\n ),\n );\n },\n onError: (error) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage: error.message || \"上传失败\",\n }\n : f,\n ),\n );\n message.error(\n `${localFile.name} 上传失败: ${error.message || \"未知错误\"}`,\n );\n },\n });\n } catch (error) {\n console.error(\"上传处理错误:\", error);\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage:\n error instanceof Error ? error.message : \"上传处理失败\",\n }\n : f,\n ),\n );\n message.error(`${localFile.name} 上传失败`);\n }\n }\n };\n\n // 模拟上传过程\n const simulateUpload = async (uploadFilesList: LocalFile[]) => {\n uploadFilesList.forEach((localFile) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress += 10;\n setFiles((prev) =>\n prev.map((f) => (f.id === localFile.id ? { ...f, progress } : f)),\n );\n\n if (progress >= 100) {\n clearInterval(interval);\n setTimeout(() => {\n // 模拟服务器响应\n const mockResponse = {\n code: 200,\n data: {\n fileId: Math.floor(Math.random() * 1000) + 1,\n tempUrl: `https://example.com/uploads/${localFile.name}`,\n fileName: localFile.name,\n fileType: getFileExtension(localFile.name),\n },\n };\n\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"success\",\n progress: 100,\n response: mockResponse,\n }\n : f,\n ),\n );\n }, 300);\n }\n }, 100);\n });\n };\n\n // 删除文件\n const handleRemoveFile = (id: string) => {\n setFiles((prev) => prev.filter((file) => file.id !== id));\n };\n\n // 触发文件选择\n const triggerFileSelect = () => {\n if (fileInputRef.current) {\n fileInputRef.current.click();\n }\n };\n\n // 处理拖拽事件\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(true);\n }\n },\n [allowUpload],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(false);\n }\n },\n [allowUpload],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n if (\n allowUpload &&\n e.dataTransfer.files &&\n e.dataTransfer.files.length > 0\n ) {\n handleFileSelect(Array.from(e.dataTransfer.files));\n }\n },\n [allowUpload, handleFileSelect],\n );\n\n // 处理提交\n const handleSubmit = () => {\n if (!value.trim() && files.length === 0) {\n message.warning(\"请输入消息或选择文件\");\n return;\n }\n\n const successFiles = files.filter((file) => file.status === \"success\");\n const uploadingFiles = files.filter((file) => file.status === \"uploading\");\n\n if (uploadingFiles.length > 0) {\n Modal.confirm({\n title: \"文件上传中\",\n content: `还有 ${uploadingFiles.length} 个文件正在上传,是否继续发送?`,\n okText: \"发送已完成的\",\n cancelText: \"等待全部完成\",\n onOk: () => {\n const formattedFiles = formatFilesForServer(successFiles);\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n },\n onCancel: () => {\n message.info(\"请等待文件上传完成后再发送\");\n },\n });\n } else {\n const formattedFiles = formatFilesForServer(successFiles);\n\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n }\n };\n\n // 格式化文件列表为服务端格式\n const formatFilesForServer = (fileList: LocalFile[]): ServerFile[] => {\n return fileList\n .filter((file) => file.status === \"success\" && file.response?.data)\n .map((file) => {\n const responseData = file.response.data;\n\n return {\n fileName: file.name,\n fileId: responseData.fileId || responseData.id || 0,\n tempUrl: responseData.tempUrl || responseData.url || \"\",\n type: responseData.fileType || getFileExtension(file.name),\n mimeType: file.type,\n };\n });\n };\n\n // 处理输入框变化\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n setValue(newValue);\n onChange?.(newValue);\n };\n\n // 处理回车键\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n // 渲染文件列表 - 使用新的 FileGallery 组件\n const renderFileList = () => {\n if (files.length === 0) return null;\n\n return <FileGallery files={files} onRemove={handleRemoveFile} />;\n };\n\n const containerClass = `${styles.container} ${isDragOver ? \"drag-over\" : \"\"}`;\n const uploading = files.some((f) => f.status === \"uploading\");\n const isDisabled = disabled || uploading || loading;\n\n // 定义按钮组件\n const SendButton = (props: any) => (\n <Tooltip title={loading ? \"停止生成\" : \"发送消息\"}>\n <button\n className={`${styles.iconButton} ${styles.sendButton} ${loading ? \"stop\" : \"\"}`}\n onClick={loading ? onStop : handleSubmit}\n disabled={uploading || disabled}\n aria-label={loading ? \"停止生成\" : \"发送消息\"}\n {...props}\n >\n {loading ? <LoadingOutlined /> : <ArrowUpOutlined />}\n </button>\n </Tooltip>\n );\n\n const UploadButton = (props: any) => (\n <Tooltip title=\"上传文件\">\n <button\n className={`${styles.iconButton} ${styles.uploadButton}`}\n onClick={triggerFileSelect}\n disabled={isDisabled}\n aria-label=\"上传文件\"\n {...props}\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n );\n\n const ClearButton = (props: any) => (\n <Popconfirm\n title=\"确定要清空聊天记录吗?\"\n onConfirm={onClear}\n placement=\"top\"\n okText=\"确定\"\n cancelText=\"取消\"\n disabled={isDisabled}\n >\n <button\n className={`${styles.iconButton} ${styles.clearButton}`}\n disabled={isDisabled}\n aria-label=\"清空聊天记录\"\n {...props}\n >\n <ClearOutlined />\n </button>\n </Popconfirm>\n );\n\n const actionsComponents: ActionsComponents = {\n SendButton,\n UploadButton,\n ClearButton,\n };\n\n // 渲染插槽内容\n const renderSlot = (\n slot:\n | React.ReactNode\n | false\n | ((\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n ) => React.ReactNode | false)\n | undefined,\n oriNode: React.ReactNode,\n ): React.ReactNode | null => {\n if (slot === false) return null;\n if (slot === undefined) return oriNode;\n if (typeof slot === \"function\") {\n const result = slot(oriNode, { components: actionsComponents });\n return result === false ? null : result;\n }\n return slot;\n };\n\n // 默认的后缀内容(操作按钮组)\n const defaultSuffix = (\n <div className={styles.buttonGroup}>\n {allowUpload && <UploadButton />}\n <SendButton />\n </div>\n );\n\n return (\n <div\n ref={containerRef}\n className={containerClass}\n onDragOver={allowUpload ? handleDragOver : undefined}\n onDragLeave={allowUpload ? handleDragLeave : undefined}\n onDrop={allowUpload ? handleDrop : undefined}\n >\n {/* 头部插槽 */}\n {renderSlot(header, false)}\n\n {allowUpload && files.length > 0 && renderFileList()}\n\n {/* 隐藏的原生 file input */}\n {allowUpload && (\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept={allowedFileTypes.join(\",\")}\n style={{ display: \"none\" }}\n onChange={(e) => {\n if (e.target.files) {\n handleFileSelect(Array.from(e.target.files));\n e.target.value = \"\";\n }\n }}\n />\n )}\n\n <div className={styles.mainArea}>\n <div className={styles.senderWrap}>\n {/* 清除按钮 */}\n {clearBtnShow && <ClearButton />}\n\n <div className={styles.inputAndButtons}>\n {/* 前缀插槽 */}\n {renderSlot(prefix, false)}\n\n <div className={styles.textAreaWrapper}>\n <Input.TextArea\n className={styles.textArea}\n value={value}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder=\"请输入消息...\"\n disabled={isDisabled}\n autoSize={{ minRows: 1, maxRows: 4 }}\n style={{\n border: \"none\",\n boxShadow: \"none\",\n outline: \"none\",\n padding: 0,\n }}\n />\n </div>\n\n {/* 后缀插槽(默认显示操作按钮) */}\n {renderSlot(suffix, defaultSuffix)}\n </div>\n </div>\n\n {/* 底部插槽(默认显示提示文字) */}\n {renderSlot(\n footer,\n <div className={styles.tip}>\n 内容由AI生成,无法确保真实准确,仅供参考\n </div>,\n )}\n </div>\n </div>\n );\n};\n\nexport default XAdkSender;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["FileGallery"]
|
|
7
7
|
}
|
|
@@ -97,7 +97,7 @@ export var 带会话列表 = {
|
|
|
97
97
|
},
|
|
98
98
|
args: {
|
|
99
99
|
url: "https://m-poc-dev.zaxline.com",
|
|
100
|
-
token: "eyJhbGciOiJSUzI1NiJ9.
|
|
100
|
+
token: "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJhdWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJuYmYiOjE3NzM2NDk5MjIsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3MzY1NzEyMiwiaWF0IjoxNzczNjQ5OTIyLCJqdGkiOiI1NzY3Mjk3MC05ZmZlLTQzYmYtOTBmMy03ZDlmNDY4OTZjMGEiLCJjbGllbnRfaWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8ifQ.ojer50ubE3oyBxPDW9JsZpQkzuvlbHYtLgl4jpdnUB1GSnlhNTPw9tShDuoLVjrKeeSVYsqfNTk-JN4xmYUxHs4cdy0-Sn6j2oLfbFYXI1p_8oQqOllhPKJWQA-JiOWMjm6iHpYOnotx14oGfgO6EKD2I9kLvRkje0DuEVKsj22s_XEimpfMCLtxCgn-lzmIVr90MU_1jt01q7MnPOA35rKTPlVLUg2Mw3a7JsmBPSvR25uDiX0x_ueG3riSko1cY37TXuSPIuBsD6N6aptv1RZ25-pGt6DjP3QOKnLfLc9N7_jIIcfbRzYYOOxp0Y4ond6fF5wWZI8S1wckZbBHiA",
|
|
101
101
|
config: {
|
|
102
102
|
appNo: "MFX5TxlheIKbekZHKoeOVNlo"
|
|
103
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Button","Space","XAdkProvider","useChatState","useChatActions","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","meta","title","component","parameters","layout","docs","description","tags","argTypes","url","control","token","默认布局","render","args","style","height","children","config","DefaultLayout","showSessionList","allowUpload","clearBtnShow","story","appNo","带会话列表","header","showFnCallDetail","自定义布局","display","flex","flexDirection","padding","background","color","borderBottom","margin","fontSize","overflow","Messages","Sender","CustomStatsBar","_useChatState","messages","loading","appInfo","_useChatActions","chat","quickQuestions","justifyContent","alignItems","marginBottom","length","appName","wrap","map","q","i","size","onClick","text","disabled","使用Hooks","Chatbot","简化界面","width","maxWidth","borderRadius","boxShadow"],"sources":["../../../../src/components/XAdkProvider/XAdkProvider.stories.tsx"],"sourcesContent":["import type { Meta, StoryObj } from \"@storybook/react-vite\";\nimport { Button, Space } from \"antd\";\nimport XAdkProvider from \"./index\";\nimport { useChatState, useChatActions } from \"./context\";\n\nconst meta: Meta<typeof XAdkProvider> = {\n title: \"AI组件/XAdkProvider 对话容器\",\n component: XAdkProvider,\n parameters: {\n layout: \"fullscreen\",\n docs: {\n description: {\n component: `\n# XAdkProvider - 新一代 Compound Components 架构\n\n基于 Compound Components 模式的 AI 聊天 SDK,提供完全可组合的聊天界面。\n\n## 核心特性\n\n- 🧩 **完全可组合**: 自由组合子组件,构建任意布局\n- 🪝 **Hooks 访问**: 通过 Hooks 轻松访问状态和方法\n- ⚡ **性能优化**: Context 三层分离,避免不必要的 rerender\n- 🔙 **向后兼容**: 旧 API 完全保留,平滑升级\n- 📘 **TypeScript**: 完整的类型支持\n\n## 可用组件\n\n- \\`XAdkProvider.DefaultLayout\\` - 默认布局 (类似 ChatGPT/DeepSeek)\n- \\`XAdkProvider.Chatbot\\` - 完整的聊天界面 (Messages + Sender)\n- \\`XAdkProvider.Messages\\` - 消息列表\n- \\`XAdkProvider.Sender\\` - 输入框\n- \\`XAdkProvider.Sidebar\\` - 会话列表\n- \\`XAdkProvider.Header\\` - 可选头部\n\n## 可用 Hooks\n\n- \\`useChatState()\\` - 访问聊天状态\n- \\`useChatActions()\\` - 访问聊天方法\n- \\`useSession()\\` - 访问会话管理\n\n## 配置说明\n\n请在使用前配置:\n- \\`url\\`: AI 服务地址 (默认: window.location.origin)\n- \\`token\\`: 认证令牌 (必填)\n- \\`config.appNo\\`: 应用编号 (必填)\n `,\n },\n },\n },\n tags: [\"autodocs\"],\n argTypes: {\n url: {\n description: \"AI 服务地址\",\n control: \"text\",\n },\n token: {\n description: \"认证令牌\",\n control: \"text\",\n },\n },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\n// ============================================\n// 示例 1: 默认布局 (类似 ChatGPT)\n// ============================================\nexport const 默认布局: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.DefaultLayout\n showSessionList={false}\n allowUpload={true}\n clearBtnShow={true}\n />\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n默认布局,类似 ChatGPT 的界面风格。\n\n\\`\\`\\`tsx\n<XAdkProvider url=\"...\" token=\"...\" config={{ appNo: 'xxx' }}>\n <XAdkProvider.DefaultLayout\n showSessionList={false}\n allowUpload={true}\n clearBtnShow={true}\n />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiLCJhdWQiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiLCJuYmYiOjE3NzI3ODU3OTMsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc5Mjk5MywiaWF0IjoxNzcyNzg1NzkzLCJqdGkiOiI4MmFjMGZmZS1lZDBlLTRiMjMtYWE3NS04NmUzZjA1OTQ2NmEiLCJjbGllbnRfaWQiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMifQ.bBipIkOwu4BQqtH_ijT1V12yw5SnDpu7HAZhWrzjRSF7NUlqXr3m25f1VU_jiE9wyHO0Pj0VMMox1xVrE90JT9zgFL2sa4IDLpoHl6B2sr-3pY8WsvTLnk9PBSyTfOjmuSRwNDZyQYx0p4xJKd0yhf5Acfh5vuvH8pW7ksGpEXKvCLqc9tpeLytE1qZm_eSWt_rjTxDzvwMv33RAWO_fEigezoXfOe8ALtWpIDXEoza6cI--2buVM6-ZAFJHwe0CA_rx5E5H7QpmonUlZZhu9JVEL7HCc76MWLnuRP9TlNuicsR3JrYvkZ8nkG4oiBSWaHAgOVizGXaf2Elr7edTNA\",\n config: {\n appNo: \"wTXH8NReD6NIhWKVfBQCxWvS\",\n },\n },\n};\n\n// ============================================\n// 示例 2: 带会话列表 (类似 DeepSeek)\n// ============================================\nexport const 带会话列表: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.DefaultLayout\n header={<></>}\n showSessionList={true}\n allowUpload={true}\n clearBtnShow={false}\n showFnCallDetail={true}\n />\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n带会话列表的布局,类似 DeepSeek/元宝 的界面风格。\n\n左侧显示历史会话列表,右侧显示聊天区域。\n\n特点:\n- ✅ 左右布局: 左侧 280px 宽的会话列表,右侧聊天区域\n- ✅ 会话管理: 支持新建、切换、重命名、删除会话\n- ✅ 自动加载: 会话列表自动加载历史记录\n- ✅ 响应式: 窄屏自动切换到侧边栏模式\n\n\\`\\`\\`tsx\n<XAdkProvider\n url=\"...\"\n token=\"...\"\n config={{\n appNo: 'xxx',\n session: {\n showSessionList: true,\n }\n }}\n>\n <XAdkProvider.DefaultLayout\n showSessionList={true}\n allowUpload={true}\n />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJhdWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJuYmYiOjE3NzMyODI3NzMsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3MzI4OTk3MywiaWF0IjoxNzczMjgyNzczLCJqdGkiOiIwYmM4NmIzNS0xYzcxLTQ2NTAtYmU1Zi01Y2E2NDI0NDgxNTEiLCJjbGllbnRfaWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8ifQ.WRUgp7RTNcGH-vh8eoOwvgwbWwdFCrxCcDOZiJ6t0vdhAothDkl2N8r1NgqpvC3jwMTjCMYbPY4ARlCBmvHq5dv65VYjA1nyEytzicVTMi2KHLigRlHq90CVYP8-c33Bv8ZTYsvzGwHhQjmVYHW9NCAUiVvCP-yMDNPeli6ts4sDUVzdZE5t8kpKG3DAhnWnaWl28UtdyduVy5j3K0BgTes-bzV-Ka2otwCljM4fvc2dVAtYNb20PTiX-dz-7SLAmwUNMb81g-CejWYUiKWS5MTRsnRfOOmPW_a2TSoRbHlvdAGGBVCdzK5b6CLmR7178RdVMU07nk7vD_szctMAcQ\",\n config: {\n appNo: \"MFX5TxlheIKbekZHKoeOVNlo\",\n },\n },\n};\n\n// ============================================\n// 示例 3: 自定义布局\n// ============================================\nexport const 自定义布局: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <div style={{ display: \"flex\", height: \"100%\" }}>\n {/* 左侧会话列表 */}\n {/* <div\n style={{\n width: 300,\n borderRight: \"1px solid #f0f0f0\",\n background: \"#fafafa\",\n }}\n >\n <XAdkProvider.Sidebar />\n </div> */}\n\n {/* 右侧聊天区 */}\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\" }}>\n {/* 自定义头部 */}\n <div\n style={{\n padding: \"16px 24px\",\n background: \"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\",\n color: \"white\",\n borderBottom: \"1px solid rgba(255,255,255,0.1)\",\n }}\n >\n <h2 style={{ margin: 0, fontSize: \"18px\" }}>🤖 AI 智能助手</h2>\n </div>\n\n {/* 消息区 */}\n <div style={{ flex: 1, overflow: \"hidden\", background: \"#f9fafb\" }}>\n <XAdkProvider.Messages />\n </div>\n\n {/* 输入区 */}\n <XAdkProvider.Sender allowUpload={true} clearBtnShow={true} />\n </div>\n </div>\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n完全自定义的布局,展示 Compound Components 的灵活性。\n\n可以任意组合 Sidebar、Messages、Sender 等组件。\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzMwNjI5MjUsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3MzA3MDEyNSwiaWF0IjoxNzczMDYyOTI1LCJqdGkiOiI0YmY3MjcxOS03NzNkLTRkZGYtOGYzNC01YjAwNjA5MWE3Y2IiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.AcWWnsWZVHvvpbT9IG64oo6mNNUFDKuaTMSCRMUvgiRyfn8f4Y64GBF_VR_XhgvNgNczXx5pXlU5AEXlvwA3RXv5Voy5Vl1dvyrLOtjZivnRJVeDVzn8Af57cXKE9QBZAS94bUMAtfmZmvqer4Lw6wuFNSg6G32BCpQH6ifR8zei3scf1Gcs0QXr00KcT3dFROmAzJscJC_KnXxGx_729BlQqupdJ05KEGHDIokqJNy5Ev_40IPmW-ZDJprXpEdReHfHnPuaUgGQRAJEW2yTf2OsyNenOwA9l0iKYK1ENDnBpsr08VUgMhJBKq-quzP5AE3eLIn-3KR0O-yT4lyBiQ\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n\n// ============================================\n// 示例 4: 使用 Hooks\n// ============================================\nconst CustomStatsBar = () => {\n const { messages, loading, appInfo } = useChatState();\n const { chat } = useChatActions();\n\n const quickQuestions = [\"介绍一下你自己\", \"你能帮我做什么?\", \"如何开始使用?\"];\n\n return (\n <div\n style={{\n padding: \"16px 20px\",\n background: \"white\",\n borderBottom: \"1px solid #f0f0f0\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: \"12px\",\n }}\n >\n <Space>\n <span style={{ fontSize: \"12px\", color: \"#999\" }}>\n 💬 消息数: <strong>{messages.length}</strong>\n </span>\n <span style={{ fontSize: \"12px\", color: \"#999\" }}>\n 🤖 {appInfo?.appName || \"加载中...\"}\n </span>\n </Space>\n <span\n style={{ fontSize: \"12px\", color: loading ? \"#1890ff\" : \"#52c41a\" }}\n >\n {loading ? \"● 生成中...\" : \"● 就绪\"}\n </span>\n </div>\n <div style={{ fontSize: \"12px\", color: \"#666\", marginBottom: \"8px\" }}>\n 💡 快捷问题:\n </div>\n <Space wrap>\n {quickQuestions.map((q, i) => (\n <Button\n key={i}\n size=\"small\"\n onClick={() => chat({ text: q })}\n disabled={loading}\n >\n {q}\n </Button>\n ))}\n </Space>\n </div>\n );\n};\n\nexport const 使用Hooks: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <div\n style={{ display: \"flex\", flexDirection: \"column\", height: \"100%\" }}\n >\n <CustomStatsBar />\n <div style={{ flex: 1 }}>\n <XAdkProvider.Chatbot />\n </div>\n </div>\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n使用 \\`useChatState\\` 和 \\`useChatActions\\` Hooks 访问状态和方法。\n\n可以在任意子组件中使用这些 Hooks 来访问聊天数据和操作。\n\n\\`\\`\\`tsx\nfunction CustomStatsBar() {\n const { messages, loading } = useChatState();\n const { chat } = useChatActions();\n\n return (\n <div>\n <p>消息数: {messages.length}</p>\n <button onClick={() => chat({ text: 'Hello' })}>\n 发送\n </button>\n </div>\n );\n}\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzI3NjE1OTQsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc2ODc5NCwiaWF0IjoxNzcyNzYxNTk0LCJqdGkiOiI2M2IyMjRkNC1iODY3LTQzNjYtYTM5ZC1hZjNmOWQ0M2YyZmMiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.QNI4bD6MjIIvv-_SFxYEOiNv9304Ps5WF3b8_qmi3YIrqJQiaJ-iT1_fENpe9dD25RXcpgIv2Xnz9cI3Lz3gHfPKwoefijhrD7_Ye-9C5ztM2OI5pfoUurc1xPvjS7FGrTMZHNbpIFXyPoDAxtzGt-hLoQAEhBhLib8lLAbAQACmBOYy3KGwJg4sSFvbLkGWgqkH2aqC8MdH50ce35leybbEJu7ImithH3rj4E2oF6EqTb3vK181DFooEJ9E_LaC_hrw8zqGh9PSJah1rO3nxUDOPnz946RLKUi0xLOtz42l6qY2nUFsd9axYunGnk2ds5gg-PcBZN_X_aa-w7SLnw\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n\n// ============================================\n// 示例 5: 简化的 Chatbot\n// ============================================\nexport const 简化界面: Story = {\n render: (args) => (\n <div\n style={{\n height: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"#f5f5f5\",\n padding: \"40px\",\n }}\n >\n <div\n style={{\n width: \"100%\",\n maxWidth: \"900px\",\n height: \"700px\",\n background: \"white\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n boxShadow: \"0 8px 24px rgba(0,0,0,0.12)\",\n }}\n >\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.Chatbot />\n </XAdkProvider>\n </div>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n最简化的聊天界面,只包含消息列表和输入框。\n\n适合嵌入到其他页面或作为对话窗口使用。\n\n\\`\\`\\`tsx\n<XAdkProvider url=\"...\" token=\"...\" config={{ appNo: 'xxx' }}>\n <XAdkProvider.Chatbot />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzI3NjE1OTQsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc2ODc5NCwiaWF0IjoxNzcyNzYxNTk0LCJqdGkiOiI2M2IyMjRkNC1iODY3LTQzNjYtYTM5ZC1hZjNmOWQ0M2YyZmMiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.QNI4bD6MjIIvv-_SFxYEOiNv9304Ps5WF3b8_qmi3YIrqJQiaJ-iT1_fENpe9dD25RXcpgIv2Xnz9cI3Lz3gHfPKwoefijhrD7_Ye-9C5ztM2OI5pfoUurc1xPvjS7FGrTMZHNbpIFXyPoDAxtzGt-hLoQAEhBhLib8lLAbAQACmBOYy3KGwJg4sSFvbLkGWgqkH2aqC8MdH50ce35leybbEJu7ImithH3rj4E2oF6EqTb3vK181DFooEJ9E_LaC_hrw8zqGh9PSJah1rO3nxUDOPnz946RLKUi0xLOtz42l6qY2nUFsd9axYunGnk2ds5gg-PcBZN_X_aa-w7SLnw\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["Button","Space","XAdkProvider","useChatState","useChatActions","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","meta","title","component","parameters","layout","docs","description","tags","argTypes","url","control","token","默认布局","render","args","style","height","children","config","DefaultLayout","showSessionList","allowUpload","clearBtnShow","story","appNo","带会话列表","header","showFnCallDetail","自定义布局","display","flex","flexDirection","padding","background","color","borderBottom","margin","fontSize","overflow","Messages","Sender","CustomStatsBar","_useChatState","messages","loading","appInfo","_useChatActions","chat","quickQuestions","justifyContent","alignItems","marginBottom","length","appName","wrap","map","q","i","size","onClick","text","disabled","使用Hooks","Chatbot","简化界面","width","maxWidth","borderRadius","boxShadow"],"sources":["../../../../src/components/XAdkProvider/XAdkProvider.stories.tsx"],"sourcesContent":["import type { Meta, StoryObj } from \"@storybook/react-vite\";\nimport { Button, Space } from \"antd\";\nimport XAdkProvider from \"./index\";\nimport { useChatState, useChatActions } from \"./context\";\n\nconst meta: Meta<typeof XAdkProvider> = {\n title: \"AI组件/XAdkProvider 对话容器\",\n component: XAdkProvider,\n parameters: {\n layout: \"fullscreen\",\n docs: {\n description: {\n component: `\n# XAdkProvider - 新一代 Compound Components 架构\n\n基于 Compound Components 模式的 AI 聊天 SDK,提供完全可组合的聊天界面。\n\n## 核心特性\n\n- 🧩 **完全可组合**: 自由组合子组件,构建任意布局\n- 🪝 **Hooks 访问**: 通过 Hooks 轻松访问状态和方法\n- ⚡ **性能优化**: Context 三层分离,避免不必要的 rerender\n- 🔙 **向后兼容**: 旧 API 完全保留,平滑升级\n- 📘 **TypeScript**: 完整的类型支持\n\n## 可用组件\n\n- \\`XAdkProvider.DefaultLayout\\` - 默认布局 (类似 ChatGPT/DeepSeek)\n- \\`XAdkProvider.Chatbot\\` - 完整的聊天界面 (Messages + Sender)\n- \\`XAdkProvider.Messages\\` - 消息列表\n- \\`XAdkProvider.Sender\\` - 输入框\n- \\`XAdkProvider.Sidebar\\` - 会话列表\n- \\`XAdkProvider.Header\\` - 可选头部\n\n## 可用 Hooks\n\n- \\`useChatState()\\` - 访问聊天状态\n- \\`useChatActions()\\` - 访问聊天方法\n- \\`useSession()\\` - 访问会话管理\n\n## 配置说明\n\n请在使用前配置:\n- \\`url\\`: AI 服务地址 (默认: window.location.origin)\n- \\`token\\`: 认证令牌 (必填)\n- \\`config.appNo\\`: 应用编号 (必填)\n `,\n },\n },\n },\n tags: [\"autodocs\"],\n argTypes: {\n url: {\n description: \"AI 服务地址\",\n control: \"text\",\n },\n token: {\n description: \"认证令牌\",\n control: \"text\",\n },\n },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\n// ============================================\n// 示例 1: 默认布局 (类似 ChatGPT)\n// ============================================\nexport const 默认布局: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.DefaultLayout\n showSessionList={false}\n allowUpload={true}\n clearBtnShow={true}\n />\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n默认布局,类似 ChatGPT 的界面风格。\n\n\\`\\`\\`tsx\n<XAdkProvider url=\"...\" token=\"...\" config={{ appNo: 'xxx' }}>\n <XAdkProvider.DefaultLayout\n showSessionList={false}\n allowUpload={true}\n clearBtnShow={true}\n />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiLCJhdWQiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiLCJuYmYiOjE3NzI3ODU3OTMsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMiXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc5Mjk5MywiaWF0IjoxNzcyNzg1NzkzLCJqdGkiOiI4MmFjMGZmZS1lZDBlLTRiMjMtYWE3NS04NmUzZjA1OTQ2NmEiLCJjbGllbnRfaWQiOiJ3VFhIOE5SZUQ2TkloV0tWZkJRQ3hXdlMifQ.bBipIkOwu4BQqtH_ijT1V12yw5SnDpu7HAZhWrzjRSF7NUlqXr3m25f1VU_jiE9wyHO0Pj0VMMox1xVrE90JT9zgFL2sa4IDLpoHl6B2sr-3pY8WsvTLnk9PBSyTfOjmuSRwNDZyQYx0p4xJKd0yhf5Acfh5vuvH8pW7ksGpEXKvCLqc9tpeLytE1qZm_eSWt_rjTxDzvwMv33RAWO_fEigezoXfOe8ALtWpIDXEoza6cI--2buVM6-ZAFJHwe0CA_rx5E5H7QpmonUlZZhu9JVEL7HCc76MWLnuRP9TlNuicsR3JrYvkZ8nkG4oiBSWaHAgOVizGXaf2Elr7edTNA\",\n config: {\n appNo: \"wTXH8NReD6NIhWKVfBQCxWvS\",\n },\n },\n};\n\n// ============================================\n// 示例 2: 带会话列表 (类似 DeepSeek)\n// ============================================\nexport const 带会话列表: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.DefaultLayout\n header={<></>}\n showSessionList={true}\n allowUpload={true}\n clearBtnShow={false}\n showFnCallDetail={true}\n />\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n带会话列表的布局,类似 DeepSeek/元宝 的界面风格。\n\n左侧显示历史会话列表,右侧显示聊天区域。\n\n特点:\n- ✅ 左右布局: 左侧 280px 宽的会话列表,右侧聊天区域\n- ✅ 会话管理: 支持新建、切换、重命名、删除会话\n- ✅ 自动加载: 会话列表自动加载历史记录\n- ✅ 响应式: 窄屏自动切换到侧边栏模式\n\n\\`\\`\\`tsx\n<XAdkProvider\n url=\"...\"\n token=\"...\"\n config={{\n appNo: 'xxx',\n session: {\n showSessionList: true,\n }\n }}\n>\n <XAdkProvider.DefaultLayout\n showSessionList={true}\n allowUpload={true}\n />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJhdWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iLCJuYmYiOjE3NzM2NDk5MjIsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3MzY1NzEyMiwiaWF0IjoxNzczNjQ5OTIyLCJqdGkiOiI1NzY3Mjk3MC05ZmZlLTQzYmYtOTBmMy03ZDlmNDY4OTZjMGEiLCJjbGllbnRfaWQiOiJNRlg1VHhsaGVJS2Jla1pIS29lT1ZObG8ifQ.ojer50ubE3oyBxPDW9JsZpQkzuvlbHYtLgl4jpdnUB1GSnlhNTPw9tShDuoLVjrKeeSVYsqfNTk-JN4xmYUxHs4cdy0-Sn6j2oLfbFYXI1p_8oQqOllhPKJWQA-JiOWMjm6iHpYOnotx14oGfgO6EKD2I9kLvRkje0DuEVKsj22s_XEimpfMCLtxCgn-lzmIVr90MU_1jt01q7MnPOA35rKTPlVLUg2Mw3a7JsmBPSvR25uDiX0x_ueG3riSko1cY37TXuSPIuBsD6N6aptv1RZ25-pGt6DjP3QOKnLfLc9N7_jIIcfbRzYYOOxp0Y4ond6fF5wWZI8S1wckZbBHiA\",\n config: {\n appNo: \"MFX5TxlheIKbekZHKoeOVNlo\",\n },\n },\n};\n\n// ============================================\n// 示例 3: 自定义布局\n// ============================================\nexport const 自定义布局: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <div style={{ display: \"flex\", height: \"100%\" }}>\n {/* 左侧会话列表 */}\n {/* <div\n style={{\n width: 300,\n borderRight: \"1px solid #f0f0f0\",\n background: \"#fafafa\",\n }}\n >\n <XAdkProvider.Sidebar />\n </div> */}\n\n {/* 右侧聊天区 */}\n <div style={{ flex: 1, display: \"flex\", flexDirection: \"column\" }}>\n {/* 自定义头部 */}\n <div\n style={{\n padding: \"16px 24px\",\n background: \"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\",\n color: \"white\",\n borderBottom: \"1px solid rgba(255,255,255,0.1)\",\n }}\n >\n <h2 style={{ margin: 0, fontSize: \"18px\" }}>🤖 AI 智能助手</h2>\n </div>\n\n {/* 消息区 */}\n <div style={{ flex: 1, overflow: \"hidden\", background: \"#f9fafb\" }}>\n <XAdkProvider.Messages />\n </div>\n\n {/* 输入区 */}\n <XAdkProvider.Sender allowUpload={true} clearBtnShow={true} />\n </div>\n </div>\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n完全自定义的布局,展示 Compound Components 的灵活性。\n\n可以任意组合 Sidebar、Messages、Sender 等组件。\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzMwNjI5MjUsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3MzA3MDEyNSwiaWF0IjoxNzczMDYyOTI1LCJqdGkiOiI0YmY3MjcxOS03NzNkLTRkZGYtOGYzNC01YjAwNjA5MWE3Y2IiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.AcWWnsWZVHvvpbT9IG64oo6mNNUFDKuaTMSCRMUvgiRyfn8f4Y64GBF_VR_XhgvNgNczXx5pXlU5AEXlvwA3RXv5Voy5Vl1dvyrLOtjZivnRJVeDVzn8Af57cXKE9QBZAS94bUMAtfmZmvqer4Lw6wuFNSg6G32BCpQH6ifR8zei3scf1Gcs0QXr00KcT3dFROmAzJscJC_KnXxGx_729BlQqupdJ05KEGHDIokqJNy5Ev_40IPmW-ZDJprXpEdReHfHnPuaUgGQRAJEW2yTf2OsyNenOwA9l0iKYK1ENDnBpsr08VUgMhJBKq-quzP5AE3eLIn-3KR0O-yT4lyBiQ\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n\n// ============================================\n// 示例 4: 使用 Hooks\n// ============================================\nconst CustomStatsBar = () => {\n const { messages, loading, appInfo } = useChatState();\n const { chat } = useChatActions();\n\n const quickQuestions = [\"介绍一下你自己\", \"你能帮我做什么?\", \"如何开始使用?\"];\n\n return (\n <div\n style={{\n padding: \"16px 20px\",\n background: \"white\",\n borderBottom: \"1px solid #f0f0f0\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: \"12px\",\n }}\n >\n <Space>\n <span style={{ fontSize: \"12px\", color: \"#999\" }}>\n 💬 消息数: <strong>{messages.length}</strong>\n </span>\n <span style={{ fontSize: \"12px\", color: \"#999\" }}>\n 🤖 {appInfo?.appName || \"加载中...\"}\n </span>\n </Space>\n <span\n style={{ fontSize: \"12px\", color: loading ? \"#1890ff\" : \"#52c41a\" }}\n >\n {loading ? \"● 生成中...\" : \"● 就绪\"}\n </span>\n </div>\n <div style={{ fontSize: \"12px\", color: \"#666\", marginBottom: \"8px\" }}>\n 💡 快捷问题:\n </div>\n <Space wrap>\n {quickQuestions.map((q, i) => (\n <Button\n key={i}\n size=\"small\"\n onClick={() => chat({ text: q })}\n disabled={loading}\n >\n {q}\n </Button>\n ))}\n </Space>\n </div>\n );\n};\n\nexport const 使用Hooks: Story = {\n render: (args) => (\n <div style={{ height: \"100vh\" }}>\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <div\n style={{ display: \"flex\", flexDirection: \"column\", height: \"100%\" }}\n >\n <CustomStatsBar />\n <div style={{ flex: 1 }}>\n <XAdkProvider.Chatbot />\n </div>\n </div>\n </XAdkProvider>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n使用 \\`useChatState\\` 和 \\`useChatActions\\` Hooks 访问状态和方法。\n\n可以在任意子组件中使用这些 Hooks 来访问聊天数据和操作。\n\n\\`\\`\\`tsx\nfunction CustomStatsBar() {\n const { messages, loading } = useChatState();\n const { chat } = useChatActions();\n\n return (\n <div>\n <p>消息数: {messages.length}</p>\n <button onClick={() => chat({ text: 'Hello' })}>\n 发送\n </button>\n </div>\n );\n}\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzI3NjE1OTQsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc2ODc5NCwiaWF0IjoxNzcyNzYxNTk0LCJqdGkiOiI2M2IyMjRkNC1iODY3LTQzNjYtYTM5ZC1hZjNmOWQ0M2YyZmMiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.QNI4bD6MjIIvv-_SFxYEOiNv9304Ps5WF3b8_qmi3YIrqJQiaJ-iT1_fENpe9dD25RXcpgIv2Xnz9cI3Lz3gHfPKwoefijhrD7_Ye-9C5ztM2OI5pfoUurc1xPvjS7FGrTMZHNbpIFXyPoDAxtzGt-hLoQAEhBhLib8lLAbAQACmBOYy3KGwJg4sSFvbLkGWgqkH2aqC8MdH50ce35leybbEJu7ImithH3rj4E2oF6EqTb3vK181DFooEJ9E_LaC_hrw8zqGh9PSJah1rO3nxUDOPnz946RLKUi0xLOtz42l6qY2nUFsd9axYunGnk2ds5gg-PcBZN_X_aa-w7SLnw\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n\n// ============================================\n// 示例 5: 简化的 Chatbot\n// ============================================\nexport const 简化界面: Story = {\n render: (args) => (\n <div\n style={{\n height: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"#f5f5f5\",\n padding: \"40px\",\n }}\n >\n <div\n style={{\n width: \"100%\",\n maxWidth: \"900px\",\n height: \"700px\",\n background: \"white\",\n borderRadius: \"12px\",\n overflow: \"hidden\",\n boxShadow: \"0 8px 24px rgba(0,0,0,0.12)\",\n }}\n >\n <XAdkProvider url={args.url} token={args.token} config={args.config}>\n <XAdkProvider.Chatbot />\n </XAdkProvider>\n </div>\n </div>\n ),\n parameters: {\n docs: {\n description: {\n story: `\n最简化的聊天界面,只包含消息列表和输入框。\n\n适合嵌入到其他页面或作为对话窗口使用。\n\n\\`\\`\\`tsx\n<XAdkProvider url=\"...\" token=\"...\" config={{ appNo: 'xxx' }}>\n <XAdkProvider.Chatbot />\n</XAdkProvider>\n\\`\\`\\`\n `,\n },\n },\n },\n args: {\n url: \"https://m-poc-dev.zaxline.com\",\n token:\n \"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJhdWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iLCJuYmYiOjE3NzI3NjE1OTQsInVzZXJfaWQiOiJWNFNPSG1KbzNaZWE0Uk51ZzdYWDJBPT0iLCJzY29wZSI6WyIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08iXSwiaXNzIjoiaHR0cDovL2htLWF1dGgtc2VydmVyLnhsaW5lLWRldi50ZXN0LnhpbmtlLmJpeiIsImV4cCI6MTc3Mjc2ODc5NCwiaWF0IjoxNzcyNzYxNTk0LCJqdGkiOiI2M2IyMjRkNC1iODY3LTQzNjYtYTM5ZC1hZjNmOWQ0M2YyZmMiLCJjbGllbnRfaWQiOiIzanQyWWJEamV3Vm4yUEhSS2FEZkpFZ08ifQ.QNI4bD6MjIIvv-_SFxYEOiNv9304Ps5WF3b8_qmi3YIrqJQiaJ-iT1_fENpe9dD25RXcpgIv2Xnz9cI3Lz3gHfPKwoefijhrD7_Ye-9C5ztM2OI5pfoUurc1xPvjS7FGrTMZHNbpIFXyPoDAxtzGt-hLoQAEhBhLib8lLAbAQACmBOYy3KGwJg4sSFvbLkGWgqkH2aqC8MdH50ce35leybbEJu7ImithH3rj4E2oF6EqTb3vK181DFooEJ9E_LaC_hrw8zqGh9PSJah1rO3nxUDOPnz946RLKUi0xLOtz42l6qY2nUFsd9axYunGnk2ds5gg-PcBZN_X_aa-w7SLnw\",\n config: {\n appNo: \"3jt2YbDjewVn2PHRKaDfJEgO\",\n },\n },\n};\n"],"mappings":"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"}
|