inl-ui 0.1.3 → 0.1.4

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.
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, createVNode, ref, watch, resolveComponent, isVNode, inject, computed, onActivated, onDeactivated, onBeforeUnmount, nextTick, Fragment, withDirectives, vShow, toRaw, reactive, provide, watchEffect, createTextVNode, onMounted, KeepAlive, shallowRef, onBeforeMount, mergeProps, onBeforeUpdate } from 'vue';
2
- import { createFromIconfontCN, SearchOutlined, DownOutlined, PoweroffOutlined, MenuUnfoldOutlined, MenuFoldOutlined, SkinFilled, FullscreenOutlined, CaretUpOutlined, CaretRightOutlined, CaretDownOutlined, FileExcelTwoTone, InboxOutlined, MessageOutlined, AudioFilled, SendOutlined } from '@ant-design/icons-vue';
2
+ import { createFromIconfontCN, SearchOutlined, DownOutlined, PoweroffOutlined, MenuUnfoldOutlined, MenuFoldOutlined, SkinFilled, FullscreenOutlined, CaretUpOutlined, CaretRightOutlined, CaretDownOutlined, FileExcelTwoTone, InboxOutlined, MessageOutlined, BorderOutlined } from '@ant-design/icons-vue';
3
3
  import { useRoute, useRouter } from 'vue-router';
4
4
  import { useMounted, resolveRef, useThrottleFn, useVModel, useMagicKeys, whenever, watchArray, useEventListener, useSessionStorage, useFullscreen, useLocalStorage, useToggle, useElementBounding, useMemory, useWindowSize, useClipboard, useBreakpoints, breakpointsAntDesign } from '@vueuse/core';
5
5
  import axios from 'axios';
@@ -11221,6 +11221,105 @@ const SszComment = defineComponent({
11221
11221
  });
11222
11222
  var index = installComponent(SszComment, "ssz-comment");
11223
11223
 
11224
+ function formatDataString(str) {
11225
+ const lines = str.split("\n");
11226
+ const result = lines.filter(line => !!line.trim()).map(line => {
11227
+ const data = JSON.parse(line.replace("data: ", ""));
11228
+ return data.text;
11229
+ }).filter(line => line !== void 0).join("");
11230
+ return result;
11231
+ }
11232
+ function request(question, streamCallback, doneCallback) {
11233
+ fetch("/mt_cpp_gpt/chat", {
11234
+ method: "POST",
11235
+ headers: {
11236
+ "Content-Type": "application/json"
11237
+ },
11238
+ body: JSON.stringify({
11239
+ query: question,
11240
+ conversation_id: ""
11241
+ })
11242
+ }).then(res => res.body).then(stream => {
11243
+ const decoder = new TextDecoder();
11244
+ const reader = stream.getReader();
11245
+ let result = "";
11246
+ function processText() {
11247
+ return reader.read().then(({
11248
+ done,
11249
+ value
11250
+ }) => {
11251
+ if (done) {
11252
+ doneCallback();
11253
+ return;
11254
+ }
11255
+ const dataString = decoder.decode(value, {
11256
+ stream: true
11257
+ });
11258
+ const str = formatDataString(dataString);
11259
+ result += str;
11260
+ streamCallback(result);
11261
+ return processText();
11262
+ });
11263
+ }
11264
+ return processText();
11265
+ });
11266
+ }
11267
+ function useQA() {
11268
+ const context = ref([]);
11269
+ const answerLoading = ref(false);
11270
+ const answer = ref("");
11271
+ setTimeout(() => {
11272
+ const questionItem = {
11273
+ type: "answer",
11274
+ content: "",
11275
+ id: /* @__PURE__ */new Date().getTime(),
11276
+ timestamp: /* @__PURE__ */new Date().getTime(),
11277
+ answers: [{
11278
+ content: "\u4F60\u597D\uFF0C\u6211\u662F\u4F60\u7684\u5DE5\u4F5C\u4F19\u4F34 \u7F8E\u5C0F\u817E! \u6211\u53EF\u4EE5\u8F85\u52A9\u4F60\u5FEB\u901F\u83B7\u53D6\u4FE1\u606F\uFF0C\u76D1\u63A7\u3001\u67E5\u770B\u751F\u4EA7\u6307\u6807\uFF0C\u56DE\u7B54\u60A8\u7684\u9009\u7164\u4E13\u4E1A\u95EE\u9898\uFF0C\u5FEB\u8BD5\u8BD5\u4E0B\u9762\u5BF9\u8BDD\u5427\u3002",
11279
+ timestamp: /* @__PURE__ */new Date().getTime(),
11280
+ hideOperates: true,
11281
+ id: /* @__PURE__ */new Date().getTime()
11282
+ }]
11283
+ };
11284
+ context.value.push(questionItem);
11285
+ }, 1e3);
11286
+ function sendQuestion(question, questionId) {
11287
+ if (answerLoading.value) return;
11288
+ answerLoading.value = true;
11289
+ let questionItem = context.value.find(item => item.id === questionId);
11290
+ question = questionItem?.content || question;
11291
+ if (!questionId) {
11292
+ questionItem = {
11293
+ id: /* @__PURE__ */new Date().getTime(),
11294
+ timestamp: /* @__PURE__ */new Date().getTime(),
11295
+ content: question,
11296
+ answers: []
11297
+ };
11298
+ context.value.push(questionItem);
11299
+ }
11300
+ const answerItem = ref({
11301
+ content: "\u6B63\u5728\u601D\u8003\u4E2D...",
11302
+ timestamp: /* @__PURE__ */new Date().getTime(),
11303
+ parentId: questionItem.id,
11304
+ id: /* @__PURE__ */new Date().getTime()
11305
+ });
11306
+ questionItem.answers.push(answerItem.value);
11307
+ request(question, data => {
11308
+ answer.value = data;
11309
+ answerItem.value.content = data;
11310
+ }, () => {
11311
+ answerLoading.value = false;
11312
+ answerItem.value.loadEnd = true;
11313
+ });
11314
+ }
11315
+ return {
11316
+ context,
11317
+ answerLoading,
11318
+ answer,
11319
+ sendQuestion
11320
+ };
11321
+ }
11322
+
11224
11323
  const Input = defineComponent({
11225
11324
  emits: ["send"],
11226
11325
  setup(props, {
@@ -11229,7 +11328,13 @@ const Input = defineComponent({
11229
11328
  }) {
11230
11329
  const value = ref("");
11231
11330
  const isFocus = ref(false);
11331
+ const loading = inject("answerLoading");
11232
11332
  const send = () => {
11333
+ if (loading.value) return;
11334
+ if (value.value.length === 0) {
11335
+ message.warn("\u8BF7\u8F93\u5165\u95EE\u9898");
11336
+ return;
11337
+ }
11233
11338
  emit("send", value.value);
11234
11339
  value.value = "";
11235
11340
  };
@@ -11241,14 +11346,24 @@ const Input = defineComponent({
11241
11346
  "class": ["chat-box-input", {
11242
11347
  focus: isFocus.value
11243
11348
  }]
11244
- }, [createVNode(AudioFilled, null, null), createVNode(resolveComponent("a-input"), {
11349
+ }, [createVNode("img", {
11350
+ "class": "img img-mic",
11351
+ "src": "/micro-assets/largeLanguageModel/mic.png",
11352
+ "alt": ""
11353
+ }, null), createVNode(resolveComponent("a-input"), {
11245
11354
  "value": value.value,
11246
11355
  "onUpdate:value": $event => value.value = $event,
11247
11356
  "bordered": false,
11248
11357
  "placeholder": "\u5982: \u67E5\u770BXXX\u76AE\u5E26\u673A\u5934\u7535\u6D41\u7B49",
11249
11358
  "onFocus": () => isFocus.value = true,
11250
- "onBlur": () => isFocus.value = false
11251
- }, null), createVNode(SendOutlined, {
11359
+ "onBlur": () => isFocus.value = false,
11360
+ "onPressEnter": send
11361
+ }, null), loading.value ? createVNode(BorderOutlined, {
11362
+ "class": "btn-abord",
11363
+ "title": "\u4E2D\u6B62\u56DE\u7B54"
11364
+ }, null) : createVNode("img", {
11365
+ "class": "img img-send",
11366
+ "src": "/micro-assets/largeLanguageModel/send.png",
11252
11367
  "onClick": send
11253
11368
  }, null)]);
11254
11369
  }
@@ -11256,15 +11371,19 @@ const Input = defineComponent({
11256
11371
 
11257
11372
  const tips = ["\u8BBE\u5907\u5DE5\u4F5C\u539F\u7406", "\u8BBE\u5907\u7EF4\u4FDD\u624B\u518C"];
11258
11373
  const Bottom = defineComponent({
11259
- setup() {
11374
+ emits: ["send"],
11375
+ setup(props, {
11376
+ emit
11377
+ }) {
11260
11378
  const inputRef = ref();
11261
11379
  const handleSend = msg => {
11262
11380
  inputRef.value.clear();
11381
+ emit("send", msg);
11263
11382
  };
11264
11383
  return () => {
11265
11384
  const tipsDom = tips.map(tip => createVNode("div", {
11266
11385
  "class": "tip",
11267
- "onClick": () => handleSend()
11386
+ "onClick": () => handleSend(tip)
11268
11387
  }, [tip]));
11269
11388
  return createVNode("div", {
11270
11389
  "class": "bottom"
@@ -11309,6 +11428,28 @@ const Avatar = defineComponent({
11309
11428
  }
11310
11429
  });
11311
11430
 
11431
+ const QuestionBubble = defineComponent({
11432
+ props: {
11433
+ content: {
11434
+ type: String,
11435
+ default: ""
11436
+ }
11437
+ },
11438
+ setup(props) {
11439
+ return () => createVNode("div", {
11440
+ "class": "question-bubble chat-bubble"
11441
+ }, [createVNode(Avatar, {
11442
+ "reverse": true,
11443
+ "avatar": "/micro-assets/platform_app/avatar.png",
11444
+ "name": "\u5F20\u660E\u5FD7"
11445
+ }, null), createVNode("div", {
11446
+ "class": "bubble question"
11447
+ }, [props.content]), createVNode("div", {
11448
+ "class": "operates"
11449
+ }, null)]);
11450
+ }
11451
+ });
11452
+
11312
11453
  const styleDark = `
11313
11454
  <style>
11314
11455
  :host > p {
@@ -11336,25 +11477,26 @@ const styleLight = `
11336
11477
 
11337
11478
  const suggestionList = ["\u7F8E\u5C0F\u817E\u80FD\u5E2E\u6211\u505A\u4EC0\u4E48\uFF1F", "\u8FD1\u4E00\u4E2A\u6708\u7684\u4ECB\u8017\u60C5\u51B5\u5982\u4F55\uFF1F", "\u5C3E\u77FF\u8DD1\u7C97\u7684\u6392\u67E5\u5904\u7406\u65B9\u6CD5\u6709\u54EA\u4E9B\uFF1F\u5C3E\u77FF\u8DD1\u7C97\u7684\u6392\u67E5\u5904\u7406\u65B9\u6CD5\u6709\u54EA\u4E9B\u5C3E\u77FF\u8DD1\u7C97\u7684\u6392\u67E5\u5904\u7406\u65B9\u6CD5\u6709\u54EA\u4E9B\u5C3E\u77FF\u8DD1\u7C97\u7684\u6392\u67E5\u5904\u7406\u65B9\u6CD5\u6709\u54EA\u4E9B"];
11338
11479
  const AnswerBubble = defineComponent({
11480
+ emits: ["send", "render", "delete"],
11481
+ props: {
11482
+ content: {
11483
+ type: Array,
11484
+ default: () => []
11485
+ }
11486
+ },
11339
11487
  setup(props, {
11340
11488
  emit
11341
11489
  }) {
11342
11490
  const chatTheme = inject("chat-theme");
11491
+ const {
11492
+ copy
11493
+ } = useClipboard({
11494
+ legacy: true
11495
+ });
11343
11496
  const bubbleRef = ref();
11497
+ const activeAnswerIndex = ref(0);
11498
+ const activeAnswer = computed(() => props.content[activeAnswerIndex.value]);
11344
11499
  let shadowRoot;
11345
- const mdText = ref(`\u4ECA\u5929\u7684\u7CBE\u7164\u4EA7\u91CF**18830.0**\u5428\uFF0C\u672B\u7164\u4EA7\u91CF**15900.0**\u5428\uFF0C\u7164\u6CE5**539.0**\u5428
11346
-
11347
- #### \u4F60\u597D\u554A
11348
-
11349
- 1. \u4F60\u597D\u554A
11350
-
11351
- 2. \u4E09\u5929\u4E4B\u5185\u6740\u4E86\u4F60
11352
-
11353
- 3. \u4F60\u662F\u771F\u6CA1\u89C1\u8FC7\u9ED1\u793E\u4F1A\u554A
11354
-
11355
- 4. \u6562\u4E0D\u6562\u8DDF\u6211\u6BD4\u5212\u6BD4\u5212
11356
-
11357
- 5. \u8BA9\u4F60\u89C1\u8BC6\u89C1\u8BC6\u4EC0\u4E48\u53EB\u9ED1\u624B`);
11358
11500
  const trasformMd = mdString => {
11359
11501
  return marked(mdString);
11360
11502
  };
@@ -11362,49 +11504,177 @@ const AnswerBubble = defineComponent({
11362
11504
  shadowRoot = bubbleRef.value.attachShadow({
11363
11505
  mode: "open"
11364
11506
  });
11507
+ renderText();
11508
+ });
11509
+ const renderText = () => {
11510
+ if (!shadowRoot) return;
11511
+ emit("render", activeAnswer.value.content);
11365
11512
  const themeStyle = chatTheme === "dark" ? styleDark : styleLight;
11366
11513
  const html = `
11367
- ${trasformMd(mdText.value)}
11514
+ ${trasformMd(activeAnswer.value.content)}
11368
11515
 
11369
11516
  ${themeStyle}
11370
11517
  `;
11371
11518
  shadowRoot.innerHTML = html;
11519
+ };
11520
+ watch([() => props.content, activeAnswerIndex], renderText, {
11521
+ deep: true
11372
11522
  });
11523
+ const operateList = reactive([{
11524
+ title: "\u590D\u5236",
11525
+ key: "copy",
11526
+ isActive: false
11527
+ }, {
11528
+ title: "\u6709\u7528",
11529
+ key: "like",
11530
+ isActive: computed(() => activeAnswer.value.isLike)
11531
+ }, {
11532
+ title: "\u65E0\u7528",
11533
+ key: "dislike",
11534
+ isActive: computed(() => activeAnswer.value.isDislike)
11535
+ }, {
11536
+ title: "\u8BC4\u8BBA",
11537
+ key: "comment",
11538
+ isActive: false
11539
+ }, {
11540
+ title: "\u91CD\u65B0\u751F\u6210",
11541
+ key: "regenerate",
11542
+ isActive: false
11543
+ }, {
11544
+ ttile: "\u5220\u9664",
11545
+ key: "delete",
11546
+ isActive: false
11547
+ }]);
11548
+ const handleOperate = key => {
11549
+ switch (key) {
11550
+ case "like":
11551
+ if (!activeAnswer.value.isDislike && !activeAnswer.value.isDislike) {
11552
+ activeAnswer.value.isLike = !activeAnswer.value.isLike;
11553
+ }
11554
+ break;
11555
+ case "dislike":
11556
+ if (!activeAnswer.value.isLike && !activeAnswer.value.isDislike) {
11557
+ activeAnswer.value.isDislike = !activeAnswer.value.isDislike;
11558
+ }
11559
+ break;
11560
+ case "copy":
11561
+ copy(activeAnswer.value.content);
11562
+ message.success("\u590D\u5236\u6210\u529F");
11563
+ break;
11564
+ case "delete":
11565
+ Modal.confirm({
11566
+ title: "\u786E\u5B9A\u5220\u9664\u8FD9\u4E2A\u56DE\u7B54\u5417\uFF1F",
11567
+ onOk: () => {
11568
+ emit("delete", activeAnswer.value.id);
11569
+ }
11570
+ });
11571
+ break;
11572
+ case "comment":
11573
+ message.info("\u6682\u672A\u5F00\u653E");
11574
+ break;
11575
+ }
11576
+ };
11373
11577
  return () => {
11374
- const suggestionListDom = suggestionList.map(item => createVNode("div", {
11578
+ suggestionList.map(item => createVNode("div", {
11375
11579
  "class": "suggestion-item",
11376
11580
  "onClick": () => emit("send", item)
11377
11581
  }, [item]));
11582
+ const showOperates = !activeAnswer.value.hideOperates && activeAnswer.value.loadEnd;
11583
+ const operateDom = operateList.map(item => {
11584
+ return createVNode(resolveComponent("a-tooltip"), {
11585
+ "title": item.title
11586
+ }, {
11587
+ default: () => [createVNode("div", {
11588
+ "class": ["operate-item", item.key, {
11589
+ active: item.isActive
11590
+ }],
11591
+ "onClick": () => handleOperate(item.key)
11592
+ }, null)]
11593
+ });
11594
+ });
11595
+ const prevDisabled = activeAnswerIndex.value === 0;
11596
+ const nextDisabled = activeAnswerIndex.value === props.content.length - 1;
11597
+ const answerNav = createVNode("div", {
11598
+ "class": "operate-item"
11599
+ }, [createVNode("span", {
11600
+ "class": ["nav", {
11601
+ disalbed: prevDisabled
11602
+ }]
11603
+ }, ["<"]), activeAnswerIndex.value + 1, "/ ", props.content.length, createVNode("span", {
11604
+ "class": ["nav", {
11605
+ disalbed: nextDisabled
11606
+ }]
11607
+ }, [">"])]);
11378
11608
  return createVNode("div", {
11379
11609
  "class": "answer-bubble chat-bubble"
11380
11610
  }, [createVNode(Avatar, {
11381
- "avatar": "",
11611
+ "avatar": "/micro-assets/largeLanguageModel/robot-avatar.png",
11382
11612
  "name": "\u7F8E\u5C0F\u817E"
11383
11613
  }, null), createVNode("div", {
11384
11614
  "ref": bubbleRef,
11385
11615
  "class": "bubble answer"
11386
- }, null), createVNode("div", {
11616
+ }, null), showOperates && createVNode("div", {
11387
11617
  "class": "operates"
11388
- }, null), createVNode("div", {
11389
- "class": "suggestion-list"
11390
- }, [suggestionListDom])]);
11618
+ }, [props.content.length > 1 && answerNav, operateDom])]);
11391
11619
  };
11392
11620
  }
11393
11621
  });
11394
11622
 
11395
- const QuestionBubble = defineComponent({
11396
- setup() {
11397
- return () => createVNode("div", {
11398
- "class": "question-bubble chat-bubble"
11399
- }, [createVNode(Avatar, {
11400
- "reverse": true,
11401
- "avatar": "",
11402
- "name": "\u5F20\u660E\u5FD7"
11403
- }, null), createVNode("div", {
11404
- "class": "bubble question"
11405
- }, ["\u6562\u4E0D\u6562\u8DDF\u6211\u6BD4\u5212\u6BD4\u5212"]), createVNode("div", {
11406
- "class": "operates"
11407
- }, null)]);
11623
+ const QaContext = defineComponent({
11624
+ props: {
11625
+ list: {
11626
+ type: Array,
11627
+ default: () => []
11628
+ }
11629
+ },
11630
+ setup(props) {
11631
+ const containerRef = ref();
11632
+ const onAnswerRender = text => {
11633
+ containerRef.value.scrollTo({
11634
+ top: containerRef.value.scrollHeight,
11635
+ behavior: "smooth"
11636
+ });
11637
+ };
11638
+ const handleDeleteAnswer = (questionId, answerId) => {
11639
+ const question = props.list.find(item => item.id === questionId);
11640
+ if (question) {
11641
+ question.answers = question.answers.filter(item => item.id !== answerId);
11642
+ }
11643
+ };
11644
+ return () => {
11645
+ const contextList = [];
11646
+ for (let i = 0; i < props.list.length; i++) {
11647
+ const questionItem = props.list[i];
11648
+ const prevItem = props.list[i - 1];
11649
+ const currentTime = questionItem.timestamp;
11650
+ let timeDiff = 0;
11651
+ if (prevItem) {
11652
+ const prevTime = prevItem.timestamp;
11653
+ timeDiff = currentTime - prevTime;
11654
+ }
11655
+ if (!prevItem || timeDiff > 1e3 * 60 * 5) {
11656
+ contextList.push(createVNode("div", {
11657
+ "class": "time-line"
11658
+ }, [dayjs(currentTime).format("MM/DD HH:mm")]));
11659
+ }
11660
+ if (questionItem.content) {
11661
+ contextList.push(createVNode(QuestionBubble, {
11662
+ "content": questionItem.content
11663
+ }, null));
11664
+ }
11665
+ if (questionItem.answers.length > 0) {
11666
+ contextList.push(createVNode(AnswerBubble, {
11667
+ "onRender": onAnswerRender,
11668
+ "content": questionItem.answers,
11669
+ "onDelete": answerId => handleDeleteAnswer(questionItem.id, answerId)
11670
+ }, null));
11671
+ }
11672
+ }
11673
+ return createVNode("div", {
11674
+ "class": "qa-context",
11675
+ "ref": containerRef
11676
+ }, [contextList]);
11677
+ };
11408
11678
  }
11409
11679
  });
11410
11680
 
@@ -11424,11 +11694,24 @@ const ChatBox = defineComponent({
11424
11694
  emit
11425
11695
  }) {
11426
11696
  provide("chat-theme", props.theme);
11427
- ref();
11697
+ const {
11698
+ context,
11699
+ answerLoading,
11700
+ sendQuestion,
11701
+ answer
11702
+ } = useQA();
11703
+ provide("answerLoading", answerLoading);
11704
+ const handleSend = msg => {
11705
+ sendQuestion(msg);
11706
+ };
11428
11707
  return () => {
11429
11708
  return createVNode("div", {
11430
11709
  "class": ["inl-chat-box", `inl-chat-box-${props.theme}`]
11431
- }, [createVNode(AnswerBubble, null, null), createVNode(QuestionBubble, null, null), createVNode(Bottom, null, null)]);
11710
+ }, [createVNode(QaContext, {
11711
+ "list": context.value
11712
+ }, null), createVNode(Bottom, {
11713
+ "onSend": handleSend
11714
+ }, null)]);
11432
11715
  };
11433
11716
  }
11434
11717
  });