@antv/dumi-theme-antv 0.8.0-beta.0 → 0.8.0-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/components/AI/HomeDialog/ModeSelector/index.js +4 -1
- package/dist/components/AI/HomeDialog/PromptTextarea/ChooseLib/index.js +5 -2
- package/dist/components/AI/HomeDialog/PromptTextarea/Uploader/DataUploader.js +225 -0
- package/dist/components/AI/HomeDialog/PromptTextarea/index.js +62 -24
- package/dist/components/AI/HomeDialog/PromptTextarea/index.module.less +1 -0
- package/dist/components/AI/HomeDialog/RecommendCase/Card.js +10 -3
- package/dist/components/AI/HomeDialog/RecommendCase/index.js +8 -3
- package/dist/components/AI/HomeDialog/index.js +12 -3
- package/dist/components/AI/constant.js +2 -2
- package/dist/hooks/useStreamingText.js +38 -18
- package/dist/hooks/useTypewriter.js +69 -0
- package/dist/locales/en.json +91 -1
- package/dist/locales/zh.json +91 -1
- package/dist/model/AIChat.js +20 -8
- package/dist/pages/AIPlayground/components/ConversationsMenu/index.js +29 -7
- package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.js +41 -18
- package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.module.less +14 -0
- package/dist/pages/AIPlayground/components/MarkdownComponent/index.js +1 -1
- package/dist/pages/AIPlayground/components/MsgBox/index.js +149 -47
- package/dist/pages/AIPlayground/components/SessionLayout/index.js +18 -10
- package/dist/pages/AIPlayground/components/SessionLayout/index.module.less +3 -0
- package/dist/pages/AIPlayground/components/TaskBox/generateCode.js +3 -4
- package/dist/pages/AIPlayground/components/TaskBox/index.js +1 -0
- package/dist/plugin/index.js +2 -2
- package/dist/slots/CodeEditor/Toolbar.js +17 -7
- package/dist/slots/CodeEditor/Toolbar.module.less +1 -0
- package/dist/slots/CodeEditor/index.js +18 -4
- package/dist/slots/CodeRunner/index.js +2 -1
- package/dist/slots/Header/Search/SearchResult.js +9 -3
- package/dist/slots/Header/index.js +24 -8
- package/dist/static/SearchAiIcon.svg +14 -0
- package/dist/utils/code.js +35 -0
- package/package.json +1 -1
|
@@ -61,49 +61,69 @@ export var useStreamingText = function useStreamingText(_ref) {
|
|
|
61
61
|
}
|
|
62
62
|
throw new Error('Response body is null');
|
|
63
63
|
case 8:
|
|
64
|
+
if (!(response.headers.get("content-type") === "application/json")) {
|
|
65
|
+
_context.next = 19;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
_context.t0 = onFinish === null || onFinish === void 0;
|
|
69
|
+
if (_context.t0) {
|
|
70
|
+
_context.next = 18;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
_context.t1 = onFinish;
|
|
74
|
+
_context.t2 = JSON;
|
|
75
|
+
_context.next = 15;
|
|
76
|
+
return response.json();
|
|
77
|
+
case 15:
|
|
78
|
+
_context.t3 = _context.sent;
|
|
79
|
+
_context.t4 = _context.t2.stringify.call(_context.t2, _context.t3);
|
|
80
|
+
(0, _context.t1)(_context.t4);
|
|
81
|
+
case 18:
|
|
82
|
+
return _context.abrupt("return");
|
|
83
|
+
case 19:
|
|
64
84
|
reader = response.body.getReader();
|
|
65
85
|
decoder = new TextDecoder();
|
|
66
86
|
accumulatedText = '';
|
|
67
|
-
case
|
|
87
|
+
case 22:
|
|
68
88
|
if (!true) {
|
|
69
|
-
_context.next =
|
|
89
|
+
_context.next = 36;
|
|
70
90
|
break;
|
|
71
91
|
}
|
|
72
|
-
_context.next =
|
|
92
|
+
_context.next = 25;
|
|
73
93
|
return reader.read();
|
|
74
|
-
case
|
|
94
|
+
case 25:
|
|
75
95
|
_yield$reader$read = _context.sent;
|
|
76
96
|
done = _yield$reader$read.done;
|
|
77
97
|
value = _yield$reader$read.value;
|
|
78
98
|
if (!done) {
|
|
79
|
-
_context.next =
|
|
99
|
+
_context.next = 31;
|
|
80
100
|
break;
|
|
81
101
|
}
|
|
82
102
|
onFinish === null || onFinish === void 0 || onFinish(accumulatedText); // 流结束时调用 onFinish
|
|
83
|
-
return _context.abrupt("break",
|
|
84
|
-
case
|
|
103
|
+
return _context.abrupt("break", 36);
|
|
104
|
+
case 31:
|
|
85
105
|
chunk = decoder.decode(value, {
|
|
86
106
|
stream: true
|
|
87
107
|
});
|
|
88
108
|
accumulatedText += chunk;
|
|
89
109
|
setText(accumulatedText);
|
|
90
|
-
_context.next =
|
|
110
|
+
_context.next = 22;
|
|
91
111
|
break;
|
|
92
|
-
case
|
|
93
|
-
_context.next =
|
|
112
|
+
case 36:
|
|
113
|
+
_context.next = 41;
|
|
94
114
|
break;
|
|
95
|
-
case
|
|
96
|
-
_context.prev =
|
|
97
|
-
_context.
|
|
98
|
-
if (_context.
|
|
99
|
-
console.error('Streaming fetch error:', _context.
|
|
100
|
-
onError === null || onError === void 0 || onError(_context.
|
|
115
|
+
case 38:
|
|
116
|
+
_context.prev = 38;
|
|
117
|
+
_context.t5 = _context["catch"](0);
|
|
118
|
+
if (_context.t5.name !== 'AbortError') {
|
|
119
|
+
console.error('Streaming fetch error:', _context.t5);
|
|
120
|
+
onError === null || onError === void 0 || onError(_context.t5);
|
|
101
121
|
}
|
|
102
|
-
case
|
|
122
|
+
case 41:
|
|
103
123
|
case "end":
|
|
104
124
|
return _context.stop();
|
|
105
125
|
}
|
|
106
|
-
}, _callee, null, [[0,
|
|
126
|
+
}, _callee, null, [[0, 38]]);
|
|
107
127
|
}));
|
|
108
128
|
return function fetchData() {
|
|
109
129
|
return _ref2.apply(this, arguments);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
import { useState, useEffect } from 'react';
|
|
8
|
+
|
|
9
|
+
// Hook的参数类型定义
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 一个自定义React Hook,用于实现打字机效果。
|
|
13
|
+
* @param {TypewriterOptions} options - 配置选项
|
|
14
|
+
* @returns {string} 当前应显示的文本
|
|
15
|
+
*/
|
|
16
|
+
export var useTypewriter = function useTypewriter(_ref) {
|
|
17
|
+
var texts = _ref.texts,
|
|
18
|
+
_ref$typingSpeed = _ref.typingSpeed,
|
|
19
|
+
typingSpeed = _ref$typingSpeed === void 0 ? 150 : _ref$typingSpeed,
|
|
20
|
+
_ref$pauseDelay = _ref.pauseDelay,
|
|
21
|
+
pauseDelay = _ref$pauseDelay === void 0 ? 2000 : _ref$pauseDelay;
|
|
22
|
+
// 当前显示第几个字符串
|
|
23
|
+
var _useState = useState(0),
|
|
24
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
25
|
+
textIndex = _useState2[0],
|
|
26
|
+
setTextIndex = _useState2[1];
|
|
27
|
+
// 当前字符串显示到第几个字符
|
|
28
|
+
var _useState3 = useState(0),
|
|
29
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
30
|
+
charIndex = _useState4[0],
|
|
31
|
+
setCharIndex = _useState4[1];
|
|
32
|
+
useEffect(function () {
|
|
33
|
+
// 获取当前要处理的完整字符串
|
|
34
|
+
var currentText = texts[textIndex];
|
|
35
|
+
|
|
36
|
+
// 如果当前字符索引小于字符串长度,说明还在打字过程中
|
|
37
|
+
if (charIndex < currentText.length) {
|
|
38
|
+
var typingTimeout = setTimeout(function () {
|
|
39
|
+
setCharIndex(function (prev) {
|
|
40
|
+
return prev + 1;
|
|
41
|
+
});
|
|
42
|
+
}, typingSpeed);
|
|
43
|
+
|
|
44
|
+
// 清除定时器,防止内存泄漏
|
|
45
|
+
return function () {
|
|
46
|
+
return clearTimeout(typingTimeout);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// 如果字已经打完
|
|
50
|
+
else {
|
|
51
|
+
var pauseTimeout = setTimeout(function () {
|
|
52
|
+
// 切换到下一个字符串
|
|
53
|
+
setTextIndex(function (prev) {
|
|
54
|
+
return (prev + 1) % texts.length;
|
|
55
|
+
});
|
|
56
|
+
// 重置字符索引,从头开始
|
|
57
|
+
setCharIndex(0);
|
|
58
|
+
}, pauseDelay);
|
|
59
|
+
|
|
60
|
+
// 清除定时器
|
|
61
|
+
return function () {
|
|
62
|
+
return clearTimeout(pauseTimeout);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}, [charIndex, textIndex, texts, typingSpeed, pauseDelay]);
|
|
66
|
+
|
|
67
|
+
// 根据当前状态截取并返回应该显示的字符串
|
|
68
|
+
return texts[textIndex].substring(0, charIndex);
|
|
69
|
+
};
|
package/dist/locales/en.json
CHANGED
|
@@ -178,5 +178,95 @@
|
|
|
178
178
|
"企业级 Node 开发框架": "Enterprise-class Node development framework",
|
|
179
179
|
"Sketch 工具集": "Sketch Tool set",
|
|
180
180
|
"互动图形解决方案": "Interactive solution",
|
|
181
|
-
"前端智能研发": "AI Coding Assistant"
|
|
181
|
+
"前端智能研发": "AI Coding Assistant",
|
|
182
|
+
"ai.placeholder.implement": "What would you like to visualize today?",
|
|
183
|
+
"ai.placeholder.solve": "What visualization problem would you like to solve today?",
|
|
184
|
+
"ai.mode.implement": "Develop",
|
|
185
|
+
"ai.mode.solve": "Q&A",
|
|
186
|
+
"ai.upload.tooltip": "Only supports csv,json,tsv,txt files. For performance and cost reasons, only the first few lines will be used as samples",
|
|
187
|
+
"ai.upload.data": "Upload Data",
|
|
188
|
+
"ai.upload.image": "Upload Image",
|
|
189
|
+
"ai.upload.analyzing": "Analyzing...",
|
|
190
|
+
"ai.upload.file.empty": "File is empty.",
|
|
191
|
+
"ai.upload.file.parse.error": "File content format error, unable to parse.",
|
|
192
|
+
"ai.upload.file.read.error": "Failed to read file.",
|
|
193
|
+
"ai.upload.file.type.error": "Unsupported file type. Please upload {types} files.",
|
|
194
|
+
"ai.upload.file.size.error": "File size cannot exceed {size}MB!",
|
|
195
|
+
"ai.upload.file.parse.type.error": "Unsupported file parsing type",
|
|
196
|
+
"ai.upload.file.summary.truncated": "... (Data summary truncated)",
|
|
197
|
+
"ai.upload.file.full.content": "User uploaded a data file, its complete content is as follows:\n\n{fileContent}",
|
|
198
|
+
"ai.upload.file.table.summary": "This is tabular data containing approximately {rowCount} rows and {columnCount} columns.\nColumn headers are: {header}\nFirst {maxLines} rows of sample data:\n{sampleRows}",
|
|
199
|
+
"ai.upload.file.json.array.summary": "This is a JSON array containing {dataLength} objects.\nKeys for each object are: {keys}\nFirst {maxLines} sample objects:\n{sampleData}",
|
|
200
|
+
"ai.upload.file.json.object.summary": "This is a JSON object. Its structure and partial data are as follows:",
|
|
201
|
+
"ai.msgbox.like": "Like",
|
|
202
|
+
"ai.msgbox.dislike": "Dislike",
|
|
203
|
+
"ai.msgbox.retry": "Try Again",
|
|
204
|
+
"ai.msgbox.copy": "Copy",
|
|
205
|
+
"ai.msgbox.start.new.chat": "Start New Chat",
|
|
206
|
+
"ai.msgbox.send.tip": "Please enter content before sending",
|
|
207
|
+
"ai.msgbox.error.response": "Sorry, I couldn't successfully process your request, please try again later",
|
|
208
|
+
"ai.recommend.title": "Featured Cases",
|
|
209
|
+
"ai.recommend.refresh": "Refresh",
|
|
210
|
+
"ai.recommend.card.caseName": "Case Name",
|
|
211
|
+
"ai.recommend.card.description": "Description",
|
|
212
|
+
"ai.markdown.copy": "Copy",
|
|
213
|
+
"ai.markdown.run": "Run this code snippet",
|
|
214
|
+
"ai.toolbar.assistant": "AI Assistant",
|
|
215
|
+
"ai.toolbar.restore": "Restore",
|
|
216
|
+
"ai.toolbar.execute": "Execute Code",
|
|
217
|
+
"ai.toolbar.open.codesandbox": "Open in CodeSandbox",
|
|
218
|
+
"ai.toolbar.open.stackblitz": "Open in StackBlitz",
|
|
219
|
+
"ai.toolbar.open.riddle": "Open in Riddle",
|
|
220
|
+
"ai.toolbar.html.code": "HTML Code",
|
|
221
|
+
"ai.conversations.expand": "Expand",
|
|
222
|
+
"ai.conversations.collapse": "Collapse",
|
|
223
|
+
"ai.conversations.new": "Start New Chat",
|
|
224
|
+
"ai.conversations.history": "History",
|
|
225
|
+
"ai.conversations.rename": "Rename",
|
|
226
|
+
"ai.conversations.pin": "Pin",
|
|
227
|
+
"ai.conversations.delete": "Delete",
|
|
228
|
+
"ai.conversations.edit.title": "Edit Conversation Name",
|
|
229
|
+
"ai.chooseLib.placeholder": "Choose Technology Stack",
|
|
230
|
+
"ai.search.try": "Try",
|
|
231
|
+
"ai.search.visualization": "Q&A",
|
|
232
|
+
"ai.assistant.editor.intro": "I am AntV AI Assistant. You can ask me questions at any time to:\n1. Interpret the code configuration of the current chart.\n2. Generate new code based on the current case through natural language dialogue to customize the chart.",
|
|
233
|
+
"ai.placeholder.whatis": "What is {title}?",
|
|
234
|
+
"header.ai.code": "AI Code Generation",
|
|
235
|
+
"header.china.mirror.title": "AntV series websites are deployed on gh-pages. If the access speed is poor, you can visit the domestic mirror site.",
|
|
236
|
+
"header.china.mirror.temp.close": "Close Temporarily",
|
|
237
|
+
"header.china.mirror.no.more": "Don't Remind Again",
|
|
238
|
+
"header.wx.qrcode.title": "Scan QR Code to Follow",
|
|
239
|
+
"feedback.page.helpful": "Was this page helpful?",
|
|
240
|
+
"feedback.page.easy.understand": "Easy to understand",
|
|
241
|
+
"feedback.page.solved.problem": "Solved my problem",
|
|
242
|
+
"feedback.page.other": "Other",
|
|
243
|
+
"feedback.page.missing.info": "Missing information I need",
|
|
244
|
+
"feedback.page.too.complex": "Too complicated/Too many steps",
|
|
245
|
+
"feedback.page.outdated": "Content is outdated",
|
|
246
|
+
"feedback.page.code.issue": "Sample/Code issue",
|
|
247
|
+
"feedback.page.reason.title": "🚀 What is the reason for your feedback?",
|
|
248
|
+
"feedback.page.issue.alert": "If something is broken or if you need a reply to a problem you've encountered, please ",
|
|
249
|
+
"feedback.page.issue.report": "open an issue instead",
|
|
250
|
+
"feedback.page.issue.alert.end": ". Otherwise, the team won't be able to answer back or ask for more information.",
|
|
251
|
+
"feedback.section.improve": "How can we improve",
|
|
252
|
+
"feedback.section.improve.end": "section? ",
|
|
253
|
+
"feedback.result.success": "Feedback Submitted",
|
|
254
|
+
"feedback.result.error": "Error, please try again later",
|
|
255
|
+
"feedback.result.thanks": "Thank you for your feedback!",
|
|
256
|
+
"feedback.result.github.issue": "Go head to GitHub issue if the problem persists.",
|
|
257
|
+
"feedback.result.problem.type": "What kind of problem are you facing?",
|
|
258
|
+
"feedback.result.reason": "🚀 What is the reason for your feedback?",
|
|
259
|
+
"feedback.result.easy.understand": "Easy to understand",
|
|
260
|
+
"feedback.result.solved.problem": "Resolved my problem",
|
|
261
|
+
"feedback.result.other": "Other",
|
|
262
|
+
"feedback.result.missing.info": "Missing the information I need",
|
|
263
|
+
"feedback.result.too.complex": "Too complicated / Too many steps",
|
|
264
|
+
"feedback.result.outdated": "Out of date",
|
|
265
|
+
"feedback.result.code.issue": "Sample / code issue",
|
|
266
|
+
"feedback.result.previous": "Previous",
|
|
267
|
+
"feedback.result.next": "Next",
|
|
268
|
+
"feedback.result.demo.error": "Demo code error, please check",
|
|
269
|
+
"feedback.result.reading.time": "Reading needs",
|
|
270
|
+
"feedback.result.minutes": "minutes",
|
|
271
|
+
"feedback.result.no.results": "No query result found"
|
|
182
272
|
}
|
package/dist/locales/zh.json
CHANGED
|
@@ -177,5 +177,95 @@
|
|
|
177
177
|
"企业级 Node 开发框架": "企业级 Node 开发框架",
|
|
178
178
|
"Sketch 工具集": "Sketch 工具集",
|
|
179
179
|
"互动图形解决方案": "互动图形解决方案",
|
|
180
|
-
"前端智能研发": "前端智能研发"
|
|
180
|
+
"前端智能研发": "前端智能研发",
|
|
181
|
+
"ai.placeholder.implement": "今天,你想可视化什么?",
|
|
182
|
+
"ai.placeholder.solve": "今天,你想解决什么可视化问题?",
|
|
183
|
+
"ai.mode.implement": "可视化研发",
|
|
184
|
+
"ai.mode.solve": "可视化答疑",
|
|
185
|
+
"ai.upload.tooltip": "仅支持csv,json,tsv,txt文件,为了性能和成本,只会使用文件的前几行作为样本",
|
|
186
|
+
"ai.upload.data": "上传数据",
|
|
187
|
+
"ai.upload.image": "上传图片",
|
|
188
|
+
"ai.upload.analyzing": "分析中...",
|
|
189
|
+
"ai.upload.file.empty": "文件为空。",
|
|
190
|
+
"ai.upload.file.parse.error": "文件内容格式错误,无法解析。",
|
|
191
|
+
"ai.upload.file.read.error": "读取文件失败。",
|
|
192
|
+
"ai.upload.file.type.error": "不支持的文件类型。请上传 {types} 文件。",
|
|
193
|
+
"ai.upload.file.size.error": "文件大小不能超过 {size}MB!",
|
|
194
|
+
"ai.upload.file.parse.type.error": "不支持的文件解析类型",
|
|
195
|
+
"ai.upload.file.summary.truncated": "... (数据摘要已截断)",
|
|
196
|
+
"ai.upload.file.full.content": "用户上传了一个数据文件,其完整内容如下:\n\n{fileContent}",
|
|
197
|
+
"ai.upload.file.table.summary": "这是一个包含约 {rowCount} 行和 {columnCount} 列的表格数据。\n列名(Header)是: {header}\n前{maxLines}行样本数据如下:\n{sampleRows}",
|
|
198
|
+
"ai.upload.file.json.array.summary": "这是一个包含 {dataLength} 个对象的JSON数组。\n每个对象的键(Keys)是: {keys}\n前{maxLines}个样本对象如下:\n{sampleData}",
|
|
199
|
+
"ai.upload.file.json.object.summary": "这是一个JSON对象。其结构和部分数据如下:",
|
|
200
|
+
"ai.msgbox.like": "点赞",
|
|
201
|
+
"ai.msgbox.dislike": "点踩",
|
|
202
|
+
"ai.msgbox.retry": "再来一次",
|
|
203
|
+
"ai.msgbox.copy": "复制",
|
|
204
|
+
"ai.msgbox.start.new.chat": "开始新对话",
|
|
205
|
+
"ai.msgbox.send.tip": "请输入内容后发送指令",
|
|
206
|
+
"ai.msgbox.error.response": "抱歉,我没能成功处理您的请求,请稍后再次提问",
|
|
207
|
+
"ai.recommend.title": "精选案例",
|
|
208
|
+
"ai.recommend.refresh": "换一批",
|
|
209
|
+
"ai.recommend.card.caseName": "案例名",
|
|
210
|
+
"ai.recommend.card.description": "描述信息",
|
|
211
|
+
"ai.markdown.copy": "复制",
|
|
212
|
+
"ai.markdown.run": "运行此代码片段",
|
|
213
|
+
"ai.toolbar.assistant": "AI 助手",
|
|
214
|
+
"ai.toolbar.restore": "还原",
|
|
215
|
+
"ai.toolbar.execute": "执行代码",
|
|
216
|
+
"ai.toolbar.open.codesandbox": "在 CodeSandbox 中打开",
|
|
217
|
+
"ai.toolbar.open.stackblitz": "在 StackBlitz 中打开",
|
|
218
|
+
"ai.toolbar.open.riddle": "在 Riddle 中打开",
|
|
219
|
+
"ai.toolbar.html.code": "HTML 代码",
|
|
220
|
+
"ai.conversations.expand": "展开",
|
|
221
|
+
"ai.conversations.collapse": "收起",
|
|
222
|
+
"ai.conversations.new": "开始新对话",
|
|
223
|
+
"ai.conversations.history": "历史对话",
|
|
224
|
+
"ai.conversations.rename": "重命名",
|
|
225
|
+
"ai.conversations.pin": "置顶",
|
|
226
|
+
"ai.conversations.delete": "删除",
|
|
227
|
+
"ai.conversations.edit.title": "编辑对话名称",
|
|
228
|
+
"ai.chooseLib.placeholder": "选择技术栈",
|
|
229
|
+
"ai.search.try": "试试",
|
|
230
|
+
"ai.search.visualization": "可视化答疑",
|
|
231
|
+
"ai.assistant.editor.intro": "我是AntV AI助手。您可以随时向我提问,让我为您:\n\n1、解读当前图表的代码配置。\n2、通过自然语言对话,基于当前案例生成新代码以定制图表。",
|
|
232
|
+
"ai.placeholder.whatis": "{title}是什么?",
|
|
233
|
+
"header.ai.code": "AI生码",
|
|
234
|
+
"header.china.mirror.title": "AntV 系列网站部署在 gh-pages 上,若访问速度不佳,可以前往国内镜像站点。",
|
|
235
|
+
"header.china.mirror.temp.close": "暂时关闭",
|
|
236
|
+
"header.china.mirror.no.more": "不再提醒",
|
|
237
|
+
"header.wx.qrcode.title": "微信扫一扫关注",
|
|
238
|
+
"feedback.page.helpful": "这个页面对你有帮助吗?",
|
|
239
|
+
"feedback.page.easy.understand": "容易理解",
|
|
240
|
+
"feedback.page.solved.problem": "解决了我的问题",
|
|
241
|
+
"feedback.page.other": "其它",
|
|
242
|
+
"feedback.page.missing.info": "缺少我需要的信息",
|
|
243
|
+
"feedback.page.too.complex": "过于复杂/步骤太多",
|
|
244
|
+
"feedback.page.outdated": "内容更新不及时",
|
|
245
|
+
"feedback.page.code.issue": "示例/代码有问题",
|
|
246
|
+
"feedback.page.reason.title": "🚀 留下你的真实感受",
|
|
247
|
+
"feedback.page.issue.alert": "如果遇到问题或发现某些功能无法正常工作,请通过",
|
|
248
|
+
"feedback.page.issue.report": "提交问题报告",
|
|
249
|
+
"feedback.page.issue.alert.end": "来反馈。否则,团队将无法提供进一步的答复或获取更多信息。",
|
|
250
|
+
"feedback.section.improve": "你认为",
|
|
251
|
+
"feedback.section.improve.end": "部分如何改进更好?",
|
|
252
|
+
"feedback.result.success": "谢谢你的反馈意见!",
|
|
253
|
+
"feedback.result.error": "报错了,请稍后再试",
|
|
254
|
+
"feedback.result.thanks": "感谢你的支持!",
|
|
255
|
+
"feedback.result.github.issue": "如果问题持续,请前往 GitHub 提交 issue。",
|
|
256
|
+
"feedback.result.problem.type": "你遇到的问题是什么?",
|
|
257
|
+
"feedback.result.reason": "🚀 留下你的真实感受",
|
|
258
|
+
"feedback.result.easy.understand": "容易理解",
|
|
259
|
+
"feedback.result.solved.problem": "有效解决了我的问题",
|
|
260
|
+
"feedback.result.other": "其它",
|
|
261
|
+
"feedback.result.missing.info": "缺少我需要的信息",
|
|
262
|
+
"feedback.result.too.complex": "过于复杂/步骤太多",
|
|
263
|
+
"feedback.result.outdated": "内容更新不及时",
|
|
264
|
+
"feedback.result.code.issue": "示例/代码有问题",
|
|
265
|
+
"feedback.result.previous": "上一篇",
|
|
266
|
+
"feedback.result.next": "下一篇",
|
|
267
|
+
"feedback.result.demo.error": "演示代码报错,请检查",
|
|
268
|
+
"feedback.result.reading.time": "阅读时间约",
|
|
269
|
+
"feedback.result.minutes": "分钟",
|
|
270
|
+
"feedback.result.no.results": "没有找到查询结果"
|
|
181
271
|
}
|
package/dist/model/AIChat.js
CHANGED
|
@@ -48,6 +48,11 @@ subscribe(AIChatStore, function () {
|
|
|
48
48
|
// 异步保存,不阻塞UI
|
|
49
49
|
localforage.setItem(STORAGE_KEY, stateToPersist);
|
|
50
50
|
});
|
|
51
|
+
export var clearEmptySession = function clearEmptySession() {
|
|
52
|
+
AIChatStore.sessions = AIChatStore.sessions.filter(function (s) {
|
|
53
|
+
return s.messages.length > 0;
|
|
54
|
+
});
|
|
55
|
+
};
|
|
51
56
|
|
|
52
57
|
// --- 初始化逻辑 ---
|
|
53
58
|
export var initializeStore = /*#__PURE__*/function () {
|
|
@@ -113,11 +118,12 @@ export var initializeStore = /*#__PURE__*/function () {
|
|
|
113
118
|
})) {
|
|
114
119
|
AIChatStore.activeSessionId = ((_AIChatStore$sessions = AIChatStore.sessions[0]) === null || _AIChatStore$sessions === void 0 ? void 0 : _AIChatStore$sessions.id) || null;
|
|
115
120
|
}
|
|
121
|
+
clearEmptySession();
|
|
116
122
|
|
|
117
123
|
// 4. 标记初始化完成,这将触发持久化订阅
|
|
118
124
|
AIChatStore.isInitialized = true;
|
|
119
125
|
// console.log('Valtio store initialized:', snapshot(AIChatStore));
|
|
120
|
-
case
|
|
126
|
+
case 22:
|
|
121
127
|
case "end":
|
|
122
128
|
return _context.stop();
|
|
123
129
|
}
|
|
@@ -188,18 +194,20 @@ export var handlePinSession = function handlePinSession(sessionId) {
|
|
|
188
194
|
subscribeKey(AIChatStore, 'activeSessionId', function () {
|
|
189
195
|
AIChatStore.codeBlock = null;
|
|
190
196
|
});
|
|
191
|
-
export var
|
|
192
|
-
// todo 埋点
|
|
193
|
-
// 1. 创建一个新的会话
|
|
197
|
+
export var createPureNewSession = function createPureNewSession(title) {
|
|
194
198
|
var newSessionId = crypto.randomUUID();
|
|
195
199
|
AIChatStore.sessions.unshift({
|
|
196
200
|
id: newSessionId,
|
|
197
|
-
title:
|
|
198
|
-
// 使用输入内容作为初始标题
|
|
201
|
+
title: title !== null && title !== void 0 ? title : 'New Conversation',
|
|
199
202
|
createdAt: Date.now(),
|
|
200
203
|
messages: []
|
|
201
204
|
});
|
|
202
205
|
AIChatStore.activeSessionId = newSessionId;
|
|
206
|
+
};
|
|
207
|
+
export var createNewSession = function createNewSession(config) {
|
|
208
|
+
// todo 埋点
|
|
209
|
+
// 1. 创建一个新的会话
|
|
210
|
+
createPureNewSession(config.promptText);
|
|
203
211
|
|
|
204
212
|
// 2. 创建临时消息并存入 store
|
|
205
213
|
AIChatStore.tempMessage = {
|
|
@@ -208,7 +216,11 @@ export var createNewSession = function createNewSession(config) {
|
|
|
208
216
|
content: config.promptText,
|
|
209
217
|
createdAt: Date.now(),
|
|
210
218
|
mode: config.mode,
|
|
211
|
-
lib: config.lib
|
|
219
|
+
lib: config.lib,
|
|
220
|
+
context: config.context
|
|
212
221
|
};
|
|
213
|
-
|
|
222
|
+
if (config.jump) {
|
|
223
|
+
var _config$lang;
|
|
224
|
+
history.push("/".concat((_config$lang = config.lang) !== null && _config$lang !== void 0 ? _config$lang : 'zh', "/ai-playground"));
|
|
225
|
+
}
|
|
214
226
|
};
|
|
@@ -13,6 +13,7 @@ import { useSnapshot } from 'valtio';
|
|
|
13
13
|
import { AIChatStore, handleDeleteSession, handlePinSession, handleRenameSession } from "../../../../model/AIChat";
|
|
14
14
|
import { history } from 'dumi';
|
|
15
15
|
import { useSetState } from "ahooks";
|
|
16
|
+
import { useIntl } from 'dumi';
|
|
16
17
|
export var ConversationsMenu = function ConversationsMenu() {
|
|
17
18
|
var _useSetState = useSetState({
|
|
18
19
|
open: false,
|
|
@@ -33,23 +34,33 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
33
34
|
var toggleCollapsed = function toggleCollapsed() {
|
|
34
35
|
setCollapsed(!collapsed);
|
|
35
36
|
};
|
|
37
|
+
var _useIntl = useIntl(),
|
|
38
|
+
formatMessage = _useIntl.formatMessage;
|
|
36
39
|
var items = [{
|
|
37
40
|
key: 'fold',
|
|
38
41
|
extra: !collapsed ? /*#__PURE__*/React.createElement(MenuFoldOutlined, null) : null,
|
|
39
42
|
onClick: toggleCollapsed,
|
|
40
43
|
label: null,
|
|
41
44
|
icon: !collapsed ? null : /*#__PURE__*/React.createElement(MenuUnfoldOutlined, null),
|
|
42
|
-
title:
|
|
45
|
+
title: collapsed ? formatMessage({
|
|
46
|
+
id: 'ai.conversations.expand'
|
|
47
|
+
}) : formatMessage({
|
|
48
|
+
id: 'ai.conversations.collapse'
|
|
49
|
+
})
|
|
43
50
|
}, {
|
|
44
51
|
key: 'new',
|
|
45
52
|
icon: /*#__PURE__*/React.createElement(PlusSquareOutlined, null),
|
|
46
|
-
label:
|
|
53
|
+
label: formatMessage({
|
|
54
|
+
id: 'ai.conversations.new'
|
|
55
|
+
}),
|
|
47
56
|
onClick: function onClick() {
|
|
48
57
|
return history.push('/');
|
|
49
58
|
}
|
|
50
59
|
}, {
|
|
51
60
|
key: 'history',
|
|
52
|
-
label:
|
|
61
|
+
label: formatMessage({
|
|
62
|
+
id: 'ai.conversations.history'
|
|
63
|
+
}),
|
|
53
64
|
icon: /*#__PURE__*/React.createElement(HistoryOutlined, null),
|
|
54
65
|
children: snap.sessions.map(function (session) {
|
|
55
66
|
return {
|
|
@@ -62,7 +73,9 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
62
73
|
menu: {
|
|
63
74
|
items: [{
|
|
64
75
|
key: 'edit',
|
|
65
|
-
label:
|
|
76
|
+
label: formatMessage({
|
|
77
|
+
id: 'ai.conversations.rename'
|
|
78
|
+
}),
|
|
66
79
|
icon: /*#__PURE__*/React.createElement(EditOutlined, null),
|
|
67
80
|
onClick: function onClick(_ref) {
|
|
68
81
|
var domEvent = _ref.domEvent;
|
|
@@ -75,7 +88,9 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
75
88
|
}
|
|
76
89
|
}, {
|
|
77
90
|
key: 'top',
|
|
78
|
-
label:
|
|
91
|
+
label: formatMessage({
|
|
92
|
+
id: 'ai.conversations.pin'
|
|
93
|
+
}),
|
|
79
94
|
icon: /*#__PURE__*/React.createElement(VerticalAlignTopOutlined, null),
|
|
80
95
|
onClick: function onClick(_ref2) {
|
|
81
96
|
var domEvent = _ref2.domEvent;
|
|
@@ -84,7 +99,9 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
84
99
|
}
|
|
85
100
|
}, {
|
|
86
101
|
key: 'delete',
|
|
87
|
-
label:
|
|
102
|
+
label: formatMessage({
|
|
103
|
+
id: 'ai.conversations.delete'
|
|
104
|
+
}),
|
|
88
105
|
icon: /*#__PURE__*/React.createElement(DeleteOutlined, null),
|
|
89
106
|
onClick: function onClick(_ref3) {
|
|
90
107
|
var domEvent = _ref3.domEvent;
|
|
@@ -118,7 +135,9 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
118
135
|
return handleSelectSession(key);
|
|
119
136
|
}
|
|
120
137
|
}), /*#__PURE__*/React.createElement(Modal, {
|
|
121
|
-
title:
|
|
138
|
+
title: formatMessage({
|
|
139
|
+
id: 'ai.conversations.edit.title'
|
|
140
|
+
}),
|
|
122
141
|
open: state.open,
|
|
123
142
|
centered: true,
|
|
124
143
|
maskClosable: false,
|
|
@@ -132,6 +151,9 @@ export var ConversationsMenu = function ConversationsMenu() {
|
|
|
132
151
|
return setState({
|
|
133
152
|
open: false
|
|
134
153
|
});
|
|
154
|
+
},
|
|
155
|
+
okButtonProps: {
|
|
156
|
+
disabled: !state.rename
|
|
135
157
|
}
|
|
136
158
|
}, /*#__PURE__*/React.createElement(Input, {
|
|
137
159
|
showCount: true,
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
1
7
|
import React from 'react';
|
|
2
8
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
3
9
|
import { a11yLight } from "react-syntax-highlighter/dist/cjs/styles/hljs";
|
|
4
10
|
import { AIChatStore } from "../../../../model/AIChat";
|
|
11
|
+
import { useCopyToClipboard } from "react-use";
|
|
12
|
+
import { CheckOutlined, CopyOutlined, PlaySquareOutlined } from "@ant-design/icons";
|
|
13
|
+
import { Space, Tooltip } from "antd";
|
|
14
|
+
import styles from "./MarkdownCodeBlock.module.less";
|
|
15
|
+
import { useIntl } from 'dumi';
|
|
5
16
|
|
|
6
17
|
// 定义 props 类型,它将接收 react-markdown 传递的所有属性
|
|
7
18
|
|
|
@@ -9,6 +20,10 @@ export var MarkdownCodeBlock = function MarkdownCodeBlock(_ref) {
|
|
|
9
20
|
var inline = _ref.inline,
|
|
10
21
|
className = _ref.className,
|
|
11
22
|
children = _ref.children;
|
|
23
|
+
var _useCopyToClipboard = useCopyToClipboard(),
|
|
24
|
+
_useCopyToClipboard2 = _slicedToArray(_useCopyToClipboard, 2),
|
|
25
|
+
copyState = _useCopyToClipboard2[0],
|
|
26
|
+
copyToClipboard = _useCopyToClipboard2[1];
|
|
12
27
|
// 1. 处理行内代码:如果是行内代码,不做特殊处理,直接返回一个 <code> 标签
|
|
13
28
|
if (inline || typeof children === 'string' && !children.includes("\n")) {
|
|
14
29
|
return /*#__PURE__*/React.createElement("code", {
|
|
@@ -23,8 +38,8 @@ export var MarkdownCodeBlock = function MarkdownCodeBlock(_ref) {
|
|
|
23
38
|
// 3. 将 children 转换为字符串,并移除末尾的换行符
|
|
24
39
|
var codeString = String(children).replace(/\n$/, '');
|
|
25
40
|
|
|
26
|
-
// 4.
|
|
27
|
-
var showRunButton = codeString
|
|
41
|
+
// 4. 判断是否显示“运行”按钮
|
|
42
|
+
var showRunButton = /\bimport\b/.test(codeString);
|
|
28
43
|
|
|
29
44
|
// 5. 定义运行代码的逻辑
|
|
30
45
|
var handleRunCode = function handleRunCode() {
|
|
@@ -33,29 +48,37 @@ export var MarkdownCodeBlock = function MarkdownCodeBlock(_ref) {
|
|
|
33
48
|
};
|
|
34
49
|
|
|
35
50
|
// 6. 返回最终的 JSX 结构
|
|
51
|
+
var intl = useIntl();
|
|
36
52
|
return /*#__PURE__*/React.createElement("div", {
|
|
37
53
|
style: {
|
|
38
54
|
position: 'relative',
|
|
39
55
|
margin: '1em 0'
|
|
40
56
|
}
|
|
41
|
-
},
|
|
57
|
+
}, /*#__PURE__*/React.createElement(Space, {
|
|
58
|
+
className: styles.button
|
|
59
|
+
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
60
|
+
title: intl.formatMessage({
|
|
61
|
+
id: 'ai.markdown.copy'
|
|
62
|
+
})
|
|
63
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
42
64
|
type: "button",
|
|
43
|
-
onClick:
|
|
44
|
-
|
|
45
|
-
position: 'absolute',
|
|
46
|
-
top: '0.5em',
|
|
47
|
-
right: '0.5em',
|
|
48
|
-
zIndex: 1,
|
|
49
|
-
padding: '5px 10px',
|
|
50
|
-
border: 'none',
|
|
51
|
-
borderRadius: '5px',
|
|
52
|
-
backgroundColor: '#4a4a4a',
|
|
53
|
-
color: 'white',
|
|
54
|
-
cursor: 'pointer',
|
|
55
|
-
fontSize: '0.8em'
|
|
65
|
+
onClick: function onClick() {
|
|
66
|
+
return copyToClipboard(codeString);
|
|
56
67
|
},
|
|
57
|
-
title:
|
|
58
|
-
|
|
68
|
+
title: intl.formatMessage({
|
|
69
|
+
id: 'ai.markdown.copy'
|
|
70
|
+
})
|
|
71
|
+
}, copyState.value === codeString ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null))), showRunButton && /*#__PURE__*/React.createElement(Tooltip, {
|
|
72
|
+
title: intl.formatMessage({
|
|
73
|
+
id: 'ai.markdown.run'
|
|
74
|
+
})
|
|
75
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: handleRunCode,
|
|
78
|
+
title: intl.formatMessage({
|
|
79
|
+
id: 'ai.markdown.run'
|
|
80
|
+
})
|
|
81
|
+
}, /*#__PURE__*/React.createElement(PlaySquareOutlined, null)))), /*#__PURE__*/React.createElement(SyntaxHighlighter, {
|
|
59
82
|
style: a11yLight,
|
|
60
83
|
language: language,
|
|
61
84
|
PreTag: "div" // 使用 div 作为外层标签,避免 pre 标签的默认样式冲突
|
|
@@ -20,7 +20,7 @@ export var MarkdownComponent = function MarkdownComponent(_ref) {
|
|
|
20
20
|
rest = _objectWithoutProperties(props, _excluded);
|
|
21
21
|
return /*#__PURE__*/React.createElement("p", _extends({
|
|
22
22
|
style: {
|
|
23
|
-
marginBottom: '
|
|
23
|
+
marginBottom: 'unset',
|
|
24
24
|
lineHeight: '1.6'
|
|
25
25
|
}
|
|
26
26
|
}, rest));
|