inl-ui 0.1.2 → 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';
@@ -7982,6 +7982,9 @@ const VideoBoxV2 = defineComponent({
7982
7982
  token: sessionStorage.getItem("token")
7983
7983
  }
7984
7984
  });
7985
+ setTimeout(() => {
7986
+ getThingValue();
7987
+ }, 3e3);
7985
7988
  infos.value.forEach(info => {
7986
7989
  if (info.thingDeviceId) {
7987
7990
  const obj = res.data.data?.shift();
@@ -8042,12 +8045,7 @@ const VideoBoxV2 = defineComponent({
8042
8045
  clearInterval(interval);
8043
8046
  clearInterval(intervalSet);
8044
8047
  getVideoParams(val);
8045
- intervalSet = setInterval(() => {
8046
- getVideoParams(val);
8047
- }, 1800 * 1e3);
8048
- interval = setInterval(() => {
8049
- getThingValue();
8050
- }, 3e3);
8048
+ intervalSet = setInterval(() => {}, 1800 * 1e3);
8051
8049
  getVideoDetail(val);
8052
8050
  const fillVal = localStorage.getItem(val);
8053
8051
  if (fillVal) {
@@ -8328,28 +8326,7 @@ const PollingPlay = defineComponent({
8328
8326
  });
8329
8327
  const alarmList = ref([]);
8330
8328
  const getAlarm = async () => {
8331
- const res = await axios.post(`/api/mtip/thing/v2/thingClient/getPropertyValuesByRelationAndCode`, {
8332
- instanceCodeList: data.pointList,
8333
- relationCodeList: ["DEVICE_MT"],
8334
- targetProperetyCodeList: ["ALARM"]
8335
- }, {
8336
- headers: {
8337
- token: sessionStorage.getItem("token") || ""
8338
- }
8339
- });
8340
- data.pointList.forEach((uuid, index) => {
8341
- const alarmConfig = res.data?.data?.[uuid];
8342
- if (alarmConfig?.length && alarmConfig?.length !== 0) {
8343
- const have = alarmConfig.find(element => element.alarmDTO?.alarmId);
8344
- if (have) {
8345
- alarmList.value[index] = true;
8346
- } else {
8347
- alarmList.value[index] = false;
8348
- }
8349
- } else {
8350
- alarmList.value[index] = false;
8351
- }
8352
- });
8329
+ return;
8353
8330
  };
8354
8331
  return () => createVNode("div", {
8355
8332
  "class": "playVideos"
@@ -11244,6 +11221,105 @@ const SszComment = defineComponent({
11244
11221
  });
11245
11222
  var index = installComponent(SszComment, "ssz-comment");
11246
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
+
11247
11323
  const Input = defineComponent({
11248
11324
  emits: ["send"],
11249
11325
  setup(props, {
@@ -11252,7 +11328,13 @@ const Input = defineComponent({
11252
11328
  }) {
11253
11329
  const value = ref("");
11254
11330
  const isFocus = ref(false);
11331
+ const loading = inject("answerLoading");
11255
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
+ }
11256
11338
  emit("send", value.value);
11257
11339
  value.value = "";
11258
11340
  };
@@ -11264,14 +11346,24 @@ const Input = defineComponent({
11264
11346
  "class": ["chat-box-input", {
11265
11347
  focus: isFocus.value
11266
11348
  }]
11267
- }, [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"), {
11268
11354
  "value": value.value,
11269
11355
  "onUpdate:value": $event => value.value = $event,
11270
11356
  "bordered": false,
11271
11357
  "placeholder": "\u5982: \u67E5\u770BXXX\u76AE\u5E26\u673A\u5934\u7535\u6D41\u7B49",
11272
11358
  "onFocus": () => isFocus.value = true,
11273
- "onBlur": () => isFocus.value = false
11274
- }, 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",
11275
11367
  "onClick": send
11276
11368
  }, null)]);
11277
11369
  }
@@ -11279,15 +11371,19 @@ const Input = defineComponent({
11279
11371
 
11280
11372
  const tips = ["\u8BBE\u5907\u5DE5\u4F5C\u539F\u7406", "\u8BBE\u5907\u7EF4\u4FDD\u624B\u518C"];
11281
11373
  const Bottom = defineComponent({
11282
- setup() {
11374
+ emits: ["send"],
11375
+ setup(props, {
11376
+ emit
11377
+ }) {
11283
11378
  const inputRef = ref();
11284
11379
  const handleSend = msg => {
11285
11380
  inputRef.value.clear();
11381
+ emit("send", msg);
11286
11382
  };
11287
11383
  return () => {
11288
11384
  const tipsDom = tips.map(tip => createVNode("div", {
11289
11385
  "class": "tip",
11290
- "onClick": () => handleSend()
11386
+ "onClick": () => handleSend(tip)
11291
11387
  }, [tip]));
11292
11388
  return createVNode("div", {
11293
11389
  "class": "bottom"
@@ -11332,6 +11428,28 @@ const Avatar = defineComponent({
11332
11428
  }
11333
11429
  });
11334
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
+
11335
11453
  const styleDark = `
11336
11454
  <style>
11337
11455
  :host > p {
@@ -11359,25 +11477,26 @@ const styleLight = `
11359
11477
 
11360
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"];
11361
11479
  const AnswerBubble = defineComponent({
11480
+ emits: ["send", "render", "delete"],
11481
+ props: {
11482
+ content: {
11483
+ type: Array,
11484
+ default: () => []
11485
+ }
11486
+ },
11362
11487
  setup(props, {
11363
11488
  emit
11364
11489
  }) {
11365
11490
  const chatTheme = inject("chat-theme");
11491
+ const {
11492
+ copy
11493
+ } = useClipboard({
11494
+ legacy: true
11495
+ });
11366
11496
  const bubbleRef = ref();
11497
+ const activeAnswerIndex = ref(0);
11498
+ const activeAnswer = computed(() => props.content[activeAnswerIndex.value]);
11367
11499
  let shadowRoot;
11368
- 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
11369
-
11370
- #### \u4F60\u597D\u554A
11371
-
11372
- 1. \u4F60\u597D\u554A
11373
-
11374
- 2. \u4E09\u5929\u4E4B\u5185\u6740\u4E86\u4F60
11375
-
11376
- 3. \u4F60\u662F\u771F\u6CA1\u89C1\u8FC7\u9ED1\u793E\u4F1A\u554A
11377
-
11378
- 4. \u6562\u4E0D\u6562\u8DDF\u6211\u6BD4\u5212\u6BD4\u5212
11379
-
11380
- 5. \u8BA9\u4F60\u89C1\u8BC6\u89C1\u8BC6\u4EC0\u4E48\u53EB\u9ED1\u624B`);
11381
11500
  const trasformMd = mdString => {
11382
11501
  return marked(mdString);
11383
11502
  };
@@ -11385,49 +11504,177 @@ const AnswerBubble = defineComponent({
11385
11504
  shadowRoot = bubbleRef.value.attachShadow({
11386
11505
  mode: "open"
11387
11506
  });
11507
+ renderText();
11508
+ });
11509
+ const renderText = () => {
11510
+ if (!shadowRoot) return;
11511
+ emit("render", activeAnswer.value.content);
11388
11512
  const themeStyle = chatTheme === "dark" ? styleDark : styleLight;
11389
11513
  const html = `
11390
- ${trasformMd(mdText.value)}
11514
+ ${trasformMd(activeAnswer.value.content)}
11391
11515
 
11392
11516
  ${themeStyle}
11393
11517
  `;
11394
11518
  shadowRoot.innerHTML = html;
11519
+ };
11520
+ watch([() => props.content, activeAnswerIndex], renderText, {
11521
+ deep: true
11395
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
+ };
11396
11577
  return () => {
11397
- const suggestionListDom = suggestionList.map(item => createVNode("div", {
11578
+ suggestionList.map(item => createVNode("div", {
11398
11579
  "class": "suggestion-item",
11399
11580
  "onClick": () => emit("send", item)
11400
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
+ }, [">"])]);
11401
11608
  return createVNode("div", {
11402
11609
  "class": "answer-bubble chat-bubble"
11403
11610
  }, [createVNode(Avatar, {
11404
- "avatar": "",
11611
+ "avatar": "/micro-assets/largeLanguageModel/robot-avatar.png",
11405
11612
  "name": "\u7F8E\u5C0F\u817E"
11406
11613
  }, null), createVNode("div", {
11407
11614
  "ref": bubbleRef,
11408
11615
  "class": "bubble answer"
11409
- }, null), createVNode("div", {
11616
+ }, null), showOperates && createVNode("div", {
11410
11617
  "class": "operates"
11411
- }, null), createVNode("div", {
11412
- "class": "suggestion-list"
11413
- }, [suggestionListDom])]);
11618
+ }, [props.content.length > 1 && answerNav, operateDom])]);
11414
11619
  };
11415
11620
  }
11416
11621
  });
11417
11622
 
11418
- const QuestionBubble = defineComponent({
11419
- setup() {
11420
- return () => createVNode("div", {
11421
- "class": "question-bubble chat-bubble"
11422
- }, [createVNode(Avatar, {
11423
- "reverse": true,
11424
- "avatar": "",
11425
- "name": "\u5F20\u660E\u5FD7"
11426
- }, null), createVNode("div", {
11427
- "class": "bubble question"
11428
- }, ["\u6562\u4E0D\u6562\u8DDF\u6211\u6BD4\u5212\u6BD4\u5212"]), createVNode("div", {
11429
- "class": "operates"
11430
- }, 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
+ };
11431
11678
  }
11432
11679
  });
11433
11680
 
@@ -11447,11 +11694,24 @@ const ChatBox = defineComponent({
11447
11694
  emit
11448
11695
  }) {
11449
11696
  provide("chat-theme", props.theme);
11450
- 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
+ };
11451
11707
  return () => {
11452
11708
  return createVNode("div", {
11453
11709
  "class": ["inl-chat-box", `inl-chat-box-${props.theme}`]
11454
- }, [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)]);
11455
11715
  };
11456
11716
  }
11457
11717
  });