@ibiz-template/vue3-components 0.7.41-alpha.40 → 0.7.41-alpha.41

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.
Files changed (66) hide show
  1. package/dist/ibiz-markdown-editor-DEV-iSvz.js +1 -0
  2. package/dist/index-Bv2fgePf.js +11 -0
  3. package/dist/{index-BewO9StC.js → index-CD2XM6M6.js} +1 -1
  4. package/dist/{index-ClxO69TM.js → index-CaWTEUU1.js} +1 -1
  5. package/dist/index.min.css +1 -1
  6. package/dist/index.system.min.js +1 -1
  7. package/dist/wang-editor-4cNAgOaJ.js +1 -0
  8. package/dist/{xlsx-util-Cg5zMYCC.js → xlsx-util-Dvg2kWh7.js} +1 -1
  9. package/es/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.controller.mjs +2 -1
  10. package/es/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.css +1 -1
  11. package/es/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.mjs +12 -2
  12. package/es/editor/code/monaco-editor/monaco-editor.mjs +41 -32
  13. package/es/editor/html/wang-editor/config/index.mjs +3 -0
  14. package/es/editor/html/wang-editor/config/toolbar.mjs +90 -0
  15. package/es/editor/html/wang-editor/constants/svg.mjs +8 -0
  16. package/es/editor/html/wang-editor/wang-editor.css +1 -1
  17. package/es/editor/html/wang-editor/wang-editor.mjs +52 -39
  18. package/es/editor/markdown/ibiz-markdown-editor/custom-menu.mjs +264 -2
  19. package/es/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.css +1 -1
  20. package/es/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.mjs +38 -6
  21. package/es/editor/markdown/ibiz-markdown-editor/render-util.mjs +33 -4
  22. package/es/editor/text-box/input/input.mjs +41 -32
  23. package/es/index.mjs +1 -1
  24. package/es/locale/en/index.mjs +3 -1
  25. package/es/locale/zh-CN/index.mjs +3 -1
  26. package/es/util/ai-chat-util/ai-chat-util.mjs +216 -0
  27. package/es/util/app-util/app-util.mjs +20 -48
  28. package/es/util/index.mjs +1 -1
  29. package/es/util/inline-ai-util/inline-ai-textarea/icon.mjs +75 -1
  30. package/es/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.css +1 -1
  31. package/es/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.hook.mjs +136 -43
  32. package/es/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.mjs +130 -48
  33. package/es/util/inline-ai-util/inline-ai-util.mjs +2 -1
  34. package/es/web-app/main.mjs +2 -0
  35. package/lib/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.cjs +12 -2
  36. package/lib/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.controller.cjs +2 -1
  37. package/lib/control/form/form-detail/form-item/composite-form-item-ex/composite-form-item-ex.css +1 -1
  38. package/lib/editor/code/monaco-editor/monaco-editor.cjs +40 -31
  39. package/lib/editor/html/wang-editor/config/index.cjs +7 -0
  40. package/lib/editor/html/wang-editor/config/toolbar.cjs +92 -0
  41. package/lib/editor/html/wang-editor/constants/svg.cjs +14 -0
  42. package/lib/editor/html/wang-editor/wang-editor.cjs +51 -38
  43. package/lib/editor/html/wang-editor/wang-editor.css +1 -1
  44. package/lib/editor/markdown/ibiz-markdown-editor/custom-menu.cjs +264 -2
  45. package/lib/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.cjs +38 -6
  46. package/lib/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.css +1 -1
  47. package/lib/editor/markdown/ibiz-markdown-editor/render-util.cjs +33 -4
  48. package/lib/editor/text-box/input/input.cjs +40 -31
  49. package/lib/index.cjs +2 -2
  50. package/lib/locale/en/index.cjs +3 -1
  51. package/lib/locale/zh-CN/index.cjs +3 -1
  52. package/lib/util/ai-chat-util/ai-chat-util.cjs +218 -0
  53. package/lib/util/app-util/app-util.cjs +19 -47
  54. package/lib/util/index.cjs +2 -2
  55. package/lib/util/inline-ai-util/inline-ai-textarea/icon.cjs +78 -0
  56. package/lib/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.cjs +129 -47
  57. package/lib/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.css +1 -1
  58. package/lib/util/inline-ai-util/inline-ai-textarea/inline-ai-textarea.hook.cjs +135 -42
  59. package/lib/util/inline-ai-util/inline-ai-util.cjs +2 -1
  60. package/lib/web-app/main.cjs +2 -0
  61. package/package.json +5 -5
  62. package/dist/ibiz-markdown-editor-CxFS8frQ.js +0 -1
  63. package/dist/index-2eZnbrr4.js +0 -11
  64. package/dist/wang-editor-BPl509oX.js +0 -1
  65. package/es/util/ai-util/ai-util.mjs +0 -68
  66. package/lib/util/ai-util/ai-util.cjs +0 -71
@@ -1,20 +1,30 @@
1
1
  import qs from 'qs';
2
2
  import { notNilEmpty } from 'qx-util';
3
- import { onMounted, onUnmounted, ref } from 'vue';
3
+ import { useUIStore } from '@ibiz-template/vue3-util';
4
+ import { onMounted, onUnmounted, ref, watch, nextTick } from 'vue';
4
5
  import { calcResPath } from '@ibiz-template/runtime';
5
6
  import { RegenerateIcon, insertTextIcon, ReplaceTextIcon, CopyTextIcon, CancelIcon } from './icon.mjs';
6
7
 
7
8
  "use strict";
8
9
  const computedInLineAIParams = (props) => {
9
- var _a;
10
+ var _a, _b, _c, _d, _e, _f, _g;
11
+ const { params, context, editorParams } = props;
12
+ const getBooleanValue = (value) => {
13
+ if (value === "false")
14
+ return false;
15
+ if (value === "true")
16
+ return true;
17
+ return null;
18
+ };
10
19
  return {
11
- srfaiappendcurdata: (_a = props.context.srfaiappendcurdata) != null ? _a : true,
12
- srfaiautoappend: props.params.srfaiautoappend === "true" || props.params.srfaiautoappend === true,
13
- srfmode: props.params.srfmode,
14
- srfaiagent: props.params.srfaiagent
20
+ srfaiappendcurdata: (_c = (_b = (_a = getBooleanValue(context.srfaiappendcurdata)) != null ? _a : getBooleanValue(params.srfaiappendcurdata)) != null ? _b : getBooleanValue(editorParams.srfaiappendcurdata)) != null ? _c : true,
21
+ autoquestion: (_e = (_d = getBooleanValue(params.autoquestion)) != null ? _d : getBooleanValue(editorParams.autoquestion)) != null ? _e : false,
22
+ srfmode: params.srfmode,
23
+ srfaiagent: params.srfaiagent,
24
+ inlinecompletionmode: (_g = (_f = params.inlinecompletionmode) != null ? _f : editorParams.inlinecompletionmode) != null ? _g : "async"
15
25
  };
16
26
  };
17
- const useInLineAIContainerClick = (props, content, isLoading) => {
27
+ const useInLineAIContainerClick = (props, message, isLoading) => {
18
28
  const handclick = async (evt) => {
19
29
  const target = evt.target;
20
30
  if (!target.closest(".ibiz-inline-ai-textarea-container") && !target.closest(".ibiz-inline-ai-alert")) {
@@ -22,7 +32,7 @@ const useInLineAIContainerClick = (props, content, isLoading) => {
22
32
  evt.stopPropagation();
23
33
  return;
24
34
  }
25
- const isChange = props.content !== content.value;
35
+ const isChange = props.content !== message.value.content;
26
36
  let isClose = true;
27
37
  if (isChange) {
28
38
  isClose = await ibiz.confirm.warning({
@@ -50,21 +60,24 @@ const useAI = (props, opts) => {
50
60
  const params = { srfactag: deACMode.codeName };
51
61
  const app = ibiz.hub.getApp(deACMode.appId);
52
62
  let history = [];
53
- const calcAIPath = (appDataEntity, isHistories = false) => {
63
+ let appDataEntity;
64
+ const calcAIPath = (isHistories = false, isAsync = false) => {
65
+ if (!appDataEntity)
66
+ return "";
54
67
  const srfkey = context[appDataEntity.codeName.toLowerCase()];
55
- const curPath = "/".concat(appDataEntity.deapicodeName2, "/chatcompletion").concat(isHistories ? "/histories" : "").concat(srfkey ? "/".concat(srfkey) : "");
68
+ const curPath = "/".concat(appDataEntity.deapicodeName2, "/").concat(isAsync ? "sse" : "", "chatcompletion").concat(isHistories ? "/histories" : "").concat(srfkey ? "/".concat(srfkey) : "");
56
69
  const resPath = calcResPath(context, appDataEntity);
57
70
  return resPath ? "/".concat(resPath).concat(curPath) : "".concat(curPath);
58
71
  };
59
72
  const loadAiHistory = async () => {
60
- const appDataEntity = await ibiz.hub.getAppDataEntity(
73
+ appDataEntity = await ibiz.hub.getAppDataEntity(
61
74
  deACMode.appDataEntityId,
62
75
  deACMode.appId
63
76
  );
64
- const path = calcAIPath(appDataEntity, true);
77
+ const path = calcAIPath(true);
65
78
  const body = {};
66
79
  if (srfaiappendcurdata)
67
- Object.assign(body, { data });
80
+ Object.assign(body, data);
68
81
  if (srfmode)
69
82
  Object.assign(body, { mode: srfmode });
70
83
  if (srfaiagent)
@@ -97,14 +110,13 @@ const useAI = (props, opts) => {
97
110
  }
98
111
  return url;
99
112
  };
100
- const askAI = async (content) => {
101
- var _a, _b;
113
+ const prepareData = (question, isAsync = false) => {
102
114
  const body = {
103
115
  messages: [
104
116
  ...history,
105
117
  {
106
118
  role: "USER",
107
- content
119
+ content: question
108
120
  }
109
121
  ]
110
122
  };
@@ -112,32 +124,92 @@ const useAI = (props, opts) => {
112
124
  Object.assign(body, { mode: srfmode });
113
125
  if (srfaiagent)
114
126
  Object.assign(body, { srfaiagent });
115
- abortController.value = new AbortController();
116
- const appDataEntity = await ibiz.hub.getAppDataEntity(
117
- deACMode.appDataEntityId,
118
- deACMode.appId
119
- );
120
- const path = attachUrlParam(calcAIPath(appDataEntity));
121
- const response = await app.net.request(path, {
122
- method: "post",
123
- data: body,
124
- signal: abortController.value.signal
127
+ let url = calcAIPath(false, isAsync);
128
+ if (!isAsync)
129
+ url = attachUrlParam(url);
130
+ return { body, url };
131
+ };
132
+ const parseContent = (text) => {
133
+ let think;
134
+ let content;
135
+ if (!text)
136
+ return { think, content };
137
+ const openThinkIndex = text.indexOf("<think>");
138
+ const closeThinkIndex = text.indexOf("</think>");
139
+ if (openThinkIndex !== -1) {
140
+ think = closeThinkIndex === -1 ? text.slice(openThinkIndex + 7) : text.slice(openThinkIndex + 7, closeThinkIndex);
141
+ content = closeThinkIndex === -1 ? void 0 : text.slice(closeThinkIndex + 8);
142
+ } else {
143
+ content = text;
144
+ }
145
+ return { think, content };
146
+ };
147
+ const asyncAskAI = (question, callBack) => {
148
+ return new Promise((resolve, reject) => {
149
+ abortController.value = new AbortController();
150
+ const { body, url } = prepareData(question, true);
151
+ app.net.sse(url, params, {
152
+ headers: {
153
+ "Content-Type": "application/json"
154
+ },
155
+ body: JSON.stringify(body),
156
+ onmessage: (e) => {
157
+ var _a;
158
+ try {
159
+ if (e.data) {
160
+ const msg = JSON.parse(e.data);
161
+ let content = msg.actionresult;
162
+ if (msg.actionstate === 30 && content)
163
+ content = (_a = JSON.parse(content).choices) == null ? void 0 : _a[0].content;
164
+ callBack({ state: msg.actionstate, content });
165
+ }
166
+ } catch (error) {
167
+ ibiz.log.error(error);
168
+ }
169
+ },
170
+ onclose: () => resolve(),
171
+ onerror: () => reject(),
172
+ signal: abortController.value.signal
173
+ });
125
174
  });
126
- if (response.ok) {
127
- const result = (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.content;
128
- return result;
175
+ };
176
+ const syncAskAI = async (question) => {
177
+ var _a, _b;
178
+ abortController.value = new AbortController();
179
+ const { body, url } = prepareData(question);
180
+ const answer = {
181
+ state: 10,
182
+ content: ""
183
+ };
184
+ try {
185
+ const response = await app.net.request(url, {
186
+ method: "post",
187
+ data: body,
188
+ signal: abortController.value.signal
189
+ });
190
+ if (response.ok)
191
+ Object.assign(answer, {
192
+ state: 30,
193
+ content: (_b = (_a = response.data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.content
194
+ });
195
+ return answer;
196
+ } catch (error) {
197
+ Object.assign(answer, {
198
+ state: 40,
199
+ content: error.message
200
+ });
201
+ return answer;
129
202
  }
130
- return "";
131
203
  };
132
- onMounted(() => {
133
- loadAiHistory();
134
- });
135
204
  return {
136
- askAI,
205
+ syncAskAI,
206
+ asyncAskAI,
207
+ parseContent,
208
+ loadAiHistory,
137
209
  abortController
138
210
  };
139
211
  };
140
- const useBase = (props, container, target) => {
212
+ const useBase = (props, element, message) => {
141
213
  const actions = [
142
214
  {
143
215
  title: ibiz.i18n.t("util.inlineAiUtil.regenerate"),
@@ -173,7 +245,9 @@ const useBase = (props, container, target) => {
173
245
  actionName: "cancel"
174
246
  }
175
247
  ];
248
+ const { zIndex } = useUIStore();
176
249
  const { options } = props;
250
+ const { containerRef, actionsRef, textareaRef } = element;
177
251
  const editorRect = options.editorElement.getBoundingClientRect();
178
252
  const offsetX = options.left - editorRect.left;
179
253
  const offsetY = options.top - editorRect.top;
@@ -182,20 +256,32 @@ const useBase = (props, container, target) => {
182
256
  const containerStyle = ref({
183
257
  width: "".concat(options.width, "px"),
184
258
  left: "".concat(options.left, "px"),
185
- top: "".concat(options.top, "px")
259
+ top: "".concat(options.top, "px"),
260
+ zIndex: zIndex.increment()
186
261
  });
187
262
  const contentStyle = ref({
188
- height: "".concat(options.height || 300, "px"),
189
- "max-height": "".concat(options.maxHeight, "px")
263
+ height: options.height ? "".concat(options.height, "px") : "auto",
264
+ "max-height": "".concat(options.maxHeight || (options.height && options.height > 300 ? options.height : 300), "px")
190
265
  });
266
+ watch(
267
+ () => message.value.content,
268
+ () => {
269
+ nextTick(() => {
270
+ if (!textareaRef.value)
271
+ return;
272
+ textareaRef.value.style.height = "auto";
273
+ textareaRef.value.style.height = "".concat(textareaRef.value.scrollHeight, "px");
274
+ });
275
+ }
276
+ );
191
277
  const updatePosition = () => {
192
- if (!container.value || !target.value)
278
+ if (!containerRef.value || !actionsRef.value)
193
279
  return;
194
280
  const rect = options.editorElement.getBoundingClientRect();
195
281
  let top = rect.top + offsetY;
196
282
  let left = rect.left + offsetX;
197
- const containerWidth = container.value.offsetWidth;
198
- const containerHeight = container.value.offsetHeight;
283
+ const containerWidth = containerRef.value.offsetWidth;
284
+ const containerHeight = containerRef.value.offsetHeight;
199
285
  const windowWidth = window.innerWidth;
200
286
  const windowHeight = window.innerHeight;
201
287
  const margin = 8;
@@ -212,7 +298,7 @@ const useBase = (props, container, target) => {
212
298
  containerStyle.value.top = "".concat(top, "px");
213
299
  containerStyle.value.left = "".concat(left, "px");
214
300
  const position = containerHeight + 4;
215
- const targetHeight = target.value.offsetHeight;
301
+ const targetHeight = actionsRef.value.offsetHeight;
216
302
  if (windowHeight - (top + containerHeight + targetHeight) > margin) {
217
303
  actionStyle.value.top = "".concat(position, "px");
218
304
  actionStyle.value.bottom = "auto";
@@ -231,18 +317,25 @@ const useBase = (props, container, target) => {
231
317
  ticking = true;
232
318
  }
233
319
  };
320
+ let observer;
234
321
  onMounted(() => {
235
- updatePosition();
236
322
  document.addEventListener("scroll", optimizedUpdatePosition, {
237
323
  capture: true
238
324
  });
239
325
  window.addEventListener("resize", optimizedUpdatePosition);
326
+ if (containerRef.value) {
327
+ observer = new ResizeObserver(optimizedUpdatePosition);
328
+ observer.observe(containerRef.value);
329
+ }
240
330
  });
241
331
  onUnmounted(() => {
332
+ zIndex.decrement();
242
333
  document.removeEventListener("scroll", optimizedUpdatePosition, {
243
334
  capture: true
244
335
  });
245
336
  window.removeEventListener("resize", optimizedUpdatePosition);
337
+ observer == null ? void 0 : observer.disconnect();
338
+ observer = null;
246
339
  });
247
340
  return { theme, actions, actionStyle, containerStyle, contentStyle };
248
341
  };
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, createVNode, withDirectives, vModelText, ref, computed, onMounted } from 'vue';
2
2
  import { useNamespace } from '@ibiz-template/vue3-util';
3
3
  import { computedInLineAIParams, useBase, useAI, useInLineAIContainerClick } from './inline-ai-textarea.hook.mjs';
4
- import { AIIcon, StopIcon, SendIcon } from './icon.mjs';
4
+ import { AIIcon, StopIcon, SendIcon, LoadingIcon, ThinkSuccessIcon, DownIcon, UpIcon } from './icon.mjs';
5
5
  import './inline-ai-textarea.css';
6
6
 
7
7
  "use strict";
@@ -15,6 +15,10 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
15
15
  type: Object,
16
16
  required: true
17
17
  },
18
+ editorParams: {
19
+ type: Object,
20
+ required: true
21
+ },
18
22
  data: {
19
23
  type: Object,
20
24
  required: true
@@ -53,21 +57,28 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
53
57
  const containerRef = ref();
54
58
  const actionsRef = ref();
55
59
  const textareaRef = ref();
56
- const textareaContent = ref(props.content);
60
+ const message = ref({
61
+ role: "USER",
62
+ error: void 0,
63
+ think: void 0,
64
+ content: props.content
65
+ });
57
66
  let question;
58
- const contentType = ref("USER");
67
+ let answerContent;
59
68
  const isLoading = ref(false);
69
+ const isCollapse = ref(false);
60
70
  const disabled = computed(() => {
61
- return contentType.value === "ASSISTANT" || isLoading.value;
71
+ return message.value.role === "ASSISTANT" || isLoading.value;
62
72
  });
63
73
  const isShow = computed(() => {
64
- return contentType.value === "ASSISTANT" && !isLoading.value;
74
+ return message.value.role === "ASSISTANT" && !isLoading.value;
65
75
  });
66
76
  const {
67
- srfaiappendcurdata,
68
- srfaiautoappend,
69
77
  srfmode,
70
- srfaiagent
78
+ srfaiagent,
79
+ autoquestion,
80
+ srfaiappendcurdata,
81
+ inlinecompletionmode
71
82
  } = computedInLineAIParams(props);
72
83
  const {
73
84
  theme,
@@ -75,34 +86,73 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
75
86
  actionStyle,
76
87
  containerStyle,
77
88
  contentStyle
78
- } = useBase(props, containerRef, actionsRef);
89
+ } = useBase(props, {
90
+ containerRef,
91
+ actionsRef,
92
+ textareaRef
93
+ }, message);
79
94
  const {
80
- askAI,
95
+ syncAskAI,
96
+ asyncAskAI,
97
+ parseContent,
98
+ loadAiHistory,
81
99
  abortController
82
100
  } = useAI(props, {
83
- srfaiappendcurdata,
84
101
  srfmode,
85
- srfaiagent
102
+ srfaiagent,
103
+ srfaiappendcurdata
86
104
  });
105
+ useInLineAIContainerClick(props, message, isLoading);
87
106
  const stopQuestionAndClose = () => {
88
107
  var _a;
89
108
  (_a = abortController.value) == null ? void 0 : _a.abort();
90
109
  props.unMountAIChat();
91
110
  };
92
- useInLineAIContainerClick(props, textareaContent, isLoading);
93
- const restoreFocus = () => {
94
- var _a;
95
- (_a = textareaRef.value) == null ? void 0 : _a.blur();
96
- props.restoreSelection();
111
+ const handleAnswer = (answer) => {
112
+ switch (answer.state) {
113
+ case 20:
114
+ answerContent += answer.content;
115
+ Object.assign(message.value, parseContent(answerContent));
116
+ break;
117
+ case 30:
118
+ answerContent = answer.content;
119
+ Object.assign(message.value, parseContent(answerContent));
120
+ break;
121
+ case 40:
122
+ isCollapse.value = true;
123
+ Object.assign(message.value, {
124
+ error: answer.content,
125
+ think: void 0,
126
+ content: void 0
127
+ });
128
+ break;
129
+ default:
130
+ break;
131
+ }
132
+ message.value.role = "ASSISTANT";
97
133
  };
98
134
  const sendQuestion = async (content) => {
135
+ var _a;
136
+ if (!content || isLoading.value)
137
+ return;
138
+ isLoading.value = true;
99
139
  try {
100
- isLoading.value = true;
101
- restoreFocus();
140
+ (_a = textareaRef.value) == null ? void 0 : _a.blur();
141
+ props.restoreSelection();
102
142
  question = content;
103
- textareaContent.value = "";
104
- textareaContent.value = await askAI(question);
105
- contentType.value = "ASSISTANT";
143
+ answerContent = void 0;
144
+ Object.assign(message.value, {
145
+ error: void 0,
146
+ think: void 0,
147
+ content: void 0
148
+ });
149
+ isCollapse.value = false;
150
+ if (inlinecompletionmode === "async") {
151
+ await asyncAskAI(question, handleAnswer);
152
+ } else {
153
+ const answer = await syncAskAI(question);
154
+ handleAnswer(answer);
155
+ }
106
156
  } catch (error) {
107
157
  ibiz.log.error(error);
108
158
  } finally {
@@ -112,13 +162,15 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
112
162
  const onKeydown = (e) => {
113
163
  if (e.code === "Enter" && !e.isComposing) {
114
164
  e.stopPropagation();
115
- if (e.shiftKey === false) {
116
- sendQuestion(textareaContent.value);
117
- }
165
+ if (e.shiftKey === false)
166
+ sendQuestion(message.value.content);
118
167
  }
119
168
  };
169
+ const onCollapseChange = () => {
170
+ isCollapse.value = !isCollapse.value;
171
+ };
120
172
  const handleAction = (_e, actionName) => {
121
- const content = textareaContent.value;
173
+ const content = message.value.content;
122
174
  switch (actionName) {
123
175
  case "regenerate":
124
176
  sendQuestion(question);
@@ -142,32 +194,69 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
142
194
  break;
143
195
  }
144
196
  };
145
- onMounted(() => {
197
+ onMounted(async () => {
146
198
  var _a;
147
- if (srfaiautoappend) {
148
- sendQuestion(textareaContent.value);
199
+ await loadAiHistory();
200
+ if (autoquestion) {
201
+ await sendQuestion(message.value.content);
149
202
  } else {
150
203
  (_a = textareaRef.value) == null ? void 0 : _a.focus();
151
204
  }
152
205
  });
206
+ const renderLoading = () => {
207
+ const value = message.value.error || message.value.content || message.value.think;
208
+ if (!isLoading.value || value)
209
+ return;
210
+ return createVNode("div", {
211
+ "class": ns.e("loading")
212
+ }, [createVNode("div", {
213
+ "class": ns.em("loading", "dot")
214
+ }, null), createVNode("div", {
215
+ "class": ns.em("loading", "dot")
216
+ }, null), createVNode("div", {
217
+ "class": ns.em("loading", "dot")
218
+ }, null)]);
219
+ };
220
+ const renderContent = () => {
221
+ if (message.value.error)
222
+ return createVNode("div", {
223
+ "class": ns.e("error")
224
+ }, [message.value.error]);
225
+ if (message.value.think)
226
+ return createVNode("div", {
227
+ "class": ns.e("think")
228
+ }, [createVNode("div", {
229
+ "class": ns.em("think", "header"),
230
+ "onClick": onCollapseChange
231
+ }, [createVNode("div", {
232
+ "class": [ns.em("think", "state-icon"), ns.is("loading", isLoading.value)]
233
+ }, [isLoading.value ? LoadingIcon : ThinkSuccessIcon]), createVNode("div", {
234
+ "class": ns.em("think", "title")
235
+ }, [isLoading.value ? ibiz.i18n.t("util.inlineAiUtil.thinking") : ibiz.i18n.t("util.inlineAiUtil.thinked")]), createVNode("div", {
236
+ "class": ns.em("think", "collapse-icon")
237
+ }, [isCollapse.value ? DownIcon : UpIcon])]), !isCollapse.value && createVNode("div", {
238
+ "class": ns.em("think", "content")
239
+ }, [message.value.think])]);
240
+ };
153
241
  return {
154
242
  ns,
155
243
  theme,
156
244
  isShow,
157
245
  actions,
246
+ message,
158
247
  disabled,
159
248
  isLoading,
160
249
  actionsRef,
161
250
  textareaRef,
162
251
  actionStyle,
163
- contentType,
164
252
  containerRef,
165
253
  contentStyle,
166
254
  containerStyle,
167
- textareaContent,
168
255
  onKeydown,
169
256
  sendQuestion,
170
257
  handleAction,
258
+ renderLoading,
259
+ renderContent,
171
260
  stopQuestionAndClose
172
261
  };
173
262
  },
@@ -185,33 +274,26 @@ const InlineAITextArea = /* @__PURE__ */ defineComponent({
185
274
  "class": this.ns.em("content", "ai-icon")
186
275
  }, [AIIcon])]), createVNode("div", {
187
276
  "class": this.ns.em("content", "textarea")
188
- }, [this.isLoading && createVNode("div", {
189
- "class": this.ns.e("loading")
190
- }, [createVNode("div", {
191
- "class": this.ns.em("loading", "dot")
192
- }, null), createVNode("div", {
193
- "class": this.ns.em("loading", "dot")
194
- }, null), createVNode("div", {
195
- "class": this.ns.em("loading", "dot")
196
- }, null)]), withDirectives(createVNode("textarea", {
277
+ }, [this.renderLoading(), this.renderContent(), withDirectives(createVNode("textarea", {
197
278
  "ref": "textareaRef",
198
279
  "disabled": this.disabled,
199
280
  "onKeydown": this.onKeydown,
200
- "onUpdate:modelValue": ($event) => this.textareaContent = $event
201
- }, null), [[vModelText, this.textareaContent]])]), createVNode("div", {
281
+ "onUpdate:modelValue": ($event) => this.message.content = $event,
282
+ "class": this.ns.is("hidden", !!this.message.error)
283
+ }, null), [[vModelText, this.message.content]])]), createVNode("div", {
202
284
  "class": this.ns.em("content", "suffix")
203
285
  }, [this.isLoading && createVNode("div", {
204
286
  "class": this.ns.em("content", "stop-icon"),
205
287
  "onClick": () => this.stopQuestionAndClose()
206
288
  }, [StopIcon, createVNode("span", null, [ibiz.i18n.t("util.inlineAiUtil.stopEdit")])]), !this.disabled && createVNode("div", {
207
289
  "class": this.ns.em("content", "sand-icon"),
208
- "onClick": () => this.sendQuestion(this.textareaContent)
209
- }, [SendIcon])])]), createVNode("div", {
210
- "class": [this.ns.e("footer"), this.ns.is("show", this.isShow)]
211
- }, [ibiz.i18n.t("util.inlineAiUtil.info")]), createVNode("div", {
290
+ "onClick": () => this.sendQuestion(this.message.content)
291
+ }, [SendIcon])])]), this.isShow && createVNode("div", {
292
+ "class": this.ns.e("footer")
293
+ }, [ibiz.i18n.t("util.inlineAiUtil.info")]), this.isShow && createVNode("div", {
212
294
  "ref": "actionsRef",
213
- "class": [this.ns.e("actions"), this.ns.is("show", this.isShow)],
214
- "style": this.actionStyle
295
+ "style": this.actionStyle,
296
+ "class": this.ns.e("actions")
215
297
  }, [this.actions.map((action) => {
216
298
  if (action.itemType === "divider")
217
299
  return createVNode("div", {
@@ -116,7 +116,7 @@ class InLineAIUtil {
116
116
  this.container.className = this.ns.b();
117
117
  document.body.appendChild(this.container);
118
118
  const { editor } = params;
119
- const { insertText, replaceSelectionText, restoreSelection } = editor;
119
+ const { insertText, replaceSelectionText, restoreSelection, editorParams } = editor;
120
120
  delete params.editor;
121
121
  const unMountAIChat = () => {
122
122
  this.destroyInlineAIComponent();
@@ -125,6 +125,7 @@ class InLineAIUtil {
125
125
  context,
126
126
  params,
127
127
  data,
128
+ editorParams,
128
129
  content: selectText,
129
130
  deACMode,
130
131
  options,
@@ -22,6 +22,7 @@ import { LoadingUtil } from '../util/loading-util/loading-util.mjs';
22
22
  import { NoticeUtil } from '../util/notice-util/notice-util.mjs';
23
23
  import { OverlayController } from '../util/overlay-controller/overlay-controller.mjs';
24
24
  import { InLineAIUtil } from '../util/inline-ai-util/inline-ai-util.mjs';
25
+ import { AIChatUtil } from '../util/ai-chat-util/ai-chat-util.mjs';
25
26
  import { FullscreenUtil } from '../util/fullscreen/fullscreen-util.mjs';
26
27
 
27
28
  "use strict";
@@ -83,6 +84,7 @@ async function runApp(plugins, opts) {
83
84
  ibiz.notice = new NoticeUtil();
84
85
  ibiz.overlay = new OverlayController();
85
86
  ibiz.inLineAIUtil = new InLineAIUtil();
87
+ ibiz.aiChatUtil = new AIChatUtil();
86
88
  ibiz.util.text.format = (value, code) => {
87
89
  return app.config.globalProperties.$textFormat(value, code);
88
90
  };
@@ -70,14 +70,20 @@ const CompositeFormItemEx = /* @__PURE__ */ vue.defineComponent({
70
70
  const isIncludes = this.c.includesList.some((id) => id === "".concat(editorType, "_").concat(editorStyle));
71
71
  const editorSwitchMenu = vue.createVNode(vue.resolveComponent("el-popover"), {
72
72
  "trigger": "click",
73
- "popper-class": this.ns2.b("menu-popover")
73
+ "popper-class": this.ns2.b("menu-popover"),
74
+ "offset": 0
74
75
  }, {
75
76
  reference: () => {
77
+ const option = this.c.switchOptions.find((item) => item.id === this.c.state.editorId);
76
78
  return vue.createVNode("div", {
77
79
  "class": this.ns2.b("menu")
78
80
  }, [vue.createVNode("div", {
81
+ "class": this.ns2.be("menu", "text-icon")
82
+ }, [vue.createVNode(vue.resolveComponent("iBizIcon"), {
83
+ "icon": option == null ? void 0 : option.icon
84
+ }, null)]), vue.createVNode("div", {
79
85
  "class": this.ns2.be("menu", "text")
80
- }, [this.c.state.editorId]), vue.createVNode("div", {
86
+ }, [(option == null ? void 0 : option.name) || this.c.state.editorId]), vue.createVNode("div", {
81
87
  "class": this.ns2.be("menu", "icon")
82
88
  }, [vue.createVNode("svg", {
83
89
  "xmlns": "http://www.w3.org/2000/svg",
@@ -101,6 +107,10 @@ const CompositeFormItemEx = /* @__PURE__ */ vue.defineComponent({
101
107
  "class": this.ns2.be("menu-item", "icon")
102
108
  }, [vue.createVNode("path", {
103
109
  "d": "M574.116299 786.736392 1238.811249 48.517862C1272.390222 11.224635 1329.414799 7.827718 1366.75664 41.450462 1403.840015 74.840484 1406.731043 132.084741 1373.10189 169.433699L655.118888 966.834607C653.072421 969.716875 650.835807 972.514337 648.407938 975.210759 615.017957 1012.29409 558.292155 1015.652019 521.195664 982.250188L72.778218 578.493306C35.910826 545.297758 32.859041 488.584019 66.481825 451.242134 99.871807 414.158803 156.597563 410.800834 193.694055 444.202665L574.116299 786.736392Z"
110
+ }, null)]), vue.createVNode("div", {
111
+ "class": this.ns2.be("menu-item", "text-icon")
112
+ }, [vue.createVNode(vue.resolveComponent("iBizIcon"), {
113
+ "icon": option.icon
104
114
  }, null)]), vue.createVNode("span", {
105
115
  "class": this.ns2.be("menu-item", "text")
106
116
  }, [option.name])]);
@@ -28,7 +28,7 @@ class CompositeFormItemExController extends runtime.FormItemController {
28
28
  __publicField(this, "includesList", ["HTMLEDITOR_DEFAULT", "MARKDOWN_DEFAULT"]);
29
29
  /**
30
30
  * @description 切换菜单选项
31
- * @type {{ id: string; name: string; editor?: IData }[]}
31
+ * @type {{ id: string; name: string; icon?: ISysImage, editor?: IData }[]}
32
32
  * @memberof CompositeFormItemExController
33
33
  */
34
34
  __publicField(this, "switchOptions", []);
@@ -62,6 +62,7 @@ class CompositeFormItemExController extends runtime.FormItemController {
62
62
  return {
63
63
  id: item.value,
64
64
  name: item.text,
65
+ icon: item.sysImage,
65
66
  editor: item.data
66
67
  };
67
68
  });