centaline-data-driven-v3 0.0.79 → 0.0.80

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "centaline-data-driven-v3",
3
- "version": "0.0.79",
3
+ "version": "0.0.80",
4
4
  "private": false,
5
5
  "description": "centaline-data-driven-v3",
6
6
  "main": "dist/centaline-data-driven-v3.umd.js",
@@ -9,15 +9,15 @@
9
9
  </div>
10
10
  <div class="header-item" v-if="model.controlLabel">
11
11
  <h3 style="line-height: 25px;">
12
- {{ model.controlLabel }}</h3>
13
- </div>
12
+ {{ model.controlLabel }}</h3>
13
+ </div>
14
14
  </div>
15
15
  <!-- 消息列表 -->
16
16
  <div class="messages" ref="messagesContainer">
17
17
  <template v-for="message in model.messages">
18
18
  <div :key="message.id" class="message" v-if="message.content"
19
19
  :class="{ 'user-message': message.sender === 'user', 'ai-message': message.sender === 'ai' }">
20
- <div class="chat-message" v-html="htmlContent(message)">
20
+ <div class="chat-message" :style="{color:message.type=='error'?'red':''}" v-html="htmlContent(message)">
21
21
  </div>
22
22
  </div>
23
23
  <div v-else class="loading-container">
@@ -56,16 +56,17 @@
56
56
 
57
57
  <script setup lang="ts">
58
58
  import { ref, reactive, nextTick, watch, computed } from 'vue'
59
+ import AIChat from '../../loader/src/AIChat'
59
60
  import common from '../../utils/common'
60
61
  import { marked } from 'marked';
61
62
  import DOMPurify from 'dompurify'
62
63
 
63
64
 
64
- const emit = defineEmits(['loaded', "change", "click", "hideAI"])
65
+ const emit = defineEmits(['loaded', "getRefFieldPara", "hideAI"])
65
66
  const props = defineProps({
66
- api: String,
67
- vmodel: Object,
68
- actionRouter: Array,
67
+ field: Object,
68
+ router: Object,
69
+ actionRouters: Array,
69
70
  form: Object,
70
71
  })
71
72
  interface StreamEventData {
@@ -73,6 +74,7 @@ interface StreamEventData {
73
74
  conversation_id?: string
74
75
  answer?: string
75
76
  task_id?: string
77
+ message?: string
76
78
  }
77
79
 
78
80
  const model = ref({});
@@ -89,7 +91,7 @@ let scrollPending = false;//滚动输入
89
91
  const headers = computed(() => {
90
92
  return {
91
93
  'Content-Type': 'application/json',
92
- Authorization: "Bearer " + props.vmodel?.code2,
94
+ Authorization: "Bearer " + props.field?.code2,
93
95
  };
94
96
  })
95
97
 
@@ -97,8 +99,8 @@ init()
97
99
  //初始化数据
98
100
  function init() {
99
101
  nextTick(function () {
100
- if (props.vmodel) {
101
- load(props.vmodel);
102
+ if (props.field) {
103
+ load(AIChat.AIModel(props));
102
104
  emit("loaded");
103
105
  }
104
106
  });
@@ -111,8 +113,8 @@ function action() {
111
113
  showAI.value = true;
112
114
  rtn = model.value.action;
113
115
  }
114
- else if (props.actionRouter) {
115
- var router = props.actionRouter.find((v1) => {
116
+ else if (props.actionRouters) {
117
+ var router = props.actionRouters.find((v1) => {
116
118
  return v1.key === model.value.fieldName1;
117
119
  });
118
120
  rtn = router.action;
@@ -189,7 +191,8 @@ const sendMessage = async () => {
189
191
  // 添加AI消息
190
192
  addMessage({
191
193
  content: "",
192
- sender: 'ai'
194
+ sender: 'ai',
195
+ type: ''
193
196
  })
194
197
 
195
198
  // AI回复
@@ -212,6 +215,12 @@ const appendMessage = (message) => {
212
215
  scheduleScroll()
213
216
  }
214
217
 
218
+ const UpdateMessageType = (type) => {
219
+ if (model.value.messages[model.value.messages.length - 1].type != 'error') {
220
+ model.value.messages[model.value.messages.length - 1].type = type;
221
+ }
222
+ }
223
+
215
224
  // 防抖滚动
216
225
  const scheduleScroll = () => {
217
226
  if (!scrollPending) {
@@ -235,14 +244,27 @@ const scheduleScroll = () => {
235
244
  //获取关联列返回对象
236
245
  function getRefFieldJson() {
237
246
  let rtn = {};
238
- if (props.form?.AIRouter.refFieldName) {
239
- let refFieldName = props.form.AIRouter.refFieldName.split(',');
240
- if (refFieldName.length > 0) {
241
- rtn = props.form.getRefFieldPara(refFieldName);
247
+ let router = props.router;
248
+ if (router.refFieldName) {
249
+ let refFieldName = router.refFieldName.split(',');
250
+ let submitData = props.form.getFormObj();
251
+ if (refFieldName.length > 0 && submitData) {
252
+ rtn = getRefFieldPara(submitData, refFieldName);
242
253
  }
243
254
  }
244
255
  return JSON.stringify(rtn);
245
256
  }
257
+ //绑定联动参数组件
258
+ function getRefFieldPara(tempFormData, refFieldNameArr) {
259
+ let submitData = {};
260
+ if (tempFormData) {
261
+ refFieldNameArr.forEach((v) => {
262
+ submitData[v] = common.getDataOfUpperLower(tempFormData, v);
263
+ });
264
+ }
265
+ return submitData;
266
+ }
267
+
246
268
 
247
269
  //获取Token
248
270
  function getToken() {
@@ -336,11 +358,14 @@ const fetchAIResponse = async (params) => {
336
358
  });
337
359
  }).then(() => {
338
360
  // 在所有行处理完毕后执行 startTypingEffect
339
-
340
-
361
+ if (outtext.value == '') {
362
+ outtext.value = ' ';
363
+ }
364
+ UpdateMessageType('message');
341
365
  startTypingEffect(outtext.value);
342
366
  outtext.value = '';
343
367
  }).catch(error => {
368
+ UpdateMessageType('error');
344
369
  if (error.name === 'AbortError') {
345
370
  console.log('Request aborted');
346
371
  } else {
@@ -407,6 +432,11 @@ const handleStreamEvent = (eventData: StreamEventData) => {
407
432
  if (eventData.conversation_id) {
408
433
  conversationId.value = eventData.conversation_id
409
434
  }
435
+ if (eventData.event == 'error') {
436
+ UpdateMessageType('error');
437
+ outtext.value += '\n\n' + eventData.message;
438
+ return;
439
+ }
410
440
 
411
441
  if (eventData.answer) {
412
442
  const lastMessage = model.value.messages[model.value.messages.length - 1]
@@ -420,7 +450,7 @@ const handleStreamEvent = (eventData: StreamEventData) => {
420
450
  }
421
451
  }
422
452
 
423
- const getTemplateType= (fullText)=>{
453
+ const getTemplateType = (fullText) => {
424
454
 
425
455
 
426
456
 
@@ -436,8 +466,8 @@ function startTypingEffect(fullText) {
436
466
  return;
437
467
  }
438
468
 
439
- // 随机生成3到10之间的字符数
440
- const randomChars = Math.floor(Math.random() * 8) + 3; // 3到10(包括3和10)
469
+ // 随机生成3到10之间的字符数
470
+ const randomChars = Math.floor(Math.random() * 8) + 3; // 3到10(包括3和10)
441
471
  const charsToLoad = Math.min(randomChars, fullText.length - index);
442
472
 
443
473
  // 获取当前要加载的字符
@@ -482,7 +512,7 @@ function hideAI() {
482
512
 
483
513
  /* 子元素之间的间距为5像素 */
484
514
  .header-item {
485
- padding: 10px;
515
+ padding: 10px;
486
516
  }
487
517
  }
488
518
 
@@ -156,14 +156,14 @@
156
156
 
157
157
 
158
158
  </div>
159
- <template v-if="model?.AIattr?.showAI">
160
- <div :style="{ flex: ' 0 0 ' + model.AIattr.width + 'px', 'box-shadow': '-10px 0 5px -9px rgba(0, 0, 0, 0.3)' }"
159
+ <template v-if="model?.aiAttr?.showAI">
160
+ <div :style="{ flex: ' 0 0 ' + model.aiAttr.width + 'px', position: 'sticky', top: '0' ,'margin-left': '10px'}"
161
161
  v-show="showAI">
162
162
  <div
163
163
  :style="{ position: 'sticky', top: '0', height: dialogHeight + 'px', overflow: 'hidden', 'border-bottom-right-radius': '4px' }">
164
164
  <AIChat :height="dialogHeight"
165
165
  :style="{ position: 'sticky', top: '0', height: dialogHeight + 'px' }"
166
- :vmodel="model.AIModel" :actionRouter="model.actionRouters" :form="model"
166
+ :field="model.aiChat" :router="model.aiRouter" :actionRouter="model.actionRouters" :form="model"
167
167
  @hideAI="AIToggle">
168
168
 
169
169
  </AIChat>
@@ -172,17 +172,11 @@
172
172
  </template>
173
173
 
174
174
  </div>
175
- <template v-if="model?.AIattr?.showAI && !showAI">
176
- <div class="btn-avatar" @click="AIToggle"
177
- :style="{ 'float': model.AIRouter.isCheckbox ? model.AIRouter.alignCss : '' }">
178
- <img class="avatar-img" :src="util.getAssetsImage('AIChat.png')" :alt="model?.AIRouter.controlLabel"
179
- :title="model?.AIRouter.controlLabel">
175
+ <template v-if="model?.aiAttr?.showAI && !showAI">
176
+ <div class="btn-avatar" @click="AIToggle">
177
+ <img class="avatar-img" :src="util.getAssetsImage('AIChat.png')" :alt="model?.aiRouter.controlLabel"
178
+ :title="model?.aiRouter.controlLabel">
180
179
  </div>
181
-
182
- <!-- <component :is="model.AIRouter.is" :vmodel="model.AIRouter"
183
- v-if="model.AIRouter.show" @fieldClick="AIToggle"
184
- :style="{ 'float': model.AIRouter.isCheckbox ? model.AIRouter.alignCss : '' }">
185
- </component> -->
186
180
  </template>
187
181
  <div style="min-height:200px" v-if="loading"></div>
188
182
  <iframe :src="downloadUrl" style="height:0px;width:0px;border-width: 0px;display: none;"> </iframe>
@@ -262,6 +256,9 @@ const refForm = ref()
262
256
  const qrtimer = ref(null)
263
257
  const downloadUrl = ref('')
264
258
  const minHeight = ref('auto')
259
+ const showAI = ref(false);
260
+ const dialogHeight = ref(props.dialogHeight || (window.innerHeight - 60));
261
+
265
262
  onUpdated(() => {
266
263
  nextTick(() => {
267
264
  qrtimer.value = setTimeout(getisScroll, 100);
@@ -321,28 +318,7 @@ function load(data) {
321
318
  function failLoad() {
322
319
  emit('failLoad', model.value);
323
320
  }
324
- const showAI = ref(false);
325
- const dialogHeight = ref(props.dialogHeight || (window.innerHeight - 60));
326
321
 
327
- function AIToggle() {
328
- showAI.value = !showAI.value;
329
- let width = model.value.AIattr.width;
330
- dialogHeight.value = (props.dialogHeight || (window.innerHeight - 60));
331
- emit('AIToggle', (showAI.value ? width : -width));
332
- }
333
-
334
-
335
- function buttonsWidth() {
336
- let rtn = '100%';
337
- if (showAI.value) {
338
- rtn = props.dialoWidth - model.value.AIattr.width - 4 + 'px';
339
- }
340
- else if (props.pageWidth) {
341
- rtn = props.pageWidth - 20 + 'px';
342
-
343
- }
344
- return rtn;
345
- }
346
322
 
347
323
  //获取关联数据
348
324
  function getFileData(field) {
@@ -649,6 +625,28 @@ function setCss() {
649
625
  minHeight.value = (document.documentElement.clientHeight - props.topHeight - 20) + 'px';
650
626
  }
651
627
  }
628
+
629
+
630
+ function AIToggle() {
631
+ showAI.value = !showAI.value;
632
+ let width = model.value.aiAttr.width;
633
+ dialogHeight.value = (props.dialogHeight || (window.innerHeight - 60));
634
+ emit('AIToggle', (showAI.value ? width : -width));
635
+ }
636
+
637
+
638
+ function buttonsWidth() {
639
+ let rtn = '100%';
640
+ if (showAI.value) {
641
+ rtn = props.dialoWidth - model.value.aiAttr.width - 4 + 'px';
642
+ }
643
+ else if (props.pageWidth) {
644
+ rtn = props.pageWidth - 20 + 'px';
645
+
646
+ }
647
+ return rtn;
648
+ }
649
+
652
650
  </script>
653
651
 
654
652
  <style scoped>
@@ -1,6 +1,7 @@
1
1
  import base from '../index';
2
2
  import valid from '../../utils/validate';
3
3
 
4
+
4
5
  function loadFromModel(source, messages, router) {
5
6
 
6
7
  var init = function (data) {
@@ -42,9 +43,27 @@ function selfValidExcute(eventName, model) {
42
43
  model.valid = true;
43
44
  return model.valid;
44
45
  }
46
+
47
+ function AIModel(source) {
48
+ let airtn = null
49
+ if (source.field) {
50
+
51
+ let field = source.field;
52
+
53
+ var messages = [];
54
+ if (Array.isArray(field.code1)) {
55
+ messages = field.code1;
56
+ } else {
57
+ messages = field.code1 && field.code1 != "[]" ? JSON.parse(field.code1) : [];
58
+ }
59
+ airtn = loadFromModel(field, messages, source.router);
60
+ }
61
+ return airtn;
62
+ }
45
63
 
46
64
  const AI = {
47
65
  loadFromModel,//获取有效文件数量
48
- selfValidExcute
66
+ selfValidExcute,
67
+ AIModel
49
68
  };
50
69
  export default AI;
@@ -3,9 +3,7 @@ import LibFunction from './LibFunction';
3
3
  import Router from './Router';
4
4
  import Enum from '../../utils/Enum';
5
5
  import common from '../../utils/common';
6
- import request from '../../utils/request';
7
- import Field from './Field';
8
- import AIChat from './AIChat';
6
+ import request from '../../utils/request';
9
7
 
10
8
  function loadFormApi(api, callBack, apiParam, failCallBack, isFormList) {
11
9
  if (api) {
@@ -722,10 +720,10 @@ function loadFromModel(source, isFormList) {
722
720
  return source.flagAlertCloseWindowAfterSave === true;
723
721
  },
724
722
 
725
- _AIattr: null,
726
- get AIattr() {
727
- if (rtn._AIattr !== null) {
728
- return rtn._AIattr;
723
+ _aiAttr: null,
724
+ get aiAttr() {
725
+ if (rtn._aiAttr !== null) {
726
+ return rtn._aiAttr;
729
727
  }
730
728
  else {
731
729
  let aiattr = { showAI: false, width: 0 };
@@ -733,14 +731,14 @@ function loadFromModel(source, isFormList) {
733
731
  aiattr.showAI = true;
734
732
  aiattr.width = parseFloat(source.aiChat.width || 300);
735
733
  }
736
- rtn._AIattr = aiattr;
737
- return rtn._AIattr;
734
+ rtn._aiAttr = aiattr;
735
+ return rtn._aiAttr;
738
736
  }
739
737
  },
740
- _AIRouter: null,
741
- get AIRouter() {
742
- if (rtn._AIRouter !== null) {
743
- return rtn._AIRouter;
738
+ _aiRouter: null,
739
+ get aiRouter() {
740
+ if (rtn._aiRouter !== null) {
741
+ return rtn._aiRouter;
744
742
  }
745
743
  else {
746
744
  var router = {};
@@ -750,28 +748,13 @@ function loadFromModel(source, isFormList) {
750
748
  return v1.key === field.fieldName1;
751
749
  });
752
750
  }
753
- rtn._AIRouter = router;
754
- return rtn._AIRouter;
751
+ rtn._aiRouter= router;
752
+ return rtn._aiRouter;
755
753
  }
754
+ },
755
+ get aiChat() {
756
+ return source.aiChat;
756
757
  },
757
- get AIModel() {
758
- let airtn = null
759
- if (source.aiChat) {
760
-
761
- let field = source.aiChat;
762
- let item = Field(field, []);
763
-
764
- var messages = [];
765
- if (Array.isArray(field.code1)) {
766
- messages = field.code1;
767
- } else {
768
- messages = field.code1 && field.code1 != "[]" ? JSON.parse(field.code1) : [];
769
- }
770
- airtn = AIChat.loadFromModel(item, messages, rtn.AIRouter);
771
- }
772
- return airtn;
773
-
774
- },
775
758
  //获取表单数据
776
759
  getFormObj() {
777
760
  var rtnFormObj = {};