pcm-agents 0.3.0 → 0.3.2

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 (146) hide show
  1. package/LICENSE +21 -21
  2. package/dist/cjs/index-BFPEnLbS.js +195 -0
  3. package/dist/cjs/index-BFPEnLbS.js.map +1 -0
  4. package/dist/cjs/index.cjs.js +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/my-component.cjs.entry.js +2 -2
  7. package/dist/cjs/my-component.cjs.entry.js.map +1 -1
  8. package/dist/cjs/my-component.entry.cjs.js.map +1 -1
  9. package/dist/cjs/pcm-agents.cjs.js +1 -1
  10. package/dist/cjs/pcm-app-chat-modal.pcm-chat-message.pcm-hr-chat-modal.pcm-jlpx-modal.pcm-mnms-modal.pcm-video-chat-modal.pcm-zygh-modal.entry.cjs.js.map +1 -0
  11. package/dist/cjs/pcm-app-chat-modal_7.cjs.entry.js +6560 -0
  12. package/dist/cjs/pcm-app-chat-modal_7.cjs.entry.js.map +1 -0
  13. package/dist/cjs/pcm-chat-modal.cjs.entry.js +17 -32
  14. package/dist/cjs/pcm-chat-modal.cjs.entry.js.map +1 -1
  15. package/dist/cjs/pcm-chat-modal.entry.cjs.js.map +1 -1
  16. package/dist/collection/collection-manifest.json +2 -0
  17. package/dist/collection/components/my-component/my-component.css +3 -3
  18. package/dist/collection/components/my-component/my-component.js +1 -1
  19. package/dist/collection/components/my-component/my-component.js.map +1 -1
  20. package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.css +2 -1
  21. package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js +137 -159
  22. package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js.map +1 -1
  23. package/dist/collection/components/pcm-chat-message/pcm-chat-message.css +66 -12
  24. package/dist/collection/components/pcm-chat-message/pcm-chat-message.js +106 -13
  25. package/dist/collection/components/pcm-chat-message/pcm-chat-message.js.map +1 -1
  26. package/dist/collection/components/pcm-chat-modal/pcm-chat-modal.js +39 -34
  27. package/dist/collection/components/pcm-chat-modal/pcm-chat-modal.js.map +1 -1
  28. package/dist/collection/components/pcm-hr-chat-modal/pcm-hr-chat-modal.js +76 -105
  29. package/dist/collection/components/pcm-hr-chat-modal/pcm-hr-chat-modal.js.map +1 -1
  30. package/dist/collection/components/pcm-jlpx-modal/pcm-jlpx-modal.css +162 -0
  31. package/dist/collection/components/pcm-jlpx-modal/pcm-jlpx-modal.js +616 -0
  32. package/dist/collection/components/pcm-jlpx-modal/pcm-jlpx-modal.js.map +1 -0
  33. package/dist/collection/components/pcm-mnms-modal/pcm-mnms-modal.css +0 -79
  34. package/dist/collection/components/pcm-mnms-modal/pcm-mnms-modal.js +133 -81
  35. package/dist/collection/components/pcm-mnms-modal/pcm-mnms-modal.js.map +1 -1
  36. package/dist/collection/components/pcm-video-chat-modal/pcm-video-chat-modal.js +77 -101
  37. package/dist/collection/components/pcm-video-chat-modal/pcm-video-chat-modal.js.map +1 -1
  38. package/dist/collection/components/pcm-zygh-modal/pcm-zygh-modal.css +273 -0
  39. package/dist/collection/components/pcm-zygh-modal/pcm-zygh-modal.js +613 -0
  40. package/dist/collection/components/pcm-zygh-modal/pcm-zygh-modal.js.map +1 -0
  41. package/dist/collection/global/global.css +324 -0
  42. package/dist/collection/index.js.map +1 -1
  43. package/dist/collection/interfaces/chat.js.map +1 -1
  44. package/dist/collection/utils/utils.js +54 -113
  45. package/dist/collection/utils/utils.js.map +1 -1
  46. package/dist/components/index.js +1298 -11280
  47. package/dist/components/index.js.map +1 -1
  48. package/dist/components/my-component.js +2 -3
  49. package/dist/components/my-component.js.map +1 -1
  50. package/dist/components/{p-C4l_DOnx.js → p-BctfuDvG.js} +106 -147
  51. package/dist/components/p-BctfuDvG.js.map +1 -0
  52. package/dist/components/{p-D0s1Q-3O.js → p-LkDC0SN2.js} +343 -16
  53. package/dist/components/p-LkDC0SN2.js.map +1 -0
  54. package/dist/components/pcm-app-chat-modal.js +1 -1
  55. package/dist/components/pcm-chat-message.js +1 -1
  56. package/dist/components/pcm-chat-modal.js +19 -34
  57. package/dist/components/pcm-chat-modal.js.map +1 -1
  58. package/dist/components/pcm-hr-chat-modal.js +70 -100
  59. package/dist/components/pcm-hr-chat-modal.js.map +1 -1
  60. package/dist/components/pcm-jlpx-modal.d.ts +11 -0
  61. package/dist/components/pcm-jlpx-modal.js +339 -0
  62. package/dist/components/pcm-jlpx-modal.js.map +1 -0
  63. package/dist/components/pcm-mnms-modal.js +109 -57
  64. package/dist/components/pcm-mnms-modal.js.map +1 -1
  65. package/dist/components/pcm-video-chat-modal.js +74 -99
  66. package/dist/components/pcm-video-chat-modal.js.map +1 -1
  67. package/dist/components/pcm-zygh-modal.d.ts +11 -0
  68. package/dist/components/pcm-zygh-modal.js +330 -0
  69. package/dist/components/pcm-zygh-modal.js.map +1 -0
  70. package/dist/esm/index-nVjZGfA8.js +189 -0
  71. package/dist/esm/index-nVjZGfA8.js.map +1 -0
  72. package/dist/esm/index.js +1 -1
  73. package/dist/esm/loader.js +1 -1
  74. package/dist/esm/my-component.entry.js +2 -2
  75. package/dist/esm/my-component.entry.js.map +1 -1
  76. package/dist/esm/pcm-agents.js +1 -1
  77. package/dist/esm/pcm-app-chat-modal.pcm-chat-message.pcm-hr-chat-modal.pcm-jlpx-modal.pcm-mnms-modal.pcm-video-chat-modal.pcm-zygh-modal.entry.js.map +1 -0
  78. package/dist/esm/pcm-app-chat-modal_7.entry.js +6552 -0
  79. package/dist/esm/pcm-app-chat-modal_7.entry.js.map +1 -0
  80. package/dist/esm/pcm-chat-modal.entry.js +17 -32
  81. package/dist/esm/pcm-chat-modal.entry.js.map +1 -1
  82. package/dist/pcm-agents/index.esm.js +1 -1
  83. package/dist/pcm-agents/my-component.entry.esm.js.map +1 -1
  84. package/dist/pcm-agents/p-55417392.entry.js +2 -0
  85. package/dist/pcm-agents/p-55417392.entry.js.map +1 -0
  86. package/dist/pcm-agents/p-a698b59f.entry.js +2 -0
  87. package/dist/pcm-agents/p-a698b59f.entry.js.map +1 -0
  88. package/dist/pcm-agents/p-f3ca99b4.entry.js +2 -0
  89. package/dist/pcm-agents/p-f3ca99b4.entry.js.map +1 -0
  90. package/dist/pcm-agents/p-nVjZGfA8.js +2 -0
  91. package/dist/pcm-agents/p-nVjZGfA8.js.map +1 -0
  92. package/dist/pcm-agents/pcm-agents.esm.js +1 -1
  93. package/dist/pcm-agents/pcm-app-chat-modal.pcm-chat-message.pcm-hr-chat-modal.pcm-jlpx-modal.pcm-mnms-modal.pcm-video-chat-modal.pcm-zygh-modal.entry.esm.js.map +1 -0
  94. package/dist/pcm-agents/pcm-chat-modal.entry.esm.js.map +1 -1
  95. package/dist/types/components/pcm-app-chat-modal/pcm-app-chat-modal.d.ts +13 -8
  96. package/dist/types/components/pcm-chat-message/pcm-chat-message.d.ts +5 -0
  97. package/dist/types/components/pcm-chat-modal/pcm-chat-modal.d.ts +8 -8
  98. package/dist/types/components/pcm-hr-chat-modal/pcm-hr-chat-modal.d.ts +6 -12
  99. package/dist/types/components/pcm-jlpx-modal/pcm-jlpx-modal.d.ts +113 -0
  100. package/dist/types/components/pcm-mnms-modal/pcm-mnms-modal.d.ts +19 -20
  101. package/dist/types/components/pcm-video-chat-modal/pcm-video-chat-modal.d.ts +4 -4
  102. package/dist/types/components/pcm-zygh-modal/pcm-zygh-modal.d.ts +117 -0
  103. package/dist/types/components.d.ts +429 -80
  104. package/dist/types/interfaces/chat.d.ts +0 -4
  105. package/dist/types/utils/utils.d.ts +29 -83
  106. package/package.json +61 -60
  107. package/readme.md +307 -307
  108. package/dist/cjs/index-DfIUl99H.js +0 -11413
  109. package/dist/cjs/index-DfIUl99H.js.map +0 -1
  110. package/dist/cjs/pcm-app-chat-modal.pcm-chat-message.pcm-mnms-modal.entry.cjs.js.map +0 -1
  111. package/dist/cjs/pcm-app-chat-modal_3.cjs.entry.js +0 -3734
  112. package/dist/cjs/pcm-app-chat-modal_3.cjs.entry.js.map +0 -1
  113. package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js +0 -1078
  114. package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js.map +0 -1
  115. package/dist/cjs/pcm-hr-chat-modal.entry.cjs.js.map +0 -1
  116. package/dist/cjs/pcm-video-chat-modal.cjs.entry.js +0 -927
  117. package/dist/cjs/pcm-video-chat-modal.cjs.entry.js.map +0 -1
  118. package/dist/cjs/pcm-video-chat-modal.entry.cjs.js.map +0 -1
  119. package/dist/components/p-C4l_DOnx.js.map +0 -1
  120. package/dist/components/p-CgDy4pJp.js +0 -1244
  121. package/dist/components/p-CgDy4pJp.js.map +0 -1
  122. package/dist/components/p-D0s1Q-3O.js.map +0 -1
  123. package/dist/esm/index-B2EtEi7v.js +0 -11409
  124. package/dist/esm/index-B2EtEi7v.js.map +0 -1
  125. package/dist/esm/pcm-app-chat-modal.pcm-chat-message.pcm-mnms-modal.entry.js.map +0 -1
  126. package/dist/esm/pcm-app-chat-modal_3.entry.js +0 -3730
  127. package/dist/esm/pcm-app-chat-modal_3.entry.js.map +0 -1
  128. package/dist/esm/pcm-hr-chat-modal.entry.js +0 -1076
  129. package/dist/esm/pcm-hr-chat-modal.entry.js.map +0 -1
  130. package/dist/esm/pcm-video-chat-modal.entry.js +0 -925
  131. package/dist/esm/pcm-video-chat-modal.entry.js.map +0 -1
  132. package/dist/pcm-agents/p-0ddd5c47.entry.js +0 -2
  133. package/dist/pcm-agents/p-0ddd5c47.entry.js.map +0 -1
  134. package/dist/pcm-agents/p-5f624943.entry.js +0 -2
  135. package/dist/pcm-agents/p-5f624943.entry.js.map +0 -1
  136. package/dist/pcm-agents/p-6c07f155.entry.js +0 -2
  137. package/dist/pcm-agents/p-6c07f155.entry.js.map +0 -1
  138. package/dist/pcm-agents/p-9a1fb6ca.entry.js +0 -2
  139. package/dist/pcm-agents/p-9a1fb6ca.entry.js.map +0 -1
  140. package/dist/pcm-agents/p-B2EtEi7v.js +0 -146
  141. package/dist/pcm-agents/p-B2EtEi7v.js.map +0 -1
  142. package/dist/pcm-agents/p-e21bc169.entry.js +0 -2
  143. package/dist/pcm-agents/p-e21bc169.entry.js.map +0 -1
  144. package/dist/pcm-agents/pcm-app-chat-modal.pcm-chat-message.pcm-mnms-modal.entry.esm.js.map +0 -1
  145. package/dist/pcm-agents/pcm-hr-chat-modal.entry.esm.js.map +0 -1
  146. package/dist/pcm-agents/pcm-video-chat-modal.entry.esm.js.map +0 -1
@@ -1,5 +1,7 @@
1
1
  import { h } from "@stencil/core";
2
2
  import { marked } from "marked";
3
+ import extendedTables from "marked-extended-tables";
4
+ import { sendHttpRequest } from "../../utils/utils";
3
5
  export class ChatMessageComponent {
4
6
  /**
5
7
  * 消息数据
@@ -13,6 +15,7 @@ export class ChatMessageComponent {
13
15
  hostElement;
14
16
  constructor() {
15
17
  // 配置 marked 选项
18
+ marked.use(extendedTables);
16
19
  marked.setOptions({
17
20
  breaks: true,
18
21
  gfm: true
@@ -35,7 +38,7 @@ export class ChatMessageComponent {
35
38
  renderUserMessage() {
36
39
  if (!this.message?.query?.trim())
37
40
  return null;
38
- return (h("div", { class: "user-message-container" }, h("div", { class: "message-bubble user-message" }, h("p", null, this.message.query), this.renderInputs())));
41
+ return (h("div", { class: "user-message-container" }, h("div", { class: "message-bubble user-message" }, this.renderInputs(), h("p", null, this.message.query))));
39
42
  }
40
43
  // 渲染助手消息部分
41
44
  renderAssistantMessage() {
@@ -48,7 +51,96 @@ export class ChatMessageComponent {
48
51
  `请稍等...` :
49
52
  htmlContent })), !showLoading && this.message.answer && (h("div", { class: "message-actions" }, h("button", { class: "copy-button", onClick: () => this.copyMessageContent(), title: "\u590D\u5236\u5185\u5BB9" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), h("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })))))));
50
53
  }
51
- // 渲染输入数据
54
+ getFileIcon(fileName) {
55
+ const extension = fileName.split('.').pop()?.toLowerCase();
56
+ switch (extension) {
57
+ case 'pdf':
58
+ return {
59
+ icon: `<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
60
+ <path d="M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z" stroke="#1677FF" stroke-width="2"/>
61
+ <path d="M19 3V9H25" stroke="#1677FF" stroke-width="2"/>
62
+ <text x="11" y="20" fill="#1677FF" font-size="8">PDF</text>
63
+ </svg>`,
64
+ color: '#1677FF'
65
+ };
66
+ case 'doc':
67
+ case 'docx':
68
+ return {
69
+ icon: `<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
70
+ <path d="M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z" stroke="#1677FF" stroke-width="2"/>
71
+ <path d="M19 3V9H25" stroke="#1677FF" stroke-width="2"/>
72
+ <text x="11" y="20" fill="#1677FF" font-size="6">DOC</text>
73
+ </svg>`,
74
+ color: '#1677FF'
75
+ };
76
+ case 'jpg':
77
+ case 'jpeg':
78
+ case 'png':
79
+ case 'gif':
80
+ return {
81
+ icon: `<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
82
+ <path d="M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z" stroke="#52C41A" stroke-width="2"/>
83
+ <path d="M19 3V9H25" stroke="#52C41A" stroke-width="2"/>
84
+ <path d="M12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14Z" fill="#52C41A"/>
85
+ <path d="M10 21L13 18L15 20L19 16L22 21H10Z" fill="#52C41A"/>
86
+ </svg>`,
87
+ color: '#52C41A'
88
+ };
89
+ default:
90
+ return {
91
+ icon: `<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
92
+ <path d="M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z" stroke="#666666" stroke-width="2"/>
93
+ <path d="M19 3V9H25" stroke="#666666" stroke-width="2"/>
94
+ </svg>`,
95
+ color: '#666666'
96
+ };
97
+ }
98
+ }
99
+ getFileName(fileUrl) {
100
+ const parts = fileUrl.split('/');
101
+ return parts[parts.length - 1];
102
+ }
103
+ // 获取预览URL
104
+ async getCosPreviewUrl(cosKey) {
105
+ try {
106
+ const result = await sendHttpRequest({
107
+ url: '/sdk/v1/files/presigned-url',
108
+ method: 'GET',
109
+ headers: {
110
+ 'authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6Ilx1NTMzYlx1ODA1OFx1NzMyYjgxMDMiLCJ1aWQiOjcsImNoYXRfdXNlciI6bnVsbCwiYm90X2lkIjoiMSIsInNlY3JldF9pZCI6Mzg5OTk1ODAyNTUxOTEwNDAsImV4cCI6MTc0NTA0OTAxM30.56OoTrp16avgl48YfWBKOHywAKHJ5qPGypqRCGCyVt0'
111
+ },
112
+ params: {
113
+ cos_key: cosKey
114
+ }
115
+ });
116
+ console.log(result);
117
+ if (result.success && result.data?.file_url) {
118
+ const baseUrl = result.data.file_url;
119
+ return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}ci-process=doc-preview&copyable=1&dstType=html`;
120
+ }
121
+ return null;
122
+ }
123
+ catch (error) {
124
+ console.error('获取预览URL失败:', error);
125
+ return null;
126
+ }
127
+ }
128
+ // 处理文件点击
129
+ async handleFileClick(fileUrl) {
130
+ const previewUrl = await this.getCosPreviewUrl(fileUrl);
131
+ if (previewUrl) {
132
+ window.open(previewUrl, '_blank');
133
+ }
134
+ else {
135
+ console.error('无法获取预览URL');
136
+ }
137
+ }
138
+ // 修改渲染文件项的部分
139
+ renderFileItem(fileName, fileUrl, index) {
140
+ const { icon } = this.getFileIcon(fileName);
141
+ return (h("div", { key: index, class: "input-view" }, h("div", { class: "input-label" }, "\u9644\u4EF6\uFF1A"), h("div", { class: "file-item", onClick: () => this.handleFileClick(fileUrl) }, h("div", { class: "file-icon", innerHTML: icon }), h("div", { class: "file-name" }, fileName))));
142
+ }
143
+ // 修改渲染输入数据的方法
52
144
  renderInputs() {
53
145
  if (!this.message.inputs)
54
146
  return null;
@@ -56,17 +148,18 @@ export class ChatMessageComponent {
56
148
  const value = this.message.inputs[key];
57
149
  if (value && !key.startsWith('hide_') && key !== 'answer') {
58
150
  if (key === 'file_url') {
59
- return h("div", { key: index, class: "file-view" }, value);
60
- }
61
- else if (key === 'file_urls' || key === 'fileUrls') {
62
- const fileList = value.split(',');
63
- return (h("div", { key: index, class: "flex flex-wrap" }, fileList.map((fileUrl, fileIndex) => (h("div", { key: fileIndex, class: "file-view" }, fileUrl)))));
151
+ const fileName = this.getFileName(value);
152
+ return this.renderFileItem(fileName, value, index);
64
153
  }
65
- else if (key === 'job_info') {
66
- return (h("div", { key: index, class: "input-view" }, h("div", { class: "input-label" }, "\u804C\u4F4D\u4FE1\u606F"), h("div", { class: "input-value" }, value)));
154
+ else if (key === 'file_urls') {
155
+ const fileList = Array.isArray(value) ? value : value.split(',');
156
+ return (h("div", { key: index, class: "file-list" }, fileList.map((fileUrl, fileIndex) => {
157
+ const fileName = this.getFileName(fileUrl);
158
+ return this.renderFileItem(fileName, fileUrl, fileIndex);
159
+ })));
67
160
  }
68
- else if (key === 'rule') {
69
- return (h("div", { key: index, class: "input-view" }, h("div", { class: "input-label" }, "\u8BC4\u4F30\u89C4\u5219"), h("div", { class: "input-value" }, value)));
161
+ else if (key === 'job_info' || key === 'rule') {
162
+ return (h("div", { key: index, class: "input-view" }, h("div", { class: "input-label" }, key === 'job_info' ? '职位信息' : '评估规则'), h("div", { class: "input-value" }, value)));
70
163
  }
71
164
  else {
72
165
  return h("div", { key: index, class: "input-metadata" }, key, ": ", `${value}`);
@@ -76,7 +169,7 @@ export class ChatMessageComponent {
76
169
  })));
77
170
  }
78
171
  render() {
79
- return (h("div", { key: '5748f17414b9442b9b791955de38437184fa2f7e', class: "message-round" }, this.renderUserMessage(), this.renderAssistantMessage()));
172
+ return (h("div", { key: '3d9014ffaf4a18e08e6cea97abce67d918512720', class: "message-round" }, this.renderUserMessage(), this.renderAssistantMessage()));
80
173
  }
81
174
  static get is() { return "pcm-chat-message"; }
82
175
  static get encapsulation() { return "shadow"; }
@@ -130,7 +223,7 @@ export class ChatMessageComponent {
130
223
  },
131
224
  "complexType": {
132
225
  "original": "Partial<ChatMessage>",
133
- "resolved": "{ id?: string; query?: string; answer?: string; time?: string; conversation_id?: string; isStreaming?: boolean; bot_id?: string; inputs?: Record<string, any>; status?: \"error\" | \"normal\"; error?: any; }",
226
+ "resolved": "{ id?: string; query?: string; answer?: string; time?: string; conversation_id?: string; isStreaming?: boolean; inputs?: Record<string, any>; status?: \"error\" | \"normal\"; error?: any; }",
134
227
  "references": {
135
228
  "Partial": {
136
229
  "location": "global",
@@ -1 +1 @@
1
- {"version":3,"file":"pcm-chat-message.js","sourceRoot":"","sources":["../../../src/components/pcm-chat-message/pcm-chat-message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h, Element, Event, EventEmitter } from '@stencil/core';\r\nimport { marked } from 'marked';\r\nimport { ChatMessage } from '../../interfaces/chat';\r\n@Component({\r\n tag: 'pcm-chat-message',\r\n styleUrl: 'pcm-chat-message.css',\r\n shadow: true,\r\n})\r\nexport class ChatMessageComponent {\r\n /**\r\n * 消息数据\r\n */\r\n @Prop() message: ChatMessage;\r\n\r\n /**\r\n * 消息变更事件\r\n */\r\n @Event() messageChange: EventEmitter<Partial<ChatMessage>>;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n constructor() {\r\n // 配置 marked 选项\r\n marked.setOptions({\r\n breaks: true,\r\n gfm: true\r\n });\r\n }\r\n\r\n // 复制消息内容到剪贴板\r\n private copyMessageContent() {\r\n if (this.message.answer) {\r\n navigator.clipboard.writeText(this.message.answer)\r\n .then(() => {\r\n // 可以添加复制成功的提示\r\n console.log('内容已复制到剪贴板');\r\n })\r\n .catch(err => {\r\n console.error('复制失败:', err);\r\n });\r\n }\r\n }\r\n\r\n // 渲染用户消息部分\r\n private renderUserMessage() {\r\n if (!this.message?.query?.trim()) return null;\r\n\r\n return (\r\n <div class=\"user-message-container\">\r\n <div class=\"message-bubble user-message\">\r\n <p>{this.message.query}</p>\r\n {this.renderInputs()}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染助手消息部分\r\n private renderAssistantMessage() {\r\n if (!this.message.answer && !this.message.isStreaming) return null;\r\n\r\n // 只有在开始流式输出且还没有内容时才显示loading\r\n const showLoading = this.message.isStreaming && !this.message.answer;\r\n const htmlContent = this.message.answer ? marked(this.message.answer) : '';\r\n\r\n return (\r\n <div class=\"assistant-message-container\">\r\n <div class=\"message-bubble assistant-message\">\r\n <div\r\n class=\"markdown-content markdown-body\"\r\n innerHTML={showLoading ? \r\n `请稍等...` : \r\n htmlContent\r\n }\r\n ></div>\r\n </div>\r\n {!showLoading && this.message.answer && (\r\n <div class=\"message-actions\">\r\n <button class=\"copy-button\" onClick={() => this.copyMessageContent()} title=\"复制内容\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染输入数据\r\n private renderInputs() {\r\n if (!this.message.inputs) return null;\r\n\r\n return (\r\n <div>\r\n {Object.keys(this.message.inputs).map((key, index) => {\r\n const value = this.message.inputs[key];\r\n if (value && !key.startsWith('hide_') && key !== 'answer') {\r\n if (key === 'file_url') {\r\n return <div key={index} class=\"file-view\">{value}</div>;\r\n } else if (key === 'file_urls' || key === 'fileUrls') {\r\n const fileList = value.split(',');\r\n return (\r\n <div key={index} class=\"flex flex-wrap\">\r\n {fileList.map((fileUrl, fileIndex) => (\r\n <div key={fileIndex} class=\"file-view\">{fileUrl}</div>\r\n ))}\r\n </div>\r\n );\r\n } else if (key === 'job_info') {\r\n return (\r\n <div key={index} class=\"input-view\">\r\n <div class=\"input-label\">职位信息</div>\r\n <div class=\"input-value\">{value}</div>\r\n </div>\r\n );\r\n } else if (key === 'rule') {\r\n return (\r\n <div key={index} class=\"input-view\">\r\n <div class=\"input-label\">评估规则</div>\r\n <div class=\"input-value\">{value}</div>\r\n </div>\r\n );\r\n } else {\r\n return <div key={index} class=\"input-metadata\">{key}: {`${value}`}</div>;\r\n }\r\n }\r\n return null;\r\n })}\r\n </div>\r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n <div class=\"message-round\">\r\n {this.renderUserMessage()}\r\n {this.renderAssistantMessage()}\r\n </div>\r\n );\r\n }\r\n} "]}
1
+ {"version":3,"file":"pcm-chat-message.js","sourceRoot":"","sources":["../../../src/components/pcm-chat-message/pcm-chat-message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h, Element, Event, EventEmitter } from '@stencil/core';\r\nimport { marked } from 'marked';\r\nimport extendedTables from 'marked-extended-tables';\r\nimport { ChatMessage } from '../../interfaces/chat';\r\nimport { sendHttpRequest } from '../../utils/utils';\r\n\r\n@Component({\r\n tag: 'pcm-chat-message',\r\n styleUrl: 'pcm-chat-message.css',\r\n shadow: true,\r\n})\r\nexport class ChatMessageComponent {\r\n /**\r\n * 消息数据\r\n */\r\n @Prop() message: ChatMessage;\r\n\r\n /**\r\n * 消息变更事件\r\n */\r\n @Event() messageChange: EventEmitter<Partial<ChatMessage>>;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n constructor() {\r\n // 配置 marked 选项\r\n marked.use(extendedTables);\r\n marked.setOptions({\r\n breaks: true,\r\n gfm: true\r\n });\r\n }\r\n\r\n // 复制消息内容到剪贴板\r\n private copyMessageContent() {\r\n if (this.message.answer) {\r\n navigator.clipboard.writeText(this.message.answer)\r\n .then(() => {\r\n // 可以添加复制成功的提示\r\n console.log('内容已复制到剪贴板');\r\n })\r\n .catch(err => {\r\n console.error('复制失败:', err);\r\n });\r\n }\r\n }\r\n\r\n // 渲染用户消息部分\r\n private renderUserMessage() {\r\n if (!this.message?.query?.trim()) return null;\r\n\r\n return (\r\n <div class=\"user-message-container\">\r\n <div class=\"message-bubble user-message\">\r\n {this.renderInputs()}\r\n <p>{this.message.query}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染助手消息部分\r\n private renderAssistantMessage() {\r\n if (!this.message.answer && !this.message.isStreaming) return null;\r\n\r\n // 只有在开始流式输出且还没有内容时才显示loading\r\n const showLoading = this.message.isStreaming && !this.message.answer;\r\n const htmlContent = this.message.answer ? marked(this.message.answer) : '';\r\n\r\n return (\r\n <div class=\"assistant-message-container\">\r\n <div class=\"message-bubble assistant-message\">\r\n <div\r\n class=\"markdown-content markdown-body\"\r\n innerHTML={showLoading ?\r\n `请稍等...` :\r\n htmlContent\r\n }\r\n ></div>\r\n </div>\r\n {!showLoading && this.message.answer && (\r\n <div class=\"message-actions\">\r\n <button class=\"copy-button\" onClick={() => this.copyMessageContent()} title=\"复制内容\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path>\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n private getFileIcon(fileName: string): { icon: string, color: string } {\r\n const extension = fileName.split('.').pop()?.toLowerCase();\r\n\r\n switch (extension) {\r\n case 'pdf':\r\n return {\r\n icon: `<svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z\" stroke=\"#1677FF\" stroke-width=\"2\"/>\r\n <path d=\"M19 3V9H25\" stroke=\"#1677FF\" stroke-width=\"2\"/>\r\n <text x=\"11\" y=\"20\" fill=\"#1677FF\" font-size=\"8\">PDF</text>\r\n </svg>`,\r\n color: '#1677FF'\r\n };\r\n case 'doc':\r\n case 'docx':\r\n return {\r\n icon: `<svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z\" stroke=\"#1677FF\" stroke-width=\"2\"/>\r\n <path d=\"M19 3V9H25\" stroke=\"#1677FF\" stroke-width=\"2\"/>\r\n <text x=\"11\" y=\"20\" fill=\"#1677FF\" font-size=\"6\">DOC</text>\r\n </svg>`,\r\n color: '#1677FF'\r\n };\r\n case 'jpg':\r\n case 'jpeg':\r\n case 'png':\r\n case 'gif':\r\n return {\r\n icon: `<svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z\" stroke=\"#52C41A\" stroke-width=\"2\"/>\r\n <path d=\"M19 3V9H25\" stroke=\"#52C41A\" stroke-width=\"2\"/>\r\n <path d=\"M12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14Z\" fill=\"#52C41A\"/>\r\n <path d=\"M10 21L13 18L15 20L19 16L22 21H10Z\" fill=\"#52C41A\"/>\r\n </svg>`,\r\n color: '#52C41A'\r\n };\r\n default:\r\n return {\r\n icon: `<svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M19 3H9C7.89543 3 7 3.89543 7 5V27C7 28.1046 7.89543 29 9 29H23C24.1046 29 25 28.1046 25 27V9L19 3Z\" stroke=\"#666666\" stroke-width=\"2\"/>\r\n <path d=\"M19 3V9H25\" stroke=\"#666666\" stroke-width=\"2\"/>\r\n </svg>`,\r\n color: '#666666'\r\n };\r\n }\r\n }\r\n\r\n private getFileName(fileUrl: string): string {\r\n const parts = fileUrl.split('/');\r\n return parts[parts.length - 1];\r\n }\r\n\r\n // 获取预览URL\r\n private async getCosPreviewUrl(cosKey: string): Promise<string | null> {\r\n try {\r\n const result = await sendHttpRequest<{ file_url: string }>({\r\n url: '/sdk/v1/files/presigned-url',\r\n method: 'GET',\r\n headers: {\r\n 'authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6Ilx1NTMzYlx1ODA1OFx1NzMyYjgxMDMiLCJ1aWQiOjcsImNoYXRfdXNlciI6bnVsbCwiYm90X2lkIjoiMSIsInNlY3JldF9pZCI6Mzg5OTk1ODAyNTUxOTEwNDAsImV4cCI6MTc0NTA0OTAxM30.56OoTrp16avgl48YfWBKOHywAKHJ5qPGypqRCGCyVt0'\r\n },\r\n params: {\r\n cos_key: cosKey\r\n }\r\n });\r\n \r\n console.log(result);\r\n \r\n if (result.success && result.data?.file_url) {\r\n const baseUrl = result.data.file_url;\r\n return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}ci-process=doc-preview&copyable=1&dstType=html`;\r\n }\r\n return null;\r\n } catch (error) {\r\n console.error('获取预览URL失败:', error);\r\n return null;\r\n }\r\n }\r\n\r\n // 处理文件点击\r\n private async handleFileClick(fileUrl: string) {\r\n const previewUrl = await this.getCosPreviewUrl(fileUrl);\r\n if (previewUrl) {\r\n window.open(previewUrl, '_blank');\r\n } else {\r\n console.error('无法获取预览URL');\r\n }\r\n }\r\n\r\n // 修改渲染文件项的部分\r\n private renderFileItem(fileName: string, fileUrl: string, index: number) {\r\n const { icon } = this.getFileIcon(fileName);\r\n return (\r\n <div key={index} class=\"input-view\">\r\n <div class=\"input-label\">附件:</div>\r\n <div class=\"file-item\" onClick={() => this.handleFileClick(fileUrl)}>\r\n <div class=\"file-icon\" innerHTML={icon}></div>\r\n <div class=\"file-name\">{fileName}</div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 修改渲染输入数据的方法\r\n private renderInputs() {\r\n if (!this.message.inputs) return null;\r\n\r\n return (\r\n <div>\r\n {Object.keys(this.message.inputs).map((key, index) => {\r\n const value = this.message.inputs[key];\r\n if (value && !key.startsWith('hide_') && key !== 'answer') {\r\n if (key === 'file_url') {\r\n const fileName = this.getFileName(value);\r\n return this.renderFileItem(fileName, value, index);\r\n } else if (key === 'file_urls') {\r\n const fileList = Array.isArray(value) ? value : value.split(',');\r\n return (\r\n <div key={index} class=\"file-list\">\r\n {fileList.map((fileUrl, fileIndex) => {\r\n const fileName = this.getFileName(fileUrl);\r\n return this.renderFileItem(fileName, fileUrl, fileIndex);\r\n })}\r\n </div>\r\n );\r\n } else if (key === 'job_info' || key === 'rule') {\r\n return (\r\n <div key={index} class=\"input-view\">\r\n <div class=\"input-label\">{key === 'job_info' ? '职位信息' : '评估规则'}</div>\r\n <div class=\"input-value\">{value}</div>\r\n </div>\r\n );\r\n } else {\r\n return <div key={index} class=\"input-metadata\">{key}: {`${value}`}</div>;\r\n }\r\n }\r\n return null;\r\n })}\r\n </div>\r\n );\r\n }\r\n\r\n render() {\r\n return (\r\n <div class=\"message-round\">\r\n {this.renderUserMessage()}\r\n {this.renderAssistantMessage()}\r\n </div>\r\n );\r\n }\r\n} "]}
@@ -1,10 +1,14 @@
1
1
  import { h } from "@stencil/core";
2
- import { convertWorkflowStreamNodeToMessageRound, sendSSERequest, sendHttpRequest } from "../../utils/utils";
2
+ import { convertWorkflowStreamNodeToMessageRound, sendSSERequest, sendHttpRequest, uploadFileToBackend } from "../../utils/utils";
3
3
  export class ChatModal {
4
4
  /**
5
5
  * 模态框标题
6
6
  */
7
7
  modalTitle = '在线客服';
8
+ /**
9
+ * API鉴权密钥
10
+ */
11
+ apiKey = '';
8
12
  /**
9
13
  * 是否显示聊天模态框
10
14
  */
@@ -46,7 +50,7 @@ export class ChatModal {
46
50
  */
47
51
  botId;
48
52
  /**
49
- * 会话ID
53
+ * 会话ID,传入继续对话,否则创建新会话
50
54
  */
51
55
  conversationId;
52
56
  /**
@@ -80,7 +84,7 @@ export class ChatModal {
80
84
  */
81
85
  defaultQuery = '';
82
86
  /**
83
- * 是否以全屏模式打开
87
+ * 是否以全屏模式打开,移动端建议设置为true
84
88
  */
85
89
  fullscreen = false;
86
90
  handleClose = () => {
@@ -95,15 +99,12 @@ export class ChatModal {
95
99
  this.suggestedQuestionsLoading = true;
96
100
  try {
97
101
  const response = await sendHttpRequest({
98
- url: `https://pcm_api.ylzhaopin.com/share/messages/${messageId}/suggested`,
99
- params: {
100
- bot_id: this.botId
101
- }
102
+ url: `/share/messages/${messageId}/suggested`,
102
103
  });
103
104
  if (this.stopSuggestedQuestionsRef.current)
104
105
  return;
105
- if (response.isOk && response.data?.result === 'success') {
106
- this.suggestedQuestions = response.data?.data || [];
106
+ if (response.success && response.data) {
107
+ this.suggestedQuestions = response.data || [];
107
108
  }
108
109
  }
109
110
  catch (error) {
@@ -130,22 +131,10 @@ export class ChatModal {
130
131
  return;
131
132
  this.isUploading = true;
132
133
  try {
133
- const formData = new FormData();
134
- formData.append('file', this.selectedFile);
135
- const response = await fetch('https://pcm_api.ylzhaopin.com/external/v1/files/upload', {
136
- method: 'POST',
137
- body: formData
134
+ const result = await uploadFileToBackend(this.selectedFile, {
135
+ 'authorization': 'Bearer ' + this.apiKey
138
136
  });
139
- const result = await response.json();
140
- console.log('result', result);
141
- if (result) {
142
- this.uploadedFileInfo.push({
143
- cos_key: result.cos_key,
144
- filename: result.filename,
145
- ext: result.ext,
146
- presigned_url: result.presigned_url
147
- });
148
- }
137
+ this.uploadedFileInfo.push(result);
149
138
  }
150
139
  catch (error) {
151
140
  console.error('文件上传错误:', error);
@@ -183,7 +172,6 @@ export class ChatModal {
183
172
  time: time, // 消息时间
184
173
  query: queryText, // 用户输入的消息内容
185
174
  answer: '', // AI助手的回复内容
186
- bot_id: this.botId, // 机器人ID
187
175
  isStreaming: true, // 是否正在流式输出
188
176
  conversation_id: this.conversationId, // 会话ID
189
177
  inputs: {}, // 输入参数
@@ -197,7 +185,6 @@ export class ChatModal {
197
185
  this.scrollToBottom();
198
186
  // 准备请求数据
199
187
  const requestData = {
200
- bot_id: this.botId,
201
188
  response_mode: 'streaming',
202
189
  conversation_id: this.conversationId,
203
190
  query: queryText,
@@ -212,7 +199,7 @@ export class ChatModal {
212
199
  };
213
200
  }
214
201
  await sendSSERequest({
215
- url: `https://pcm_api.ylzhaopin.com/share/chat-messages`,
202
+ url: `/sdk/v1/chat/chat-messages`,
216
203
  method: 'POST',
217
204
  data: requestData,
218
205
  onMessage: (data) => {
@@ -334,19 +321,18 @@ export class ChatModal {
334
321
  this.isLoadingHistory = true;
335
322
  try {
336
323
  const response = await sendHttpRequest({
337
- url: `https://pcm_api.ylzhaopin.com/share/messages`,
324
+ url: `/share/messages`,
338
325
  params: {
339
326
  conversation_id: this.conversationId,
340
- bot_id: this.botId,
341
327
  user: '1234567890',
342
328
  limit: 20
343
329
  }
344
330
  });
345
- if (!response.isOk || !response.data) {
331
+ if (!response.success || !response.data) {
346
332
  throw new Error('加载历史消息失败');
347
333
  }
348
334
  // 适配新的接口返回格式
349
- const historyData = response.data.data || [];
335
+ const historyData = response.data || [];
350
336
  // 清空现有消息,确保不会重复
351
337
  this.currentStreamingMessage = null;
352
338
  this.messages = [];
@@ -356,7 +342,6 @@ export class ChatModal {
356
342
  return {
357
343
  ...msg,
358
344
  time: timeStr,
359
- bot_id: this.botId,
360
345
  isStreaming: false,
361
346
  status: msg.status === 'error' ? 'error' : 'normal'
362
347
  };
@@ -448,6 +433,26 @@ export class ChatModal {
448
433
  "reflect": false,
449
434
  "defaultValue": "'\u5728\u7EBF\u5BA2\u670D'"
450
435
  },
436
+ "apiKey": {
437
+ "type": "string",
438
+ "mutable": false,
439
+ "complexType": {
440
+ "original": "string",
441
+ "resolved": "string",
442
+ "references": {}
443
+ },
444
+ "required": false,
445
+ "optional": false,
446
+ "docs": {
447
+ "tags": [],
448
+ "text": "API\u9274\u6743\u5BC6\u94A5"
449
+ },
450
+ "getter": false,
451
+ "setter": false,
452
+ "attribute": "api-key",
453
+ "reflect": false,
454
+ "defaultValue": "''"
455
+ },
451
456
  "isOpen": {
452
457
  "type": "boolean",
453
458
  "mutable": true,
@@ -578,7 +583,7 @@ export class ChatModal {
578
583
  "optional": true,
579
584
  "docs": {
580
585
  "tags": [],
581
- "text": "\u4F1A\u8BDDID"
586
+ "text": "\u4F1A\u8BDDID\uFF0C\u4F20\u5165\u7EE7\u7EED\u5BF9\u8BDD\uFF0C\u5426\u5219\u521B\u5EFA\u65B0\u4F1A\u8BDD"
582
587
  },
583
588
  "getter": false,
584
589
  "setter": false,
@@ -617,7 +622,7 @@ export class ChatModal {
617
622
  "optional": false,
618
623
  "docs": {
619
624
  "tags": [],
620
- "text": "\u662F\u5426\u4EE5\u5168\u5C4F\u6A21\u5F0F\u6253\u5F00"
625
+ "text": "\u662F\u5426\u4EE5\u5168\u5C4F\u6A21\u5F0F\u6253\u5F00\uFF0C\u79FB\u52A8\u7AEF\u5EFA\u8BAE\u8BBE\u7F6E\u4E3Atrue"
621
626
  },
622
627
  "getter": false,
623
628
  "setter": false,
@@ -1 +1 @@
1
- {"version":3,"file":"pcm-chat-modal.js","sourceRoot":"","sources":["../../../src/components/pcm-chat-modal/pcm-chat-modal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h, State, Event, EventEmitter, Element, Watch } from '@stencil/core';\r\nimport { convertWorkflowStreamNodeToMessageRound, UserInputMessageType, sendSSERequest, sendHttpRequest } from '../../utils/utils';\r\nimport { ChatMessage } from '../../interfaces/chat';\r\n\r\n@Component({\r\n tag: 'pcm-chat-modal',\r\n styleUrl: 'pcm-chat-modal.css',\r\n shadow: true,\r\n})\r\nexport class ChatModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '在线客服';\r\n\r\n /**\r\n * 是否显示聊天模态框\r\n */\r\n @Prop({ mutable: true }) isOpen: boolean = false;\r\n\r\n /**\r\n * 聊天消息历史\r\n */\r\n @State() messages: ChatMessage[] = [];\r\n\r\n /**\r\n * 当前输入的消息\r\n */\r\n @State() currentMessage: string = '';\r\n\r\n /**\r\n * 当发送消息时触发\r\n */\r\n @Event() messageSent: EventEmitter<string>;\r\n\r\n /**\r\n * 点击模态框关闭时触发\r\n */\r\n @Event() modalClosed: EventEmitter<void>;\r\n\r\n /**\r\n * 应用图标URL\r\n */\r\n @Prop() icon?: string;\r\n\r\n /**\r\n * 聊天框的页面层级\r\n */\r\n @Prop() zIndex?: number = 1000;\r\n\r\n /**\r\n * 是否展示顶部标题栏\r\n */\r\n @Prop() isShowHeader: boolean = true;\r\n\r\n /**\r\n * 是否展示右上角的关闭按钮\r\n */\r\n @Prop() isNeedClose: boolean = true;\r\n\r\n /**\r\n * 机器人ID\r\n */\r\n @Prop() botId: string;\r\n\r\n /**\r\n * 会话ID\r\n */\r\n @Prop({ mutable: true }) conversationId?: string;\r\n\r\n\r\n /**\r\n * 当前助手回复的消息\r\n */\r\n @State() currentAssistantMessage: string = '';\r\n\r\n /**\r\n * 是否正在加载回复\r\n */\r\n @State() isLoading: boolean = false;\r\n\r\n /**\r\n * 当前正在流式输出的消息\r\n */\r\n @State() currentStreamingMessage: ChatMessage | null = null;\r\n\r\n // 添加新的状态控制\r\n @State() shouldAutoScroll: boolean = true;\r\n private readonly SCROLL_THRESHOLD = 30;\r\n\r\n @State() isLoadingHistory: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n // 添加新的 Event\r\n @Event() streamComplete: EventEmitter<{\r\n conversation_id: string;\r\n event: string;\r\n message_id: string;\r\n id: string;\r\n }>;\r\n\r\n @State() suggestedQuestions: string[] = [];\r\n @State() suggestedQuestionsLoading: boolean = false;\r\n private stopSuggestedQuestionsRef: { current: boolean } = { current: false };\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: { cos_key: string, filename: string, ext: string, presigned_url: string }[] = [];\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '';\r\n\r\n /**\r\n * 是否以全屏模式打开\r\n */\r\n @Prop() fullscreen: boolean = false;\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleInputChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.currentMessage = input.value;\r\n };\r\n\r\n private async getSuggestedQuestions(messageId: string) {\r\n this.stopSuggestedQuestionsRef.current = false;\r\n this.suggestedQuestionsLoading = true;\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `https://pcm_api.ylzhaopin.com/share/messages/${messageId}/suggested`,\r\n params: {\r\n bot_id: this.botId\r\n }\r\n });\r\n\r\n if (this.stopSuggestedQuestionsRef.current) return;\r\n\r\n if (response.isOk && response.data?.result === 'success') {\r\n this.suggestedQuestions = response.data?.data || [];\r\n }\r\n } catch (error) {\r\n console.error('获取问题建议失败:', error);\r\n } finally {\r\n this.suggestedQuestionsLoading = false;\r\n }\r\n }\r\n\r\n private handleStopSuggestedQuestions = () => {\r\n this.suggestedQuestions = [];\r\n this.stopSuggestedQuestionsRef.current = true;\r\n };\r\n\r\n private handleFileChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this.selectedFile = input.files[0];\r\n \r\n // 文件选择后立即上传\r\n await this.uploadFile();\r\n }\r\n };\r\n\r\n private async uploadFile() {\r\n if (!this.selectedFile) return;\r\n \r\n this.isUploading = true;\r\n \r\n try {\r\n const formData = new FormData();\r\n formData.append('file', this.selectedFile);\r\n \r\n const response = await fetch('https://pcm_api.ylzhaopin.com/external/v1/files/upload', {\r\n method: 'POST',\r\n body: formData\r\n });\r\n \r\n \r\n const result = await response.json();\r\n console.log('result', result);\r\n if (result) {\r\n this.uploadedFileInfo.push({\r\n cos_key: result.cos_key,\r\n filename: result.filename,\r\n ext: result.ext,\r\n presigned_url: result.presigned_url\r\n });\r\n } \r\n } catch (error) {\r\n console.error('文件上传错误:', error);\r\n this.clearSelectedFile();\r\n alert('文件上传失败,请重试');\r\n } finally {\r\n this.isUploading = false;\r\n }\r\n }\r\n\r\n private handleUploadClick = () => {\r\n const fileInput = this.hostElement.shadowRoot?.querySelector('.file-input') as HTMLInputElement;\r\n fileInput?.click();\r\n };\r\n\r\n private clearSelectedFile = () => {\r\n this.selectedFile = null;\r\n this.uploadedFileInfo = [];\r\n const fileInput = this.hostElement.shadowRoot?.querySelector('.file-input') as HTMLInputElement;\r\n if (fileInput) {\r\n fileInput.value = '';\r\n }\r\n };\r\n\r\n\r\n private async sendMessageToAPI(message: string) {\r\n this.handleStopSuggestedQuestions();\r\n console.log('开始发送消息:', message);\r\n this.isLoading = true;\r\n let answer = '';\r\n\r\n const now = new Date();\r\n const time = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;\r\n\r\n // 如果消息为空但有文件,使用默认文本\r\n const queryText = message.trim() || (this.uploadedFileInfo.length > 0 ? '请分析这个文件' : '');\r\n\r\n // 创建新的消息对象时确保必填字段都有值\r\n const newMessage: ChatMessage = {\r\n id: `temp-${Date.now()}`, // 消息唯一标识\r\n time: time, // 消息时间\r\n query: queryText, // 用户输入的消息内容\r\n answer: '', // AI助手的回复内容\r\n bot_id: this.botId, // 机器人ID\r\n isStreaming: true, // 是否正在流式输出\r\n conversation_id: this.conversationId, // 会话ID\r\n inputs: {}, // 输入参数\r\n status: \"normal\", // 消息状态\r\n error: null // 错误信息\r\n };\r\n\r\n // 设置当前流式消息\r\n this.currentStreamingMessage = newMessage;\r\n\r\n this.shouldAutoScroll = true;\r\n // 滚动到底部\r\n this.scrollToBottom();\r\n\r\n // 准备请求数据\r\n const requestData: any = {\r\n bot_id: this.botId,\r\n response_mode: 'streaming',\r\n conversation_id: this.conversationId,\r\n query: queryText,\r\n user: '1234567890'\r\n };\r\n // 如果有上传的文件,添加到inputs参数\r\n if (this.uploadedFileInfo.length > 0) {\r\n const fileUrls = this.uploadedFileInfo.map(fileInfo => fileInfo.cos_key).join(',');\r\n\r\n requestData.inputs = {\r\n ...requestData.inputs,\r\n input: fileUrls\r\n };\r\n }\r\n\r\n await sendSSERequest({\r\n url: `https://pcm_api.ylzhaopin.com/share/chat-messages`,\r\n method: 'POST',\r\n data: requestData,\r\n onMessage: (data) => {\r\n console.log('收到Stream数据:', data);\r\n\r\n if (data.conversation_id && !this.conversationId) {\r\n this.conversationId = data.conversation_id;\r\n this.updateUrlWithConversationId(data.conversation_id);\r\n }\r\n\r\n if (data.event === 'message') {\r\n const inputMessage: UserInputMessageType = { message: message };\r\n convertWorkflowStreamNodeToMessageRound('message', inputMessage, data);\r\n\r\n if (data.event === 'agent_message' || data.event === 'message') {\r\n if (data.answer) {\r\n answer += data.answer;\r\n const updatedMessage: ChatMessage = {\r\n ...this.currentStreamingMessage,\r\n answer,\r\n isStreaming: true\r\n };\r\n this.currentStreamingMessage = updatedMessage;\r\n this.scrollToBottom();\r\n }\r\n }\r\n }\r\n if (data.event === \"message_end\") {\r\n this.streamComplete.emit({\r\n conversation_id: data.conversation_id || '',\r\n event: data.event,\r\n message_id: data.message_id,\r\n id: data.id,\r\n });\r\n }\r\n },\r\n onError: (error) => {\r\n console.error('发生错误:', error);\r\n this.messages = [...this.messages, {\r\n ...newMessage,\r\n answer: '抱歉,发生了错误,请稍后再试。',\r\n error: error,\r\n isStreaming: false\r\n }];\r\n this.currentStreamingMessage = null;\r\n this.isLoading = false;\r\n },\r\n onComplete: () => {\r\n console.log('请求完成');\r\n this.isLoading = false;\r\n this.messages = [...this.messages, this.currentStreamingMessage];\r\n\r\n // 在消息完成后获取问题建议\r\n if (this.currentStreamingMessage) {\r\n this.getSuggestedQuestions(this.currentStreamingMessage.conversation_id);\r\n }\r\n\r\n this.currentStreamingMessage = null;\r\n }\r\n });\r\n }\r\n // 监听滚动事件,用于控制聊天历史记录的自动滚动行为。\r\n private handleScroll = () => {\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n if (!chatHistory) return;\r\n\r\n const { scrollTop, scrollHeight, clientHeight } = chatHistory;\r\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\r\n\r\n // 更新是否应该自动滚动的状态\r\n this.shouldAutoScroll = distanceFromBottom <= this.SCROLL_THRESHOLD;\r\n };\r\n\r\n private scrollToBottom() {\r\n if (!this.shouldAutoScroll) return;\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n console.log('chatHistory', chatHistory);\r\n if (chatHistory && this.isOpen) {\r\n // 强制浏览器重新计算布局\r\n chatHistory.scrollTop = chatHistory.scrollHeight;\r\n }\r\n }\r\n\r\n // 添加 componentDidRender 生命周期方法,用于在组件渲染后滚动到底部\r\n componentDidRender() {\r\n if (this.isLoadingHistory || (this.shouldAutoScroll && this.isOpen)) {\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n if (chatHistory) {\r\n chatHistory.scrollTop = chatHistory.scrollHeight;\r\n }\r\n }\r\n }\r\n\r\n private updateUrlWithConversationId(conversationId: string) {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n if (!urlParams.get('conversation_id')) {\r\n const newUrl = new URL(window.location.href);\r\n newUrl.searchParams.set('conversation_id', conversationId);\r\n window.history.replaceState({}, '', newUrl);\r\n }\r\n }\r\n\r\n private handleSendMessage = () => {\r\n if ((!this.currentMessage.trim() && this.uploadedFileInfo.length === 0) || this.isLoading) return;\r\n\r\n // 触发消息发送事件\r\n this.messageSent.emit(this.currentMessage);\r\n\r\n // 发送消息到API\r\n this.sendMessageToAPI(this.currentMessage);\r\n\r\n // 清空输入框\r\n this.currentMessage = '';\r\n \r\n // 清除已选择的文件\r\n this.clearSelectedFile();\r\n\r\n // 保持输入框焦点\r\n const inputElement = this.hostElement.shadowRoot?.querySelector('input');\r\n inputElement?.focus();\r\n };\r\n\r\n private handleKeyDown = (event: KeyboardEvent) => {\r\n if (event.key === 'Enter' && !event.shiftKey) {\r\n event.preventDefault();\r\n this.handleSendMessage();\r\n }\r\n };\r\n\r\n // 修改 loadHistoryMessages 方法\r\n private async loadHistoryMessages() {\r\n if (!this.conversationId) return;\r\n\r\n this.isLoadingHistory = true;\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `https://pcm_api.ylzhaopin.com/share/messages`,\r\n params: {\r\n conversation_id: this.conversationId,\r\n bot_id: this.botId,\r\n user: '1234567890',\r\n limit: 20\r\n }\r\n });\r\n\r\n if (!response.isOk || !response.data) {\r\n throw new Error('加载历史消息失败');\r\n }\r\n\r\n // 适配新的接口返回格式\r\n const historyData = response.data.data || [];\r\n\r\n // 清空现有消息,确保不会重复\r\n this.currentStreamingMessage = null;\r\n this.messages = [];\r\n\r\n const formattedMessages: ChatMessage[] = historyData.map(msg => {\r\n const time = new Date(msg.created_at * 1000);\r\n const timeStr = `${time.getHours()}:${time.getMinutes().toString().padStart(2, '0')}`;\r\n\r\n return {\r\n ...msg,\r\n time: timeStr,\r\n bot_id: this.botId,\r\n isStreaming: false,\r\n status: msg.status === 'error' ? 'error' : 'normal' as const\r\n };\r\n });\r\n\r\n this.messages = formattedMessages;\r\n\r\n // 使用 requestAnimationFrame 确保在下一帧渲染后滚动\r\n requestAnimationFrame(() => {\r\n this.shouldAutoScroll = true;\r\n this.scrollToBottom();\r\n });\r\n\r\n } catch (error) {\r\n console.error('加载历史消息失败:', error);\r\n } finally {\r\n this.isLoadingHistory = false;\r\n }\r\n }\r\n\r\n\r\n // 添加 isOpen 的 watch 方法\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (newValue && this.conversationId) {\r\n await this.loadHistoryMessages();\r\n }\r\n }\r\n\r\n @Watch('defaultQuery')\r\n handleDefaultQueryChange(newValue: string) {\r\n if (newValue && !this.currentMessage) {\r\n this.currentMessage = newValue;\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 组件加载时设置默认查询\r\n if (this.defaultQuery) {\r\n this.currentMessage = this.defaultQuery;\r\n }\r\n }\r\n\r\n render() {\r\n if (!this.isOpen) return null;\r\n\r\n const modalStyle = {\r\n zIndex: String(this.zIndex)\r\n };\r\n\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen\r\n };\r\n\r\n const overlayClass = {\r\n 'modal-overlay': true,\r\n 'fullscreen-overlay': this.fullscreen\r\n };\r\n\r\n return (\r\n <div class={overlayClass} style={modalStyle}>\r\n <div class={containerClass}>\r\n {this.isShowHeader && (\r\n <div class=\"modal-header\">\r\n <div class=\"header-left\">\r\n {this.icon && <img src={this.icon} class=\"header-icon\" alt=\"应用图标\" />}\r\n <h3>{this.modalTitle}</h3>\r\n </div>\r\n {this.isNeedClose && (\r\n <button class=\"close-button\" onClick={this.handleClose}>\r\n <span>×</span>\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n <div class=\"chat-history\" onScroll={this.handleScroll}>\r\n {this.isLoadingHistory ? (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p>加载历史消息中...</p>\r\n </div>\r\n ) : (\r\n <>\r\n {this.messages.map((message) => (\r\n <div id={`message_${message.id}`} key={message.id}>\r\n <pcm-chat-message\r\n message={message}\r\n onMessageChange={(event) => {\r\n const updatedMessages = this.messages.map(msg =>\r\n msg.id === message.id ? { ...msg, ...event.detail } : msg\r\n );\r\n this.messages = updatedMessages;\r\n }}\r\n ></pcm-chat-message>\r\n </div>\r\n ))}\r\n {this.currentStreamingMessage && (\r\n <div id={`message_${this.currentStreamingMessage.id}`}>\r\n <pcm-chat-message\r\n message={this.currentStreamingMessage}\r\n ></pcm-chat-message>\r\n </div>\r\n )}\r\n {this.messages.length === 0 && !this.currentStreamingMessage && (\r\n <div class=\"empty-state\">\r\n <p>请输入消息</p>\r\n </div>\r\n )}\r\n </>\r\n )}\r\n\r\n {this.suggestedQuestionsLoading ? (\r\n <div class=\"loading-suggestions\">\r\n <div class=\"loading-spinner-small\"></div>\r\n </div>\r\n ) : (\r\n this.suggestedQuestions.length > 0 && (\r\n <div class=\"suggested-questions\">\r\n {this.suggestedQuestions.map((question, index) => (\r\n <div\r\n key={index}\r\n class=\"suggested-question\"\r\n onClick={() => {\r\n this.currentMessage = question;\r\n this.handleSendMessage();\r\n }}\r\n >\r\n {question}\r\n <span class=\"arrow-right\">→</span>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n )}\r\n </div>\r\n\r\n {/* 添加文件预览区域 */}\r\n {this.selectedFile && (\r\n <div class=\"file-preview\">\r\n <div class=\"file-info\">\r\n <span class=\"file-name\" title={this.selectedFile.name}>\r\n {this.selectedFile.name}\r\n {this.isUploading && <span class=\"uploading-indicator\"> (上传中...)</span>}\r\n {this.uploadedFileInfo.length > 0 && <span class=\"upload-success\"> (已上传)</span>}\r\n </span>\r\n <button class=\"remove-file\" onClick={this.clearSelectedFile}>\r\n ×\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div class=\"message-input\">\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n onChange={this.handleFileChange}\r\n accept=\"image/*,.pdf,.doc,.docx,.txt\"\r\n />\r\n <button\r\n class=\"upload-button\"\r\n onClick={this.handleUploadClick}\r\n title=\"上传文件\"\r\n disabled={this.isUploading}\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\">\r\n <path\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n stroke-width=\"2\"\r\n d=\"M12 4v16m0-16l-4 4m4-4l4 4\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <div class=\"input-wrapper\">\r\n <input\r\n type=\"text\"\r\n placeholder=\"请输入消息...\"\r\n value={this.currentMessage}\r\n onInput={this.handleInputChange}\r\n onKeyDown={this.handleKeyDown}\r\n disabled={this.isLoading}\r\n />\r\n </div>\r\n\r\n <button\r\n class=\"send-button\"\r\n onClick={() => this.handleSendMessage()}\r\n disabled={(!this.currentMessage.trim() && this.uploadedFileInfo.length === 0) || this.isLoading || this.isUploading}\r\n >\r\n {this.isLoading ? '发送中...' : '发送'}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n} "]}
1
+ {"version":3,"file":"pcm-chat-modal.js","sourceRoot":"","sources":["../../../src/components/pcm-chat-modal/pcm-chat-modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAgB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EAAE,uCAAuC,EAAwB,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAsB,MAAM,mBAAmB,CAAC;AAQ5K,MAAM,OAAO,SAAS;IACpB;;OAEG;IACK,UAAU,GAAW,MAAM,CAAC;IAEpC;;OAEG;IAC6B,MAAM,GAAW,EAAE,CAAC;IAEpD;;OAEG;IACsB,MAAM,GAAY,KAAK,CAAC;IAEjD;;OAEG;IACM,QAAQ,GAAkB,EAAE,CAAC;IAEtC;;OAEG;IACM,cAAc,GAAW,EAAE,CAAC;IAErC;;OAEG;IACM,WAAW,CAAuB;IAE3C;;OAEG;IACM,WAAW,CAAqB;IAEzC;;OAEG;IACK,IAAI,CAAU;IAEtB;;OAEG;IACK,MAAM,GAAY,IAAI,CAAC;IAE/B;;OAEG;IACK,YAAY,GAAY,IAAI,CAAC;IAErC;;OAEG;IACK,WAAW,GAAY,IAAI,CAAC;IAEpC;;OAEG;IACK,KAAK,CAAS;IAEtB;;OAEG;IACsB,cAAc,CAAU;IAGjD;;OAEG;IACM,uBAAuB,GAAW,EAAE,CAAC;IAE9C;;OAEG;IACM,SAAS,GAAY,KAAK,CAAC;IAEpC;;OAEG;IACM,uBAAuB,GAAuB,IAAI,CAAC;IAE5D,WAAW;IACF,gBAAgB,GAAY,IAAI,CAAC;IACzB,gBAAgB,GAAG,EAAE,CAAC;IAE9B,gBAAgB,GAAY,KAAK,CAAC;IAE3C,+BAA+B;IACpB,WAAW,CAAc;IAEpC,aAAa;IACJ,cAAc,CAKpB;IAEM,kBAAkB,GAAa,EAAE,CAAC;IAClC,yBAAyB,GAAY,KAAK,CAAC;IAC5C,yBAAyB,GAAyB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAEpE,YAAY,GAAgB,IAAI,CAAC;IACjC,WAAW,GAAY,KAAK,CAAC;IAC7B,gBAAgB,GAAyB,EAAE,CAAC;IAErD;;OAEG;IACK,YAAY,GAAW,EAAE,CAAC;IAElC;;OAEG;IACK,UAAU,GAAY,KAAK,CAAC;IAE5B,WAAW,GAAG,GAAG,EAAE;QACzB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC,CAAC;IAEM,iBAAiB,GAAG,CAAC,KAAY,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;QAC/C,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC;IACpC,CAAC,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QACnD,IAAI,CAAC,yBAAyB,CAAC,OAAO,GAAG,KAAK,CAAC;QAC/C,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;gBACrC,GAAG,EAAE,mBAAmB,SAAS,YAAY;aAC9C,CAAC,CAAC;YAEH,IAAI,IAAI,CAAC,yBAAyB,CAAC,OAAO;gBAAE,OAAO;YAEnD,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACtC,IAAI,CAAC,kBAAkB,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;YAChD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,yBAAyB,GAAG,KAAK,CAAC;QACzC,CAAC;IACH,CAAC;IAEO,4BAA4B,GAAG,GAAG,EAAE;QAC1C,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,yBAAyB,CAAC,OAAO,GAAG,IAAI,CAAC;IAChD,CAAC,CAAC;IAEM,gBAAgB,GAAG,KAAK,EAAE,KAAY,EAAE,EAAE;QAChD,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;QAC/C,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAEnC,YAAY;YACZ,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IAEM,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAE/B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,YAAY,EAAE;gBAC1D,eAAe,EAAE,SAAS,GAAG,IAAI,CAAC,MAAM;aACzC,CAAC,CAAC;YAEH,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAChC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,KAAK,CAAC,YAAY,CAAC,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,iBAAiB,GAAG,GAAG,EAAE;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAqB,CAAC;QAChG,SAAS,EAAE,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC;IAEM,iBAAiB,GAAG,GAAG,EAAE;QAC/B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAqB,CAAC;QAChG,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAGM,KAAK,CAAC,gBAAgB,CAAC,OAAe;QAC5C,IAAI,CAAC,4BAA4B,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QAEjF,oBAAoB;QACpB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAExF,qBAAqB;QACrB,MAAM,UAAU,GAAgB;YAC9B,EAAE,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,EAAE,EAAG,SAAS;YACpC,IAAI,EAAE,IAAI,EAAiB,OAAO;YAClC,KAAK,EAAE,SAAS,EAAW,YAAY;YACvC,MAAM,EAAE,EAAE,EAAiB,YAAY;YACvC,WAAW,EAAE,IAAI,EAAS,WAAW;YACrC,eAAe,EAAE,IAAI,CAAC,cAAc,EAAG,OAAO;YAC9C,MAAM,EAAE,EAAE,EAAgB,OAAO;YACjC,MAAM,EAAE,QAAQ,EAAU,OAAO;YACjC,KAAK,EAAE,IAAI,CAAc,OAAO;SACjC,CAAC;QAEF,WAAW;QACX,IAAI,CAAC,uBAAuB,GAAG,UAAU,CAAC;QAE1C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,QAAQ;QACR,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,SAAS;QACT,MAAM,WAAW,GAAQ;YACvB,aAAa,EAAE,WAAW;YAC1B,eAAe,EAAE,IAAI,CAAC,cAAc;YACpC,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,YAAY;SACnB,CAAC;QACF,uBAAuB;QACvB,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEnF,WAAW,CAAC,MAAM,GAAG;gBACnB,GAAG,WAAW,CAAC,MAAM;gBACrB,KAAK,EAAE,QAAQ;aAChB,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,CAAC;YACnB,GAAG,EAAE,4BAA4B;YACjC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;gBAEjC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBACjD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC;oBAC3C,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBACzD,CAAC;gBAED,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,MAAM,YAAY,GAAyB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;oBAChE,uCAAuC,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;oBAEvE,IAAI,IAAI,CAAC,KAAK,KAAK,eAAe,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;wBAC/D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;4BAChB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;4BACtB,MAAM,cAAc,GAAgB;gCAClC,GAAG,IAAI,CAAC,uBAAuB;gCAC/B,MAAM;gCACN,WAAW,EAAE,IAAI;6BAClB,CAAC;4BACF,IAAI,CAAC,uBAAuB,GAAG,cAAc,CAAC;4BAC9C,IAAI,CAAC,cAAc,EAAE,CAAC;wBACxB,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,IAAI,IAAI,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;oBACjC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;wBACvB,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,EAAE;wBAC3C,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,EAAE,EAAE,IAAI,CAAC,EAAE;qBACZ,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC9B,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE;wBACjC,GAAG,UAAU;wBACb,MAAM,EAAE,iBAAiB;wBACzB,KAAK,EAAE,KAAK;wBACZ,WAAW,EAAE,KAAK;qBACnB,CAAC,CAAC;gBACH,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;gBACpC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACzB,CAAC;YACD,UAAU,EAAE,GAAG,EAAE;gBACf,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;gBAEjE,eAAe;gBACf,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;oBACjC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC;gBAC3E,CAAC;gBAED,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACtC,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IACD,4BAA4B;IACpB,YAAY,GAAG,GAAG,EAAE;QAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QAChF,IAAI,CAAC,WAAW;YAAE,OAAO;QAEzB,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC;QAC9D,MAAM,kBAAkB,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,CAAC;QAEnE,gBAAgB;QAChB,IAAI,CAAC,gBAAgB,GAAG,kBAAkB,IAAI,IAAI,CAAC,gBAAgB,CAAC;IACtE,CAAC,CAAC;IAEM,cAAc;QACpB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACxC,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/B,cAAc;YACd,WAAW,CAAC,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC;QACnD,CAAC;IACH,CAAC;IAED,6CAA6C;IAC7C,kBAAkB;QAChB,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;YAChF,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;IAEO,2BAA2B,CAAC,cAAsB;QACxD,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEO,iBAAiB,GAAG,GAAG,EAAE;QAC/B,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAElG,WAAW;QACX,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAE3C,WAAW;QACX,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAE3C,QAAQ;QACR,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QAEzB,WAAW;QACX,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,UAAU;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QACzE,YAAY,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC;IAEM,aAAa,GAAG,CAAC,KAAoB,EAAE,EAAE;QAC/C,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC7C,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,4BAA4B;IACpB,KAAK,CAAC,mBAAmB;QAC/B,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO;QAEjC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;gBACrC,GAAG,EAAE,iBAAiB;gBACtB,MAAM,EAAE;oBACN,eAAe,EAAE,IAAI,CAAC,cAAc;oBACpC,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,EAAE;iBACV;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;YAED,aAAa;YACb,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;YAExC,gBAAgB;YAChB,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACpC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YAEnB,MAAM,iBAAiB,GAAkB,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBAC7D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;gBAC7C,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBAEtF,OAAO;oBACL,GAAG,GAAG;oBACN,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,KAAK;oBAClB,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAiB;iBAC7D,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,GAAG,iBAAiB,CAAC;YAElC,uCAAuC;YACvC,qBAAqB,CAAC,GAAG,EAAE;gBACzB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC7B,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,CAAC,CAAC,CAAC;QAEL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAChC,CAAC;IACH,CAAC;IAGD,uBAAuB;IAEvB,KAAK,CAAC,kBAAkB,CAAC,QAAiB;QACxC,IAAI,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACpC,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAGD,wBAAwB,CAAC,QAAgB;QACvC,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACrC,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC;QACjC,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,cAAc;QACd,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAE9B,MAAM,UAAU,GAAG;YACjB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;SAC5B,CAAC;QAEF,MAAM,cAAc,GAAG;YACrB,iBAAiB,EAAE,IAAI;YACvB,YAAY,EAAE,IAAI,CAAC,UAAU;SAC9B,CAAC;QAEF,MAAM,YAAY,GAAG;YACnB,eAAe,EAAE,IAAI;YACrB,oBAAoB,EAAE,IAAI,CAAC,UAAU;SACtC,CAAC;QAEF,OAAO,CACL,WAAK,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU;YACzC,WAAK,KAAK,EAAE,cAAc;gBACvB,IAAI,CAAC,YAAY,IAAI,CACpB,WAAK,KAAK,EAAC,cAAc;oBACvB,WAAK,KAAK,EAAC,aAAa;wBACrB,IAAI,CAAC,IAAI,IAAI,WAAK,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAC,aAAa,EAAC,GAAG,EAAC,0BAAM,GAAG;wBACpE,cAAK,IAAI,CAAC,UAAU,CAAM,CACtB;oBACL,IAAI,CAAC,WAAW,IAAI,CACnB,cAAQ,KAAK,EAAC,cAAc,EAAC,OAAO,EAAE,IAAI,CAAC,WAAW;wBACpD,yBAAc,CACP,CACV,CACG,CACP;gBAED,WAAK,KAAK,EAAC,cAAc,EAAC,QAAQ,EAAE,IAAI,CAAC,YAAY;oBAClD,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CACvB,WAAK,KAAK,EAAC,mBAAmB;wBAC5B,WAAK,KAAK,EAAC,iBAAiB,GAAO;wBACnC,6DAAiB,CACb,CACP,CAAC,CAAC,CAAC,CACF;wBACG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC9B,WAAK,EAAE,EAAE,WAAW,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;4BAC/C,wBACE,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE;oCACzB,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAC9C,GAAG,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAC1D,CAAC;oCACF,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC;gCAClC,CAAC,GACiB,CAChB,CACP,CAAC;wBACD,IAAI,CAAC,uBAAuB,IAAI,CAC/B,WAAK,EAAE,EAAE,WAAW,IAAI,CAAC,uBAAuB,CAAC,EAAE,EAAE;4BACnD,wBACE,OAAO,EAAE,IAAI,CAAC,uBAAuB,GACnB,CAChB,CACP;wBACA,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAC9D,WAAK,KAAK,EAAC,aAAa;4BACtB,8CAAY,CACR,CACP,CACA,CACJ;oBAEA,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAChC,WAAK,KAAK,EAAC,qBAAqB;wBAC9B,WAAK,KAAK,EAAC,uBAAuB,GAAO,CACrC,CACP,CAAC,CAAC,CAAC,CACF,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,CACpC,WAAK,KAAK,EAAC,qBAAqB,IAC7B,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAChD,WACE,GAAG,EAAE,KAAK,EACV,KAAK,EAAC,oBAAoB,EAC1B,OAAO,EAAE,GAAG,EAAE;4BACZ,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC;4BAC/B,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBAC3B,CAAC;wBAEA,QAAQ;wBACT,YAAM,KAAK,EAAC,aAAa,aAAS,CAC9B,CACP,CAAC,CACE,CACP,CACF,CACG;gBAGL,IAAI,CAAC,YAAY,IAAI,CACpB,WAAK,KAAK,EAAC,cAAc;oBACvB,WAAK,KAAK,EAAC,WAAW;wBACpB,YAAM,KAAK,EAAC,WAAW,EAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;4BAClD,IAAI,CAAC,YAAY,CAAC,IAAI;4BACtB,IAAI,CAAC,WAAW,IAAI,YAAM,KAAK,EAAC,qBAAqB,+BAAiB;4BACtE,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,YAAM,KAAK,EAAC,gBAAgB,4BAAc,CAC1E;wBACP,cAAQ,KAAK,EAAC,aAAa,EAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,aAElD,CACL,CACF,CACP;gBAED,WAAK,KAAK,EAAC,eAAe;oBACxB,aACE,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,YAAY,EAClB,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAC/B,MAAM,EAAC,8BAA8B,GACrC;oBACF,cACE,KAAK,EAAC,eAAe,EACrB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAC/B,KAAK,EAAC,0BAAM,EACZ,QAAQ,EAAE,IAAI,CAAC,WAAW;wBAE1B,WAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc;4BACxD,8BACiB,OAAO,qBACN,OAAO,kBACV,GAAG,EAChB,CAAC,EAAC,4BAA4B,GAC9B,CACE,CACC;oBAET,WAAK,KAAK,EAAC,eAAe;wBACxB,aACE,IAAI,EAAC,MAAM,EACX,WAAW,EAAC,mCAAU,EACtB,KAAK,EAAE,IAAI,CAAC,cAAc,EAC1B,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAC/B,SAAS,EAAE,IAAI,CAAC,aAAa,EAC7B,QAAQ,EAAE,IAAI,CAAC,SAAS,GACxB,CACE;oBAEN,cACE,KAAK,EAAC,aAAa,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,EACvC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,IAElH,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAC1B,CACL,CACF,CACF,CACP,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, Prop, h, State, Event, EventEmitter, Element, Watch } from '@stencil/core';\r\nimport { convertWorkflowStreamNodeToMessageRound, UserInputMessageType, sendSSERequest, sendHttpRequest, uploadFileToBackend, FileUploadResponse } from '../../utils/utils';\r\nimport { ChatMessage } from '../../interfaces/chat';\r\n\r\n@Component({\r\n tag: 'pcm-chat-modal',\r\n styleUrl: 'pcm-chat-modal.css',\r\n shadow: true,\r\n})\r\nexport class ChatModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '在线客服';\r\n\r\n /**\r\n * API鉴权密钥\r\n */\r\n @Prop({ attribute: 'api-key' }) apiKey: string = '';\r\n\r\n /**\r\n * 是否显示聊天模态框\r\n */\r\n @Prop({ mutable: true }) isOpen: boolean = false;\r\n\r\n /**\r\n * 聊天消息历史\r\n */\r\n @State() messages: ChatMessage[] = [];\r\n\r\n /**\r\n * 当前输入的消息\r\n */\r\n @State() currentMessage: string = '';\r\n\r\n /**\r\n * 当发送消息时触发\r\n */\r\n @Event() messageSent: EventEmitter<string>;\r\n\r\n /**\r\n * 点击模态框关闭时触发\r\n */\r\n @Event() modalClosed: EventEmitter<void>;\r\n\r\n /**\r\n * 应用图标URL\r\n */\r\n @Prop() icon?: string;\r\n\r\n /**\r\n * 聊天框的页面层级\r\n */\r\n @Prop() zIndex?: number = 1000;\r\n\r\n /**\r\n * 是否展示顶部标题栏\r\n */\r\n @Prop() isShowHeader: boolean = true;\r\n\r\n /**\r\n * 是否展示右上角的关闭按钮\r\n */\r\n @Prop() isNeedClose: boolean = true;\r\n\r\n /**\r\n * 机器人ID\r\n */\r\n @Prop() botId: string;\r\n\r\n /**\r\n * 会话ID,传入继续对话,否则创建新会话\r\n */\r\n @Prop({ mutable: true }) conversationId?: string;\r\n\r\n\r\n /**\r\n * 当前助手回复的消息\r\n */\r\n @State() currentAssistantMessage: string = '';\r\n\r\n /**\r\n * 是否正在加载回复\r\n */\r\n @State() isLoading: boolean = false;\r\n\r\n /**\r\n * 当前正在流式输出的消息\r\n */\r\n @State() currentStreamingMessage: ChatMessage | null = null;\r\n\r\n // 添加新的状态控制\r\n @State() shouldAutoScroll: boolean = true;\r\n private readonly SCROLL_THRESHOLD = 30;\r\n\r\n @State() isLoadingHistory: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n // 添加新的 Event\r\n @Event() streamComplete: EventEmitter<{\r\n conversation_id: string;\r\n event: string;\r\n message_id: string;\r\n id: string;\r\n }>;\r\n\r\n @State() suggestedQuestions: string[] = [];\r\n @State() suggestedQuestionsLoading: boolean = false;\r\n private stopSuggestedQuestionsRef: { current: boolean } = { current: false };\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse[] = [];\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '';\r\n\r\n /**\r\n * 是否以全屏模式打开,移动端建议设置为true\r\n */\r\n @Prop() fullscreen: boolean = false;\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleInputChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.currentMessage = input.value;\r\n };\r\n\r\n private async getSuggestedQuestions(messageId: string) {\r\n this.stopSuggestedQuestionsRef.current = false;\r\n this.suggestedQuestionsLoading = true;\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `/share/messages/${messageId}/suggested`,\r\n });\r\n\r\n if (this.stopSuggestedQuestionsRef.current) return;\r\n\r\n if (response.success && response.data) {\r\n this.suggestedQuestions = response.data || [];\r\n }\r\n } catch (error) {\r\n console.error('获取问题建议失败:', error);\r\n } finally {\r\n this.suggestedQuestionsLoading = false;\r\n }\r\n }\r\n\r\n private handleStopSuggestedQuestions = () => {\r\n this.suggestedQuestions = [];\r\n this.stopSuggestedQuestionsRef.current = true;\r\n };\r\n\r\n private handleFileChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this.selectedFile = input.files[0];\r\n \r\n // 文件选择后立即上传\r\n await this.uploadFile();\r\n }\r\n };\r\n\r\n private async uploadFile() {\r\n if (!this.selectedFile) return;\r\n \r\n this.isUploading = true;\r\n \r\n try {\r\n const result = await uploadFileToBackend(this.selectedFile, {\r\n 'authorization': 'Bearer ' + this.apiKey\r\n });\r\n \r\n this.uploadedFileInfo.push(result);\r\n } catch (error) {\r\n console.error('文件上传错误:', error);\r\n this.clearSelectedFile();\r\n alert('文件上传失败,请重试');\r\n } finally {\r\n this.isUploading = false;\r\n }\r\n }\r\n\r\n private handleUploadClick = () => {\r\n const fileInput = this.hostElement.shadowRoot?.querySelector('.file-input') as HTMLInputElement;\r\n fileInput?.click();\r\n };\r\n\r\n private clearSelectedFile = () => {\r\n this.selectedFile = null;\r\n this.uploadedFileInfo = [];\r\n const fileInput = this.hostElement.shadowRoot?.querySelector('.file-input') as HTMLInputElement;\r\n if (fileInput) {\r\n fileInput.value = '';\r\n }\r\n };\r\n\r\n\r\n private async sendMessageToAPI(message: string) {\r\n this.handleStopSuggestedQuestions();\r\n console.log('开始发送消息:', message);\r\n this.isLoading = true;\r\n let answer = '';\r\n\r\n const now = new Date();\r\n const time = `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`;\r\n\r\n // 如果消息为空但有文件,使用默认文本\r\n const queryText = message.trim() || (this.uploadedFileInfo.length > 0 ? '请分析这个文件' : '');\r\n\r\n // 创建新的消息对象时确保必填字段都有值\r\n const newMessage: ChatMessage = {\r\n id: `temp-${Date.now()}`, // 消息唯一标识\r\n time: time, // 消息时间\r\n query: queryText, // 用户输入的消息内容\r\n answer: '', // AI助手的回复内容\r\n isStreaming: true, // 是否正在流式输出\r\n conversation_id: this.conversationId, // 会话ID\r\n inputs: {}, // 输入参数\r\n status: \"normal\", // 消息状态\r\n error: null // 错误信息\r\n };\r\n\r\n // 设置当前流式消息\r\n this.currentStreamingMessage = newMessage;\r\n\r\n this.shouldAutoScroll = true;\r\n // 滚动到底部\r\n this.scrollToBottom();\r\n\r\n // 准备请求数据\r\n const requestData: any = {\r\n response_mode: 'streaming',\r\n conversation_id: this.conversationId,\r\n query: queryText,\r\n user: '1234567890'\r\n };\r\n // 如果有上传的文件,添加到inputs参数\r\n if (this.uploadedFileInfo.length > 0) {\r\n const fileUrls = this.uploadedFileInfo.map(fileInfo => fileInfo.cos_key).join(',');\r\n\r\n requestData.inputs = {\r\n ...requestData.inputs,\r\n input: fileUrls\r\n };\r\n }\r\n\r\n await sendSSERequest({\r\n url: `/sdk/v1/chat/chat-messages`,\r\n method: 'POST',\r\n data: requestData,\r\n onMessage: (data) => {\r\n console.log('收到Stream数据:', data);\r\n\r\n if (data.conversation_id && !this.conversationId) {\r\n this.conversationId = data.conversation_id;\r\n this.updateUrlWithConversationId(data.conversation_id);\r\n }\r\n\r\n if (data.event === 'message') {\r\n const inputMessage: UserInputMessageType = { message: message };\r\n convertWorkflowStreamNodeToMessageRound('message', inputMessage, data);\r\n\r\n if (data.event === 'agent_message' || data.event === 'message') {\r\n if (data.answer) {\r\n answer += data.answer;\r\n const updatedMessage: ChatMessage = {\r\n ...this.currentStreamingMessage,\r\n answer,\r\n isStreaming: true\r\n };\r\n this.currentStreamingMessage = updatedMessage;\r\n this.scrollToBottom();\r\n }\r\n }\r\n }\r\n if (data.event === \"message_end\") {\r\n this.streamComplete.emit({\r\n conversation_id: data.conversation_id || '',\r\n event: data.event,\r\n message_id: data.message_id,\r\n id: data.id,\r\n });\r\n }\r\n },\r\n onError: (error) => {\r\n console.error('发生错误:', error);\r\n this.messages = [...this.messages, {\r\n ...newMessage,\r\n answer: '抱歉,发生了错误,请稍后再试。',\r\n error: error,\r\n isStreaming: false\r\n }];\r\n this.currentStreamingMessage = null;\r\n this.isLoading = false;\r\n },\r\n onComplete: () => {\r\n console.log('请求完成');\r\n this.isLoading = false;\r\n this.messages = [...this.messages, this.currentStreamingMessage];\r\n\r\n // 在消息完成后获取问题建议\r\n if (this.currentStreamingMessage) {\r\n this.getSuggestedQuestions(this.currentStreamingMessage.conversation_id);\r\n }\r\n\r\n this.currentStreamingMessage = null;\r\n }\r\n });\r\n }\r\n // 监听滚动事件,用于控制聊天历史记录的自动滚动行为。\r\n private handleScroll = () => {\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n if (!chatHistory) return;\r\n\r\n const { scrollTop, scrollHeight, clientHeight } = chatHistory;\r\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\r\n\r\n // 更新是否应该自动滚动的状态\r\n this.shouldAutoScroll = distanceFromBottom <= this.SCROLL_THRESHOLD;\r\n };\r\n\r\n private scrollToBottom() {\r\n if (!this.shouldAutoScroll) return;\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n console.log('chatHistory', chatHistory);\r\n if (chatHistory && this.isOpen) {\r\n // 强制浏览器重新计算布局\r\n chatHistory.scrollTop = chatHistory.scrollHeight;\r\n }\r\n }\r\n\r\n // 添加 componentDidRender 生命周期方法,用于在组件渲染后滚动到底部\r\n componentDidRender() {\r\n if (this.isLoadingHistory || (this.shouldAutoScroll && this.isOpen)) {\r\n const chatHistory = this.hostElement.shadowRoot?.querySelector('.chat-history');\r\n if (chatHistory) {\r\n chatHistory.scrollTop = chatHistory.scrollHeight;\r\n }\r\n }\r\n }\r\n\r\n private updateUrlWithConversationId(conversationId: string) {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n if (!urlParams.get('conversation_id')) {\r\n const newUrl = new URL(window.location.href);\r\n newUrl.searchParams.set('conversation_id', conversationId);\r\n window.history.replaceState({}, '', newUrl);\r\n }\r\n }\r\n\r\n private handleSendMessage = () => {\r\n if ((!this.currentMessage.trim() && this.uploadedFileInfo.length === 0) || this.isLoading) return;\r\n\r\n // 触发消息发送事件\r\n this.messageSent.emit(this.currentMessage);\r\n\r\n // 发送消息到API\r\n this.sendMessageToAPI(this.currentMessage);\r\n\r\n // 清空输入框\r\n this.currentMessage = '';\r\n \r\n // 清除已选择的文件\r\n this.clearSelectedFile();\r\n\r\n // 保持输入框焦点\r\n const inputElement = this.hostElement.shadowRoot?.querySelector('input');\r\n inputElement?.focus();\r\n };\r\n\r\n private handleKeyDown = (event: KeyboardEvent) => {\r\n if (event.key === 'Enter' && !event.shiftKey) {\r\n event.preventDefault();\r\n this.handleSendMessage();\r\n }\r\n };\r\n\r\n // 修改 loadHistoryMessages 方法\r\n private async loadHistoryMessages() {\r\n if (!this.conversationId) return;\r\n\r\n this.isLoadingHistory = true;\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `/share/messages`,\r\n params: {\r\n conversation_id: this.conversationId,\r\n user: '1234567890',\r\n limit: 20\r\n }\r\n });\r\n\r\n if (!response.success || !response.data) {\r\n throw new Error('加载历史消息失败');\r\n }\r\n\r\n // 适配新的接口返回格式\r\n const historyData = response.data || [];\r\n\r\n // 清空现有消息,确保不会重复\r\n this.currentStreamingMessage = null;\r\n this.messages = [];\r\n\r\n const formattedMessages: ChatMessage[] = historyData.map(msg => {\r\n const time = new Date(msg.created_at * 1000);\r\n const timeStr = `${time.getHours()}:${time.getMinutes().toString().padStart(2, '0')}`;\r\n\r\n return {\r\n ...msg,\r\n time: timeStr,\r\n isStreaming: false,\r\n status: msg.status === 'error' ? 'error' : 'normal' as const\r\n };\r\n });\r\n\r\n this.messages = formattedMessages;\r\n\r\n // 使用 requestAnimationFrame 确保在下一帧渲染后滚动\r\n requestAnimationFrame(() => {\r\n this.shouldAutoScroll = true;\r\n this.scrollToBottom();\r\n });\r\n\r\n } catch (error) {\r\n console.error('加载历史消息失败:', error);\r\n } finally {\r\n this.isLoadingHistory = false;\r\n }\r\n }\r\n\r\n\r\n // 添加 isOpen 的 watch 方法\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (newValue && this.conversationId) {\r\n await this.loadHistoryMessages();\r\n }\r\n }\r\n\r\n @Watch('defaultQuery')\r\n handleDefaultQueryChange(newValue: string) {\r\n if (newValue && !this.currentMessage) {\r\n this.currentMessage = newValue;\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 组件加载时设置默认查询\r\n if (this.defaultQuery) {\r\n this.currentMessage = this.defaultQuery;\r\n }\r\n }\r\n\r\n render() {\r\n if (!this.isOpen) return null;\r\n\r\n const modalStyle = {\r\n zIndex: String(this.zIndex)\r\n };\r\n\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen\r\n };\r\n\r\n const overlayClass = {\r\n 'modal-overlay': true,\r\n 'fullscreen-overlay': this.fullscreen\r\n };\r\n\r\n return (\r\n <div class={overlayClass} style={modalStyle}>\r\n <div class={containerClass}>\r\n {this.isShowHeader && (\r\n <div class=\"modal-header\">\r\n <div class=\"header-left\">\r\n {this.icon && <img src={this.icon} class=\"header-icon\" alt=\"应用图标\" />}\r\n <h3>{this.modalTitle}</h3>\r\n </div>\r\n {this.isNeedClose && (\r\n <button class=\"close-button\" onClick={this.handleClose}>\r\n <span>×</span>\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n <div class=\"chat-history\" onScroll={this.handleScroll}>\r\n {this.isLoadingHistory ? (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p>加载历史消息中...</p>\r\n </div>\r\n ) : (\r\n <>\r\n {this.messages.map((message) => (\r\n <div id={`message_${message.id}`} key={message.id}>\r\n <pcm-chat-message\r\n message={message}\r\n onMessageChange={(event) => {\r\n const updatedMessages = this.messages.map(msg =>\r\n msg.id === message.id ? { ...msg, ...event.detail } : msg\r\n );\r\n this.messages = updatedMessages;\r\n }}\r\n ></pcm-chat-message>\r\n </div>\r\n ))}\r\n {this.currentStreamingMessage && (\r\n <div id={`message_${this.currentStreamingMessage.id}`}>\r\n <pcm-chat-message\r\n message={this.currentStreamingMessage}\r\n ></pcm-chat-message>\r\n </div>\r\n )}\r\n {this.messages.length === 0 && !this.currentStreamingMessage && (\r\n <div class=\"empty-state\">\r\n <p>请输入消息</p>\r\n </div>\r\n )}\r\n </>\r\n )}\r\n\r\n {this.suggestedQuestionsLoading ? (\r\n <div class=\"loading-suggestions\">\r\n <div class=\"loading-spinner-small\"></div>\r\n </div>\r\n ) : (\r\n this.suggestedQuestions.length > 0 && (\r\n <div class=\"suggested-questions\">\r\n {this.suggestedQuestions.map((question, index) => (\r\n <div\r\n key={index}\r\n class=\"suggested-question\"\r\n onClick={() => {\r\n this.currentMessage = question;\r\n this.handleSendMessage();\r\n }}\r\n >\r\n {question}\r\n <span class=\"arrow-right\">→</span>\r\n </div>\r\n ))}\r\n </div>\r\n )\r\n )}\r\n </div>\r\n\r\n {/* 添加文件预览区域 */}\r\n {this.selectedFile && (\r\n <div class=\"file-preview\">\r\n <div class=\"file-info\">\r\n <span class=\"file-name\" title={this.selectedFile.name}>\r\n {this.selectedFile.name}\r\n {this.isUploading && <span class=\"uploading-indicator\"> (上传中...)</span>}\r\n {this.uploadedFileInfo.length > 0 && <span class=\"upload-success\"> (已上传)</span>}\r\n </span>\r\n <button class=\"remove-file\" onClick={this.clearSelectedFile}>\r\n ×\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div class=\"message-input\">\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n onChange={this.handleFileChange}\r\n accept=\"image/*,.pdf,.doc,.docx,.txt\"\r\n />\r\n <button\r\n class=\"upload-button\"\r\n onClick={this.handleUploadClick}\r\n title=\"上传文件\"\r\n disabled={this.isUploading}\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\">\r\n <path\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n stroke-width=\"2\"\r\n d=\"M12 4v16m0-16l-4 4m4-4l4 4\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <div class=\"input-wrapper\">\r\n <input\r\n type=\"text\"\r\n placeholder=\"请输入消息...\"\r\n value={this.currentMessage}\r\n onInput={this.handleInputChange}\r\n onKeyDown={this.handleKeyDown}\r\n disabled={this.isLoading}\r\n />\r\n </div>\r\n\r\n <button\r\n class=\"send-button\"\r\n onClick={() => this.handleSendMessage()}\r\n disabled={(!this.currentMessage.trim() && this.uploadedFileInfo.length === 0) || this.isLoading || this.isUploading}\r\n >\r\n {this.isLoading ? '发送中...' : '发送'}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n} "]}