centaline-data-driven-v3 0.0.81 → 0.0.83
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/centaline-data-driven-v3.umd.js +57 -57
- package/package.json +1 -1
- package/src/components/Layout/Layout.vue +1 -3
- package/src/components/web/AIChat.vue +122 -21
- package/src/components/web/ComboBox.vue +3 -2
- package/src/components/web/Form.vue +2 -2
- package/src/components/web/dialog.vue +5 -5
- package/src/loader/src/Router.js +3 -0
- package/src/main.js +10 -5
- package/src/views/SearchList.vue +4 -0
package/package.json
CHANGED
|
@@ -301,11 +301,9 @@ function clickHandler(routerKey, rowindex, forname, forrowindex, flagHaveAlert)
|
|
|
301
301
|
if (typeof rowindex !== "undefined") {
|
|
302
302
|
if (props.flagFormList) {
|
|
303
303
|
emit("rolRouterclick", routerKey, rowindex, props.vmodel.$sourceIndex);
|
|
304
|
-
|
|
305
304
|
}
|
|
306
305
|
else {
|
|
307
|
-
emit("rolRouterclick", routerKey, rowindex, forname, forrowindex, flagHaveAlert);
|
|
308
|
-
|
|
306
|
+
emit("rolRouterclick", routerKey, rowindex, forname, forrowindex, flagHaveAlert,props.vmodel,props.actionRouter);
|
|
309
307
|
}
|
|
310
308
|
}
|
|
311
309
|
}
|
|
@@ -17,8 +17,22 @@
|
|
|
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
|
-
<
|
|
21
|
-
|
|
20
|
+
<template v-if="message.type == 'table'">
|
|
21
|
+
<div :style="{ 'width': tablewidth - 70 + 'px' }">
|
|
22
|
+
<div v-if="JSON.parse(message.content).title" style="margin-bottom: 10px;" v-html="JSON.parse(message.content).title"></div>
|
|
23
|
+
<template v-for="(row, rowindex) in JSON.parse(message.content).rows" :key="rowindex">
|
|
24
|
+
<ct-layout :vmodel="row" :cellLayout="JSON.parse(message.content).cellLayout" :rowindex="rowindex"
|
|
25
|
+
@rolRouterclick="rolRouterCellClickHandler"
|
|
26
|
+
:actionRouter="JSON.parse(message.content).actionRouters">
|
|
27
|
+
</ct-layout>
|
|
28
|
+
</template>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
<template v-else>
|
|
32
|
+
<div class="chat-message" :style="{ color: message.type == 'error' ? 'red' : '' }"
|
|
33
|
+
v-html="htmlContent(message)">
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
22
36
|
</div>
|
|
23
37
|
<div v-else class="loading-container">
|
|
24
38
|
<div class="loading-circle"></div>
|
|
@@ -55,12 +69,13 @@
|
|
|
55
69
|
|
|
56
70
|
|
|
57
71
|
<script setup lang="ts">
|
|
58
|
-
import { ref,
|
|
72
|
+
import { ref, onActivated, nextTick, watch, computed, onMounted } from 'vue'
|
|
59
73
|
import AIChat from '../../loader/src/AIChat'
|
|
60
74
|
import common from '../../utils/common'
|
|
61
75
|
import { marked } from 'marked';
|
|
62
76
|
import DOMPurify from 'dompurify'
|
|
63
|
-
|
|
77
|
+
import Router from '../../loader/src/Router';
|
|
78
|
+
import { RouterClickHandler } from '../../utils/mixins';
|
|
64
79
|
|
|
65
80
|
const emit = defineEmits(['loaded', "getRefFieldPara", "hideAI"])
|
|
66
81
|
const props = defineProps({
|
|
@@ -68,6 +83,11 @@ const props = defineProps({
|
|
|
68
83
|
router: Object,
|
|
69
84
|
actionRouters: Array,
|
|
70
85
|
form: Object,
|
|
86
|
+
tablewidth: Number,
|
|
87
|
+
isVisible: {
|
|
88
|
+
Boolean,
|
|
89
|
+
default: false,
|
|
90
|
+
},
|
|
71
91
|
})
|
|
72
92
|
interface StreamEventData {
|
|
73
93
|
event: string
|
|
@@ -139,6 +159,7 @@ function load(data) {
|
|
|
139
159
|
action();
|
|
140
160
|
}
|
|
141
161
|
|
|
162
|
+
|
|
142
163
|
// Marked 配置
|
|
143
164
|
marked.setOptions({
|
|
144
165
|
breaks: true,
|
|
@@ -149,12 +170,20 @@ marked.setOptions({
|
|
|
149
170
|
function htmlContent(message) {
|
|
150
171
|
return DOMPurify.sanitize(marked(message.content) + '')
|
|
151
172
|
};
|
|
152
|
-
|
|
153
|
-
|
|
173
|
+
|
|
174
|
+
// 监听多个值并执行不同逻辑
|
|
175
|
+
watch([() => inputMessage, () => props.isVisible], ([newVal1, newVal2], [oldVal1, oldVal2]) => {
|
|
154
176
|
nextTick(() => {
|
|
155
|
-
|
|
177
|
+
if (newVal1 !== oldVal1) {
|
|
178
|
+
adjustTextareaHeight();
|
|
179
|
+
}
|
|
180
|
+
if (newVal2) {
|
|
181
|
+
if (textareaRef.value) {
|
|
182
|
+
textareaRef.value.focus();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
156
185
|
});
|
|
157
|
-
});
|
|
186
|
+
}, { flush: 'sync' }); // 控制监听的时机
|
|
158
187
|
|
|
159
188
|
// 调整 textarea 高度
|
|
160
189
|
const adjustTextareaHeight = () => {
|
|
@@ -225,9 +254,9 @@ const scheduleScroll = (flagScroll) => {
|
|
|
225
254
|
if (!scrollPending) {
|
|
226
255
|
if (messagesContainer.value) {
|
|
227
256
|
const container = messagesContainer.value;
|
|
228
|
-
|
|
257
|
+
|
|
229
258
|
const distanceToBottom = container.scrollHeight - (container.scrollTop + container.clientHeight);
|
|
230
|
-
if (flagScroll||distanceToBottom <= 20) {
|
|
259
|
+
if (flagScroll || distanceToBottom <= 20) {
|
|
231
260
|
scrollPending = true
|
|
232
261
|
nextTick(() => {
|
|
233
262
|
if (messagesContainer.value) {
|
|
@@ -305,7 +334,8 @@ const fetchAIResponse = async (params) => {
|
|
|
305
334
|
})
|
|
306
335
|
}).then(response => {
|
|
307
336
|
if (!response.ok) {
|
|
308
|
-
|
|
337
|
+
common.message('网络响应不正常', 'error');
|
|
338
|
+
return;
|
|
309
339
|
}
|
|
310
340
|
|
|
311
341
|
// 获取响应的 ReadableStream
|
|
@@ -320,8 +350,6 @@ const fetchAIResponse = async (params) => {
|
|
|
320
350
|
if (isStopped) {
|
|
321
351
|
// 如果停止标志为 true,直接返回
|
|
322
352
|
outtext.value += "\n\n用户停止"
|
|
323
|
-
startTypingEffect(outtext.value);
|
|
324
|
-
outtext.value = '';
|
|
325
353
|
resolve();
|
|
326
354
|
return;
|
|
327
355
|
}
|
|
@@ -358,11 +386,28 @@ const fetchAIResponse = async (params) => {
|
|
|
358
386
|
}).then(() => {
|
|
359
387
|
// 在所有行处理完毕后执行 startTypingEffect
|
|
360
388
|
if (outtext.value == '') {
|
|
361
|
-
|
|
389
|
+
|
|
362
390
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
391
|
+
let TemplateType = getTemplateType(outtext.value);
|
|
392
|
+
UpdateMessageType(TemplateType);
|
|
393
|
+
|
|
394
|
+
let type = model.value.messages[model.value.messages.length - 1].type;
|
|
395
|
+
if (type == "table" || type == "form") {
|
|
396
|
+
var data = JSON.parse(outtext.value).content;
|
|
397
|
+
if (type == "table") {
|
|
398
|
+
var actionRouters = [];
|
|
399
|
+
data.actionRouters.forEach((v) => {
|
|
400
|
+
var router = Router(v);
|
|
401
|
+
router.is = "ct-button";
|
|
402
|
+
actionRouters.push(router);
|
|
403
|
+
});
|
|
404
|
+
data.actionRouters = actionRouters
|
|
405
|
+
}
|
|
406
|
+
appendMessage(JSON.stringify(data));
|
|
407
|
+
} else {
|
|
408
|
+
startTypingEffect(outtext.value);
|
|
409
|
+
}
|
|
410
|
+
afoot.value = false;
|
|
366
411
|
}).catch(error => {
|
|
367
412
|
UpdateMessageType('error');
|
|
368
413
|
if (error.name === 'AbortError') {
|
|
@@ -386,7 +431,7 @@ function stopRequest() {
|
|
|
386
431
|
}).then(response => response.json()) // 将响应转换为 JSON
|
|
387
432
|
.then(data => {
|
|
388
433
|
if (data.result == 'success') {
|
|
389
|
-
afoot.value =
|
|
434
|
+
afoot.value = false;
|
|
390
435
|
}
|
|
391
436
|
|
|
392
437
|
// 如果服务器返回 { result: "success" },这里会输出这个对象
|
|
@@ -450,13 +495,29 @@ const handleStreamEvent = (eventData: StreamEventData) => {
|
|
|
450
495
|
}
|
|
451
496
|
|
|
452
497
|
const getTemplateType = (fullText) => {
|
|
498
|
+
var rtn = "message";
|
|
499
|
+
try {
|
|
500
|
+
const eventData = JSON.parse(fullText)
|
|
501
|
+
if (eventData) {
|
|
502
|
+
if (eventData.content?.rows) {
|
|
503
|
+
rtn = 'table';
|
|
504
|
+
}
|
|
505
|
+
else if (eventData.content?.fields) {
|
|
506
|
+
rtn = 'form';
|
|
507
|
+
}
|
|
508
|
+
}
|
|
453
509
|
|
|
510
|
+
} catch (error) {
|
|
454
511
|
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return rtn;
|
|
455
515
|
|
|
456
516
|
}
|
|
457
517
|
|
|
458
518
|
|
|
459
519
|
function startTypingEffect(fullText) {
|
|
520
|
+
|
|
460
521
|
let index = 0;
|
|
461
522
|
let timer = setInterval(() => {
|
|
462
523
|
// 检查索引是否超出字符串长度
|
|
@@ -481,13 +542,39 @@ function startTypingEffect(fullText) {
|
|
|
481
542
|
clearInterval(timer); // 清除定时器
|
|
482
543
|
}
|
|
483
544
|
}, 100); // 每100毫秒加载10个字符
|
|
484
|
-
|
|
545
|
+
outtext.value = '';
|
|
546
|
+
|
|
485
547
|
}
|
|
486
548
|
|
|
487
549
|
function hideAI() {
|
|
488
550
|
emit("hideAI", false);
|
|
489
551
|
|
|
490
552
|
}
|
|
553
|
+
//layout组件 路由操作
|
|
554
|
+
function rolRouterCellClickHandler(routerKey, rowindex, forname, forrowindex, flagHaveAlert, rowData, actionRouter) {
|
|
555
|
+
var submitData = {};
|
|
556
|
+
let field = actionRouter.find((b) => {
|
|
557
|
+
return b.key === routerKey;
|
|
558
|
+
});
|
|
559
|
+
field = Router(field);
|
|
560
|
+
if (typeof forname !== "undefined") {
|
|
561
|
+
field.submitListField.forEach((k) => {
|
|
562
|
+
submitData[k] = rowData[forname][forrowindex][k];
|
|
563
|
+
});
|
|
564
|
+
} else {
|
|
565
|
+
field.submitListField.forEach((k) => {
|
|
566
|
+
submitData[k] = rowData[k];
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
if (field.isCallTel) {
|
|
570
|
+
submitData.flagHaveAlert = flagHaveAlert || false;
|
|
571
|
+
}
|
|
572
|
+
let action = field.action;
|
|
573
|
+
if (field.actionField) {
|
|
574
|
+
action = rowData[field.actionField];
|
|
575
|
+
}
|
|
576
|
+
RouterClickHandler(field, submitData, action, model.value, 'table')
|
|
577
|
+
}
|
|
491
578
|
</script>
|
|
492
579
|
|
|
493
580
|
<style scoped>
|
|
@@ -523,6 +610,7 @@ function hideAI() {
|
|
|
523
610
|
display: flex;
|
|
524
611
|
flex-direction: column;
|
|
525
612
|
gap: 1rem;
|
|
613
|
+
|
|
526
614
|
}
|
|
527
615
|
|
|
528
616
|
/* 隐藏滚动条 */
|
|
@@ -545,6 +633,10 @@ function hideAI() {
|
|
|
545
633
|
max-height: none;
|
|
546
634
|
/* 不限制子级高度 */
|
|
547
635
|
border-radius: 10px;
|
|
636
|
+
word-wrap: break-word;
|
|
637
|
+
/* 确保内容自动换行 */
|
|
638
|
+
word-break: break-word;
|
|
639
|
+
/* 长单词或连续字符也能换行 */
|
|
548
640
|
|
|
549
641
|
}
|
|
550
642
|
|
|
@@ -558,6 +650,10 @@ function hideAI() {
|
|
|
558
650
|
align-self: flex-start;
|
|
559
651
|
background-color: white;
|
|
560
652
|
border: 1px solid #e0e0e0;
|
|
653
|
+
max-width: 100%;
|
|
654
|
+
/* 确保不超出父级宽度 */
|
|
655
|
+
width: auto;
|
|
656
|
+
/* 去掉固定宽度 */
|
|
561
657
|
}
|
|
562
658
|
|
|
563
659
|
.chat-message {
|
|
@@ -636,9 +732,9 @@ function hideAI() {
|
|
|
636
732
|
overflow: auto;
|
|
637
733
|
resize: none;
|
|
638
734
|
/* 禁用手动调整大小 */
|
|
639
|
-
min-height:
|
|
735
|
+
min-height: 40px;
|
|
640
736
|
/* 设置最大高度 */
|
|
641
|
-
max-height:
|
|
737
|
+
max-height: 65px;
|
|
642
738
|
/* 设置最大高度 */
|
|
643
739
|
}
|
|
644
740
|
|
|
@@ -647,6 +743,11 @@ function hideAI() {
|
|
|
647
743
|
outline: none;
|
|
648
744
|
}
|
|
649
745
|
|
|
746
|
+
.chat-input::placeholder {
|
|
747
|
+
color: #a8abb2;
|
|
748
|
+
opacity: 1;
|
|
749
|
+
}
|
|
750
|
+
|
|
650
751
|
.chat-editor-action {
|
|
651
752
|
display: flex;
|
|
652
753
|
justify-content: space-between;
|
|
@@ -48,6 +48,7 @@ import Axios from 'axios';
|
|
|
48
48
|
import { ref, nextTick } from 'vue'
|
|
49
49
|
import { Search } from '@element-plus/icons-vue'
|
|
50
50
|
import { initData, changeHandler } from '../../utils/mixins';
|
|
51
|
+
import common from '../../utils/common'
|
|
51
52
|
import ComboBox from '../../loader/src/ComboBox';
|
|
52
53
|
const emit = defineEmits(['click', 'input', 'change', 'popupSearchList', 'search'])
|
|
53
54
|
const props = defineProps({
|
|
@@ -125,7 +126,7 @@ function getOptions(key) {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
if(data.length==0){
|
|
128
|
-
nodatatext.value = '无数据';
|
|
129
|
+
nodatatext.value = common.LocalizedString('无数据', '無數據');
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
nextTick(function () {
|
|
@@ -133,7 +134,7 @@ function getOptions(key) {
|
|
|
133
134
|
});
|
|
134
135
|
}
|
|
135
136
|
else{
|
|
136
|
-
nodatatext.value = '无数据';
|
|
137
|
+
nodatatext.value = common.LocalizedString('无数据', '無數據');
|
|
137
138
|
}
|
|
138
139
|
})
|
|
139
140
|
}
|
|
@@ -157,14 +157,14 @@
|
|
|
157
157
|
|
|
158
158
|
</div>
|
|
159
159
|
<template v-if="model?.aiAttr?.showAI">
|
|
160
|
-
<div :style="{ flex: ' 0 0 ' + model.aiAttr.width + 'px', position: 'sticky', top: '0' ,'
|
|
160
|
+
<div :style="{ flex: ' 0 0 ' + model.aiAttr.width + 'px', position: 'sticky', top: '0' ,'box-shadow': '-10px 0 5px -9px rgba(0, 0, 0, 0.3)' }"
|
|
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
166
|
:field="model.aiChat" :router="model.aiRouter" :actionRouter="model.actionRouters" :form="model"
|
|
167
|
-
@hideAI="AIToggle">
|
|
167
|
+
@hideAI="AIToggle" :isVisible="showAI" :tablewidth="model.aiAttr.width">
|
|
168
168
|
|
|
169
169
|
</AIChat>
|
|
170
170
|
</div>
|
|
@@ -19,7 +19,7 @@ onActivated(() => {
|
|
|
19
19
|
})
|
|
20
20
|
function close() {
|
|
21
21
|
emit('close', props);
|
|
22
|
-
if (props.vmodel.content[0].attrs && typeof props.vmodel.content[0].attrs["onCloseDialog"] === "function") {
|
|
22
|
+
if (props.vmodel.content[0].component != 'ct-iframe' && props.vmodel.content[0].attrs && typeof props.vmodel.content[0].attrs["onCloseDialog"] === "function") {
|
|
23
23
|
props.vmodel.content[0].attrs["onCloseDialog"]();
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -145,11 +145,11 @@ const render = () => {
|
|
|
145
145
|
//AI弹框宽度自适应
|
|
146
146
|
if (!item.attrs.onAIToggle) {
|
|
147
147
|
item.attrs.onAIToggle = (newWidth) => {
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
item.width = parseFloat(item.width) + newWidth + 'px';
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
//加载失败关闭弹框
|
|
154
154
|
if (!item.attrs.onFailLoad) {
|
|
155
155
|
item.attrs.onFailLoad = () => {
|
|
@@ -195,8 +195,8 @@ const render = () => {
|
|
|
195
195
|
item.documentWidth = (props.vmodel.pane.clientWidth - 20) + 'px';
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
item.attrs.dialoWidth = parseInt((item.width||0).replace('px', ''));
|
|
199
|
-
item.attrs.dialogHeight = parseInt((item.height||0).replace('px', ''));
|
|
198
|
+
item.attrs.dialoWidth = parseInt((item.width || 0).replace('px', ''));
|
|
199
|
+
item.attrs.dialogHeight = parseInt((item.height || 0).replace('px', ''));
|
|
200
200
|
return h('div', {
|
|
201
201
|
style: {
|
|
202
202
|
width: item.width,
|
package/src/loader/src/Router.js
CHANGED
package/src/main.js
CHANGED
|
@@ -22,16 +22,18 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
|
22
22
|
|
|
23
23
|
app.use(centaline, {
|
|
24
24
|
baseUrl:"http://10.88.22.66/IBS.Mvc/api/",
|
|
25
|
+
//baseUrl: "https://kq-api.centaline.com.cn/onecard-api/",
|
|
26
|
+
//baseUrl: "http://10.88.22.13:6060/onecard-api/",
|
|
25
27
|
//baseUrl: "http://10.88.22.66:6060/xian/",
|
|
26
28
|
//baseUrl: "http://10.1.245.50:38735/max-uplink-api/",
|
|
27
29
|
//baseUrl: "http://10.1.245.111:38028/",
|
|
28
|
-
|
|
30
|
+
|
|
29
31
|
flagRouterSelf: true,
|
|
30
|
-
flagApp:
|
|
32
|
+
flagApp: true,//是否app端
|
|
31
33
|
zindex: 999,
|
|
32
34
|
showRequestSuccessMessage: true,
|
|
33
35
|
showRequestErrorMessage: true,
|
|
34
|
-
language:'HK',
|
|
36
|
+
language: 'HK',
|
|
35
37
|
handler: {
|
|
36
38
|
// 打开tab页
|
|
37
39
|
openTab: function (action) {
|
|
@@ -64,10 +66,13 @@ app.use(centaline, {
|
|
|
64
66
|
return {
|
|
65
67
|
//authObject: '{token:"aplus eyJhbGciOiJIUzI1NiIsInppcCI6IkRFRiJ9.eNrEjjsOwjAQBe-ydVay1xvvOl3sJA2HiPIxElSIJBIIcXdAQEfPFK-YZt4Nlm2EChqtDafOYWqpRG6kxLoTxZhUTSRxHLUPH_DHfOmt5SDWt1gHScieHapNiol94q5pXYoNFJAvJ6isGHWmNMYVcBjWtyCr_iW2JZ93-fqPc8f18MwGIqFRCIO1GXmWGYd9npCZJ6N5JjYZ7g8AAAD__w.HgtNKtHWooj8c9Hy_vB8CfKq-qOeHMp0irnW0DfXtHo"}',
|
|
66
68
|
//oldToken: 'd92d4a3b-2274-42e8-96f0-100ffb579b6e',
|
|
67
|
-
//authObject: '{token:"
|
|
68
|
-
authObject: '{EmpID:"
|
|
69
|
+
//authObject: '{token:"1647-1907352839429165056",platform:"WEB"}',
|
|
70
|
+
authObject: '{EmpID:"Token_2fa5c93f-ae55-4e77-98a4-ef9c8b3bec34",MachineCode:"7c4b2ffd-920a-462c-a586-37bbfb45c4fe",SSO_Token:"SSOToken_2fa5c93f-ae55-4e77-98a4-ef9c8b3bec34",Platform:"IOS"}',
|
|
69
71
|
};
|
|
70
72
|
},
|
|
73
|
+
getToken() {
|
|
74
|
+
return "1647-1907319603235786752"
|
|
75
|
+
},
|
|
71
76
|
// 请求完成事件,可判断是否登录过期执行响应操作
|
|
72
77
|
requestComplete: function (response) {
|
|
73
78
|
// console.log(response);
|
package/src/views/SearchList.vue
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
<ct-searchlist :apiParam="apiParam" :searchConditionApi="'/propertyTenderList/getLayoutOfSearch'"
|
|
8
8
|
:searchDataApi="'/propertyTenderList/getListOfSearchModel'"></ct-searchlist>
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
<!-- <ct-searchlist :apiParam="apiParam" :searchConditionApi="'/EmployeeAttendanceBillList/getLayoutOfSearchForMy'"
|
|
12
|
+
:searchDataApi="'/EmployeeAttendanceBillList/getListOfSearchModelForMy'"></ct-searchlist> -->
|
|
9
13
|
<ct-dialoglist ref="dialogList"></ct-dialoglist>
|
|
10
14
|
|
|
11
15
|
</div>
|