pcm-agents 0.6.61 → 0.6.63

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 (162) hide show
  1. package/dist/cjs/components-position-selector_28.cjs.entry.js +3671 -3515
  2. package/dist/cjs/components-position-selector_28.cjs.entry.js.map +1 -1
  3. package/dist/cjs/index-C_qhED9Z.js +4 -4
  4. package/dist/cjs/{index-C939KGz6.js → index-NR0bG-Uv.js} +3 -3
  5. package/dist/cjs/{index-C939KGz6.js.map → index-NR0bG-Uv.js.map} +1 -1
  6. package/dist/cjs/index.cjs.js +1 -1
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/oem-htws-modal.cjs.entry.js +1 -1
  9. package/dist/cjs/oem-jd-modal.cjs.entry.js +2 -2
  10. package/dist/cjs/oem-jlpp-modal.cjs.entry.js +1 -1
  11. package/dist/cjs/oem-jlsx-modal.cjs.entry.js +2 -2
  12. package/dist/cjs/{pcm-jlzz-modal.cjs.entry.js → oem-jlzz-modal.cjs.entry.js} +13 -158
  13. package/dist/cjs/oem-jlzz-modal.cjs.entry.js.map +1 -0
  14. package/dist/{pcm-agents/pcm-jlzz-modal.entry.esm.js.map → cjs/oem-jlzz-modal.entry.cjs.js.map} +1 -1
  15. package/dist/cjs/oem-mnct-modal.cjs.entry.js +1 -1
  16. package/dist/cjs/oem-qgqjl-modal.cjs.entry.js +1 -1
  17. package/dist/cjs/oem-zygh-modal.cjs.entry.js +1 -1
  18. package/dist/cjs/pcm-agents.cjs.js +1 -1
  19. package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js +2 -2
  20. package/dist/cjs/pcm-mnms-modal.cjs.entry.js +2 -3
  21. package/dist/cjs/pcm-mnms-modal.cjs.entry.js.map +1 -1
  22. package/dist/cjs/pcm-mnms-modal.entry.cjs.js.map +1 -1
  23. package/dist/cjs/pcm-zygh-v2-modal.cjs.entry.js +1 -1
  24. package/dist/cjs/{sentry-reporter-DXDpkMTS.js → sentry-reporter-BvQcVVQ_.js} +3 -3
  25. package/dist/cjs/{sentry-reporter-DXDpkMTS.js.map → sentry-reporter-BvQcVVQ_.js.map} +1 -1
  26. package/dist/collection/components/oem-mnms-modal/oem-mnms-modal.js +2 -3
  27. package/dist/collection/components/oem-mnms-modal/oem-mnms-modal.js.map +1 -1
  28. package/dist/collection/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.js +1 -1
  29. package/dist/collection/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.js.map +1 -1
  30. package/dist/collection/components/pcm-jlzz-modal/pcm-jlzz-modal.js +34 -0
  31. package/dist/collection/components/pcm-jlzz-modal/pcm-jlzz-modal.js.map +1 -1
  32. package/dist/collection/components/pcm-mnms-modal/pcm-mnms-modal.js +2 -3
  33. package/dist/collection/components/pcm-mnms-modal/pcm-mnms-modal.js.map +1 -1
  34. package/dist/collection/components/pcm-mnms-zp-modal/pcm-mnms-zp-modal.js +2 -3
  35. package/dist/collection/components/pcm-mnms-zp-modal/pcm-mnms-zp-modal.js.map +1 -1
  36. package/dist/components/components-position-selector.js +1 -1
  37. package/dist/components/index.js +1 -1
  38. package/dist/components/oem-htws-modal.js +6 -6
  39. package/dist/components/oem-jd-modal.js +4 -4
  40. package/dist/components/oem-jlpp-modal.js +8 -8
  41. package/dist/components/oem-jlsx-modal.js +6 -6
  42. package/dist/components/oem-jlzz-modal.js +6 -6
  43. package/dist/components/oem-mnct-modal.js +8 -8
  44. package/dist/components/oem-mnms-modal.js +10 -11
  45. package/dist/components/oem-mnms-modal.js.map +1 -1
  46. package/dist/components/oem-qgqjl-modal.js +8 -8
  47. package/dist/components/oem-zygh-modal.js +6 -6
  48. package/dist/components/{p-CfvqfIAT.js → p-B0in66n7.js} +3 -3
  49. package/dist/components/{p-CfvqfIAT.js.map → p-B0in66n7.js.map} +1 -1
  50. package/dist/components/{p-B_sMa6Wg.js → p-C3QG0kk0.js} +4 -4
  51. package/dist/components/{p-B_sMa6Wg.js.map → p-C3QG0kk0.js.map} +1 -1
  52. package/dist/components/{p-BvzZ1qpT.js → p-CNKZCbo_.js} +5 -5
  53. package/dist/components/{p-BvzZ1qpT.js.map → p-CNKZCbo_.js.map} +1 -1
  54. package/dist/components/{p-D88J-Sqf.js → p-CNx58GiW.js} +3 -3
  55. package/dist/components/{p-D88J-Sqf.js.map → p-CNx58GiW.js.map} +1 -1
  56. package/dist/components/{p-CLRf3Ghu.js → p-DY30qE8x.js} +3 -3
  57. package/dist/components/{p-CLRf3Ghu.js.map → p-DY30qE8x.js.map} +1 -1
  58. package/dist/components/{p-CzTEcT75.js → p-DeoeSzgS.js} +3 -3
  59. package/dist/components/{p-CzTEcT75.js.map → p-DeoeSzgS.js.map} +1 -1
  60. package/dist/components/{p-C-T9jPVd.js → p-Dl6ISIDE.js} +3 -3
  61. package/dist/components/{p-C-T9jPVd.js.map → p-Dl6ISIDE.js.map} +1 -1
  62. package/dist/components/{p-CDtnxtHn.js → p-_ysXxBbt.js} +3 -3
  63. package/dist/components/{p-CDtnxtHn.js.map → p-_ysXxBbt.js.map} +1 -1
  64. package/dist/components/{p-SkhfviAi.js → p-ebsIIpQh.js} +3 -3
  65. package/dist/components/{p-SkhfviAi.js.map → p-ebsIIpQh.js.map} +1 -1
  66. package/dist/components/{p-BnveSmhC.js → p-zNL5HFbN.js} +3 -3
  67. package/dist/components/{p-BnveSmhC.js.map → p-zNL5HFbN.js.map} +1 -1
  68. package/dist/components/pcm-1zhanshi-mnms-modal.js +6 -6
  69. package/dist/components/pcm-1zhanshi-mnms-modal.js.map +1 -1
  70. package/dist/components/pcm-app-chat-modal.js +1 -1
  71. package/dist/components/pcm-card.js +1 -1
  72. package/dist/components/pcm-chat-message.js +1 -1
  73. package/dist/components/pcm-digital-human.js +1 -1
  74. package/dist/components/pcm-export-records-modal.js +1 -1
  75. package/dist/components/pcm-hr-chat-modal.js +2 -2
  76. package/dist/components/pcm-htws-modal.js +7 -7
  77. package/dist/components/pcm-hyzj-modal.js +4 -4
  78. package/dist/components/pcm-jd-modal.js +4 -4
  79. package/dist/components/pcm-jlpp-modal.js +7 -7
  80. package/dist/components/pcm-jlsx-modal.js +5 -5
  81. package/dist/components/pcm-jlzz-modal.js +22 -6
  82. package/dist/components/pcm-jlzz-modal.js.map +1 -1
  83. package/dist/components/pcm-mnct-modal.js +4 -4
  84. package/dist/components/pcm-mnms-modal.js +9 -10
  85. package/dist/components/pcm-mnms-modal.js.map +1 -1
  86. package/dist/components/pcm-mnms-zp-modal.js +9 -10
  87. package/dist/components/pcm-mnms-zp-modal.js.map +1 -1
  88. package/dist/components/pcm-mobile-input-btn.js +1 -1
  89. package/dist/components/pcm-mobile-upload-btn.js +1 -1
  90. package/dist/components/pcm-msbg-modal.js +4 -4
  91. package/dist/components/pcm-qgqjl-modal.js +7 -7
  92. package/dist/components/pcm-upload.js +1 -1
  93. package/dist/components/pcm-virtual-chat-modal.js +1 -1
  94. package/dist/components/pcm-zsk-chat-modal.js +2 -2
  95. package/dist/components/pcm-zygh-modal.js +6 -6
  96. package/dist/components/pcm-zygh-v2-modal.js +6 -6
  97. package/dist/esm/components-position-selector_28.entry.js +3671 -3515
  98. package/dist/esm/components-position-selector_28.entry.js.map +1 -1
  99. package/dist/esm/index-Bq0K-WqZ.js +4 -4
  100. package/dist/esm/{index-CHvJS-H3.js → index-DcHaiJdv.js} +3 -3
  101. package/dist/esm/{index-CHvJS-H3.js.map → index-DcHaiJdv.js.map} +1 -1
  102. package/dist/esm/index.js +1 -1
  103. package/dist/esm/loader.js +1 -1
  104. package/dist/esm/oem-htws-modal.entry.js +1 -1
  105. package/dist/esm/oem-jd-modal.entry.js +2 -2
  106. package/dist/esm/oem-jlpp-modal.entry.js +1 -1
  107. package/dist/esm/oem-jlsx-modal.entry.js +2 -2
  108. package/dist/esm/{pcm-jlzz-modal.entry.js → oem-jlzz-modal.entry.js} +13 -158
  109. package/dist/esm/{pcm-jlzz-modal.entry.js.map → oem-jlzz-modal.entry.js.map} +1 -1
  110. package/dist/esm/oem-mnct-modal.entry.js +1 -1
  111. package/dist/esm/oem-qgqjl-modal.entry.js +1 -1
  112. package/dist/esm/oem-zygh-modal.entry.js +1 -1
  113. package/dist/esm/pcm-agents.js +1 -1
  114. package/dist/esm/pcm-hr-chat-modal.entry.js +2 -2
  115. package/dist/esm/pcm-mnms-modal.entry.js +2 -3
  116. package/dist/esm/pcm-mnms-modal.entry.js.map +1 -1
  117. package/dist/esm/pcm-zygh-v2-modal.entry.js +1 -1
  118. package/dist/esm/{sentry-reporter-B4QtDqo5.js → sentry-reporter-BZ6jaP_d.js} +3 -3
  119. package/dist/esm/{sentry-reporter-B4QtDqo5.js.map → sentry-reporter-BZ6jaP_d.js.map} +1 -1
  120. package/dist/pcm-agents/index.esm.js +1 -1
  121. package/dist/{cjs/pcm-jlzz-modal.entry.cjs.js.map → pcm-agents/oem-jlzz-modal.entry.esm.js.map} +1 -1
  122. package/dist/pcm-agents/{p-59317c49.entry.js → p-079c81fd.entry.js} +2 -2
  123. package/dist/pcm-agents/{p-8110e9ac.entry.js → p-178f3772.entry.js} +2 -2
  124. package/dist/pcm-agents/{p-1e7fce4d.entry.js → p-22e147d9.entry.js} +2 -2
  125. package/dist/pcm-agents/{p-8bd845ed.entry.js → p-26c3bb94.entry.js} +2 -2
  126. package/dist/pcm-agents/p-285a11db.entry.js +2 -0
  127. package/dist/pcm-agents/{p-ccbdd899.entry.js.map → p-285a11db.entry.js.map} +1 -1
  128. package/dist/pcm-agents/{p-0bf21647.entry.js → p-359d3474.entry.js} +2 -2
  129. package/dist/pcm-agents/{p-1b567acf.entry.js → p-4a91a26a.entry.js} +2 -2
  130. package/dist/pcm-agents/{p-9eafe75b.entry.js → p-6037c915.entry.js} +2 -2
  131. package/dist/pcm-agents/{p-406da9d5.entry.js → p-7a6267c2.entry.js} +2 -2
  132. package/dist/pcm-agents/p-CBQPOkZb.js +2 -0
  133. package/dist/pcm-agents/{p-UID-6O7M.js.map → p-CBQPOkZb.js.map} +1 -1
  134. package/dist/pcm-agents/{p-CaZKzVLc.js → p-WTSeW6oH.js} +2 -2
  135. package/dist/pcm-agents/{p-CaZKzVLc.js.map → p-WTSeW6oH.js.map} +1 -1
  136. package/dist/pcm-agents/p-ca2fb22a.entry.js +245 -0
  137. package/dist/pcm-agents/p-ca2fb22a.entry.js.map +1 -0
  138. package/dist/pcm-agents/{p-fefd9ac6.entry.js → p-da967a8c.entry.js} +2 -2
  139. package/dist/pcm-agents/{p-f89bb8a2.entry.js → p-df3f8c9a.entry.js} +2 -2
  140. package/dist/pcm-agents/{p-f89bb8a2.entry.js.map → p-df3f8c9a.entry.js.map} +1 -1
  141. package/dist/pcm-agents/pcm-agents.esm.js +1 -1
  142. package/dist/pcm-agents/pcm-mnms-modal.entry.esm.js.map +1 -1
  143. package/dist/types/components/oem-mnms-modal/oem-mnms-modal.d.ts +0 -1
  144. package/dist/types/components/pcm-jlzz-modal/pcm-jlzz-modal.d.ts +5 -0
  145. package/dist/types/components/pcm-mnms-modal/pcm-mnms-modal.d.ts +0 -1
  146. package/dist/types/components/pcm-mnms-zp-modal/pcm-mnms-zp-modal.d.ts +0 -1
  147. package/dist/types/components.d.ts +14 -6
  148. package/package.json +1 -1
  149. package/dist/cjs/pcm-jlzz-modal.cjs.entry.js.map +0 -1
  150. package/dist/pcm-agents/p-7a11e5b2.entry.js +0 -245
  151. package/dist/pcm-agents/p-7a11e5b2.entry.js.map +0 -1
  152. package/dist/pcm-agents/p-UID-6O7M.js +0 -2
  153. package/dist/pcm-agents/p-ccbdd899.entry.js +0 -2
  154. /package/dist/pcm-agents/{p-59317c49.entry.js.map → p-079c81fd.entry.js.map} +0 -0
  155. /package/dist/pcm-agents/{p-8110e9ac.entry.js.map → p-178f3772.entry.js.map} +0 -0
  156. /package/dist/pcm-agents/{p-1e7fce4d.entry.js.map → p-22e147d9.entry.js.map} +0 -0
  157. /package/dist/pcm-agents/{p-8bd845ed.entry.js.map → p-26c3bb94.entry.js.map} +0 -0
  158. /package/dist/pcm-agents/{p-0bf21647.entry.js.map → p-359d3474.entry.js.map} +0 -0
  159. /package/dist/pcm-agents/{p-1b567acf.entry.js.map → p-4a91a26a.entry.js.map} +0 -0
  160. /package/dist/pcm-agents/{p-9eafe75b.entry.js.map → p-6037c915.entry.js.map} +0 -0
  161. /package/dist/pcm-agents/{p-406da9d5.entry.js.map → p-7a6267c2.entry.js.map} +0 -0
  162. /package/dist/pcm-agents/{p-fefd9ac6.entry.js.map → p-da967a8c.entry.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"names":["componentsPositionSelectorCss","globalCss","oemJlzzModalCss","hostCss","oemMnmsModalCss","OemMnmsModal","modalTitle","token","isOpen","modalClosed","icon","zIndex","isShowHeader","isNeedClose","conversationId","defaultQuery","maxRecordingTime","waitingTime","fullscreen","customInputs","showWorkspaceHistory","oemId","digitalId","openingIndex","enableVirtualHuman","showEndInterviewButton","uploadSuccess","streamComplete","conversationStart","interviewComplete","tokenInvalid","someErrorEvent","interviewMode","recordingError","showCopyButton","showFeedbackButtons","selectedFile","isUploading","uploadedFileInfo","showChatModal","phoneNumber","verificationCode","isSendingCode","countdown","isVerifyingCode","showPositionSelector","jobDescription","isSubmitting","tokenInvalidListener","removeErrorListener","virtualChatModalRef","handleTokenChange","newToken","authStore","getToken","setToken","handleIsOpenChange","newValue","this","setComponentActive","resetState","verifyApiKey","componentWillLoad","configStore","setItem","emit","ErrorEventBus","addErrorListener","errorDetail","document","addEventListener","disconnectedCallback","removeEventListener","countdownTimer","clearInterval","handleClose","handleJobDescriptionChange","event","textarea","target","value","handlePhoneNumberChange","input","handleVerificationCodeChange","startCountdown","setInterval","handleSendCode","async","trim","Message","error","phoneRegex","test","result","sendSmsCode","success","message","handleOpenPositionSelector","info","handleClosePositionSelector","handlePositionSelected","position","detail","formatted_text","handleStartInterview","job_info","verifySmsCode","pcmUploadRef","getIsUploading","render","modalStyle","String","containerClass","overlayClass","isLoading","disableJdInput","Boolean","disableResumeUpload","file_url","resume_content","h","class","style","src","alt","onClick","htmlFor","type","name","onOk","e","id","placeholder","rows","onInput","disabled","ref","el","maxFileSize","multiple","mobileUploadAble","acceptFileSuffixList","uploadParams","tags","defaultFileList","cos_key","file_name","file_size","ext","undefined","onUploadChange","maxLength","length","href","rel","botId","question_number","interview_type","phone","onPositionSelected","pcm1zhanshiMnmsModalCss","ZhanshiMnmsModal","pcmAppChatModalCss","markdownCss","pcmButtonCss","PcmButton","size","loading","shape","backgroundColor","textColor","borderColor","borderRadius","width","block","borderStyle","classes","customStyle","key","Object","keys","filter","join","pcmCardCss","PcmCard","cardTitle","description","iconUrl","author","authorAvatarUrl","showChatTag","customChatTag","useButtonText","botData","watchBotIdHandler","fetchBotData","response","sendHttpRequest","url","method","data","Error","err","console","title","desc","iconFromBot","logo","authorName","author_name","authorAvatar","author_avatar","hasChatTag","flag","usersCount","use_count","starsCount","follow_count","usageCount","view_count","log","userIconUrl","pcmChatMessageCss","pcmConfirmModalCss","PcmConfirmModal","okText","cancelText","okType","maskClosable","mask","centered","ok","cancel","closed","afterOpen","afterClose","bodyOverflowBeforeOpen","transitionEndHandler","open","close","visibleChanged","body","overflow","modal","hostElement","shadowRoot","querySelector","once","cachedZIndex","getItem","handleMaskClick","handleCancel","handleOk","maskStyle","contentClass","okButtonClass","pcmDigitalHumanCss","pcmDrawerCss","PcmDrawer","drawerTitle","height","closable","drawer","drawerStyle","pcmExportRecordsModalCss","DEFAULT_PAGINATION","page","EXPORT_BATCH_STATUS_MAP","text","color","PcmExportRecordsModal","sourceId","pagination","showMessage","messageText","messageType","watchOpen","fetchData","p","params","bot_id","source_id","records","total","handleDownload","record","downloadUrl","getCosPresignedUrl","fileName","link","createElement","setAttribute","appendChild","click","remove","showMessageToast","handleDelete","setTimeout","handleRefresh","handlePageChange","newPagination","formatDate","dateString","date","Date","toLocaleString","year","month","day","hour","minute","second","renderEmpty","renderTag","status","statusInfo","toString","renderButton","variant","renderTable","textAlign","map","created_at","renderPagination","totalPages","Math","ceil","currentPage","onChange","parseInt","selected","renderMessage","stopPropagation","pcmHtwsModalCss","HtwsModal","mobileInputAble","filePreviewMode","inputMode","freeInputText","handleToggleInput","handleFreeInputChange","viewBox","fill","stroke","d","uploadText","pcmHyzjModalCss","HyzjModal","clearSelectedFile","handleFileChange","files","handleUploadClick","fileInput","uploadFile","uploadFileToBackend","SentryReporter","captureError","action","component","emitError","alert","hideFileUpload","pcmJdModalCss","PcmJdModal","showSaveJdButton","saveJdButtonText","step","jobName","tagGroups","shuffledTagGroups","selectedAITags","selectedTags","salary","benefits","education","salaryRanges","educationRequirements","handleJobNameChange","handleNextStep","handlePositionAnalysis","handlePrevStep","inputs","input_info","workflow_code","outputs","jsonText","markdownJsonMatch","match","parsedOutput","JSON","parse","tagGroup","initialSelectedTags","shuffled","group","allTags","defaultTags","optionalTags","i","j","floor","random","dimensionName","handleTagClick","category","currentTags","newTags","includes","t","handleAITagClick","tag","handleSubmitStructured","salaryRange","range","find","r","selectedBenefits","edu","jobInfo","entries","forEach","dimension","handleSubmitFree","renderTagGroup","options","option","isSelected","renderAITagGroups","renderLoadingState","pcmJlppModalCss","JlppModal","mobileJdInputAble","handleStartAnalysis","hideJdInput","hideResumeUpload","hasFileAndJob","pcmJlsxModalCss","pcmMessageCss","PcmMessage","content","duration","visible","timer","componentDidLoad","window","clearTimeout","show","parentNode","removeChild","renderIcon","pcmMnctModalCss","MnctModal","questionNumber","canOutputAnalysis","handleQuestionNumberChange","handleAnalysisToggle","checked","min","max","can_outputAnalysis","pcmMnmsZpModalCss","MnmsZpModal","VALUES_TO_CHARSET","Map","Charset","label","values","static","constructor","freeze","Number","isInteger","set","toBit","toInt32","getBitMask","getBitOffset","findMSBSet","clz32","calculateBCHCode","poly","msbSetInPoly","VALUES_TO_MODE","Mode","bits","characterCountBitsSet","Int32Array","getCharacterCountBits","version","offset","N1","N2","N3","N4","isDark","matrix","x","y","get","applyMaskPenaltyRule1Internal","isVertical","penalty","prevBit","numSameBitCells","bit","applyMaskPenaltyRule1","applyMaskPenaltyRule2","isFourWhite","from","to","applyMaskPenaltyRule3","numPenalties","applyMaskPenaltyRule4","numDarkCells","numTotalCells","fivePercentVariances","abs","calculateMaskPenalty","isApplyMask","temporary","intermediate","VALUES_TO_ECLEVEL","ECLevel","level","ECB","count","numDataCodewords","ECBlocks","ecBlocks","numTotalCodewords","numTotalECCodewords","numTotalDataCodewords","numECCodewordsPerBlock","numBlocks","Version","alignmentPatterns","getECBlocks","VERSIONS","Polynomial","field","coefficients","firstNonZero","array","subarray","isZero","getDegree","getCoefficient","degree","evaluate","a","coefficient","multiply","other","zero","otherCoefficients","otherLength","product","multiplyByMonomial","addOrSubtract","largerCoefficients","largerLength","smallerCoefficients","smallerLength","divide","quotient","remainder","denominatorLeadingTerm","invertDenominatorLeadingTerm","invert","remainderDegree","degreeDiff","scale","term","iterationQuotient","buildPolynomial","GaloisField","one","generator","expTable","logTable","primitive","exp","b","QR_CODE_FIELD_256","getUnicodeCodes","maxCode","bytes","character","code","codePointAt","push","Uint8Array","encode","charset","ASCII","ISO_8859_1","UTF_8","TextEncoder","LOAD_FACTOR","index","makeArray","BitArray","alloc","byteLength","xor","maskBits","append","writeToUint8Array","bitOffset","byteOffset","byte","clear","ByteMatrix","Int8Array","FORMAT_INFO_POLY","FORMAT_INFO_MASK","VERSION_INFO_POLY","FINDER_PATTERN_SHAPE","ALIGNMENT_PATTERN_SHAPE","FORMAT_INFO_COORDINATES","isEmpty","embedFinderPattern","pattern","embedHorizontalSeparator","embedVerticalSeparator","embedFinderPatternsAndSeparators","pdpWidth","hspWidth","vspHeight","embedTimingPatterns","embedAlignmentPattern","embedAlignmentPatterns","embedDarkModule","makeFormatInfoBits","ecLevel","formatInfo","bchCode","embedFormatInfo","formatInfoBits","makeVersionInfoBits","embedVersionInfo","versionInfoBits","bitIndex","embedCodewords","codewords","offsetX","upward","offsetY","embedFunctionPatterns","embedEncodingRegion","buildMatrix","BlockPair","ecCodewords","dataCodewords","buildGenerator","generators","lastGenerator","nextGenerator","Encoder","received","ecLength","dataBytes","infoCoefficients","base","numZeroCoefficients","zeroCoefficientsOffset","generateECCodewords","numECCodewords","buffer","injectECCodewords","maxNumECCodewords","maxNumDataCodewords","dataCodewordsOffset","blocks","appendTerminator","capacity","numBitsInLastByte","numPaddingCodewords","isByteMode","segment","mode","BYTE","isHanziMode","HANZI","appendModeInfo","appendECI","currentECIValue","ECI","appendFNC1Info","fnc1","indicator","FNC1_FIRST_POSITION","FNC1_SECOND_POSITION","getSegmentLength","appendLengthInfo","numLetters","willFit","numInputBits","numInputCodewords","chooseVersion","calculateBitsNeeded","segmentBlocks","bitsNeeded","head","chooseRecommendVersion","provisionalBitsNeeded","provisionalVersion","chooseBestMaskAndMatrix","bestMask","bestMatrix","minPenalty","MAX_CODE","Dict","bof","eof","depth","unused","codes","reset","add","DictStream","dict","write","pipe","stream","writeByte","remain","writeBytes","compress","pixels","pixelIndex","nextCode","ByteStream","writeInt16","fromCharCode","Base64Stream","pad","GIFImage","foreground","background","toDataURL","base64","Encoded","moduleSize","margin","colors","matrixSize","gif","assertContent","assertCharset","assertHints","hints","assertLevel","indexOf","assertVersion","encode$1","segments","versionNumber","isFNC1Appended","Byte","uploadNumberSDK","number","isWorking","onError","pcmMobileInputBtnCss","MobileUploadBtn","uploadHeaders","QR_CODE_VALID_TIME","mobileUrl","setStartMobileUpload","startMobileUploadLoading","qrcodeStatus","expireTime","setStartMobileUploadWrapper","qrcodeUrl","setMobileUrlWrapper","encoder","qrcode","pollingQueryNumberInfo","num","res","resData","custom_data","handleStartMobileUpload","that","reqData","cfg","fromUserName","fromUserId","upload","update_id","expireDate","now","getHours","padStart","getMinutes","theMobileUrl","PCM_DOMAIN","cancelLoading","cancelMobileUpload","mobile","isMobile","marginTop","fontSize","navigator","clipboard","writeText","then","catch","readOnly","pcmMobileUploadBtnCss","maxFileCount","Infinity","file_list","is_knowledge_doc","maxSize","maxCount","customAccept","it","item","pcmMsbgModalCss","MsbgModal","file_urls","file_names","pcmQgqjlModalCss","pcmUploadCss","PcmUpload","uploadFailed","uploadChange","selectedFiles","file","state","FileUploadState","Success","some","Uploading","clearSelectedFiles","Failed","Array","currentFileCount","remainingSlots","validFiles","invalidFiles","suffix","split","pop","toLowerCase","supportedFormats","maxSizeText","formatFileSize","newFileItems","uploadResult","targetIndex","emitUploadChange","uploadBtn","textDecoration","marginLeft","_","itemIndex","pcmVirtualChatModalCss","pcmZskChatModalCss","pcmZyghModalCss","ZyghModal","planningComplete","selectedPlanType","handlePlanTypeChange","handleStartPlanning","handlePlanningComplete","hasFileAndType","onInterviewComplete"],"sources":["src/components/components-position-selector/components-position-selector.css?tag=components-position-selector&encapsulation=shadow","src/global/global.css?tag=components-position-selector&encapsulation=shadow","src/components/oem-jlzz-modal/oem-jlzz-modal.css?tag=oem-jlzz-modal&encapsulation=shadow","src/global/global.css?tag=oem-jlzz-modal&encapsulation=shadow","src/global/host.css?tag=oem-jlzz-modal&encapsulation=shadow","src/components/oem-mnms-modal/oem-mnms-modal.css?tag=oem-mnms-modal&encapsulation=shadow","src/global/global.css?tag=oem-mnms-modal&encapsulation=shadow","src/global/host.css?tag=oem-mnms-modal&encapsulation=shadow","src/components/oem-mnms-modal/oem-mnms-modal.tsx","src/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/global/global.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/global/host.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.tsx","src/components/pcm-app-chat-modal/pcm-app-chat-modal.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/global/markdown.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/global/host.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/components/pcm-button/pcm-button.css?tag=pcm-button&encapsulation=shadow","src/global/host.css?tag=pcm-button&encapsulation=shadow","src/components/pcm-button/pcm-button.tsx","src/components/pcm-card/pcm-card.css?tag=pcm-card&encapsulation=shadow","src/global/host.css?tag=pcm-card&encapsulation=shadow","src/components/pcm-card/pcm-card.tsx","src/global/markdown.css?tag=pcm-chat-message&encapsulation=shadow","src/components/pcm-chat-message/pcm-chat-message.css?tag=pcm-chat-message&encapsulation=shadow","src/global/host.css?tag=pcm-chat-message&encapsulation=shadow","src/components/pcm-confirm-modal/pcm-confirm-modal.css?tag=pcm-confirm-modal&encapsulation=shadow","src/global/host.css?tag=pcm-confirm-modal&encapsulation=shadow","src/components/pcm-confirm-modal/pcm-confirm-modal.tsx","src/components/pcm-digital-human/pcm-digital-human.css?tag=pcm-digital-human&encapsulation=shadow","src/global/host.css?tag=pcm-digital-human&encapsulation=shadow","src/components/pcm-drawer/pcm-drawer.css?tag=pcm-drawer&encapsulation=shadow","src/global/host.css?tag=pcm-drawer&encapsulation=shadow","src/components/pcm-drawer/pcm-drawer.tsx","src/components/pcm-export-records-modal/pcm-export-records-modal.css?tag=pcm-export-records-modal&encapsulation=shadow","src/components/pcm-export-records-modal/pcm-export-records-modal.tsx","src/components/pcm-htws-modal/pcm-htws-modal.css?tag=pcm-htws-modal&encapsulation=shadow","src/global/global.css?tag=pcm-htws-modal&encapsulation=shadow","src/global/host.css?tag=pcm-htws-modal&encapsulation=shadow","src/components/pcm-htws-modal/pcm-htws-modal.tsx","src/components/pcm-hyzj-modal/pcm-hyzj-modal.css?tag=pcm-hyzj-modal&encapsulation=shadow","src/global/global.css?tag=pcm-hyzj-modal&encapsulation=shadow","src/global/host.css?tag=pcm-hyzj-modal&encapsulation=shadow","src/components/pcm-hyzj-modal/pcm-hyzj-modal.tsx","src/components/pcm-jd-modal/pcm-jd-modal.css?tag=pcm-jd-modal&encapsulation=shadow","src/global/global.css?tag=pcm-jd-modal&encapsulation=shadow","src/global/host.css?tag=pcm-jd-modal&encapsulation=shadow","src/components/pcm-jd-modal/pcm-jd-modal.tsx","src/components/pcm-jlpp-modal/pcm-jlpp-modal.css?tag=pcm-jlpp-modal&encapsulation=shadow","src/global/global.css?tag=pcm-jlpp-modal&encapsulation=shadow","src/global/host.css?tag=pcm-jlpp-modal&encapsulation=shadow","src/components/pcm-jlpp-modal/pcm-jlpp-modal.tsx","src/global/global.css?tag=pcm-jlsx-modal&encapsulation=shadow","src/components/pcm-jlsx-modal/pcm-jlsx-modal.css?tag=pcm-jlsx-modal&encapsulation=shadow","src/global/markdown.css?tag=pcm-jlsx-modal&encapsulation=shadow","src/global/host.css?tag=pcm-jlsx-modal&encapsulation=shadow","src/components/pcm-message/pcm-message.css?tag=pcm-message&encapsulation=shadow","src/global/host.css?tag=pcm-message&encapsulation=shadow","src/components/pcm-message/pcm-message.tsx","src/components/pcm-mnct-modal/pcm-mnct-modal.css?tag=pcm-mnct-modal&encapsulation=shadow","src/global/global.css?tag=pcm-mnct-modal&encapsulation=shadow","src/global/host.css?tag=pcm-mnct-modal&encapsulation=shadow","src/components/pcm-mnct-modal/pcm-mnct-modal.tsx","src/components/pcm-mnms-zp-modal/pcm-mnms-zp-modal.css?tag=pcm-mnms-zp-modal&encapsulation=shadow","src/global/global.css?tag=pcm-mnms-zp-modal&encapsulation=shadow","src/global/host.css?tag=pcm-mnms-zp-modal&encapsulation=shadow","src/components/pcm-mnms-zp-modal/pcm-mnms-zp-modal.tsx","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/Charset.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/utils.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/Mode.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/mask.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/ECLevel.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/ECB.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/ECBlocks.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/Version.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/reedsolomon/Polynomial.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/reedsolomon/GaloisField.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/encoding/index.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/BitArray.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/ByteMatrix.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/utils/matrix.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/BlockPair.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/reedsolomon/Encoder.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/utils/encoder.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/utils/lzw/Dict.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/utils/lzw/DictStream.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/utils/lzw/index.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/utils/ByteStream.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/utils/Base64Stream.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/common/image/GIFImage.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/Encoded.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/utils/asserts.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/Encoder.js","node_modules/.pnpm/@nuintun+qrcode@5.0.2/node_modules/@nuintun/qrcode/esm/encoder/segments/Byte.js","src/components/pcm-mobile-input-btn/uploadNumberSDK.ts","src/components/pcm-mobile-input-btn/pcm-mobile-input-btn.css?tag=pcm-mobile-input-btn&encapsulation=shadow","src/global/global.css?tag=pcm-mobile-input-btn&encapsulation=shadow","src/global/host.css?tag=pcm-mobile-input-btn&encapsulation=shadow","src/components/pcm-mobile-input-btn/pcm-mobile-input-btn.tsx","src/components/pcm-mobile-upload-btn/uploadNumberSDK.ts","src/components/pcm-mobile-upload-btn/pcm-mobile-upload-btn.css?tag=pcm-mobile-upload-btn&encapsulation=shadow","src/global/global.css?tag=pcm-mobile-upload-btn&encapsulation=shadow","src/global/host.css?tag=pcm-mobile-upload-btn&encapsulation=shadow","src/components/pcm-mobile-upload-btn/pcm-mobile-upload-btn.tsx","src/components/pcm-msbg-modal/pcm-msbg-modal.css?tag=pcm-msbg-modal&encapsulation=shadow","src/global/global.css?tag=pcm-msbg-modal&encapsulation=shadow","src/global/host.css?tag=pcm-msbg-modal&encapsulation=shadow","src/components/pcm-msbg-modal/pcm-msbg-modal.tsx","src/components/pcm-qgqjl-modal/pcm-qgqjl-modal.css?tag=pcm-qgqjl-modal&encapsulation=shadow","src/global/global.css?tag=pcm-qgqjl-modal&encapsulation=shadow","src/global/host.css?tag=pcm-qgqjl-modal&encapsulation=shadow","src/components/pcm-upload/pcm-upload.css?tag=pcm-upload&encapsulation=shadow","src/global/global.css?tag=pcm-upload&encapsulation=shadow","src/global/host.css?tag=pcm-upload&encapsulation=shadow","src/components/pcm-upload/pcm-upload.tsx","src/components/pcm-virtual-chat-modal/pcm-virtual-chat-modal.css?tag=pcm-virtual-chat-modal&encapsulation=shadow","src/global/host.css?tag=pcm-virtual-chat-modal&encapsulation=shadow","src/components/pcm-zsk-chat-modal/pcm-zsk-chat-modal.css?tag=pcm-zsk-chat-modal&encapsulation=shadow","src/global/host.css?tag=pcm-zsk-chat-modal&encapsulation=shadow","src/global/global.css?tag=pcm-zygh-modal&encapsulation=shadow","src/components/pcm-zygh-modal/pcm-zygh-modal.css?tag=pcm-zygh-modal&encapsulation=shadow","src/global/host.css?tag=pcm-zygh-modal&encapsulation=shadow","src/components/pcm-zygh-modal/pcm-zygh-modal.tsx"],"sourcesContent":[":host {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.position-selector-container {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n background: #fff;\r\n}\r\n\r\n/* 搜索栏样式 */\r\n.search-bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.search-input-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n min-width: 200px;\r\n max-width: 500px;\r\n}\r\n\r\n.search-icon {\r\n position: absolute;\r\n left: 12px;\r\n color: #bfbfbf;\r\n pointer-events: none;\r\n}\r\n\r\n.search-input {\r\n width: 100%;\r\n height: 36px;\r\n padding: 4px 36px 4px 36px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n color: rgba(0, 0, 0, 0.85);\r\n background-color: #fff;\r\n background-image: none;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.search-input:hover {\r\n border-color: #40a9ff;\r\n}\r\n\r\n.search-input:focus {\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.search-input::placeholder {\r\n color: #bfbfbf;\r\n}\r\n\r\n.clear-button {\r\n position: absolute;\r\n right: 12px;\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #bfbfbf;\r\n transition: color 0.3s;\r\n}\r\n\r\n.clear-button:hover {\r\n color: #8c8c8c;\r\n}\r\n\r\n.search-button {\r\n padding: 4px 15px;\r\n height: 36px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: #fff;\r\n background-color: #1890ff;\r\n border: 1px solid #1890ff;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n}\r\n\r\n.search-button:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.search-button:active {\r\n background-color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n/* 加载状态 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px;\r\n gap: 16px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.loading-spinner {\r\n width: 32px;\r\n height: 32px;\r\n border: 3px solid #f0f0f0;\r\n border-top-color: #1890ff;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n\r\n/* 空状态 */\r\n.empty-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n gap: 16px;\r\n}\r\n\r\n.empty-icon {\r\n opacity: 0.5;\r\n}\r\n\r\n.empty-text {\r\n margin: 0;\r\n color: #8c8c8c;\r\n font-size: 14px;\r\n}\r\n\r\n/* 职位列表 */\r\n.position-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n min-height: 0;\r\n}\r\n\r\n.table-container {\r\n width: 100%;\r\n overflow-x: auto;\r\n}\r\n\r\n.position-table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n font-size: 14px;\r\n}\r\n\r\n.position-table thead {\r\n background-color: #fafafa;\r\n position: sticky;\r\n top: 0;\r\n z-index: 1;\r\n}\r\n\r\n.position-table th {\r\n padding: 12px 16px;\r\n text-align: left;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n border-bottom: 1px solid #f0f0f0;\r\n white-space: nowrap;\r\n}\r\n\r\n.position-table td {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n color: rgba(0, 0, 0, 0.65);\r\n}\r\n\r\n.position-table tbody tr {\r\n transition: background-color 0.3s;\r\n}\r\n\r\n.position-table tbody tr:hover {\r\n background-color: #fafafa;\r\n}\r\n\r\n.position-table tbody tr.selected-row {\r\n background-color: #e6f7ff;\r\n}\r\n\r\n/* 列宽设置 */\r\n.checkbox-column {\r\n width: 50px;\r\n text-align: center;\r\n}\r\n\r\n.title-column {\r\n min-width: 150px;\r\n max-width: 200px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.company-column {\r\n min-width: 120px;\r\n max-width: 180px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.location-column {\r\n min-width: 100px;\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.requirements-column {\r\n min-width: 200px;\r\n max-width: 300px;\r\n}\r\n\r\n.requirements-text {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n white-space: normal;\r\n word-break: break-word;\r\n line-height: 1.5;\r\n}\r\n\r\n.salary-column {\r\n min-width: 100px;\r\n white-space: nowrap;\r\n}\r\n\r\n.action-column {\r\n width: 100px;\r\n text-align: center;\r\n}\r\n\r\n/* 复选框样式 */\r\n.position-checkbox {\r\n width: 16px;\r\n height: 16px;\r\n cursor: pointer;\r\n accent-color: #1890ff;\r\n}\r\n\r\n/* 选择按钮 */\r\n.select-button {\r\n padding: 4px 15px;\r\n height: 28px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: #fff;\r\n background-color: #1890ff;\r\n border: 1px solid #1890ff;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.select-button:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.select-button:active {\r\n background-color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .search-bar {\r\n padding: 12px;\r\n gap: 8px;\r\n }\r\n\r\n .search-input-wrapper {\r\n min-width: auto;\r\n max-width: none;\r\n }\r\n\r\n .search-input {\r\n height: 40px;\r\n font-size: 16px;\r\n }\r\n\r\n .search-button {\r\n height: 40px;\r\n padding: 4px 12px;\r\n }\r\n\r\n .table-container {\r\n overflow-x: auto;\r\n -webkit-overflow-scrolling: touch;\r\n }\r\n\r\n .position-table {\r\n font-size: 12px;\r\n }\r\n\r\n .position-table th,\r\n .position-table td {\r\n padding: 8px 12px;\r\n }\r\n\r\n .title-column,\r\n .company-column,\r\n .location-column {\r\n min-width: 100px;\r\n }\r\n\r\n .select-button {\r\n padding: 4px 12px;\r\n height: 32px;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n/* 分页器样式 */\r\n.pagination-container {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 16px;\r\n padding: 16px;\r\n border-top: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.pagination-button {\r\n padding: 4px 15px;\r\n height: 32px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: rgba(0, 0, 0, 0.85);\r\n background-color: #fff;\r\n border: 1px solid #d9d9d9;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.pagination-button:hover:not(:disabled) {\r\n color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.pagination-button:active:not(:disabled) {\r\n color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n.pagination-button:disabled {\r\n color: rgba(0, 0, 0, 0.25);\r\n background-color: #f5f5f5;\r\n border-color: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n.pagination-info {\r\n font-size: 14px;\r\n color: rgba(0, 0, 0, 0.65);\r\n}\r\n\r\n/* 滚动条样式 */\r\n.position-list::-webkit-scrollbar {\r\n width: 8px;\r\n height: 8px;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-track {\r\n background: #f1f1f1;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-thumb {\r\n background: #888;\r\n border-radius: 4px;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-thumb:hover {\r\n background: #555;\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",".resume-type-container {\r\n display: flex;\r\n flex-direction: row;\r\n gap: 32px;\r\n margin-bottom: 16px;\r\n border-bottom: 2px solid #f0f0f0;\r\n padding-left: 4px;\r\n}\r\n\r\n.resume-type-item {\r\n cursor: pointer;\r\n font-size: 16px;\r\n color: #333;\r\n padding: 0 0 8px 0;\r\n position: relative;\r\n background: none;\r\n border: none;\r\n outline: none;\r\n font-weight: 400;\r\n transition: color 0.2s;\r\n}\r\n\r\n.resume-type-item.selected {\r\n color: #2563eb;\r\n font-weight: 600;\r\n}\r\n\r\n.resume-type-item.selected::after {\r\n content: '';\r\n display: block;\r\n position: absolute;\r\n left: 0;\r\n bottom: -2px;\r\n width: 100%;\r\n height: 2px;\r\n background: #2563eb;\r\n border-radius: 2px;\r\n}\r\n\r\n.chat-content {\r\n background-color: #f7f9fc;\r\n border: 1px solid #e0e6f1;\r\n border-radius: 8px;\r\n padding: 16px;\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n}\r\n\r\n.chat-content-icon {\r\n font-size: 24px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.chat-content-text {\r\n font-size: 14px;\r\n color: #595959;\r\n line-height: 1.6;\r\n}\r\n\r\n.resume-type-item:not(.selected):hover {\r\n color: #2563eb;\r\n}\r\n.iframe-container {\r\n width: 100%;\r\n height: 85vh;\r\n}\r\n\r\n.iframe-container iframe {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.optimizing-modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background: rgba(0, 0, 0, 0.35);\r\n z-index: 2000;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.optimizing-modal-content {\r\n background: #fff;\r\n border-radius: 8px;\r\n padding: 32px 40px;\r\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n.optimizing-modal-content .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid #e0e0e0;\r\n border-top: 4px solid #2563eb;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n}\r\n.converstation-list {\r\n height: 600px;\r\n overflow: auto;\r\n}\r\n.conversation-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 16px;\r\n margin: 0 8px 4px 8px;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n border: 1px solid transparent;\r\n}\r\n\r\n.conversation-item:hover {\r\n background: #f5f5f5;\r\n}\r\n\r\n.conversation-item.active {\r\n background: #e6f7ff;\r\n border-color: #1890ff;\r\n}\r\n.conversation-meta {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 12px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.conversation-time {\r\n flex-shrink: 0;\r\n}\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n.optimizing-modal-content .loading-text {\r\n font-size: 18px;\r\n color: #222;\r\n font-weight: 500;\r\n margin: 0;\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","/* 标签和按钮容器 */\r\n.label-with-button {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.button-group {\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.position-selector-button {\r\n padding: 4px 12px;\r\n background: #1890ff;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 13px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n white-space: nowrap;\r\n height: 28px;\r\n line-height: 20px;\r\n}\r\n\r\n.position-selector-button:hover {\r\n background: #40a9ff;\r\n}\r\n\r\n.position-selector-button:active {\r\n background: #096dd9;\r\n}\r\n\r\n/* 手机号输入框样式 */\r\n.phone-input {\r\n width: calc(100% - 16px);\r\n padding: 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n}\r\n\r\n.phone-input:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 验证码容器样式 */\r\n.verification-code-container {\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.verification-code-input {\r\n flex: 1;\r\n padding: 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n}\r\n\r\n.verification-code-input:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 发送验证码按钮样式 */\r\n.send-code-button {\r\n padding: 8px 16px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n white-space: nowrap;\r\n min-width: 100px;\r\n}\r\n\r\n.send-code-button:hover:not(:disabled) {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.send-code-button:disabled {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: rgba(0, 0, 0, 0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n/* 职位选择器弹窗样式 */\r\n.position-selector-modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 3000;\r\n padding: 20px;\r\n}\r\n\r\n.position-selector-modal {\r\n background: white;\r\n border-radius: 8px;\r\n width: 90%;\r\n max-width: 900px;\r\n height: 80vh;\r\n max-height: 600px;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n animation: modalFadeIn 0.3s ease;\r\n}\r\n\r\n@keyframes modalFadeIn {\r\n from {\r\n opacity: 0;\r\n transform: scale(0.95) translateY(-20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: scale(1) translateY(0);\r\n }\r\n}\r\n\r\n.position-selector-modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 16px 24px;\r\n border-bottom: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.position-selector-modal-header h3 {\r\n margin: 0;\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.position-selector-close-btn {\r\n background: none;\r\n border: none;\r\n font-size: 24px;\r\n line-height: 1;\r\n cursor: pointer;\r\n color: rgba(0, 0, 0, 0.45);\r\n padding: 0;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 4px;\r\n transition: all 0.3s;\r\n}\r\n\r\n.position-selector-close-btn:hover {\r\n background-color: rgba(0, 0, 0, 0.06);\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.position-selector-modal-body {\r\n flex: 1;\r\n overflow: hidden;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .position-selector-modal {\r\n width: 100%;\r\n height: 90vh;\r\n max-height: none;\r\n border-radius: 8px 8px 0 0;\r\n margin-top: auto;\r\n }\r\n\r\n .position-selector-modal-overlay {\r\n padding: 0;\r\n align-items: flex-end;\r\n }\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey, sendSmsCode, verifySmsCode, Position } from '../../utils/utils';\r\nimport {\r\n StreamCompleteEventData,\r\n ConversationStartEventData,\r\n InterviewCompleteEventData,\r\n RecordingErrorEventData,\r\n} from '../../interfaces/events';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { Message } from '../../services/message.service';\r\n\r\n/**\r\n * 模拟面试(求职)\r\n */\r\n\r\n@Component({\r\n tag: 'oem-mnms-modal',\r\n styleUrls: ['oem-mnms-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class OemMnmsModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '模拟面试';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '请开始模拟面试';\r\n\r\n /**\r\n * 视频录制最大时长(秒)默认120\r\n */\r\n @Prop() maxRecordingTime: number = 120;\r\n\r\n /**\r\n * 等待录制时间(秒)默认10\r\n */\r\n @Prop() waitingTime: number = 10;\r\n\r\n /**\r\n * 是否以全屏模式打开,移动端建议设置为true\r\n */\r\n @Prop() fullscreen: boolean = false;\r\n\r\n /**\r\n * 自定义输入参数,可传入以下参数:<br>\r\n * customInputs.job_info时,JD输入区域不可修改。<br>\r\n * customInputs.file_url或customInputs.resume_content时,简历上传区域不可修改。<br>\r\n * customInputs.resume_content:可传入json字符串,或纯文本字符串,字符串内容为简历内容。<br>\r\n * customInputs.url_callback:可传入url字符串,当报告生成后,会调用该url进行回调。该url请使用post请求,接收报告字段为report_content,会话id字段为conversation_id。<br>\r\n * customInputs.interview_type:可传入数字,传入 1 时,开启题目连续模式,一次性生成所有题目。不传入或传入其他值时,题目将逐个生成。<br>\r\n * customInputs.question_number时,会设置面试题总数量, 默认5题。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * OEM ID,用于获取职位列表\r\n */\r\n @Prop() oemId?: string;\r\n\r\n /**\r\n * 虚拟数字人ID,指定则开启虚拟数字人功能</br>\r\n * 智琪:79202506752 </br>\r\n * 艾綝:79402522624 </br>\r\n * 艾姮:79597885440 </br>\r\n */\r\n @Prop() digitalId?: string;\r\n\r\n /**\r\n * 数字人开场白索引,用于选择开场白和开场视频(可选:0, 1, 2)\r\n * 0、您好,我是聘才猫 AI 面试助手。很高兴为你主持这场面试!在开始前,请确保:身处安静、光线充足的环境。网络顺畅,摄像头和麦克风工作正常。现在我正在查看本次面试的相关信息,为您生成专属面试题,马上就好,请稍等片刻。</br>\r\n * 1、您好,我是您的 AI 面试助手。欢迎参加本次AI面试!为了获得最佳效果,请确认:您在安静、明亮的环境中。您的网络稳定,摄像头和麦克风已开启。我们正在后台为您准备本次专属面试内容,很快开始,请稍候。<br>\r\n * 2、您好,我是您的 AI 面试助手。面试马上开始。趁此片刻,请快速确认:周围安静吗?光线足够吗?网络没问题?摄像头和麦克风准备好了吗?我们正在为您加载个性化的面试环节,稍等就好!\r\n */\r\n @Prop() openingIndex: number = 0;\r\n\r\n /**\r\n * 是否启用全屏数字人模式,此模式下面试报告只会通过url_callback回调返回\r\n */\r\n @Prop() enableVirtualHuman: boolean = false;\r\n\r\n /**\r\n * 是否显示结束面试按钮\r\n */\r\n @Prop() showEndInterviewButton: boolean = false;\r\n\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n\r\n\r\n /**\r\n * 面试模式:text - 文本模式,video - 视频模式\r\n */\r\n @Prop() interviewMode: 'text' | 'video' = 'text';\r\n\r\n /**\r\n * 录制错误事件\r\n */\r\n @Event() recordingError: EventEmitter<RecordingErrorEventData>;\r\n\r\n /**\r\n * 是否显示复制按钮\r\n */\r\n @Prop() showCopyButton: boolean = true;\r\n\r\n /**\r\n * 是否显示点赞点踩按钮\r\n */\r\n @Prop() showFeedbackButtons: boolean = true;\r\n\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 手机号和验证码相关状态\r\n @State() phoneNumber: string = '';\r\n @State() verificationCode: string = '';\r\n @State() isSendingCode: boolean = false;\r\n @State() countdown: number = 0;\r\n @State() isVerifyingCode: boolean = false;\r\n\r\n // 职位选择器相关状态\r\n @State() showPositionSelector: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n // 添加对子组件的引用\r\n private virtualChatModalRef: HTMLPcmVirtualChatModalElement | null = null;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 当模态框关闭时,调用子组件方法停止所有活动\r\n if (this.virtualChatModalRef) {\r\n await this.virtualChatModalRef.setComponentActive(false);\r\n }\r\n // 重置状态\r\n this.resetState();\r\n } else {\r\n await verifyApiKey(this.token);\r\n\r\n // 如果有会话ID,直接显示聊天模态框\r\n if (this.conversationId) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n\r\n // 初始化时设置 token,但不验证(验证在 @Watch('isOpen') 中处理)\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n // 清理倒计时定时器\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n\r\n /**\r\n * 重置组件状态\r\n */\r\n private resetState() {\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n this.isSubmitting = false;\r\n this.selectedFile = null;\r\n this.isUploading = false;\r\n this.uploadedFileInfo = null;\r\n // 重置手机号和验证码相关状态\r\n this.phoneNumber = '';\r\n this.verificationCode = '';\r\n this.isSendingCode = false;\r\n this.isVerifyingCode = false;\r\n this.countdown = 0;\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleJobDescriptionChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.jobDescription = textarea.value;\r\n };\r\n\r\n private handlePhoneNumberChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.phoneNumber = input.value;\r\n };\r\n\r\n private handleVerificationCodeChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.verificationCode = input.value;\r\n };\r\n\r\n private countdownTimer: NodeJS.Timeout | null = null;\r\n\r\n private startCountdown = () => {\r\n this.countdown = 60;\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n }\r\n this.countdownTimer = setInterval(() => {\r\n this.countdown--;\r\n if (this.countdown <= 0) {\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n }, 1000);\r\n };\r\n\r\n private handleSendCode = async () => {\r\n if (!this.phoneNumber.trim()) {\r\n Message.error('请输入手机号');\r\n return;\r\n }\r\n\r\n // 验证手机号格式\r\n const phoneRegex = /^1[3-9]\\d{9}$/;\r\n if (!phoneRegex.test(this.phoneNumber.trim())) {\r\n Message.error('请输入正确的手机号');\r\n return;\r\n }\r\n\r\n this.isSendingCode = true;\r\n try {\r\n const result = await sendSmsCode(this.phoneNumber.trim(), 0);\r\n if (result.success) {\r\n Message.success('验证码已发送');\r\n this.startCountdown();\r\n } else {\r\n Message.error(result.message || '发送验证码失败');\r\n }\r\n } catch (error) {\r\n Message.error('发送验证码失败');\r\n } finally {\r\n this.isSendingCode = false;\r\n }\r\n };\r\n\r\n private handleOpenPositionSelector = () => {\r\n if (!this.oemId) {\r\n Message.info('未配置OEM ID,无法选择职位');\r\n return;\r\n }\r\n this.showPositionSelector = true;\r\n };\r\n\r\n private handleClosePositionSelector = () => {\r\n this.showPositionSelector = false;\r\n };\r\n\r\n private handlePositionSelected = (event: CustomEvent<Position & { formatted_text?: string }>) => {\r\n const position = event.detail;\r\n // 直接使用职位选择器组件提供的格式化文本\r\n this.jobDescription = position.formatted_text || '';\r\n this.showPositionSelector = false;\r\n Message.success('职位信息已填充');\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n // 检查职位描述是否填写(优先使用customInputs.job_info)\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n Message.error('请输入职位描述');\r\n return;\r\n }\r\n\r\n // 如果填写了手机号,则需要验证验证码\r\n if (this.phoneNumber.trim()) {\r\n // 验证手机号格式\r\n const phoneRegex = /^1[3-9]\\d{9}$/;\r\n if (!phoneRegex.test(this.phoneNumber.trim())) {\r\n Message.error('请输入正确的手机号');\r\n return;\r\n }\r\n\r\n // 验证验证码是否填写\r\n if (!this.verificationCode.trim()) {\r\n Message.error('请输入验证码');\r\n return;\r\n }\r\n\r\n // 验证验证码是否正确\r\n this.isVerifyingCode = true;\r\n try {\r\n const result = await verifySmsCode(this.phoneNumber.trim(), this.verificationCode.trim(), 0);\r\n if (!result.success) {\r\n Message.error(result.error.detail || '验证码错误');\r\n this.isVerifyingCode = false;\r\n return;\r\n }\r\n } catch (error) {\r\n Message.error('验证码校验失败');\r\n this.isVerifyingCode = false;\r\n return;\r\n }\r\n this.isVerifyingCode = false;\r\n }\r\n\r\n // 判断文件是否正在上传\r\n if (await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n };\r\n\r\n private pcmUploadRef;\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\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen,\r\n 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 判断是否禁用JD输入区域(有预设job_info时禁用)\r\n const disableJdInput = Boolean(this.customInputs && this.customInputs.job_info);\r\n\r\n // 判断是否禁用简历上传区域(有预设file_url或resume_content时禁用)\r\n const disableResumeUpload = Boolean(this.customInputs && (this.customInputs.file_url || this.customInputs.resume_content));\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 <div>{this.modalTitle}</div>\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 {/* 输入界面 - 仅在不显示聊天模态框且没有会话ID时显示 */}\r\n {!this.showChatModal && !this.conversationId && (\r\n <div class=\"input-container\">\r\n {/* JD输入区域 */}\r\n <div class=\"jd-input-section\">\r\n <div class=\"label-with-button\">\r\n <label htmlFor=\"job-description\">请输入职位描述 (JD)</label>\r\n {!disableJdInput && (\r\n <div class=\"button-group\">\r\n {this.oemId && (\r\n <button\r\n class=\"position-selector-button\"\r\n onClick={this.handleOpenPositionSelector}\r\n type=\"button\"\r\n >\r\n 选择职位\r\n </button>\r\n )}\r\n <pcm-mobile-input-btn\r\n name=\"职位描述\"\r\n onOk={(e) => {\r\n this.jobDescription = e.detail;\r\n }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder=\"请输入职位描述,包括职责、要求等信息...\"\r\n rows={6}\r\n value={this.customInputs?.job_info || this.jobDescription}\r\n onInput={this.handleJobDescriptionChange}\r\n disabled={disableJdInput}\r\n ></textarea>\r\n </div>\r\n\r\n {/* 简历上传区域 */}\r\n <div class=\"jd-input-section\">\r\n <label>上传简历(选填)</label>\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\r\n mobileUploadAble={true}\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['resume'],\r\n }}\r\n defaultFileList={this.customInputs?.file_url ? [{\r\n cos_key: this.customInputs.file_url,\r\n file_name: this.customInputs?.file_name || '预设简历',\r\n file_size: 0,\r\n ext: '',\r\n }] : undefined}\r\n disabled={disableResumeUpload}\r\n onUploadChange={(e) => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n\r\n {/* 手机号和验证码区域(可选) */}\r\n <div class=\"jd-input-section\">\r\n <label>手机号(选填,填写后报告结果将通过短信发送)</label>\r\n <input\r\n type=\"tel\"\r\n class=\"phone-input\"\r\n placeholder=\"请输入手机号\"\r\n maxLength={11}\r\n value={this.phoneNumber}\r\n onInput={this.handlePhoneNumberChange}\r\n />\r\n </div>\r\n\r\n {/* 验证码输入区域 - 仅在填写了手机号时显示 */}\r\n {this.phoneNumber.trim().length === 11 && (\r\n <div class=\"jd-input-section\">\r\n <label>验证码</label>\r\n <div class=\"verification-code-container\">\r\n <input\r\n type=\"text\"\r\n class=\"verification-code-input\"\r\n placeholder=\"请输入验证码\"\r\n maxLength={6}\r\n value={this.verificationCode}\r\n onInput={this.handleVerificationCodeChange}\r\n />\r\n <button\r\n class=\"send-code-button\"\r\n disabled={this.isSendingCode || this.countdown > 0 || !this.phoneNumber.trim()}\r\n onClick={this.handleSendCode}\r\n >\r\n {this.isSendingCode ? '发送中...' : this.countdown > 0 ? `${this.countdown}秒` : '发送验证码'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={!(this.customInputs?.job_info || this.jobDescription.trim()) || this.isUploading || this.isSubmitting || this.isVerifyingCode}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isVerifyingCode ? '验证中...' : this.isSubmitting ? '处理中...' : '开始面试'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n {this.enableVirtualHuman && this.digitalId ? (\r\n <pcm-virtual-chat-modal\r\n ref={el => this.virtualChatModalRef = el}\r\n isOpen={true}\r\n fullscreen={this.fullscreen}\r\n botId=\"3022316191018884\"\r\n digitalId={this.digitalId}\r\n openingIndex={this.openingIndex}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n waitingTime={this.waitingTime}\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n question_number: this.customInputs?.question_number || 5,\r\n interview_type:\"1\",\r\n phone: this.phoneNumber.trim() || undefined\r\n }}\r\n ></pcm-virtual-chat-modal>\r\n ) : (\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018884\"\r\n digitalId={this.digitalId}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n maxRecordingTime={this.maxRecordingTime}\r\n waitingTime={this.waitingTime}\r\n showCopyButton={this.showCopyButton}\r\n showFeedbackButtons={this.showFeedbackButtons}\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n question_number: this.customInputs?.question_number || 5,\r\n phone: this.phoneNumber.trim() || undefined\r\n }}\r\n interviewMode={this.interviewMode}\r\n ></pcm-app-chat-modal>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* 职位选择器弹窗 */}\r\n {this.showPositionSelector && (\r\n <div class=\"position-selector-modal-overlay\">\r\n <div class=\"position-selector-modal\">\r\n <div class=\"position-selector-modal-header\">\r\n <h3>选择职位</h3>\r\n <button class=\"position-selector-close-btn\" onClick={this.handleClosePositionSelector}>\r\n ×\r\n </button>\r\n </div>\r\n <div class=\"position-selector-modal-body\">\r\n <components-position-selector\r\n oemId={this.oemId}\r\n multiple={false}\r\n onPositionSelected={this.handlePositionSelected}\r\n ></components-position-selector>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n} ",null,"/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport {\r\n StreamCompleteEventData,\r\n ConversationStartEventData,\r\n InterviewCompleteEventData,\r\n RecordingErrorEventData,\r\n} from '../../interfaces/events';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\n\r\n/**\r\n * 模拟面试\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-1zhanshi-mnms-modal',\r\n styleUrls: ['pcm-1zhanshi-mnms-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ZhanshiMnmsModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '模拟面试';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '请开始模拟面试';\r\n\r\n /**\r\n * 视频录制最大时长(秒)默认120\r\n */\r\n @Prop() maxRecordingTime: number = 120;\r\n\r\n /**\r\n * 等待录制时间(秒)默认10\r\n */\r\n @Prop() waitingTime: number = 10;\r\n\r\n /**\r\n * 是否以全屏模式打开,移动端建议设置为true\r\n */\r\n @Prop() fullscreen: boolean = false;\r\n\r\n /**\r\n * 自定义输入参数,传入customInputs.job_info时,会隐藏JD输入区域<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 虚拟数字人ID,指定则开启虚拟数字人功能\r\n */\r\n @Prop() digitalId?: string;\r\n\r\n /**\r\n * 数字人开场白索引,用于选择开场白和开场视频(可选:0, 1, 2)\r\n * 0、您好,我是聘才猫 AI 面试助手。很高兴为你主持这场面试!在开始前,请确保:身处安静、光线充足的环境。网络顺畅,摄像头和麦克风工作正常。现在我正在查看本次面试的相关信息,为您生成专属面试题,马上就好,请稍等片刻。</br>\r\n * 1、您好,我是您的 AI 面试助手。欢迎参加本次AI面试!为了获得最佳效果,请确认:您在安静、明亮的环境中。您的网络稳定,摄像头和麦克风已开启。我们正在后台为您准备本次专属面试内容,很快开始,请稍候。<br>\r\n * 2、您好,我是您的 AI 面试助手。面试马上开始。趁此片刻,请快速确认:周围安静吗?光线足够吗?网络没问题?摄像头和麦克风准备好了吗?我们正在为您加载个性化的面试环节,稍等就好!\r\n */\r\n @Prop() openingIndex: number = 0;\r\n\r\n /**\r\n * 是否启用全屏虚拟数字人模式,此模式下面试结果只会通过interviewComplete事件返回或者通过url_callback回调返回\r\n */\r\n @Prop() enableVirtualHuman: boolean = false;\r\n\r\n /**\r\n * 是否显示结束面试按钮\r\n */\r\n @Prop() showEndInterviewButton: boolean = false;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 录制错误事件\r\n */\r\n @Event() recordingError: EventEmitter<RecordingErrorEventData>;\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n // 添加对子组件的引用\r\n private virtualChatModalRef: HTMLPcmVirtualChatModalElement | null = null;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 当模态框关闭时,调用子组件方法停止所有活动\r\n if (this.virtualChatModalRef) {\r\n await this.virtualChatModalRef.setComponentActive(false);\r\n }\r\n // 重置状态\r\n this.resetState();\r\n } else {\r\n await verifyApiKey(this.token);\r\n this.showChatModal = true;\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n \r\n /**\r\n * 重置组件状态\r\n */\r\n private resetState() {\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n this.isSubmitting = false;\r\n this.selectedFile = null;\r\n this.isUploading = false;\r\n this.uploadedFileInfo = null;\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\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 <div>{this.modalTitle}</div>\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 {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n {this.enableVirtualHuman ? (\r\n <pcm-virtual-chat-modal\r\n ref={el => this.virtualChatModalRef = el}\r\n isOpen={true}\r\n fullscreen={this.fullscreen}\r\n botId=\"3022316191018903\"\r\n digitalId={this.digitalId}\r\n openingIndex={this.openingIndex}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n waitingTime={this.waitingTime}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n interview_type: \"1\"\r\n }}\r\n ></pcm-virtual-chat-modal>\r\n ) : (\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n botId=\"3022316191018903\"\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n maxRecordingTime={this.maxRecordingTime}\r\n waitingTime={this.waitingTime}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.uploadedFileInfo?.cos_key,\r\n file_name: this.uploadedFileInfo?.file_name,\r\n }}\r\n interviewMode='video'\r\n ></pcm-app-chat-modal>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",":host {\r\n display: block;\r\n font-size: 16px;\r\n}\r\n\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n overflow-y: auto;\r\n z-index: 1000;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.modal-container {\r\n background: white;\r\n border-radius: 8px;\r\n width: 100%;\r\n max-width: 900px;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* 确保内容区域也使用 flex 布局并占满剩余空间 */\r\n.modal-container.fullscreen > div:not(.modal-header):not(.initial-upload) {\r\n display: flex;\r\n flex-direction: column;\r\n flex: 1;\r\n overflow: hidden;\r\n /* 防止内容溢出 */\r\n height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 800px;\r\n /* height: 80vh; */\r\n /* max-height: 700px; */\r\n min-width: 320px;\r\n min-height: 400px;\r\n}\r\n\r\n.video-preview.placeholder {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n background: #eaeaea;\r\n}\r\n\r\n.placeholder-status {\r\n color: #00000066;\r\n}\r\n\r\n.placeholder-status p {\r\n font-size: 16px;\r\n}\r\n\r\n.waiting-message p {\r\n margin: 0;\r\n font-size: 16px;\r\n color: white;\r\n font-weight: 500;\r\n}\r\n\r\n.recording-container {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n.video-container {\r\n width: 100%;\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: center;\r\n margin-bottom: 20px;\r\n}\r\n\r\n.video-area {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n.stop-recording-button {\r\n width: 100%;\r\n height: 100%;\r\n font-size: 16px;\r\n background: #f44336;\r\n border-radius: 6px;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n}\r\n\r\n.stop-recording-button:hover {\r\n background: #d32f2f;\r\n}\r\n\r\n.play-audio-container {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n /* 防止头部被压缩 */\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.header-left div {\r\n font-size: 16px;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n.chat-container {\r\n background-image: url(https://pub.pincaimao.com/static/web/images/login/bg_login_m.png);\r\n background-size: 100%;\r\n height: 100%;\r\n border-radius: 0px 0px 8px 8px;\r\n}\r\n\r\n.chat-history {\r\n position: relative;\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 20px;\r\n scroll-behavior: smooth;\r\n height: 400px;\r\n}\r\n\r\n/* 添加全屏模式下的样式 */\r\n.fullscreen .chat-history {\r\n height: auto;\r\n flex: 1 1 auto;\r\n}\r\n\r\n.message-input {\r\n padding: 16px;\r\n border-top: 1px solid #eee;\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.message-input input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n outline: none;\r\n transition: border-color 0.2s ease;\r\n}\r\n\r\n.message-input input:focus {\r\n border-color: #bbb;\r\n}\r\n\r\n/* 消息样式 */\r\n.message {\r\n margin-bottom: 16px;\r\n opacity: 1;\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.message-content {\r\n max-width: 70%;\r\n padding: 8px 12px;\r\n border-radius: 8px;\r\n word-break: break-word;\r\n}\r\n\r\n.message-content p {\r\n margin: 0;\r\n word-break: break-word;\r\n}\r\n\r\n.user-message {\r\n display: flex;\r\n justify-content: flex-end;\r\n}\r\n\r\n.agent-message {\r\n display: flex;\r\n justify-content: flex-start;\r\n}\r\n\r\n.user-message .message-content {\r\n background-color: #007bff;\r\n color: white;\r\n}\r\n\r\n.agent-message .message-content {\r\n background-color: #f1f1f1;\r\n}\r\n\r\n.message-time {\r\n font-size: 12px;\r\n color: #999;\r\n margin-top: 4px;\r\n display: block;\r\n}\r\n/** 结束对话按钮 */\r\n.cancel-button {\r\n width: 150px;\r\n height: 38px;\r\n background: #0d75fb;\r\n color: #fff;\r\n border: none;\r\n margin-bottom: 10px;\r\n cursor: pointer;\r\n border-radius: 6px;\r\n}\r\n.cancel-button.disabled {\r\n background: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* 发送按钮样式 */\r\n.send-button {\r\n width: 38px;\r\n height: 38px;\r\n border-radius: 16px;\r\n background: #0d75fb;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: background-color 0.2s ease;\r\n}\r\n\r\n.send-button img {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.send-button:hover {\r\n background: #0a62d6;\r\n}\r\n\r\n.send-button.disabled {\r\n background: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n.empty-state {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n color: #999;\r\n text-align: center;\r\n}\r\n\r\n.loading-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n background-color: rgba(255, 255, 255, 0.98);\r\n z-index: 1;\r\n opacity: 1;\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.loading-container p {\r\n margin-top: 16px;\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 3px solid #f3f3f3;\r\n border-top: 3px solid #1890ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n/* 修改 messages-wrapper 的样式 */\r\n.messages-wrapper {\r\n width: 100%;\r\n min-height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n /* 当内容少时,将内容放在底部 */\r\n justify-content: flex-end;\r\n}\r\n\r\n/* 当有很多消息时,取消固定在底部 */\r\n.messages-wrapper.has-overflow {\r\n justify-content: flex-start;\r\n}\r\n\r\n.suggested-questions {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n padding: 16px;\r\n}\r\n\r\n.suggested-question {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background-color: #f3f4f6;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: #374151;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.suggested-question:hover {\r\n background-color: #e5e7eb;\r\n}\r\n\r\n.arrow-right {\r\n margin-left: 8px;\r\n}\r\n\r\n.loading-suggestions {\r\n display: flex;\r\n justify-content: center;\r\n padding: 16px;\r\n}\r\n\r\n.loading-spinner-small {\r\n width: 20px;\r\n height: 20px;\r\n border: 2px solid #e5e7eb;\r\n border-top-color: #6b7280;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n/* 添加上传按钮样式 */\r\n.upload-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #666;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.upload-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.upload-button svg {\r\n width: 20px;\r\n height: 20px;\r\n}\r\n\r\n/* 隐藏原生文件输入框 */\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n/* 添加文件名显示区域样式 */\r\n.selected-file {\r\n font-size: 12px;\r\n color: #666;\r\n margin-left: 8px;\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n padding: 0 4px;\r\n background: white;\r\n}\r\n\r\n.input-wrapper input {\r\n border: none;\r\n flex: 1;\r\n padding: 8px;\r\n outline: none;\r\n}\r\n\r\n.input-wrapper:focus-within {\r\n border-color: #bbb;\r\n}\r\n\r\n/* 文件预览区域样式 */\r\n.file-preview {\r\n padding: 8px 16px;\r\n border-top: 1px solid #eee;\r\n background-color: #f9f9f9;\r\n}\r\n\r\n.recording-section {\r\n border-top: 1px solid #eee;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 10px 20px 0px 20px;\r\n border-radius: 14px 14px 0 0;\r\n flex: 0 0 auto;\r\n}\r\n\r\n.recording-section .video-preview {\r\n width: 100%;\r\n height: 200px;\r\n max-width: 400px;\r\n position: relative;\r\n margin-bottom: 10px;\r\n border: 1px solid #ddd;\r\n border-radius: 12px;\r\n overflow: hidden;\r\n}\r\n\r\n.recording-section video {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n/* 修改 recording-status 样式 */\r\n.recording-status {\r\n position: absolute;\r\n top: 10px;\r\n left: 10px;\r\n background-color: rgba(0, 0, 0, 0.6);\r\n color: white;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n font-size: 14px;\r\n z-index: 0;\r\n}\r\n\r\n.recording-status .recording-dot {\r\n display: inline-block;\r\n width: 10px;\r\n height: 10px;\r\n background-color: red;\r\n border-radius: 50%;\r\n margin-right: 5px;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n.recording-status.warning {\r\n color: #ff4d4f;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n@keyframes blink {\r\n 0% {\r\n opacity: 1;\r\n }\r\n\r\n 50% {\r\n opacity: 0.5;\r\n }\r\n\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.recording-section .stop-recording-button {\r\n background-color: #f44336;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-weight: bold;\r\n}\r\n\r\n.recording-section .stop-recording-button:hover {\r\n background-color: #d32f2f;\r\n}\r\n\r\n.fullscreen {\r\n width: 100vw;\r\n border-radius: 0;\r\n height: 100vh;\r\n display: flex;\r\n flex-direction: column;\r\n overflow-y: auto;\r\n}\r\n\r\n.recording-controls {\r\n margin-top: 10px;\r\n height: 53px;\r\n width: 100%;\r\n max-width: 400px;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n\r\n.recording-controls .waiting-message {\r\n text-align: center;\r\n color: white;\r\n font-size: 16px;\r\n background-color: #0d75fb;\r\n border-radius: 6px;\r\n width: 95%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n}\r\n\r\n.recording-controls .waiting-message.loading {\r\n background: #faad14;\r\n}\r\n\r\n.recording-controls .waiting-message p {\r\n margin: 0;\r\n font-size: 16px;\r\n color: white;\r\n font-weight: 500;\r\n}\r\n\r\n.recording-controls .stop-recording-button {\r\n background-color: #dc3545;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-size: 16px;\r\n}\r\n\r\n.recording-controls .stop-recording-button:hover {\r\n background-color: #c82333;\r\n}\r\n\r\n/* 添加禁用状态的样式 */\r\n.recording-controls .stop-recording-button.disabled {\r\n background: #ccc;\r\n cursor: not-allowed;\r\n}\r\n\r\n.recording-controls .stop-recording-button.disabled:hover {\r\n background: #ccc;\r\n}\r\n\r\n/* 添加进度条和数字进度的样式 */\r\n.progress-container {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n width: 100%;\r\n max-width: 400px;\r\n margin-top: 10px;\r\n padding: 0 5px;\r\n}\r\n\r\n.progress-bar-container {\r\n height: 4px;\r\n background-color: #e5e5e5;\r\n border-radius: 2px;\r\n overflow: hidden;\r\n margin-right: 10px;\r\n width: 75px;\r\n}\r\n\r\n.progress-bar {\r\n height: 100%;\r\n background-image: linear-gradient(111deg, #4a9fff 0%, #1058ff 100%);\r\n border-radius: 2px;\r\n transition: width 0.3s ease;\r\n}\r\n\r\n.progress-text {\r\n font-size: 14px;\r\n color: #666;\r\n white-space: nowrap;\r\n}\r\n\r\n/* 重新设计文本输入区域样式 */\r\n.text-input-area {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n padding: 0px 16px 16px 16px;\r\n border-radius: 8px;\r\n border: none;\r\n /* 确保容器本身没有边框 */\r\n}\r\n\r\n/* 修改文本输入框样式 */\r\n.text-answer-input {\r\n flex: 1;\r\n min-height: 80px;\r\n padding: 12px 12px 0px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 8px 8px 0 0;\r\n resize: none;\r\n font-size: 16px;\r\n background-color: #fff;\r\n border-bottom: none;\r\n outline: none;\r\n /* 移除默认的焦点轮廓 */\r\n}\r\n\r\n/* 修改工具栏样式 */\r\n.input-toolbar {\r\n display: flex;\r\n justify-content: end;\r\n align-items: center;\r\n padding: 8px 12px;\r\n background-color: #fff;\r\n border: 1px solid #ddd;\r\n border-top: none;\r\n border-radius: 0 0 8px 8px;\r\n}\r\n\r\n/* 当输入框获得焦点时,修改边框颜色 */\r\n.text-answer-input:focus {\r\n border-color: rgb(74, 144, 226);\r\n border-bottom: none;\r\n}\r\n\r\n.text-answer-input:focus + .input-toolbar {\r\n border-color: rgb(74, 144, 226);\r\n border-top: none;\r\n}\r\n\r\n/* 左侧工具按钮区域 */\r\n.toolbar-actions {\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n margin-right: 10px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n}\r\n\r\n.toolbar-actions:hover {\r\n background-color: #f0f0f0;\r\n}\r\n\r\n/* 修改工具按钮样式,确保居中 */\r\n.toolbar-button {\r\n background: transparent;\r\n border: none;\r\n color: #666;\r\n cursor: pointer;\r\n padding: 0;\r\n margin: 0;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n/* 确保按钮内部的内容也居中 */\r\n.toolbar-button > div,\r\n.toolbar-button > svg {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n/* 发送按钮样式 */\r\n.submit-text-button {\r\n padding: 6px 16px;\r\n background-color: #4a90e2;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.submit-text-button:hover:not(.disabled) {\r\n background-color: #3a7bc8;\r\n}\r\n\r\n.submit-text-button.disabled {\r\n background-color: #b3b3b3;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* 语音输入按钮样式 */\r\n.toolbar-button.recording {\r\n background-color: rgba(255, 0, 0, 0.1);\r\n color: #ff3b30;\r\n animation: pulse 1.5s infinite;\r\n}\r\n\r\n.toolbar-button.converting {\r\n background-color: rgba(0, 122, 255, 0.1);\r\n color: #007aff;\r\n}\r\n\r\n.toolbar-button .recording-time {\r\n font-size: 12px;\r\n margin-left: 4px;\r\n}\r\n\r\n.converting-indicator {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.converting-indicator svg {\r\n animation: spin 1.5s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@keyframes pulse {\r\n 0% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.4);\r\n }\r\n\r\n 70% {\r\n box-shadow: 0 0 0 6px rgba(255, 0, 0, 0);\r\n }\r\n\r\n 100% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0);\r\n }\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 0;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 工作区样式 */\r\n.workspace-section {\r\n width: 100%;\r\n padding: 0px 16px 16px;\r\n}\r\n\r\n.workspace-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: end;\r\n gap: 12px;\r\n position: relative;\r\n}\r\n\r\n.workspace-button {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 8px 16px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: white;\r\n color: #666;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.workspace-button:hover {\r\n border-color: #4096ff;\r\n color: #4096ff;\r\n box-shadow: 0 2px 4px rgba(64, 150, 255, 0.1);\r\n}\r\n\r\n.workspace-button svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n/* 结束面试按钮样式 */\r\n.workspace-button.end-interview-button {\r\n background: #ff4d4f;\r\n color: white;\r\n border-color: #ff4d4f;\r\n}\r\n\r\n.workspace-button.end-interview-button:hover:not(:disabled) {\r\n background: #ff7875;\r\n border-color: #ff7875;\r\n color: white;\r\n box-shadow: 0 2px 4px rgba(255, 77, 79, 0.2);\r\n}\r\n\r\n.workspace-button.end-interview-button:disabled {\r\n background: #d9d9d9;\r\n border-color: #d9d9d9;\r\n color: #999;\r\n cursor: not-allowed;\r\n box-shadow: none;\r\n}\r\n\r\n/* 数字人容器样式 */\r\n.digital-human-wrapper {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 120px;\r\n height: 80px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 8px;\r\n background: #fafafa;\r\n overflow: hidden;\r\n position: absolute;\r\n right: 0px;\r\n}\r\n\r\n\r\n/* 历史会话抽屉样式 */\r\n.history-drawer-content {\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.conversation-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 8px 0;\r\n}\r\n\r\n.loading-conversations,\r\n.empty-conversations {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px 20px;\r\n color: #999;\r\n}\r\n\r\n.loading-conversations .loading-spinner-small {\r\n margin-bottom: 12px;\r\n}\r\n\r\n.conversation-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 16px;\r\n margin: 0 8px 4px 8px;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n border: 1px solid transparent;\r\n}\r\n\r\n.conversation-item:hover {\r\n background: #f5f5f5;\r\n}\r\n\r\n.conversation-item.active {\r\n background: #e6f7ff;\r\n border-color: #1890ff;\r\n}\r\n\r\n.conversation-info {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.conversation-title {\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: #262626;\r\n margin-bottom: 4px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.conversation-meta {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 12px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.conversation-time {\r\n flex-shrink: 0;\r\n}\r\n\r\n.message-count {\r\n flex-shrink: 0;\r\n}\r\n\r\n.conversation-status {\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n font-size: 11px;\r\n font-weight: 500;\r\n}\r\n\r\n.conversation-status.completed {\r\n background: #f6ffed;\r\n color: #52c41a;\r\n}\r\n\r\n.conversation-status.running {\r\n background: #fff7e6;\r\n color: #fa8c16;\r\n}\r\n\r\n.current-indicator {\r\n flex-shrink: 0;\r\n color: #1890ff;\r\n margin-left: 8px;\r\n}\r\n","\r\n.markdown-body {\r\n --base-size-4: 4px;\r\n --base-size-8: 8px;\r\n --base-size-16: 16px;\r\n --base-size-24: 24px;\r\n --base-size-40: 40px;\r\n --base-text-weight-normal: 400;\r\n --base-text-weight-medium: 500;\r\n --base-text-weight-semibold: 600;\r\n --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\r\n --fgColor-accent: Highlight;\r\n }\r\n \r\n @media (prefers-color-scheme: dark) {\r\n \r\n .markdown-body,\r\n [data-theme=\"dark\"] {\r\n /* dark */\r\n color-scheme: dark;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n @media (prefers-color-scheme: light) {\r\n \r\n .markdown-body,\r\n [data-theme=\"light\"] {\r\n /* light */\r\n color-scheme: light;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n .markdown-body {\r\n -ms-text-size-adjust: 100%;\r\n -webkit-text-size-adjust: 100%;\r\n margin: 0;\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\";\r\n font-size: 16px;\r\n line-height: 1.5;\r\n word-wrap: break-word;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n fill: currentColor;\r\n vertical-align: text-bottom;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link:before,\r\n .markdown-body h2:hover .anchor .octicon-link:before,\r\n .markdown-body h3:hover .anchor .octicon-link:before,\r\n .markdown-body h4:hover .anchor .octicon-link:before,\r\n .markdown-body h5:hover .anchor .octicon-link:before,\r\n .markdown-body h6:hover .anchor .octicon-link:before {\r\n width: 16px;\r\n height: 16px;\r\n content: ' ';\r\n display: inline-block;\r\n background-color: currentColor;\r\n -webkit-mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n }\r\n \r\n .markdown-body details,\r\n .markdown-body figcaption,\r\n .markdown-body figure {\r\n display: block;\r\n }\r\n \r\n .markdown-body summary {\r\n display: list-item;\r\n }\r\n \r\n .markdown-body [hidden] {\r\n display: none !important;\r\n }\r\n \r\n .markdown-body a {\r\n background-color: transparent;\r\n color: var(--fgColor-accent);\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body abbr[title] {\r\n border-bottom: none;\r\n -webkit-text-decoration: underline dotted;\r\n text-decoration: underline dotted;\r\n }\r\n \r\n .markdown-body b,\r\n .markdown-body strong {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dfn {\r\n font-style: italic;\r\n }\r\n \r\n .markdown-body h1 {\r\n margin: .67em 0;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.5em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body mark {\r\n background-color: var(--bgColor-attention-muted);\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body small {\r\n font-size: 90%;\r\n }\r\n \r\n .markdown-body sub,\r\n .markdown-body sup {\r\n font-size: 75%;\r\n line-height: 0;\r\n position: relative;\r\n vertical-align: baseline;\r\n }\r\n \r\n .markdown-body sub {\r\n bottom: -0.25em;\r\n }\r\n \r\n .markdown-body sup {\r\n top: -0.5em;\r\n }\r\n \r\n .markdown-body img {\r\n border-style: none;\r\n max-width: 100%;\r\n box-sizing: content-box;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body kbd,\r\n .markdown-body pre,\r\n .markdown-body samp {\r\n font-family: monospace;\r\n font-size: 1em;\r\n }\r\n \r\n .markdown-body figure {\r\n margin: 1em var(--base-size-40);\r\n }\r\n \r\n .markdown-body hr {\r\n box-sizing: content-box;\r\n overflow: hidden;\r\n background: transparent;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n height: .25em;\r\n padding: 0;\r\n margin: var(--base-size-24) 0;\r\n background-color: var(--borderColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body input {\r\n font: inherit;\r\n margin: 0;\r\n overflow: visible;\r\n font-family: inherit;\r\n font-size: inherit;\r\n line-height: inherit;\r\n }\r\n \r\n .markdown-body [type=button],\r\n .markdown-body [type=reset],\r\n .markdown-body [type=submit] {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n }\r\n \r\n .markdown-body [type=checkbox],\r\n .markdown-body [type=radio] {\r\n box-sizing: border-box;\r\n padding: 0;\r\n }\r\n \r\n .markdown-body [type=number]::-webkit-inner-spin-button,\r\n .markdown-body [type=number]::-webkit-outer-spin-button {\r\n height: auto;\r\n }\r\n \r\n .markdown-body [type=search]::-webkit-search-cancel-button,\r\n .markdown-body [type=search]::-webkit-search-decoration {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body ::-webkit-input-placeholder {\r\n color: inherit;\r\n opacity: .54;\r\n }\r\n \r\n .markdown-body ::-webkit-file-upload-button {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n font: inherit;\r\n }\r\n \r\n .markdown-body a:hover {\r\n text-decoration: underline;\r\n }\r\n \r\n .markdown-body ::placeholder {\r\n color: var(--fgColor-muted);\r\n opacity: 1;\r\n }\r\n \r\n .markdown-body hr::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body hr::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body table {\r\n border-spacing: 0;\r\n border-collapse: collapse;\r\n display: block;\r\n width: max-content;\r\n max-width: 100%;\r\n overflow: auto;\r\n font-variant: tabular-nums;\r\n }\r\n \r\n .markdown-body td,\r\n .markdown-body th {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body details summary {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body a:focus,\r\n .markdown-body [role=button]:focus,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=checkbox]:focus {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:focus:not(:focus-visible),\r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body input[type=radio]:focus:not(:focus-visible),\r\n .markdown-body input[type=checkbox]:focus:not(:focus-visible) {\r\n outline: solid 1px transparent;\r\n }\r\n \r\n .markdown-body a:focus-visible,\r\n .markdown-body [role=button]:focus-visible,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:not([class]):focus,\r\n .markdown-body a:not([class]):focus-visible,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline-offset: 0;\r\n }\r\n \r\n .markdown-body kbd {\r\n display: inline-block;\r\n padding: var(--base-size-4);\r\n font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n line-height: 10px;\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n background-color: var(--bgColor-muted);\r\n border: solid 1px var(--borderColor-neutral-muted);\r\n border-bottom-color: var(--borderColor-neutral-muted);\r\n border-radius: 6px;\r\n box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted);\r\n }\r\n \r\n .markdown-body h1,\r\n .markdown-body h2,\r\n .markdown-body h3,\r\n .markdown-body h4,\r\n .markdown-body h5,\r\n .markdown-body h6 {\r\n margin-top: var(--base-size-24);\r\n margin-bottom: var(--base-size-16);\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n line-height: 1.25;\r\n }\r\n \r\n .markdown-body h2 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.2em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body h3 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 1.05em;\r\n }\r\n \r\n .markdown-body h4 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 0.875em;\r\n }\r\n \r\n .markdown-body h5 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .85em;\r\n }\r\n \r\n .markdown-body h6 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .80em;\r\n color: var(--fgColor-muted);\r\n }\r\n \r\n .markdown-body p {\r\n margin-top: 0;\r\n margin-bottom: 10px;\r\n }\r\n \r\n .markdown-body blockquote {\r\n margin: 0;\r\n padding: 0 1em;\r\n color: var(--fgColor-muted);\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body ul,\r\n .markdown-body ol {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n padding-left: 2em;\r\n }\r\n \r\n .markdown-body ol ol,\r\n .markdown-body ul ol {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ul ul ol,\r\n .markdown-body ul ol ol,\r\n .markdown-body ol ul ol,\r\n .markdown-body ol ol ol {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body dd {\r\n margin-left: 0;\r\n }\r\n \r\n .markdown-body tt,\r\n .markdown-body code,\r\n .markdown-body samp {\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n }\r\n \r\n .markdown-body pre {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n word-wrap: normal;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n overflow: visible !important;\r\n vertical-align: text-bottom;\r\n fill: currentColor;\r\n }\r\n \r\n .markdown-body input::-webkit-outer-spin-button,\r\n .markdown-body input::-webkit-inner-spin-button {\r\n margin: 0;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body .mr-2 {\r\n margin-right: var(--base-size-8, 8px) !important;\r\n }\r\n \r\n .markdown-body::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body>*:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body>*:last-child {\r\n margin-bottom: 0 !important;\r\n }\r\n \r\n .markdown-body a:not([href]) {\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body .absent {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body .anchor {\r\n float: left;\r\n padding-right: var(--base-size-4);\r\n margin-left: -20px;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .anchor:focus {\r\n outline: none;\r\n }\r\n \r\n .markdown-body p,\r\n .markdown-body blockquote,\r\n .markdown-body ul,\r\n .markdown-body ol,\r\n .markdown-body dl,\r\n .markdown-body table,\r\n .markdown-body pre,\r\n .markdown-body details {\r\n margin-top: 0;\r\n margin-bottom: var(--base-size-16);\r\n font-size: 16px;\r\n font-weight: 400;\r\n }\r\n \r\n .markdown-body blockquote>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body blockquote>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body h1 .octicon-link,\r\n .markdown-body h2 .octicon-link,\r\n .markdown-body h3 .octicon-link,\r\n .markdown-body h4 .octicon-link,\r\n .markdown-body h5 .octicon-link,\r\n .markdown-body h6 .octicon-link {\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n visibility: hidden;\r\n }\r\n \r\n .markdown-body h1:hover .anchor,\r\n .markdown-body h2:hover .anchor,\r\n .markdown-body h3:hover .anchor,\r\n .markdown-body h4:hover .anchor,\r\n .markdown-body h5:hover .anchor,\r\n .markdown-body h6:hover .anchor {\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link,\r\n .markdown-body h2:hover .anchor .octicon-link,\r\n .markdown-body h3:hover .anchor .octicon-link,\r\n .markdown-body h4:hover .anchor .octicon-link,\r\n .markdown-body h5:hover .anchor .octicon-link,\r\n .markdown-body h6:hover .anchor .octicon-link {\r\n visibility: visible;\r\n }\r\n \r\n .markdown-body h1 tt,\r\n .markdown-body h1 code,\r\n .markdown-body h2 tt,\r\n .markdown-body h2 code,\r\n .markdown-body h3 tt,\r\n .markdown-body h3 code,\r\n .markdown-body h4 tt,\r\n .markdown-body h4 code,\r\n .markdown-body h5 tt,\r\n .markdown-body h5 code,\r\n .markdown-body h6 tt,\r\n .markdown-body h6 code {\r\n padding: 0 .2em;\r\n font-size: inherit;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2,\r\n .markdown-body summary h3,\r\n .markdown-body summary h4,\r\n .markdown-body summary h5,\r\n .markdown-body summary h6 {\r\n display: inline-block;\r\n }\r\n \r\n .markdown-body summary h1 .anchor,\r\n .markdown-body summary h2 .anchor,\r\n .markdown-body summary h3 .anchor,\r\n .markdown-body summary h4 .anchor,\r\n .markdown-body summary h5 .anchor,\r\n .markdown-body summary h6 .anchor {\r\n margin-left: -40px;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2 {\r\n padding-bottom: 0;\r\n border-bottom: 0;\r\n }\r\n \r\n .markdown-body ul.no-list,\r\n .markdown-body ol.no-list {\r\n padding: 0;\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body ol[type=\"a s\"] {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"A s\"] {\r\n list-style-type: upper-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"i s\"] {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"I s\"] {\r\n list-style-type: upper-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"1\"] {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body div>ol:not([type]) {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body ul ul,\r\n .markdown-body ul ol,\r\n .markdown-body ol ol,\r\n .markdown-body ol ul {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body li>p {\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body li+li {\r\n margin-top: .25em;\r\n }\r\n \r\n .markdown-body dl {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body dl dt {\r\n padding: 0;\r\n margin-top: var(--base-size-16);\r\n font-size: 1em;\r\n font-style: italic;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dl dd {\r\n padding: 0 var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body table th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body table th,\r\n .markdown-body table td {\r\n padding: 6px 13px;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body table td>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body table tr {\r\n background-color: var(--bgColor-default);\r\n border-top: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body table tr:nth-child(2n) {\r\n background-color: var(--bgColor-muted);\r\n }\r\n \r\n .markdown-body table img {\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body img[align=right] {\r\n padding-left: 20px;\r\n }\r\n \r\n .markdown-body img[align=left] {\r\n padding-right: 20px;\r\n }\r\n \r\n .markdown-body .emoji {\r\n max-width: none;\r\n vertical-align: text-top;\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body span.frame {\r\n display: block;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.frame>span {\r\n display: block;\r\n float: left;\r\n width: auto;\r\n padding: 7px;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body span.frame span img {\r\n display: block;\r\n float: left;\r\n }\r\n \r\n .markdown-body span.frame span span {\r\n display: block;\r\n padding: 5px 0 0;\r\n clear: both;\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body span.align-center {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-center>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-center span img {\r\n margin: 0 auto;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-right {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-right>span {\r\n display: block;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.align-right span img {\r\n margin: 0;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.float-left {\r\n display: block;\r\n float: left;\r\n margin-right: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-left span {\r\n margin: 13px 0 0;\r\n }\r\n \r\n .markdown-body span.float-right {\r\n display: block;\r\n float: right;\r\n margin-left: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-right>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body tt {\r\n padding: .2em .4em;\r\n margin: 0;\r\n font-size: 85%;\r\n white-space: break-spaces;\r\n background-color: var(--bgColor-neutral-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body code br,\r\n .markdown-body tt br {\r\n display: none;\r\n }\r\n \r\n .markdown-body del code {\r\n text-decoration: inherit;\r\n }\r\n \r\n .markdown-body samp {\r\n font-size: 85%;\r\n }\r\n \r\n .markdown-body pre code {\r\n font-size: 100%;\r\n }\r\n \r\n .markdown-body pre>code {\r\n padding: 0;\r\n margin: 0;\r\n word-break: normal;\r\n white-space: pre;\r\n background: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .highlight {\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .highlight pre {\r\n margin-bottom: 0;\r\n word-break: normal;\r\n }\r\n \r\n .markdown-body .highlight pre,\r\n .markdown-body pre {\r\n padding: var(--base-size-16);\r\n overflow: auto;\r\n font-size: 85%;\r\n line-height: 1.45;\r\n color: var(--fgColor-default);\r\n background-color: var(--bgColor-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body pre code,\r\n .markdown-body pre tt {\r\n display: inline;\r\n max-width: auto;\r\n padding: 0;\r\n margin: 0;\r\n overflow: visible;\r\n line-height: inherit;\r\n word-wrap: normal;\r\n background-color: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data td,\r\n .markdown-body .csv-data th {\r\n padding: 5px;\r\n overflow: hidden;\r\n font-size: 12px;\r\n line-height: 1;\r\n text-align: left;\r\n white-space: nowrap;\r\n }\r\n \r\n .markdown-body .csv-data .blob-num {\r\n padding: 10px var(--base-size-8) 9px;\r\n text-align: right;\r\n background: var(--bgColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data tr {\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body .csv-data th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n background: var(--bgColor-muted);\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::before {\r\n content: \"[\";\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::after {\r\n content: \"]\";\r\n }\r\n \r\n .markdown-body .footnotes {\r\n font-size: 12px;\r\n color: var(--fgColor-muted);\r\n border-top: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .footnotes ol {\r\n padding-left: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes ol ul {\r\n display: inline-block;\r\n padding-left: var(--base-size-16);\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes li {\r\n position: relative;\r\n }\r\n \r\n .markdown-body .footnotes li:target::before {\r\n position: absolute;\r\n top: calc(var(--base-size-8)*-1);\r\n right: calc(var(--base-size-8)*-1);\r\n bottom: calc(var(--base-size-8)*-1);\r\n left: calc(var(--base-size-24)*-1);\r\n pointer-events: none;\r\n content: \"\";\r\n border: 2px solid var(--borderColor-accent-emphasis);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body .footnotes li:target {\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body .footnotes .data-footnote-backref g-emoji {\r\n font-family: monospace;\r\n }\r\n \r\n .markdown-body body:has(:modal) {\r\n padding-right: var(--dialog-scrollgutter) !important;\r\n }\r\n \r\n .markdown-body .pl-c {\r\n color: var(--color-prettylights-syntax-comment);\r\n }\r\n \r\n .markdown-body .pl-c1,\r\n .markdown-body .pl-s .pl-v {\r\n color: var(--color-prettylights-syntax-constant);\r\n }\r\n \r\n .markdown-body .pl-e,\r\n .markdown-body .pl-en {\r\n color: var(--color-prettylights-syntax-entity);\r\n }\r\n \r\n .markdown-body .pl-smi,\r\n .markdown-body .pl-s .pl-s1 {\r\n color: var(--color-prettylights-syntax-storage-modifier-import);\r\n }\r\n \r\n .markdown-body .pl-ent {\r\n color: var(--color-prettylights-syntax-entity-tag);\r\n }\r\n \r\n .markdown-body .pl-k {\r\n color: var(--color-prettylights-syntax-keyword);\r\n }\r\n \r\n .markdown-body .pl-s,\r\n .markdown-body .pl-pds,\r\n .markdown-body .pl-s .pl-pse .pl-s1,\r\n .markdown-body .pl-sr,\r\n .markdown-body .pl-sr .pl-cce,\r\n .markdown-body .pl-sr .pl-sre,\r\n .markdown-body .pl-sr .pl-sra {\r\n color: var(--color-prettylights-syntax-string);\r\n }\r\n \r\n .markdown-body .pl-v,\r\n .markdown-body .pl-smw {\r\n color: var(--color-prettylights-syntax-variable);\r\n }\r\n \r\n .markdown-body .pl-bu {\r\n color: var(--color-prettylights-syntax-brackethighlighter-unmatched);\r\n }\r\n \r\n .markdown-body .pl-ii {\r\n color: var(--color-prettylights-syntax-invalid-illegal-text);\r\n background-color: var(--color-prettylights-syntax-invalid-illegal-bg);\r\n }\r\n \r\n .markdown-body .pl-c2 {\r\n color: var(--color-prettylights-syntax-carriage-return-text);\r\n background-color: var(--color-prettylights-syntax-carriage-return-bg);\r\n }\r\n \r\n .markdown-body .pl-sr .pl-cce {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-string-regexp);\r\n }\r\n \r\n .markdown-body .pl-ml {\r\n color: var(--color-prettylights-syntax-markup-list);\r\n }\r\n \r\n .markdown-body .pl-mh,\r\n .markdown-body .pl-mh .pl-en,\r\n .markdown-body .pl-ms {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-heading);\r\n }\r\n \r\n .markdown-body .pl-mi {\r\n font-style: italic;\r\n color: var(--color-prettylights-syntax-markup-italic);\r\n }\r\n \r\n .markdown-body .pl-mb {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-bold);\r\n }\r\n \r\n .markdown-body .pl-md {\r\n color: var(--color-prettylights-syntax-markup-deleted-text);\r\n background-color: var(--color-prettylights-syntax-markup-deleted-bg);\r\n }\r\n \r\n .markdown-body .pl-mi1 {\r\n color: var(--color-prettylights-syntax-markup-inserted-text);\r\n background-color: var(--color-prettylights-syntax-markup-inserted-bg);\r\n }\r\n \r\n .markdown-body .pl-mc {\r\n color: var(--color-prettylights-syntax-markup-changed-text);\r\n background-color: var(--color-prettylights-syntax-markup-changed-bg);\r\n }\r\n \r\n .markdown-body .pl-mi2 {\r\n color: var(--color-prettylights-syntax-markup-ignored-text);\r\n background-color: var(--color-prettylights-syntax-markup-ignored-bg);\r\n }\r\n \r\n .markdown-body .pl-mdr {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-meta-diff-range);\r\n }\r\n \r\n .markdown-body .pl-ba {\r\n color: var(--color-prettylights-syntax-brackethighlighter-angle);\r\n }\r\n \r\n .markdown-body .pl-sg {\r\n color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);\r\n }\r\n \r\n .markdown-body .pl-corl {\r\n text-decoration: underline;\r\n color: var(--color-prettylights-syntax-constant-other-reference-link);\r\n }\r\n \r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body [role=tabpanel][tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body button:focus:not(:focus-visible),\r\n .markdown-body summary:focus:not(:focus-visible),\r\n .markdown-body a:focus:not(:focus-visible) {\r\n outline: none;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body [tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body details-dialog:focus:not(:focus-visible) {\r\n outline: none;\r\n }\r\n \r\n .markdown-body g-emoji {\r\n display: inline-block;\r\n min-width: 1ch;\r\n font-family: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\r\n font-size: 1em;\r\n font-style: normal !important;\r\n font-weight: var(--base-text-weight-normal, 400);\r\n line-height: 1;\r\n vertical-align: -0.075em;\r\n }\r\n \r\n .markdown-body g-emoji img {\r\n width: 1em;\r\n height: 1em;\r\n }\r\n \r\n .markdown-body .task-list-item {\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body .task-list-item label {\r\n font-weight: var(--base-text-weight-normal, 400);\r\n }\r\n \r\n .markdown-body .task-list-item.enabled label {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body .task-list-item+.task-list-item {\r\n margin-top: var(--base-size-4);\r\n }\r\n \r\n .markdown-body .task-list-item .handle {\r\n display: none;\r\n }\r\n \r\n .markdown-body .task-list-item-checkbox {\r\n margin: 0 .2em .25em -1.4em;\r\n vertical-align: middle;\r\n }\r\n \r\n .markdown-body ul:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body ol:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body .contains-task-list:hover .task-list-item-convert-container,\r\n .markdown-body .contains-task-list:focus-within .task-list-item-convert-container {\r\n display: block;\r\n width: auto;\r\n height: 24px;\r\n overflow: visible;\r\n clip: auto;\r\n }\r\n \r\n .markdown-body ::-webkit-calendar-picker-indicator {\r\n filter: invert(50%);\r\n }\r\n \r\n .markdown-body .markdown-alert {\r\n padding: var(--base-size-8) var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n color: inherit;\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .markdown-alert>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert .markdown-alert-title {\r\n display: flex;\r\n font-weight: var(--base-text-weight-medium, 500);\r\n align-items: center;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note {\r\n border-left-color: var(--borderColor-accent-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title {\r\n color: var(--fgColor-accent);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important {\r\n border-left-color: var(--borderColor-done-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title {\r\n color: var(--fgColor-done);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning {\r\n border-left-color: var(--borderColor-attention-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title {\r\n color: var(--fgColor-attention);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip {\r\n border-left-color: var(--borderColor-success-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title {\r\n color: var(--fgColor-success);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution {\r\n border-left-color: var(--borderColor-danger-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body>*:first-child>.heading-element:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body .highlight pre:has(+.zeroclipboard-container) {\r\n min-height: 52px;\r\n }",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",":host {\r\n display: inline-block;\r\n}\r\n\r\n.pcm-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-weight: 400;\r\n white-space: nowrap;\r\n text-align: center;\r\n background-image: none;\r\n border: 1px solid transparent;\r\n cursor: pointer;\r\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\r\n user-select: none;\r\n touch-action: manipulation;\r\n height: 32px;\r\n padding: 0 15px;\r\n font-size: 14px;\r\n border-radius: 4px;\r\n color: rgba(0, 0, 0, 0.85);\r\n background-color: white;\r\n border-color: #d9d9d9;\r\n outline: none;\r\n}\r\n\r\n.pcm-button:hover {\r\n border-color: #40a9ff;\r\n color: #40a9ff;\r\n}\r\n\r\n.pcm-button:active {\r\n border-color: #096dd9;\r\n color: #096dd9;\r\n}\r\n\r\n/* 按钮类型样式 */\r\n.pcm-button-default {\r\n background-color: white;\r\n border-color: #d9d9d9;\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.pcm-button-primary {\r\n background-color: #1677FF;\r\n border-color: #1677FF;\r\n color: white;\r\n}\r\n\r\n.pcm-button-primary:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n color: white;\r\n}\r\n\r\n.pcm-button-primary:active {\r\n background-color: #096dd9;\r\n border-color: #096dd9;\r\n color: white;\r\n}\r\n\r\n.pcm-button-dashed {\r\n background-color: white;\r\n border-color: #d9d9d9;\r\n border-style: dashed;\r\n}\r\n\r\n.pcm-button-text {\r\n background-color: transparent;\r\n border-color: transparent;\r\n color: rgba(0, 0, 0, 0.85);\r\n box-shadow: none;\r\n}\r\n\r\n.pcm-button-text:hover {\r\n background-color: rgba(0, 0, 0, 0.05);\r\n border-color: transparent;\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.pcm-button-link {\r\n background-color: transparent;\r\n border-color: transparent;\r\n color: #1677FF;\r\n box-shadow: none;\r\n}\r\n\r\n.pcm-button-link:hover {\r\n color: #40a9ff;\r\n background-color: transparent;\r\n border-color: transparent;\r\n}\r\n\r\n/* 按钮尺寸样式 */\r\n.pcm-button-large {\r\n height: 40px;\r\n padding: 0 20px;\r\n font-size: 16px;\r\n}\r\n\r\n.pcm-button-small {\r\n height: 24px;\r\n padding: 0 7px;\r\n font-size: 12px;\r\n}\r\n\r\n/* 按钮形状样式 */\r\n.pcm-button-circle {\r\n min-width: 32px;\r\n padding: 0;\r\n border-radius: 50%;\r\n}\r\n\r\n.pcm-button-large.pcm-button-circle {\r\n min-width: 40px;\r\n}\r\n\r\n.pcm-button-small.pcm-button-circle {\r\n min-width: 24px;\r\n}\r\n\r\n.pcm-button-round {\r\n border-radius: 40px;\r\n}\r\n\r\n/* 按钮加载状态样式 */\r\n.pcm-button-loading {\r\n opacity: 0.65;\r\n cursor: default;\r\n}\r\n\r\n.loading-icon {\r\n width: 14px;\r\n height: 14px;\r\n margin-right: 8px;\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: loading-spin 1s infinite linear;\r\n display: inline-block;\r\n}\r\n\r\n@keyframes loading-spin {\r\n 0% { \r\n transform: rotate(0deg); \r\n }\r\n 100% { \r\n transform: rotate(360deg); \r\n }\r\n}\r\n\r\n/* 按钮禁用状态样式 */\r\n.pcm-button-disabled {\r\n cursor: not-allowed;\r\n opacity: 0.65;\r\n}\r\n\r\n.pcm-button-disabled:hover,\r\n.pcm-button-disabled:active {\r\n color: rgba(0, 0, 0, 0.25);\r\n background-color: #f5f5f5;\r\n border-color: #d9d9d9;\r\n}\r\n\r\n.pcm-button-primary.pcm-button-disabled:hover,\r\n.pcm-button-primary.pcm-button-disabled:active {\r\n background-color: #1677FF;\r\n border-color: #1677FF;\r\n color: white;\r\n}\r\n\r\n/* 图标样式 */\r\n.button-icon {\r\n margin-right: 8px;\r\n display: inline-flex;\r\n align-items: center;\r\n}\r\n\r\n.button-icon img {\r\n width: 16px;\r\n height: 16px;\r\n}\r\n\r\n.pcm-button-small .button-icon img {\r\n width: 12px;\r\n height: 12px;\r\n}\r\n\r\n.pcm-button-large .button-icon img {\r\n width: 18px;\r\n height: 18px;\r\n}\r\n\r\n/* 块级按钮样式 */\r\n.pcm-button-block {\r\n width: 100%;\r\n display: flex;\r\n}\r\n",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h} from '@stencil/core';\r\n\r\n/**\r\n * 按钮组件\r\n * 一个简化版的类似于 ant-design 的按钮组件,支持自定义文字、颜色、圆角等属性\r\n */\r\n@Component({\r\n tag: 'pcm-button',\r\n styleUrls: ['pcm-button.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmButton {\r\n /**\r\n * 按钮类型\r\n * 可选值: 'primary', 'default', 'dashed', 'text', 'link'\r\n */\r\n @Prop() type: 'primary' | 'default' | 'dashed' | 'text' | 'link' = 'default';\r\n\r\n /**\r\n * 按钮尺寸\r\n * 可选值: 'large', 'middle', 'small'\r\n */\r\n @Prop() size: 'large' | 'middle' | 'small' = 'middle';\r\n\r\n /**\r\n * 是否为加载状态\r\n */\r\n @Prop() loading: boolean = false;\r\n\r\n /**\r\n * 是否为禁用状态\r\n */\r\n @Prop() disabled: boolean = false;\r\n\r\n /**\r\n * 设置按钮的图标\r\n * 使用图标的URL或者base64字符串\r\n */\r\n @Prop() icon: string = 'https://pub.pincaimao.com/static/common/i_pcm_logo.png';\r\n\r\n\r\n /**\r\n * 自定义按钮形状\r\n * 可选值: 'default', 'circle', 'round'\r\n */\r\n @Prop() shape: 'default' | 'circle' | 'round' = 'default';\r\n\r\n /**\r\n * 自定义按钮背景色\r\n */\r\n @Prop() backgroundColor: string = '';\r\n\r\n /**\r\n * 自定义按钮文字颜色\r\n */\r\n @Prop() textColor: string = '';\r\n\r\n /**\r\n * 自定义按钮边框颜色\r\n */\r\n @Prop() borderColor: string = '';\r\n\r\n /**\r\n * 自定义按钮圆角大小(像素)\r\n */\r\n @Prop() borderRadius: number = null;\r\n\r\n /**\r\n * 按钮宽度(像素或百分比)\r\n */\r\n @Prop() width: string = '';\r\n\r\n /**\r\n * 是否为块级按钮(宽度撑满父元素)\r\n */\r\n @Prop() block: boolean = false;\r\n\r\n /**\r\n * 按钮边框样式\r\n * 可选值: 'solid', 'dashed', 'dotted', 'none'\r\n */\r\n @Prop() borderStyle: 'solid' | 'dashed' | 'dotted' | 'none' = 'solid';\r\n\r\n render() {\r\n // 计算样式类名\r\n const classes = {\r\n 'pcm-button': true,\r\n [`pcm-button-${this.type}`]: true,\r\n [`pcm-button-${this.size}`]: true,\r\n [`pcm-button-${this.shape}`]: true,\r\n 'pcm-button-loading': this.loading,\r\n 'pcm-button-disabled': this.disabled,\r\n 'pcm-button-block': this.block\r\n };\r\n\r\n // 计算自定义样式\r\n const customStyle = {};\r\n if (this.backgroundColor) {\r\n customStyle['backgroundColor'] = this.backgroundColor;\r\n }\r\n if (this.textColor) {\r\n customStyle['color'] = this.textColor;\r\n }\r\n if (this.borderColor) {\r\n customStyle['borderColor'] = this.borderColor;\r\n }\r\n if (this.borderRadius !== null) {\r\n customStyle['borderRadius'] = `${this.borderRadius}px`;\r\n }\r\n if (this.width) {\r\n customStyle['width'] = this.width;\r\n }\r\n if (this.borderStyle) {\r\n customStyle['borderStyle'] = this.borderStyle;\r\n }\r\n\r\n return (\r\n <button\r\n class={Object.keys(classes).filter(key => classes[key]).join(' ')}\r\n style={customStyle}\r\n disabled={this.disabled}\r\n type=\"button\"\r\n >\r\n {this.loading && (\r\n <span class=\"loading-icon\"></span>\r\n )}\r\n {this.icon && !this.loading && (\r\n <span class=\"button-icon\">\r\n <img src={this.icon} alt=\"\" />\r\n </span>\r\n )}\r\n <slot />\r\n </button>\r\n );\r\n }\r\n}\r\n",":host {\r\n display: block;\r\n}\r\n\r\n/* 加载和错误状态样式 */\r\n.loading-container,\r\n.error-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 200px;\r\n width: 100%;\r\n color: #86909C;\r\n font-size: 14px;\r\n text-align: center;\r\n}\r\n\r\n.loading-spinner {\r\n width: 32px;\r\n height: 32px;\r\n border: 3px solid #f3f3f3;\r\n border-top: 3px solid #1677FF;\r\n border-radius: 50%;\r\n margin-bottom: 12px;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n}\r\n\r\n.error-icon {\r\n width: 32px;\r\n height: 32px;\r\n background-color: #FFF0F0;\r\n color: #F53F3F;\r\n border-radius: 50%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 20px;\r\n font-weight: bold;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.error-message {\r\n color: #86909C;\r\n max-width: 80%;\r\n}\r\n\r\n.card-container {\r\n border-radius: 8px;\r\n padding: 16px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n display: flex;\r\n flex-direction: column;\r\n background-color: #ffffff;\r\n border: 1px solid #E5E6EB;\r\n position: relative;\r\n height: 100%;\r\n min-width: 300px;\r\n}\r\n\r\n.card-container:hover {\r\n transform: translateY(-2px);\r\n box-shadow: 0 4px 16px rgba(0, 21, 41, 0.08);\r\n}\r\n\r\n.card-header {\r\n display: flex;\r\n width: 100%;\r\n padding-bottom: 16px;\r\n gap: 12px;\r\n}\r\n\r\n.card-icon {\r\n width: 64px;\r\n height: 64px;\r\n margin-right: 12px;\r\n flex-shrink: 0;\r\n overflow: hidden;\r\n border-radius: 2px;\r\n background-color: #f8f9fa;\r\n}\r\n\r\n.card-icon img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: contain;\r\n}\r\n\r\n.card-info {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n.title-row {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.title-wrapper {\r\n flex: 1;\r\n margin-right: 8px;\r\n overflow: hidden;\r\n}\r\n\r\n.card-title {\r\n font-size: 18px;\r\n font-weight: 700;\r\n color: #1D2129;\r\n line-height: 24px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n display: block;\r\n width: 100%;\r\n}\r\n\r\n.chat-tag {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 24px;\r\n padding: 0 8px;\r\n background-color: #F2F7E8;\r\n color: #56961F;\r\n font-size: 12px;\r\n border-radius: 4px;\r\n font-weight: 500;\r\n flex-shrink: 0;\r\n}\r\n\r\n.author-row {\r\n display: flex;\r\n align-items: center;\r\n margin-top: 8px;\r\n}\r\n\r\n.author-avatar {\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n margin-right: 4px;\r\n background-color: #f8f9fa;\r\n overflow: hidden;\r\n}\r\n\r\n.author-name {\r\n font-size: 12px;\r\n color: #86909C;\r\n}\r\n\r\n.card-description {\r\n font-size: 12px;\r\n color: #86909C;\r\n margin-top: 8px;\r\n line-height: 18px;\r\n height: 54px;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 3;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: pre-line;\r\n word-break: break-word;\r\n}\r\n\r\n.card-footer {\r\n padding-top: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n border-top: 1px solid #E5E6EB;\r\n}\r\n\r\n.stats-container {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n}\r\n\r\n.stat-item {\r\n display: flex;\r\n align-items: center;\r\n margin-right: 8px;\r\n color: #86909C;\r\n}\r\n\r\n.stat-icon {\r\n width: 16px;\r\n height: 16px;\r\n margin-right: 4px;\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n background-size: contain;\r\n}\r\n\r\n.user-icon {\r\n /* 为图标添加SVG背景 */\r\n background-image: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' focusable='false' aria-hidden='true'%3E%3Cpath d='M12 14c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6Zm0-10C9.8 4 8 5.8 8 8s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4Z' fill='currentColor'%3E%3C/path%3E%3Cpath d='M21.9 20.6c-.1-.2-2.3-5.6-9.9-5.6-7.6 0-9.8 5.4-9.9 5.6-.2.5 0 1.1.6 1.3.5.2 1.1 0 1.3-.5 0-.2 1.8-4.4 8-4.4s8 4.2 8.1 4.4c.2.5.8.8 1.3.5.5-.2.7-.8.5-1.3Z' fill='currentColor'%3E%3C/path%3E%3C/svg%3E\");\r\n}\r\n\r\n.star-icon {\r\n /* 为图标添加SVG背景 */\r\n background-image: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' focusable='false' aria-hidden='true'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 5.03 9.57 9.1c-.17.3-.46.5-.8.55l-4.3.79 3 3.46c.22.26.32.6.28.93l-.62 4.46 4.41-1.9c.3-.12.63-.12.92 0l4.4 1.9-.6-4.46c-.05-.34.05-.67.27-.93l3-3.46-4.3-.79a1.17 1.17 0 0 1-.8-.55L12 5.03Zm-1-2.46a1.16 1.16 0 0 1 2 0l3.03 5.07 5.51 1c.89.17 1.26 1.24.68 1.92l-3.8 4.4.77 5.71c.13.9-.78 1.6-1.61 1.23L12 19.5l-5.58 2.4a1.17 1.17 0 0 1-1.61-1.23l.78-5.7-3.8-4.4a1.17 1.17 0 0 1 .67-1.92l5.51-1L11 2.56Z' fill='currentColor'%3E%3C/path%3E%3C/svg%3E\");\r\n}\r\n\r\n.video-icon {\r\n /* 为图标添加SVG背景 */\r\n background-image: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' focusable='false' aria-hidden='true'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H4Zm0 2h16v16H4V4Zm5.5 3.13A1 1 0 0 0 8 8v8a1 1 0 0 0 1.5.87l7-4a1 1 0 0 0 0-1.74l-7-4ZM13.98 12 10 14.28V9.72L13.98 12Z' fill='currentColor'%3E%3C/path%3E%3C/svg%3E\");\r\n}\r\n\r\n.stat-value {\r\n font-size: 12px;\r\n}\r\n\r\n.use-button {\r\n font-size: 12px;\r\n color: #86909C;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n}\r\n\r\n.use-button:hover {\r\n color: #1677FF;\r\n}\r\n\r\n/* 响应式样式 */\r\n@media screen and (max-width: 768px) {\r\n .card-container {\r\n padding: 12px;\r\n }\r\n \r\n .card-header {\r\n gap: 8px;\r\n padding-bottom: 12px;\r\n }\r\n \r\n .card-icon {\r\n width: 48px;\r\n height: 48px;\r\n }\r\n \r\n .card-title {\r\n font-size: 16px;\r\n line-height: 20px;\r\n }\r\n \r\n .card-description {\r\n font-size: 12px;\r\n line-height: 16px;\r\n height: 48px;\r\n }\r\n} ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Watch,Event, EventEmitter } from '@stencil/core';\r\nimport { sendHttpRequest } from '../../utils/utils';\r\nimport { authStore } from '../../../store/auth.store';\r\n\r\n/**\r\n * 智能体卡片组件\r\n * 用于展示各业务功能入口,点击后根据回调打开对应的模态框\r\n */\r\n@Component({\r\n tag: 'pcm-card',\r\n styleUrls: ['pcm-card.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmCard {\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: string;\r\n /**\r\n * 自定义卡片标题\r\n */\r\n @Prop() cardTitle: string = '';\r\n\r\n /**\r\n * 自定义卡片描述\r\n */\r\n @Prop() description: string = '';\r\n\r\n /**\r\n * 自定义卡片图标URL\r\n */\r\n @Prop() iconUrl: string = '';\r\n\r\n\r\n /**\r\n * 自定义作者名称\r\n */\r\n @Prop() author: string = '';\r\n\r\n /**\r\n * 自定义作者头像URL\r\n */\r\n @Prop() authorAvatarUrl: string = '';\r\n\r\n /**\r\n * 是否显示右侧对话标签\r\n */\r\n @Prop() showChatTag: boolean = false;\r\n\r\n /**\r\n * 自定义右侧标签\r\n */\r\n @Prop() customChatTag: string = '';\r\n\r\n /**\r\n * 自定义立即使用按钮文本\r\n */\r\n @Prop() useButtonText: string = '立即使用';\r\n\r\n /**\r\n * 智能体ID\r\n */\r\n @Prop() botId: string = '';\r\n\r\n /**\r\n * 内部状态:用于存储从接口获取的智能体数据\r\n */\r\n @State() botData: any = null;\r\n\r\n /**\r\n * 内部状态:加载状态\r\n */\r\n @State() loading: boolean = false;\r\n\r\n /**\r\n * 内部状态:错误信息\r\n */\r\n @State() error: string = '';\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n private tokenInvalidListener: () => void;\r\n\r\n /**\r\n * 监听 botId 变化,当 botId 改变时重新获取数据\r\n */\r\n @Watch('botId')\r\n watchBotIdHandler(newValue: string) {\r\n if (newValue) {\r\n this.fetchBotData();\r\n }\r\n }\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n /**\r\n * 组件将要加载时,如果有 botId 则获取数据\r\n */\r\n componentWillLoad() {\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n if (this.botId) {\r\n this.fetchBotData();\r\n }\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n\r\n /**\r\n * 获取机器人数据\r\n */\r\n private async fetchBotData() {\r\n if (!this.botId) return;\r\n\r\n this.loading = true;\r\n this.error = '';\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `/sdk/v1/agent/${this.botId}/info`,\r\n method: 'GET',\r\n });\r\n\r\n if (response.success && response.data) {\r\n this.botData = response.data;\r\n } else {\r\n throw new Error(response.message || '获取智能体信息失败');\r\n }\r\n } catch (err) {\r\n this.error = err.message || '获取智能体信息失败';\r\n console.error('获取智能体信息失败:', err);\r\n } finally {\r\n this.loading = false;\r\n }\r\n }\r\n\r\n render() {\r\n // 从 botData 中获取信息,如果用户传入的属性存在则优先使用用户传入的\r\n const title = this.cardTitle || (this.botData?.title || '');\r\n const desc = this.description || (this.botData?.description || '');\r\n // 处理图标,可能会在不同属性中\r\n const iconFromBot = this.botData?.icon || this.botData?.iconUrl || this.botData?.logo || '';\r\n const icon = this.iconUrl || iconFromBot;\r\n\r\n const authorName = this.author || (this.botData?.author_name || '');\r\n const authorAvatar = this.authorAvatarUrl || (this.botData?.author_avatar || '');\r\n const hasChatTag = this.customChatTag || (this.botData?.flag || '');\r\n const usersCount = this.botData?.use_count || 0;\r\n const starsCount = this.botData?.follow_count || 0;\r\n const usageCount = this.botData?.view_count || 0;\r\n\r\n console.log('渲染数据:', {\r\n title,\r\n icon,\r\n iconFromBot,\r\n userIconUrl: this.iconUrl,\r\n botData: this.botData,\r\n authorName,\r\n authorAvatar\r\n });\r\n\r\n return (\r\n <div\r\n class=\"card-container\"\r\n >\r\n {this.loading ? (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <div>加载中...</div>\r\n </div>\r\n ) : this.error ? (\r\n <div class=\"error-container\">\r\n <div class=\"error-icon\">!</div>\r\n <div class=\"error-message\">{this.error}</div>\r\n </div>\r\n ) : (\r\n <div>\r\n <div class=\"card-header\">\r\n {icon && (\r\n <div class=\"card-icon\">\r\n <img src={icon} alt={title} />\r\n </div>\r\n )}\r\n <div class=\"card-info\">\r\n <div class=\"title-row\">\r\n <div class=\"title-wrapper\">\r\n <div class=\"card-title\">{title}</div>\r\n </div>\r\n {this.showChatTag && hasChatTag && <div class=\"chat-tag\">{hasChatTag}</div>}\r\n </div>\r\n\r\n {authorName && (\r\n <div class=\"author-row\">\r\n {authorAvatar && (\r\n <img class=\"author-avatar\" src={authorAvatar} alt={authorName} />\r\n )}\r\n <div class=\"author-name\">{authorName}</div>\r\n </div>\r\n )}\r\n\r\n {desc && (\r\n <div class=\"card-description\">{desc}</div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-footer\">\r\n <div class=\"stats-container\">\r\n <div class=\"stat-item\">\r\n <span class=\"stat-icon user-icon\"></span>\r\n <div class=\"stat-value\">{usersCount}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <span class=\"stat-icon star-icon\"></span>\r\n <div class=\"stat-value\">{starsCount}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <span class=\"stat-icon video-icon\"></span>\r\n <div class=\"stat-value\">{usageCount}</div>\r\n </div>\r\n </div>\r\n <div class=\"use-button\">{this.useButtonText || '立即使用'}</div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n} ","\r\n.markdown-body {\r\n --base-size-4: 4px;\r\n --base-size-8: 8px;\r\n --base-size-16: 16px;\r\n --base-size-24: 24px;\r\n --base-size-40: 40px;\r\n --base-text-weight-normal: 400;\r\n --base-text-weight-medium: 500;\r\n --base-text-weight-semibold: 600;\r\n --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\r\n --fgColor-accent: Highlight;\r\n }\r\n \r\n @media (prefers-color-scheme: dark) {\r\n \r\n .markdown-body,\r\n [data-theme=\"dark\"] {\r\n /* dark */\r\n color-scheme: dark;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n @media (prefers-color-scheme: light) {\r\n \r\n .markdown-body,\r\n [data-theme=\"light\"] {\r\n /* light */\r\n color-scheme: light;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n .markdown-body {\r\n -ms-text-size-adjust: 100%;\r\n -webkit-text-size-adjust: 100%;\r\n margin: 0;\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\";\r\n font-size: 16px;\r\n line-height: 1.5;\r\n word-wrap: break-word;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n fill: currentColor;\r\n vertical-align: text-bottom;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link:before,\r\n .markdown-body h2:hover .anchor .octicon-link:before,\r\n .markdown-body h3:hover .anchor .octicon-link:before,\r\n .markdown-body h4:hover .anchor .octicon-link:before,\r\n .markdown-body h5:hover .anchor .octicon-link:before,\r\n .markdown-body h6:hover .anchor .octicon-link:before {\r\n width: 16px;\r\n height: 16px;\r\n content: ' ';\r\n display: inline-block;\r\n background-color: currentColor;\r\n -webkit-mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n }\r\n \r\n .markdown-body details,\r\n .markdown-body figcaption,\r\n .markdown-body figure {\r\n display: block;\r\n }\r\n \r\n .markdown-body summary {\r\n display: list-item;\r\n }\r\n \r\n .markdown-body [hidden] {\r\n display: none !important;\r\n }\r\n \r\n .markdown-body a {\r\n background-color: transparent;\r\n color: var(--fgColor-accent);\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body abbr[title] {\r\n border-bottom: none;\r\n -webkit-text-decoration: underline dotted;\r\n text-decoration: underline dotted;\r\n }\r\n \r\n .markdown-body b,\r\n .markdown-body strong {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dfn {\r\n font-style: italic;\r\n }\r\n \r\n .markdown-body h1 {\r\n margin: .67em 0;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.5em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body mark {\r\n background-color: var(--bgColor-attention-muted);\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body small {\r\n font-size: 90%;\r\n }\r\n \r\n .markdown-body sub,\r\n .markdown-body sup {\r\n font-size: 75%;\r\n line-height: 0;\r\n position: relative;\r\n vertical-align: baseline;\r\n }\r\n \r\n .markdown-body sub {\r\n bottom: -0.25em;\r\n }\r\n \r\n .markdown-body sup {\r\n top: -0.5em;\r\n }\r\n \r\n .markdown-body img {\r\n border-style: none;\r\n max-width: 100%;\r\n box-sizing: content-box;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body kbd,\r\n .markdown-body pre,\r\n .markdown-body samp {\r\n font-family: monospace;\r\n font-size: 1em;\r\n }\r\n \r\n .markdown-body figure {\r\n margin: 1em var(--base-size-40);\r\n }\r\n \r\n .markdown-body hr {\r\n box-sizing: content-box;\r\n overflow: hidden;\r\n background: transparent;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n height: .25em;\r\n padding: 0;\r\n margin: var(--base-size-24) 0;\r\n background-color: var(--borderColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body input {\r\n font: inherit;\r\n margin: 0;\r\n overflow: visible;\r\n font-family: inherit;\r\n font-size: inherit;\r\n line-height: inherit;\r\n }\r\n \r\n .markdown-body [type=button],\r\n .markdown-body [type=reset],\r\n .markdown-body [type=submit] {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n }\r\n \r\n .markdown-body [type=checkbox],\r\n .markdown-body [type=radio] {\r\n box-sizing: border-box;\r\n padding: 0;\r\n }\r\n \r\n .markdown-body [type=number]::-webkit-inner-spin-button,\r\n .markdown-body [type=number]::-webkit-outer-spin-button {\r\n height: auto;\r\n }\r\n \r\n .markdown-body [type=search]::-webkit-search-cancel-button,\r\n .markdown-body [type=search]::-webkit-search-decoration {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body ::-webkit-input-placeholder {\r\n color: inherit;\r\n opacity: .54;\r\n }\r\n \r\n .markdown-body ::-webkit-file-upload-button {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n font: inherit;\r\n }\r\n \r\n .markdown-body a:hover {\r\n text-decoration: underline;\r\n }\r\n \r\n .markdown-body ::placeholder {\r\n color: var(--fgColor-muted);\r\n opacity: 1;\r\n }\r\n \r\n .markdown-body hr::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body hr::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body table {\r\n border-spacing: 0;\r\n border-collapse: collapse;\r\n display: block;\r\n width: max-content;\r\n max-width: 100%;\r\n overflow: auto;\r\n font-variant: tabular-nums;\r\n }\r\n \r\n .markdown-body td,\r\n .markdown-body th {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body details summary {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body a:focus,\r\n .markdown-body [role=button]:focus,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=checkbox]:focus {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:focus:not(:focus-visible),\r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body input[type=radio]:focus:not(:focus-visible),\r\n .markdown-body input[type=checkbox]:focus:not(:focus-visible) {\r\n outline: solid 1px transparent;\r\n }\r\n \r\n .markdown-body a:focus-visible,\r\n .markdown-body [role=button]:focus-visible,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:not([class]):focus,\r\n .markdown-body a:not([class]):focus-visible,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline-offset: 0;\r\n }\r\n \r\n .markdown-body kbd {\r\n display: inline-block;\r\n padding: var(--base-size-4);\r\n font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n line-height: 10px;\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n background-color: var(--bgColor-muted);\r\n border: solid 1px var(--borderColor-neutral-muted);\r\n border-bottom-color: var(--borderColor-neutral-muted);\r\n border-radius: 6px;\r\n box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted);\r\n }\r\n \r\n .markdown-body h1,\r\n .markdown-body h2,\r\n .markdown-body h3,\r\n .markdown-body h4,\r\n .markdown-body h5,\r\n .markdown-body h6 {\r\n margin-top: var(--base-size-24);\r\n margin-bottom: var(--base-size-16);\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n line-height: 1.25;\r\n }\r\n \r\n .markdown-body h2 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.2em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body h3 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 1.05em;\r\n }\r\n \r\n .markdown-body h4 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 0.875em;\r\n }\r\n \r\n .markdown-body h5 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .85em;\r\n }\r\n \r\n .markdown-body h6 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .80em;\r\n color: var(--fgColor-muted);\r\n }\r\n \r\n .markdown-body p {\r\n margin-top: 0;\r\n margin-bottom: 10px;\r\n }\r\n \r\n .markdown-body blockquote {\r\n margin: 0;\r\n padding: 0 1em;\r\n color: var(--fgColor-muted);\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body ul,\r\n .markdown-body ol {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n padding-left: 2em;\r\n }\r\n \r\n .markdown-body ol ol,\r\n .markdown-body ul ol {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ul ul ol,\r\n .markdown-body ul ol ol,\r\n .markdown-body ol ul ol,\r\n .markdown-body ol ol ol {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body dd {\r\n margin-left: 0;\r\n }\r\n \r\n .markdown-body tt,\r\n .markdown-body code,\r\n .markdown-body samp {\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n }\r\n \r\n .markdown-body pre {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n word-wrap: normal;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n overflow: visible !important;\r\n vertical-align: text-bottom;\r\n fill: currentColor;\r\n }\r\n \r\n .markdown-body input::-webkit-outer-spin-button,\r\n .markdown-body input::-webkit-inner-spin-button {\r\n margin: 0;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body .mr-2 {\r\n margin-right: var(--base-size-8, 8px) !important;\r\n }\r\n \r\n .markdown-body::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body>*:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body>*:last-child {\r\n margin-bottom: 0 !important;\r\n }\r\n \r\n .markdown-body a:not([href]) {\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body .absent {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body .anchor {\r\n float: left;\r\n padding-right: var(--base-size-4);\r\n margin-left: -20px;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .anchor:focus {\r\n outline: none;\r\n }\r\n \r\n .markdown-body p,\r\n .markdown-body blockquote,\r\n .markdown-body ul,\r\n .markdown-body ol,\r\n .markdown-body dl,\r\n .markdown-body table,\r\n .markdown-body pre,\r\n .markdown-body details {\r\n margin-top: 0;\r\n margin-bottom: var(--base-size-16);\r\n font-size: 16px;\r\n font-weight: 400;\r\n }\r\n \r\n .markdown-body blockquote>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body blockquote>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body h1 .octicon-link,\r\n .markdown-body h2 .octicon-link,\r\n .markdown-body h3 .octicon-link,\r\n .markdown-body h4 .octicon-link,\r\n .markdown-body h5 .octicon-link,\r\n .markdown-body h6 .octicon-link {\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n visibility: hidden;\r\n }\r\n \r\n .markdown-body h1:hover .anchor,\r\n .markdown-body h2:hover .anchor,\r\n .markdown-body h3:hover .anchor,\r\n .markdown-body h4:hover .anchor,\r\n .markdown-body h5:hover .anchor,\r\n .markdown-body h6:hover .anchor {\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link,\r\n .markdown-body h2:hover .anchor .octicon-link,\r\n .markdown-body h3:hover .anchor .octicon-link,\r\n .markdown-body h4:hover .anchor .octicon-link,\r\n .markdown-body h5:hover .anchor .octicon-link,\r\n .markdown-body h6:hover .anchor .octicon-link {\r\n visibility: visible;\r\n }\r\n \r\n .markdown-body h1 tt,\r\n .markdown-body h1 code,\r\n .markdown-body h2 tt,\r\n .markdown-body h2 code,\r\n .markdown-body h3 tt,\r\n .markdown-body h3 code,\r\n .markdown-body h4 tt,\r\n .markdown-body h4 code,\r\n .markdown-body h5 tt,\r\n .markdown-body h5 code,\r\n .markdown-body h6 tt,\r\n .markdown-body h6 code {\r\n padding: 0 .2em;\r\n font-size: inherit;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2,\r\n .markdown-body summary h3,\r\n .markdown-body summary h4,\r\n .markdown-body summary h5,\r\n .markdown-body summary h6 {\r\n display: inline-block;\r\n }\r\n \r\n .markdown-body summary h1 .anchor,\r\n .markdown-body summary h2 .anchor,\r\n .markdown-body summary h3 .anchor,\r\n .markdown-body summary h4 .anchor,\r\n .markdown-body summary h5 .anchor,\r\n .markdown-body summary h6 .anchor {\r\n margin-left: -40px;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2 {\r\n padding-bottom: 0;\r\n border-bottom: 0;\r\n }\r\n \r\n .markdown-body ul.no-list,\r\n .markdown-body ol.no-list {\r\n padding: 0;\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body ol[type=\"a s\"] {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"A s\"] {\r\n list-style-type: upper-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"i s\"] {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"I s\"] {\r\n list-style-type: upper-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"1\"] {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body div>ol:not([type]) {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body ul ul,\r\n .markdown-body ul ol,\r\n .markdown-body ol ol,\r\n .markdown-body ol ul {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body li>p {\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body li+li {\r\n margin-top: .25em;\r\n }\r\n \r\n .markdown-body dl {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body dl dt {\r\n padding: 0;\r\n margin-top: var(--base-size-16);\r\n font-size: 1em;\r\n font-style: italic;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dl dd {\r\n padding: 0 var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body table th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body table th,\r\n .markdown-body table td {\r\n padding: 6px 13px;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body table td>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body table tr {\r\n background-color: var(--bgColor-default);\r\n border-top: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body table tr:nth-child(2n) {\r\n background-color: var(--bgColor-muted);\r\n }\r\n \r\n .markdown-body table img {\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body img[align=right] {\r\n padding-left: 20px;\r\n }\r\n \r\n .markdown-body img[align=left] {\r\n padding-right: 20px;\r\n }\r\n \r\n .markdown-body .emoji {\r\n max-width: none;\r\n vertical-align: text-top;\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body span.frame {\r\n display: block;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.frame>span {\r\n display: block;\r\n float: left;\r\n width: auto;\r\n padding: 7px;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body span.frame span img {\r\n display: block;\r\n float: left;\r\n }\r\n \r\n .markdown-body span.frame span span {\r\n display: block;\r\n padding: 5px 0 0;\r\n clear: both;\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body span.align-center {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-center>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-center span img {\r\n margin: 0 auto;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-right {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-right>span {\r\n display: block;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.align-right span img {\r\n margin: 0;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.float-left {\r\n display: block;\r\n float: left;\r\n margin-right: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-left span {\r\n margin: 13px 0 0;\r\n }\r\n \r\n .markdown-body span.float-right {\r\n display: block;\r\n float: right;\r\n margin-left: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-right>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body tt {\r\n padding: .2em .4em;\r\n margin: 0;\r\n font-size: 85%;\r\n white-space: break-spaces;\r\n background-color: var(--bgColor-neutral-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body code br,\r\n .markdown-body tt br {\r\n display: none;\r\n }\r\n \r\n .markdown-body del code {\r\n text-decoration: inherit;\r\n }\r\n \r\n .markdown-body samp {\r\n font-size: 85%;\r\n }\r\n \r\n .markdown-body pre code {\r\n font-size: 100%;\r\n }\r\n \r\n .markdown-body pre>code {\r\n padding: 0;\r\n margin: 0;\r\n word-break: normal;\r\n white-space: pre;\r\n background: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .highlight {\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .highlight pre {\r\n margin-bottom: 0;\r\n word-break: normal;\r\n }\r\n \r\n .markdown-body .highlight pre,\r\n .markdown-body pre {\r\n padding: var(--base-size-16);\r\n overflow: auto;\r\n font-size: 85%;\r\n line-height: 1.45;\r\n color: var(--fgColor-default);\r\n background-color: var(--bgColor-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body pre code,\r\n .markdown-body pre tt {\r\n display: inline;\r\n max-width: auto;\r\n padding: 0;\r\n margin: 0;\r\n overflow: visible;\r\n line-height: inherit;\r\n word-wrap: normal;\r\n background-color: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data td,\r\n .markdown-body .csv-data th {\r\n padding: 5px;\r\n overflow: hidden;\r\n font-size: 12px;\r\n line-height: 1;\r\n text-align: left;\r\n white-space: nowrap;\r\n }\r\n \r\n .markdown-body .csv-data .blob-num {\r\n padding: 10px var(--base-size-8) 9px;\r\n text-align: right;\r\n background: var(--bgColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data tr {\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body .csv-data th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n background: var(--bgColor-muted);\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::before {\r\n content: \"[\";\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::after {\r\n content: \"]\";\r\n }\r\n \r\n .markdown-body .footnotes {\r\n font-size: 12px;\r\n color: var(--fgColor-muted);\r\n border-top: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .footnotes ol {\r\n padding-left: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes ol ul {\r\n display: inline-block;\r\n padding-left: var(--base-size-16);\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes li {\r\n position: relative;\r\n }\r\n \r\n .markdown-body .footnotes li:target::before {\r\n position: absolute;\r\n top: calc(var(--base-size-8)*-1);\r\n right: calc(var(--base-size-8)*-1);\r\n bottom: calc(var(--base-size-8)*-1);\r\n left: calc(var(--base-size-24)*-1);\r\n pointer-events: none;\r\n content: \"\";\r\n border: 2px solid var(--borderColor-accent-emphasis);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body .footnotes li:target {\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body .footnotes .data-footnote-backref g-emoji {\r\n font-family: monospace;\r\n }\r\n \r\n .markdown-body body:has(:modal) {\r\n padding-right: var(--dialog-scrollgutter) !important;\r\n }\r\n \r\n .markdown-body .pl-c {\r\n color: var(--color-prettylights-syntax-comment);\r\n }\r\n \r\n .markdown-body .pl-c1,\r\n .markdown-body .pl-s .pl-v {\r\n color: var(--color-prettylights-syntax-constant);\r\n }\r\n \r\n .markdown-body .pl-e,\r\n .markdown-body .pl-en {\r\n color: var(--color-prettylights-syntax-entity);\r\n }\r\n \r\n .markdown-body .pl-smi,\r\n .markdown-body .pl-s .pl-s1 {\r\n color: var(--color-prettylights-syntax-storage-modifier-import);\r\n }\r\n \r\n .markdown-body .pl-ent {\r\n color: var(--color-prettylights-syntax-entity-tag);\r\n }\r\n \r\n .markdown-body .pl-k {\r\n color: var(--color-prettylights-syntax-keyword);\r\n }\r\n \r\n .markdown-body .pl-s,\r\n .markdown-body .pl-pds,\r\n .markdown-body .pl-s .pl-pse .pl-s1,\r\n .markdown-body .pl-sr,\r\n .markdown-body .pl-sr .pl-cce,\r\n .markdown-body .pl-sr .pl-sre,\r\n .markdown-body .pl-sr .pl-sra {\r\n color: var(--color-prettylights-syntax-string);\r\n }\r\n \r\n .markdown-body .pl-v,\r\n .markdown-body .pl-smw {\r\n color: var(--color-prettylights-syntax-variable);\r\n }\r\n \r\n .markdown-body .pl-bu {\r\n color: var(--color-prettylights-syntax-brackethighlighter-unmatched);\r\n }\r\n \r\n .markdown-body .pl-ii {\r\n color: var(--color-prettylights-syntax-invalid-illegal-text);\r\n background-color: var(--color-prettylights-syntax-invalid-illegal-bg);\r\n }\r\n \r\n .markdown-body .pl-c2 {\r\n color: var(--color-prettylights-syntax-carriage-return-text);\r\n background-color: var(--color-prettylights-syntax-carriage-return-bg);\r\n }\r\n \r\n .markdown-body .pl-sr .pl-cce {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-string-regexp);\r\n }\r\n \r\n .markdown-body .pl-ml {\r\n color: var(--color-prettylights-syntax-markup-list);\r\n }\r\n \r\n .markdown-body .pl-mh,\r\n .markdown-body .pl-mh .pl-en,\r\n .markdown-body .pl-ms {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-heading);\r\n }\r\n \r\n .markdown-body .pl-mi {\r\n font-style: italic;\r\n color: var(--color-prettylights-syntax-markup-italic);\r\n }\r\n \r\n .markdown-body .pl-mb {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-bold);\r\n }\r\n \r\n .markdown-body .pl-md {\r\n color: var(--color-prettylights-syntax-markup-deleted-text);\r\n background-color: var(--color-prettylights-syntax-markup-deleted-bg);\r\n }\r\n \r\n .markdown-body .pl-mi1 {\r\n color: var(--color-prettylights-syntax-markup-inserted-text);\r\n background-color: var(--color-prettylights-syntax-markup-inserted-bg);\r\n }\r\n \r\n .markdown-body .pl-mc {\r\n color: var(--color-prettylights-syntax-markup-changed-text);\r\n background-color: var(--color-prettylights-syntax-markup-changed-bg);\r\n }\r\n \r\n .markdown-body .pl-mi2 {\r\n color: var(--color-prettylights-syntax-markup-ignored-text);\r\n background-color: var(--color-prettylights-syntax-markup-ignored-bg);\r\n }\r\n \r\n .markdown-body .pl-mdr {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-meta-diff-range);\r\n }\r\n \r\n .markdown-body .pl-ba {\r\n color: var(--color-prettylights-syntax-brackethighlighter-angle);\r\n }\r\n \r\n .markdown-body .pl-sg {\r\n color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);\r\n }\r\n \r\n .markdown-body .pl-corl {\r\n text-decoration: underline;\r\n color: var(--color-prettylights-syntax-constant-other-reference-link);\r\n }\r\n \r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body [role=tabpanel][tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body button:focus:not(:focus-visible),\r\n .markdown-body summary:focus:not(:focus-visible),\r\n .markdown-body a:focus:not(:focus-visible) {\r\n outline: none;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body [tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body details-dialog:focus:not(:focus-visible) {\r\n outline: none;\r\n }\r\n \r\n .markdown-body g-emoji {\r\n display: inline-block;\r\n min-width: 1ch;\r\n font-family: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\r\n font-size: 1em;\r\n font-style: normal !important;\r\n font-weight: var(--base-text-weight-normal, 400);\r\n line-height: 1;\r\n vertical-align: -0.075em;\r\n }\r\n \r\n .markdown-body g-emoji img {\r\n width: 1em;\r\n height: 1em;\r\n }\r\n \r\n .markdown-body .task-list-item {\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body .task-list-item label {\r\n font-weight: var(--base-text-weight-normal, 400);\r\n }\r\n \r\n .markdown-body .task-list-item.enabled label {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body .task-list-item+.task-list-item {\r\n margin-top: var(--base-size-4);\r\n }\r\n \r\n .markdown-body .task-list-item .handle {\r\n display: none;\r\n }\r\n \r\n .markdown-body .task-list-item-checkbox {\r\n margin: 0 .2em .25em -1.4em;\r\n vertical-align: middle;\r\n }\r\n \r\n .markdown-body ul:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body ol:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body .contains-task-list:hover .task-list-item-convert-container,\r\n .markdown-body .contains-task-list:focus-within .task-list-item-convert-container {\r\n display: block;\r\n width: auto;\r\n height: 24px;\r\n overflow: visible;\r\n clip: auto;\r\n }\r\n \r\n .markdown-body ::-webkit-calendar-picker-indicator {\r\n filter: invert(50%);\r\n }\r\n \r\n .markdown-body .markdown-alert {\r\n padding: var(--base-size-8) var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n color: inherit;\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .markdown-alert>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert .markdown-alert-title {\r\n display: flex;\r\n font-weight: var(--base-text-weight-medium, 500);\r\n align-items: center;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note {\r\n border-left-color: var(--borderColor-accent-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title {\r\n color: var(--fgColor-accent);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important {\r\n border-left-color: var(--borderColor-done-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title {\r\n color: var(--fgColor-done);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning {\r\n border-left-color: var(--borderColor-attention-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title {\r\n color: var(--fgColor-attention);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip {\r\n border-left-color: var(--borderColor-success-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title {\r\n color: var(--fgColor-success);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution {\r\n border-left-color: var(--borderColor-danger-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body>*:first-child>.heading-element:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body .highlight pre:has(+.zeroclipboard-container) {\r\n min-height: 52px;\r\n }",":host {\r\n display: block;\r\n width: 100%;\r\n}\r\n\r\n.message-round {\r\n margin-bottom: 16px;\r\n width: 100%;\r\n}\r\n\r\n.user-message-container {\r\n display: flex;\r\n flex-direction: row-reverse;\r\n align-items: flex-start;\r\n margin-bottom: 15px;\r\n position: relative;\r\n}\r\n\r\n.assistant-message-container {\r\n display: flex;\r\n flex-direction: row;\r\n align-items: flex-start;\r\n margin-bottom: 15px;\r\n position: relative;\r\n}\r\n\r\n/* 添加消息气泡样式 */\r\n.message-bubble {\r\n max-width: 85%;\r\n position: relative;\r\n}\r\n\r\n/* 用户消息气泡样式 */\r\n.user-message {\r\n padding: 5px 10px;\r\n background: #f5f7ff;\r\n font-size: 14px;\r\n color: #1F2328;\r\n border-radius: 6px;\r\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n/* 助手消息气泡样式 */\r\n.assistant-message {\r\n padding: 15px 10px;\r\n background-color: #fff;\r\n border-radius: 6px;\r\n font-size: 14px;\r\n color: #1F2328;\r\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.message-time {\r\n font-size: 12px;\r\n color: #999;\r\n margin-top: 4px;\r\n}\r\n\r\n/* 用户消息时间样式 */\r\n.user-message-container .message-time {\r\n color: rgba(255, 255, 255, 0.7);\r\n}\r\n\r\n.loading-dots {\r\n display: flex;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background-color: #f0f0f0;\r\n border-radius: 18px;\r\n border-top-left-radius: 4px;\r\n}\r\n\r\n.loading-dots span {\r\n width: 8px;\r\n height: 8px;\r\n margin: 0 3px;\r\n background-color: #999;\r\n border-radius: 50%;\r\n display: inline-block;\r\n animation: dot-pulse 1.5s infinite ease-in-out;\r\n}\r\n\r\n.loading-dots span:nth-child(2) {\r\n animation-delay: 0.2s;\r\n}\r\n\r\n.loading-dots span:nth-child(3) {\r\n animation-delay: 0.4s;\r\n}\r\n\r\n@keyframes dot-pulse {\r\n\r\n 0%,\r\n 80%,\r\n 100% {\r\n transform: scale(0.8);\r\n opacity: 0.5;\r\n }\r\n\r\n 40% {\r\n transform: scale(1.2);\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.file-view {\r\n margin-top: 8px;\r\n padding: 12px;\r\n background-color: #f8f9fa;\r\n border: 1px solid #e9ecef;\r\n border-radius: 6px;\r\n font-size: 14px;\r\n word-break: break-all;\r\n color: #2c3e50;\r\n line-height: 1.5;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.input-view {\r\n margin-top: 8px;\r\n margin-bottom: 10px;\r\n padding-bottom: 10px;\r\n border: 1px solid #e9ecef;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n background-color: #ffffff;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n\r\n.input-label-container {\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 4px;\r\n background-color: #f8f9fa;\r\n border-bottom: 1px solid #e9ecef;\r\n padding: 8px 12px;\r\n}\r\n\r\n.copy-input-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 2px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #8c8c8c;\r\n opacity: 0.7;\r\n transition: opacity 0.2s ease;\r\n margin-left: 5px;\r\n}\r\n\r\n.copy-input-button:hover {\r\n opacity: 1;\r\n color: #1677ff;\r\n}\r\n\r\n.input-label {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #495057;\r\n}\r\n\r\n.input-value {\r\n padding: 12px 12px 0px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n color: #2c3e50;\r\n background-color: #ffffff;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.input-metadata {\r\n font-size: 13px;\r\n margin-top: 8px;\r\n}\r\n\r\n/* 基本的消息操作按钮位置 */\r\n.message-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n transition: opacity 0.2s ease;\r\n margin-top: 15px;\r\n}\r\n\r\n\r\n.action-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n padding: 4px 15px;\r\n font-size: 14px;\r\n height: 32px;\r\n background-color: white;\r\n cursor: pointer;\r\n color: rgba(0, 0, 0, 0.88);\r\n transition: all 0.2s;\r\n}\r\n\r\n.action-button:hover {\r\n color: #1677ff;\r\n border-color: #1677ff;\r\n}\r\n\r\n.action-button.primary {\r\n color: #1677ff;\r\n border-color: #1677ff;\r\n}\r\n\r\n.action-button.primary:hover {\r\n color: #4096ff;\r\n border-color: #4096ff;\r\n}\r\n\r\n.action-button.icon-only {\r\n padding: 4px 8px;\r\n margin-right: 9px;\r\n}\r\n\r\n.button-icon {\r\n margin-right: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.icon-only .button-icon {\r\n margin-right: 0;\r\n}\r\n\r\n.file-list {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 12px;\r\n margin-top: 8px;\r\n}\r\n\r\n.file-item {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n width: 80px;\r\n cursor: pointer;\r\n padding: 8px;\r\n border-radius: 4px;\r\n transition: background-color 0.3s;\r\n margin: 5px 10px;\r\n}\r\n\r\n.file-item:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.file-icon {\r\n margin-bottom: 4px;\r\n}\r\n\r\n.file-name {\r\n font-size: 12px;\r\n text-align: center;\r\n width: 100%;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n color: #8B4513;\r\n}\r\n\r\n.action-button.active {\r\n color: #1677ff;\r\n background-color: rgba(22, 119, 255, 0.1);\r\n}\r\n\r\n.action-button.active .button-icon svg {\r\n stroke: #1677ff;\r\n}\r\n\r\n.inputs-container {\r\n margin-top: 8px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n\r\n.file-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.file-item {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 12px;\r\n background-color: #f5f5f5;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.file-item:hover {\r\n background-color: #e8e8e8;\r\n}\r\n\r\n.file-icon {\r\n margin-right: 8px;\r\n}\r\n\r\n.file-name {\r\n font-size: 14px;\r\n color: #333;\r\n word-break: break-word;\r\n}\r\n\r\n.input-view {\r\n background-color: #f9f9f9;\r\n border-radius: 8px;\r\n padding: 12px;\r\n border: 1px solid #e8e8e8;\r\n}\r\n\r\n.input-label-container {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.input-label {\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.input-value {\r\n color: #666;\r\n line-height: 1.5;\r\n word-break: break-word;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n}\r\n\r\n.copy-input-button {\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n color: #1677ff;\r\n padding: 4px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.copy-input-button:hover {\r\n background-color: rgba(22, 119, 255, 0.1);\r\n}\r\n\r\n.input-metadata {\r\n font-size: 14px;\r\n color: #666;\r\n padding: 4px 0;\r\n}\r\n\r\n/* 文件卡片样式 */\r\n.file-card {\r\n display: flex;\r\n align-items: center;\r\n padding: 12px;\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 200px 100px no-repeat, #fff;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n border: 1px solid #e8e8e8;\r\n margin-top: 8px;\r\n}\r\n\r\n.file-card:hover {\r\n background-color: #f0f0f0;\r\n}\r\n\r\n.file-card-icon {\r\n margin-right: 12px;\r\n flex-shrink: 0;\r\n border-radius: 12px;\r\n background: #0d75fb;\r\n width: 48px;\r\n height: 48px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.file-card-icon img {\r\n width: 40px;\r\n height: 40px;\r\n}\r\n\r\n.file-card-content {\r\n display: flex;\r\n flex-direction: column;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.file-card-type {\r\n font-size: 14px;\r\n color: #8c8c8c;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.file-card-name {\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: #333;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n width: 100%;\r\n}\r\n\r\n/* 复制按钮样式 */\r\n.copy-card-button {\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n color: #8c8c8c;\r\n padding: 8px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n transition: color 0.2s;\r\n}\r\n\r\n.copy-card-button:hover {\r\n color: #1677ff;\r\n}\r\n\r\n.avatar {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n overflow: hidden;\r\n flex-shrink: 0;\r\n}\r\n\r\n.avatar img {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n\r\n.user-avatar {\r\n margin-left: 8px;\r\n}\r\n\r\n.assistant-avatar {\r\n margin-right: 8px;\r\n}\r\n\r\n.retry-button {\r\n background-color: #ff6b35 !important;\r\n color: white !important;\r\n border: none !important;\r\n}\r\n\r\n.retry-button:hover {\r\n background-color: #e55a2b !important;\r\n}\r\n\r\n.retry-button .button-icon {\r\n margin-right: 4px;\r\n}\r\n\r\n/* 视频容器样式 */\r\n.video-inputs-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: end;\r\n}\r\n\r\n.video-container {\r\n margin-top: 0px;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n background-color: #000;\r\n width: 250px;\r\n height: auto;\r\n max-height: 250px;\r\n transition: transform 0.2s ease, box-shadow 0.2s ease;\r\n}\r\n\r\n.video-container:hover {\r\n transform: translateY(-2px);\r\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);\r\n}\r\n\r\n.video-container video {\r\n display: block;\r\n width: 100%;\r\n max-width: 500px;\r\n height: auto;\r\n border-radius: 8px;\r\n}\r\n\r\n.video-container video:focus {\r\n outline: none;\r\n}\r\n\r\n/* 视频加载状态样式 */\r\n.video-loading {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.loading-spinner {\r\n width: 24px;\r\n height: 24px;\r\n border: 2px solid #e9ecef;\r\n border-top: 2px solid #1677ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 12px;\r\n}\r\n\r\n@keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n}\r\n\r\n/* 响应式设计 */\r\n@media (max-width: 768px) {\r\n .video-container {\r\n width: 100%;\r\n max-width: 300px;\r\n }\r\n}",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",":host {\r\n display: block;\r\n}\r\n\r\n.confirm-modal-container {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 0;\r\n height: 0;\r\n overflow: visible;\r\n}\r\n\r\n.confirm-modal-mask {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.45);\r\n opacity: 0;\r\n visibility: hidden;\r\n transition: opacity 0.3s ease, visibility 0.3s ease;\r\n}\r\n\r\n.mask-visible {\r\n opacity: 1;\r\n visibility: visible;\r\n}\r\n\r\n.confirm-modal-content {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: 20px;\r\n opacity: 0;\r\n visibility: hidden;\r\n transition: opacity 0.3s ease, visibility 0.3s ease;\r\n}\r\n\r\n.confirm-modal-content.centered {\r\n align-items: center;\r\n}\r\n\r\n.modal-content-visible {\r\n opacity: 1;\r\n visibility: visible;\r\n}\r\n\r\n.modal-wrapper {\r\n background: white;\r\n border-radius: 8px;\r\n width: 100%;\r\n max-width: 400px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n overflow: hidden;\r\n transform: scale(0.9) translateY(-20px);\r\n transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1);\r\n}\r\n\r\n.modal-content-visible .modal-wrapper {\r\n transform: scale(1) translateY(0);\r\n}\r\n\r\n.modal-header {\r\n padding: 16px 24px;\r\n border-bottom: 1px solid #f0f0f0;\r\n background: #fff;\r\n}\r\n\r\n.modal-title {\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n margin: 0;\r\n line-height: 1.5;\r\n}\r\n\r\n.modal-body {\r\n padding: 24px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n color: rgba(0, 0, 0, 0.65);\r\n}\r\n\r\n.modal-footer {\r\n padding: 10px 16px;\r\n text-align: right;\r\n background: transparent;\r\n border-top: 1px solid #f0f0f0;\r\n border-radius: 0 0 8px 8px;\r\n}\r\n\r\n.modal-button {\r\n line-height: 1.5;\r\n position: relative;\r\n display: inline-block;\r\n font-weight: 400;\r\n white-space: nowrap;\r\n text-align: center;\r\n border: 1px solid transparent;\r\n cursor: pointer;\r\n transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);\r\n user-select: none;\r\n touch-action: manipulation;\r\n height: 32px;\r\n padding: 4px 15px;\r\n font-size: 14px;\r\n border-radius: 6px;\r\n outline: 0;\r\n margin-left: 8px;\r\n}\r\n\r\n.cancel-button {\r\n color: rgba(0, 0, 0, 0.65);\r\n border-color: #d9d9d9;\r\n background: #fff;\r\n}\r\n\r\n.cancel-button:hover {\r\n color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.cancel-button:active {\r\n color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n.ok-button {\r\n color: #fff;\r\n background: #1890ff;\r\n border-color: #1890ff;\r\n}\r\n\r\n.ok-button:hover {\r\n background: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.ok-button:active {\r\n background: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n.ok-primary {\r\n background: #1890ff;\r\n border-color: #1890ff;\r\n}\r\n\r\n.ok-primary:hover {\r\n background: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.ok-primary:active {\r\n background: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n.ok-danger {\r\n background: #ff4d4f;\r\n border-color: #ff4d4f;\r\n}\r\n\r\n.ok-danger:hover {\r\n background: #ff7875;\r\n border-color: #ff7875;\r\n}\r\n\r\n.ok-danger:active {\r\n background: #d9363e;\r\n border-color: #d9363e;\r\n}\r\n\r\n.ok-default {\r\n color: rgba(0, 0, 0, 0.65);\r\n background: #fff;\r\n border-color: #d9d9d9;\r\n}\r\n\r\n.ok-default:hover {\r\n color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.ok-default:active {\r\n color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .confirm-modal-content {\r\n padding: 16px;\r\n }\r\n \r\n .confirm-modal-content.centered {\r\n padding: 16px;\r\n }\r\n \r\n .modal-wrapper {\r\n max-width: none;\r\n margin: 0 auto;\r\n }\r\n \r\n .modal-header {\r\n padding: 12px 16px;\r\n }\r\n \r\n .modal-title {\r\n font-size: 16px;\r\n }\r\n \r\n .modal-body {\r\n padding: 16px;\r\n }\r\n \r\n .modal-footer {\r\n padding: 8px 12px 12px;\r\n }\r\n \r\n .modal-button {\r\n height: 36px;\r\n font-size: 16px;\r\n margin-left: 8px;\r\n margin-top: 8px;\r\n }\r\n}\r\n\r\n/* 无障碍支持 */\r\n@media (prefers-reduced-motion: reduce) {\r\n .confirm-modal-mask,\r\n .confirm-modal-content,\r\n .modal-wrapper,\r\n .modal-button {\r\n transition: none;\r\n }\r\n} ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, Event, EventEmitter, Watch, Method, Element, State } from '@stencil/core';\r\nimport { configStore } from '../../../store/config.store';\r\n\r\n/**\r\n * 确认模态框组件\r\n * 通用的确认对话框组件,类似 Ant Design 的 Modal 组件\r\n */\r\n@Component({\r\n tag: 'pcm-confirm-modal',\r\n styleUrls: ['pcm-confirm-modal.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmConfirmModal {\r\n /**\r\n * 模态框是否可见\r\n */\r\n @Prop({ mutable: true, reflect: true }) isOpen: boolean = false;\r\n\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '确认';\r\n\r\n /**\r\n * 确认按钮文本\r\n */\r\n @Prop() okText: string = '确认';\r\n\r\n /**\r\n * 取消按钮文本\r\n */\r\n @Prop() cancelText: string = '取消';\r\n\r\n /**\r\n * 确认按钮类型\r\n */\r\n @Prop() okType: 'default' | 'primary' | 'danger' = 'primary';\r\n\r\n /**\r\n * 点击蒙层是否允许关闭\r\n */\r\n @Prop() maskClosable: boolean = true;\r\n\r\n /**\r\n * 是否显示蒙层\r\n */\r\n @Prop() mask: boolean = true;\r\n\r\n /**\r\n * 是否居中显示\r\n */\r\n @Prop() centered: boolean = true;\r\n\r\n /**\r\n * 确认按钮点击事件\r\n */\r\n @Event() ok: EventEmitter<void>;\r\n\r\n /**\r\n * 取消按钮点击事件\r\n */\r\n @Event() cancel: EventEmitter<void>;\r\n\r\n /**\r\n * 模态框关闭后的回调\r\n */\r\n @Event() closed: EventEmitter<void>;\r\n\r\n /**\r\n * 模态框打开后的回调\r\n */\r\n @Event() afterOpen: EventEmitter<void>;\r\n\r\n /**\r\n * 模态框关闭后的回调\r\n */\r\n @Event() afterClose: EventEmitter<void>;\r\n\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() zIndex: number = 2000;\r\n\r\n private bodyOverflowBeforeOpen: string = '';\r\n private transitionEndHandler: () => void;\r\n\r\n /**\r\n * 打开模态框\r\n */\r\n @Method()\r\n async open() {\r\n this.isOpen = true;\r\n }\r\n\r\n /**\r\n * 关闭模态框\r\n */\r\n @Method()\r\n async close() {\r\n this.isOpen = false;\r\n }\r\n\r\n @Watch('isOpen')\r\n visibleChanged(newValue: boolean) {\r\n if (newValue) {\r\n // 打开模态框时,禁止背景滚动\r\n this.bodyOverflowBeforeOpen = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n \r\n // 添加过渡结束事件监听器\r\n const modal = this.hostElement.shadowRoot.querySelector('.modal-wrapper') as HTMLElement;\r\n if (modal) {\r\n this.transitionEndHandler = () => {\r\n this.afterOpen.emit();\r\n };\r\n modal.addEventListener('transitionend', this.transitionEndHandler, { once: true });\r\n }\r\n } else {\r\n // 关闭模态框时,恢复背景滚动\r\n document.body.style.overflow = this.bodyOverflowBeforeOpen;\r\n \r\n // 添加过渡结束事件监听器\r\n const modal = this.hostElement.shadowRoot.querySelector('.modal-wrapper') as HTMLElement;\r\n if (modal) {\r\n this.transitionEndHandler = () => {\r\n this.afterClose.emit();\r\n };\r\n modal.addEventListener('transitionend', this.transitionEndHandler, { once: true });\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 尝试从缓存中读取 zIndex\r\n const cachedZIndex = configStore.getItem<number>('modal-zIndex');\r\n if (cachedZIndex) {\r\n this.zIndex = cachedZIndex + 1000; // 确保比其他模态框更高\r\n }\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件卸载时恢复背景滚动\r\n if (this.isOpen) {\r\n document.body.style.overflow = this.bodyOverflowBeforeOpen;\r\n }\r\n \r\n // 移除事件监听器\r\n const modal = this.hostElement.shadowRoot?.querySelector('.modal-wrapper') as HTMLElement;\r\n if (modal && this.transitionEndHandler) {\r\n modal.removeEventListener('transitionend', this.transitionEndHandler);\r\n }\r\n }\r\n\r\n private handleMaskClick = () => {\r\n if (this.maskClosable) {\r\n this.handleCancel();\r\n }\r\n };\r\n\r\n private handleOk = () => {\r\n this.ok.emit();\r\n };\r\n\r\n private handleCancel = () => {\r\n this.cancel.emit();\r\n this.isOpen = false;\r\n this.closed.emit();\r\n };\r\n\r\n render() {\r\n const modalStyle = {\r\n zIndex: `${this.zIndex + 1}`,\r\n };\r\n\r\n const maskStyle = {\r\n zIndex: `${this.zIndex}`,\r\n };\r\n\r\n const containerClass = {\r\n 'confirm-modal-container': true,\r\n 'modal-open': this.isOpen\r\n };\r\n\r\n const contentClass = {\r\n 'confirm-modal-content': true, \r\n 'modal-content-visible': this.isOpen,\r\n 'centered': this.centered\r\n };\r\n\r\n const okButtonClass = {\r\n 'modal-button': true,\r\n 'ok-button': true,\r\n [`ok-${this.okType}`]: true\r\n };\r\n\r\n return (\r\n <div class={containerClass}>\r\n {this.mask && (\r\n <div \r\n class={{ 'confirm-modal-mask': true, 'mask-visible': this.isOpen }} \r\n style={maskStyle}\r\n onClick={this.handleMaskClick}\r\n ></div>\r\n )}\r\n <div \r\n class={contentClass}\r\n style={modalStyle}\r\n >\r\n <div class=\"modal-wrapper\">\r\n <div class=\"modal-header\">\r\n <div class=\"modal-title\">{this.modalTitle}</div>\r\n </div>\r\n \r\n <div class=\"modal-body\">\r\n <slot></slot>\r\n </div>\r\n \r\n <div class=\"modal-footer\">\r\n <button \r\n class=\"modal-button cancel-button\"\r\n onClick={this.handleCancel}\r\n >\r\n {this.cancelText}\r\n </button>\r\n <button \r\n class={okButtonClass}\r\n onClick={this.handleOk}\r\n >\r\n {this.okText}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",".digital-human-container {\r\n position: relative;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n transition: box-shadow 0.3s;\r\n width: 100%;\r\n height: 100%;\r\n background: transparent;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.digital-human-container video {\r\n width: 100%;\r\n height: 100%;\r\n display: block;\r\n object-fit: cover;\r\n background: transparent;\r\n border-radius: 8px;\r\n}\r\n\r\n.generating-indicator {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: rgba(0, 0, 0, 0.7);\r\n border-radius: 50%;\r\n width: 30px;\r\n height: 30px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.loading-spinner {\r\n width: 16px;\r\n height: 16px;\r\n border: 2px solid #ffffff;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n/* 移动端样式 */\r\n@media screen and (max-width: 768px) {\r\n .digital-human-container {\r\n border-radius: 6px;\r\n }\r\n\r\n .digital-human-container video {\r\n border-radius: 6px;\r\n }\r\n}",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",":host {\r\n display: block;\r\n}\r\n\r\n.drawer-container {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 0;\r\n height: 0;\r\n overflow: visible;\r\n}\r\n\r\n.drawer-mask {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.45);\r\n opacity: 0;\r\n visibility: hidden;\r\n transition: opacity 0.3s ease, visibility 0.3s ease;\r\n}\r\n\r\n.mask-visible {\r\n opacity: 1;\r\n visibility: visible;\r\n}\r\n\r\n.drawer-content {\r\n position: fixed;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n display: flex;\r\n flex-direction: column;\r\n background-color: #fff;\r\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);\r\n transform: translateX(100%);\r\n transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1);\r\n}\r\n\r\n.drawer-content-visible {\r\n transform: translateX(0);\r\n}\r\n\r\n.drawer-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 16px 24px;\r\n color: rgba(0, 0, 0, 0.85);\r\n border-bottom: 1px solid #f0f0f0;\r\n}\r\n\r\n.drawer-title {\r\n flex: 1;\r\n margin: 0;\r\n font-size: 16px;\r\n line-height: 22px;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n.drawer-body {\r\n flex: 1;\r\n padding: 24px;\r\n overflow: auto;\r\n}\r\n\r\n/* 响应式样式 */\r\n@media (max-width: 768px) {\r\n .drawer-content {\r\n width: 100% !important;\r\n }\r\n \r\n .drawer-header {\r\n padding: 12px 16px;\r\n }\r\n \r\n .drawer-body {\r\n padding: 16px;\r\n }\r\n} ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, Event, EventEmitter, Watch, Method, Element, State } from '@stencil/core';\r\nimport { configStore } from '../../../store/config.store';\r\n\r\n/**\r\n * 抽屉组件\r\n * 从屏幕边缘滑出的浮层面板,类似 Ant Design 的 Drawer 组件\r\n */\r\n@Component({\r\n tag: 'pcm-drawer',\r\n styleUrls: ['pcm-drawer.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmDrawer {\r\n /**\r\n * 抽屉是否可见\r\n */\r\n @Prop({ mutable: true, reflect: true }) isOpen: boolean = false;\r\n\r\n /**\r\n * 抽屉标题\r\n */\r\n @Prop() drawerTitle: string = '';\r\n\r\n /**\r\n * 宽度,可以是像素值或百分比\r\n */\r\n @Prop() width: string = '378px';\r\n\r\n /**\r\n * 高度,在 placement 为 top 或 bottom 时使用\r\n */\r\n @Prop() height: string = '378px';\r\n\r\n /**\r\n * 是否显示关闭按钮\r\n */\r\n @Prop() closable: boolean = true;\r\n\r\n /**\r\n * 点击蒙层是否允许关闭\r\n */\r\n @Prop() maskClosable: boolean = true;\r\n\r\n\r\n /**\r\n * 抽屉关闭后的回调\r\n */\r\n @Event() closed: EventEmitter<void>;\r\n\r\n /**\r\n * 抽屉打开后的回调\r\n */\r\n @Event() afterOpen: EventEmitter<void>;\r\n\r\n /**\r\n * 抽屉关闭后的回调\r\n */\r\n @Event() afterClose: EventEmitter<void>;\r\n\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() zIndex: number = 1500;\r\n\r\n private bodyOverflowBeforeOpen: string = '';\r\n private transitionEndHandler: () => void;\r\n\r\n /**\r\n * 打开抽屉\r\n */\r\n @Method()\r\n async open() {\r\n this.isOpen = true;\r\n }\r\n\r\n /**\r\n * 关闭抽屉\r\n */\r\n @Method()\r\n async close() {\r\n this.isOpen = false;\r\n }\r\n\r\n @Watch('isOpen')\r\n visibleChanged(newValue: boolean) {\r\n if (newValue) {\r\n // 打开抽屉时,禁止背景滚动\r\n this.bodyOverflowBeforeOpen = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n \r\n // 添加过渡结束事件监听器\r\n const drawer = this.hostElement.shadowRoot.querySelector('.drawer-content') as HTMLElement;\r\n if (drawer) {\r\n this.transitionEndHandler = () => {\r\n this.afterOpen.emit();\r\n };\r\n drawer.addEventListener('transitionend', this.transitionEndHandler, { once: true });\r\n }\r\n } else {\r\n // 关闭抽屉时,恢复背景滚动\r\n document.body.style.overflow = this.bodyOverflowBeforeOpen;\r\n \r\n // 添加过渡结束事件监听器\r\n const drawer = this.hostElement.shadowRoot.querySelector('.drawer-content') as HTMLElement;\r\n if (drawer) {\r\n this.transitionEndHandler = () => {\r\n this.afterClose.emit();\r\n };\r\n drawer.addEventListener('transitionend', this.transitionEndHandler, { once: true });\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 尝试从缓存中读取 zIndex\r\n const cachedZIndex = configStore.getItem<number>('modal-zIndex');\r\n if (cachedZIndex) {\r\n this.zIndex = cachedZIndex + 500;\r\n }\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件卸载时恢复背景滚动\r\n if (this.isOpen) {\r\n document.body.style.overflow = this.bodyOverflowBeforeOpen;\r\n }\r\n \r\n // 移除事件监听器\r\n const drawer = this.hostElement.shadowRoot?.querySelector('.drawer-content') as HTMLElement;\r\n if (drawer && this.transitionEndHandler) {\r\n drawer.removeEventListener('transitionend', this.transitionEndHandler);\r\n }\r\n }\r\n\r\n private handleMaskClick = () => {\r\n if (this.maskClosable) {\r\n this.handleClose();\r\n }\r\n };\r\n\r\n private handleClose = () => {\r\n this.isOpen = false;\r\n this.closed.emit();\r\n };\r\n\r\n render() {\r\n const drawerStyle = {\r\n width: this.width,\r\n zIndex: `${this.zIndex + 1}`,\r\n };\r\n\r\n const maskStyle = {\r\n zIndex: `${this.zIndex}`,\r\n };\r\n\r\n return (\r\n <div class={{ 'drawer-container': true, 'drawer-open': this.isOpen }}>\r\n <div \r\n class={{ 'drawer-mask': true, 'mask-visible': this.isOpen }} \r\n style={maskStyle}\r\n onClick={this.handleMaskClick}\r\n ></div>\r\n <div \r\n class={{ 'drawer-content': true, 'drawer-content-visible': this.isOpen }} \r\n style={drawerStyle}\r\n >\r\n <div class=\"drawer-header\">\r\n {this.drawerTitle && <div class=\"drawer-title\">{this.drawerTitle}</div>}\r\n {this.closable && (\r\n <button class=\"close-button\" onClick={this.handleClose}>\r\n <span>×</span>\r\n </button>\r\n )}\r\n </div>\r\n <div class=\"drawer-body\">\r\n <slot></slot>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ","/* 模态框遮罩层 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.45);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 1000;\r\n backdrop-filter: blur(4px);\r\n}\r\n\r\n/* 模态框容器 */\r\n.modal-container {\r\n background: white;\r\n border-radius: 8px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n max-width: min(1000px, calc(100vw - 40px));\r\n max-height: calc(100vh - 40px);\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n/* 模态框头部 */\r\n.modal-header {\r\n padding: 16px 24px;\r\n border-bottom: 1px solid #f0f0f0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n background: #fafafa;\r\n}\r\n\r\n.modal-title {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #262626;\r\n}\r\n\r\n.modal-close {\r\n background: none;\r\n border: none;\r\n font-size: 18px;\r\n color: #8c8c8c;\r\n cursor: pointer;\r\n padding: 4px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n}\r\n\r\n.modal-close:hover {\r\n background-color: #f5f5f5;\r\n color: #262626;\r\n}\r\n\r\n/* 模态框主体 */\r\n.modal-body {\r\n padding: 24px;\r\n flex: 1;\r\n overflow: auto;\r\n}\r\n\r\n/* 按钮样式 */\r\n.btn {\r\n border: none;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: 400;\r\n transition: all 0.2s;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n}\r\n\r\n.btn-small {\r\n padding: 4px 8px;\r\n font-size: 12px;\r\n}\r\n\r\n.btn-medium {\r\n padding: 8px 16px;\r\n}\r\n\r\n.btn-primary {\r\n background-color: #1890ff;\r\n color: white;\r\n border: 1px solid #1890ff;\r\n}\r\n\r\n.btn-primary:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.btn-default {\r\n background-color: white;\r\n color: #595959;\r\n border: 1px solid #d9d9d9;\r\n}\r\n\r\n.btn-default:hover {\r\n background-color: #f5f5f5;\r\n border-color: #40a9ff;\r\n color: #40a9ff;\r\n}\r\n\r\n.btn-danger {\r\n background-color: #f5222d;\r\n color: white;\r\n border: 1px solid #f5222d;\r\n}\r\n\r\n.btn-danger:hover {\r\n background-color: #cf1322;\r\n border-color: #cf1322;\r\n}\r\n\r\n/* 表格容器 */\r\n.table-container {\r\n border: 1px solid #f0f0f0;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n margin-bottom: 16px;\r\n}\r\n\r\n/* 表格样式 */\r\n.table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n background: white;\r\n}\r\n\r\n.table th {\r\n background-color: #fafafa;\r\n padding: 12px 16px;\r\n font-weight: 600;\r\n color: #262626;\r\n border-bottom: 1px solid #f0f0f0;\r\n font-size: 14px;\r\n}\r\n\r\n.table td {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n color: #595959;\r\n font-size: 14px;\r\n}\r\n\r\n.table tbody tr:hover {\r\n background-color: #f5f5f5;\r\n}\r\n\r\n.table tbody tr:last-child td {\r\n border-bottom: none;\r\n}\r\n\r\n/* 标签样式 */\r\n.tag {\r\n display: inline-block;\r\n padding: 2px 8px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n font-weight: 400;\r\n color: white;\r\n text-align: center;\r\n min-width: 60px;\r\n}\r\n\r\n/* 操作按钮容器 */\r\n.action-buttons {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n/* 加载状态 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.loading-spinner {\r\n width: 32px;\r\n height: 32px;\r\n border: 3px solid #f0f0f0;\r\n border-top: 3px solid #1890ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n}\r\n\r\n@keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n}\r\n\r\n/* 空状态 */\r\n.empty-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.empty-icon {\r\n font-size: 48px;\r\n margin-bottom: 16px;\r\n opacity: 0.6;\r\n}\r\n\r\n.empty-text {\r\n font-size: 14px;\r\n color: #8c8c8c;\r\n}\r\n\r\n/* 分页容器 */\r\n.pagination-container {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 16px 0;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.pagination-info {\r\n color: #8c8c8c;\r\n font-size: 14px;\r\n}\r\n\r\n.pagination-controls {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.pagination-btn {\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n background: white;\r\n color: #595959;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n transition: all 0.2s;\r\n}\r\n\r\n.pagination-btn:hover:not(:disabled) {\r\n border-color: #40a9ff;\r\n color: #40a9ff;\r\n}\r\n\r\n.pagination-btn:disabled {\r\n background-color: #f5f5f5;\r\n color: #bfbfbf;\r\n cursor: not-allowed;\r\n border-color: #f0f0f0;\r\n}\r\n\r\n.pagination-current {\r\n color: #262626;\r\n font-size: 14px;\r\n font-weight: 500;\r\n padding: 0 8px;\r\n}\r\n\r\n.pagination-size-select {\r\n padding: 6px 8px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n background: white;\r\n color: #595959;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n}\r\n\r\n.pagination-size-select:hover {\r\n border-color: #40a9ff;\r\n}\r\n\r\n.pagination-size-select:focus {\r\n outline: none;\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 消息提示 */\r\n.message {\r\n position: fixed;\r\n top: 24px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n padding: 12px 24px;\r\n border-radius: 6px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n z-index: 1100;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n animation: messageSlideIn 0.3s ease-out;\r\n}\r\n\r\n.message-success {\r\n background-color: #f6ffed;\r\n color: #52c41a;\r\n border: 1px solid #b7eb8f;\r\n}\r\n\r\n.message-error {\r\n background-color: #fff2f0;\r\n color: #ff4d4f;\r\n border: 1px solid #ffccc7;\r\n}\r\n\r\n@keyframes messageSlideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateX(-50%) translateY(-20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateX(-50%) translateY(0);\r\n }\r\n}\r\n\r\n/* 响应式设计 */\r\n@media (max-width: 768px) {\r\n .modal-container {\r\n margin: 20px;\r\n max-width: calc(100vw - 40px);\r\n }\r\n \r\n .modal-header {\r\n padding: 12px 16px;\r\n }\r\n \r\n .modal-body {\r\n padding: 16px;\r\n }\r\n \r\n .table th,\r\n .table td {\r\n padding: 8px 12px;\r\n font-size: 13px;\r\n }\r\n \r\n .pagination-container {\r\n flex-direction: column;\r\n gap: 12px;\r\n align-items: stretch;\r\n }\r\n \r\n .pagination-controls {\r\n justify-content: center;\r\n }\r\n \r\n .modal-title {\r\n font-size: 14px;\r\n gap: 8px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .table-container {\r\n overflow-x: auto;\r\n }\r\n \r\n .table {\r\n min-width: 600px;\r\n }\r\n \r\n .action-buttons {\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n}","import { Component, Prop, State, h, Watch, Event, EventEmitter } from '@stencil/core';\r\nimport { getCosPresignedUrl, sendHttpRequest } from '../../utils/utils';\r\n\r\ninterface ExportRecord {\r\n id: string;\r\n file_name: string;\r\n status: number;\r\n created_at: string;\r\n cos_key?: string;\r\n}\r\n\r\ninterface PaginationType {\r\n page: number;\r\n size: number;\r\n total?: number;\r\n}\r\n\r\nconst DEFAULT_PAGINATION = {\r\n page: 1,\r\n size: 10,\r\n};\r\n\r\nconst EXPORT_BATCH_STATUS_MAP: Record<string, { text: string; color: string }> = {\r\n '0': { text: '处理中', color: '#1890ff' },\r\n '1': { text: '已完成', color: '#52c41a' },\r\n '-1': { text: '失败', color: '#ff4d4f' },\r\n};\r\n\r\n@Component({\r\n tag: 'pcm-export-records-modal',\r\n styleUrl: 'pcm-export-records-modal.css',\r\n shadow: true,\r\n})\r\nexport class PcmExportRecordsModal {\r\n @Prop() botId?: string;\r\n @Prop() sourceId?: string;\r\n @Prop() open: boolean = false;\r\n @Event() cancel: EventEmitter<void>;\r\n\r\n @State() loading: boolean = true;\r\n @State() pagination: PaginationType = DEFAULT_PAGINATION;\r\n @State() data: ExportRecord[] = [];\r\n @State() showMessage: boolean = false;\r\n @State() messageText: string = '';\r\n @State() messageType: 'success' | 'error' = 'success';\r\n\r\n @Watch('open')\r\n watchOpen(newValue: boolean) {\r\n if (newValue) {\r\n this.fetchData(this.pagination);\r\n }\r\n }\r\n\r\n private async fetchData(p: PaginationType) {\r\n this.loading = true;\r\n try {\r\n // 模拟API调用\r\n const response = await sendHttpRequest({\r\n url: '/sdk/v1/export_batch/page',\r\n method: 'GET',\r\n params: {\r\n page: p.page,\r\n size: p.size,\r\n bot_id: this.botId,\r\n source_id: this.sourceId,\r\n },\r\n });\r\n if (response.success && response.data) {\r\n const records = response?.data?.records ?? [];\r\n this.data = records;\r\n this.pagination = {\r\n ...p,\r\n total: response?.data?.total ?? 0,\r\n };\r\n }\r\n } catch (error) {\r\n console.error('Failed to fetch data:', error);\r\n } finally {\r\n this.loading = false;\r\n }\r\n }\r\n\r\n private async handleDownload(record: ExportRecord) {\r\n try {\r\n const downloadUrl = await getCosPresignedUrl(record.cos_key);\r\n const fileName = record.file_name;\r\n if (downloadUrl) {\r\n const link = document.createElement(\"a\");\r\n link.href = downloadUrl;\r\n link.setAttribute(\"download\", fileName);\r\n document.body.appendChild(link);\r\n link.click();\r\n link.remove();\r\n this.showMessageToast('下载成功', 'success');\r\n } else {\r\n this.showMessageToast('获取下载链接失败', 'error');\r\n }\r\n \r\n } catch (error) {\r\n this.showMessageToast('下载失败', 'error');\r\n }\r\n }\r\n\r\n private async handleDelete(record: ExportRecord) {\r\n try {\r\n const response = await sendHttpRequest({\r\n url: `/sdk/v1/export_batch/delete/${record.id}`,\r\n method: \"DELETE\",\r\n });\r\n if (response?.success) {\r\n this.showMessageToast('删除成功', 'success');\r\n setTimeout(() => {\r\n this.fetchData(this.pagination);\r\n }, 100);\r\n }\r\n } catch (error) {\r\n this.showMessageToast(`删除失败: ${error.message}`, 'error');\r\n }\r\n }\r\n\r\n private showMessageToast(text: string, type: 'success' | 'error') {\r\n this.messageText = text;\r\n this.messageType = type;\r\n this.showMessage = true;\r\n setTimeout(() => {\r\n this.showMessage = false;\r\n }, 3000);\r\n }\r\n\r\n private handleRefresh = () => {\r\n this.fetchData(this.pagination);\r\n };\r\n\r\n private handlePageChange = (page: number, size: number) => {\r\n const newPagination = {\r\n ...this.pagination,\r\n page,\r\n size,\r\n };\r\n this.fetchData(newPagination);\r\n };\r\n\r\n private formatDate(dateString: string): string {\r\n const date = new Date(dateString);\r\n return date.toLocaleString('zh-CN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n second: '2-digit',\r\n });\r\n }\r\n\r\n private renderEmpty() {\r\n return (\r\n <div class=\"empty-container\">\r\n <div class=\"empty-icon\">📄</div>\r\n <div class=\"empty-text\">暂无任务</div>\r\n </div>\r\n );\r\n }\r\n\r\n private renderTag(status: number) {\r\n const statusInfo = EXPORT_BATCH_STATUS_MAP[status.toString()] || { text: '未知', color: '#d9d9d9' };\r\n return (\r\n <span class=\"tag\" style={{ backgroundColor: statusInfo.color }}>\r\n {statusInfo.text}\r\n </span>\r\n );\r\n }\r\n\r\n private renderButton(text: string, onClick: () => void, variant: 'primary' | 'default' | 'danger' = 'default', size: 'small' | 'medium' = 'medium') {\r\n return (\r\n <button\r\n class={`btn btn-${variant} btn-${size}`}\r\n onClick={onClick}\r\n >\r\n {text}\r\n </button>\r\n );\r\n }\r\n\r\n private renderTable() {\r\n if (this.loading) {\r\n return (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <div>加载中...</div>\r\n </div>\r\n );\r\n }\r\n\r\n if (!this.data || this.data.length === 0) {\r\n return this.renderEmpty();\r\n }\r\n\r\n return (\r\n <div class=\"table-container\">\r\n <table class=\"table\">\r\n <thead>\r\n <tr>\r\n <th style={{ width: '300px', textAlign: 'center' }}>文件名</th>\r\n <th style={{ width: '100px', textAlign: 'center' }}>状态</th>\r\n <th style={{ width: '180px', textAlign: 'center' }}>创建时间</th>\r\n <th style={{ width: '100px', textAlign: 'left' }}>操作</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n {this.data.map((record) => (\r\n <tr key={record.id}>\r\n <td style={{ textAlign: 'center' }}>{record.file_name}</td>\r\n <td style={{ textAlign: 'center' }}>\r\n {this.renderTag(record.status)}\r\n </td>\r\n <td style={{ textAlign: 'center' }}>\r\n {this.formatDate(record.created_at)}\r\n </td>\r\n <td style={{ textAlign: 'left' }}>\r\n <div class=\"action-buttons\">\r\n {record.status !== 0 && this.renderButton(\r\n '删除',\r\n () => this.handleDelete(record),\r\n 'danger',\r\n 'small'\r\n )}\r\n {record.cos_key && this.renderButton(\r\n '下载',\r\n () => this.handleDownload(record),\r\n 'primary',\r\n 'small'\r\n )}\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n }\r\n\r\n private renderPagination() {\r\n if (!this.pagination.total || this.pagination.total === 0) {\r\n return null;\r\n }\r\n\r\n const totalPages = Math.ceil(this.pagination.total / this.pagination.size);\r\n const currentPage = this.pagination.page;\r\n\r\n return (\r\n <div class=\"pagination-container\">\r\n <div class=\"pagination-info\">\r\n 共{this.pagination.total}条\r\n </div>\r\n <div class=\"pagination-controls\">\r\n <button\r\n class=\"pagination-btn\"\r\n disabled={currentPage <= 1}\r\n onClick={() => this.handlePageChange(currentPage - 1, this.pagination.size)}\r\n >\r\n 上一页\r\n </button>\r\n <span class=\"pagination-current\">\r\n {currentPage} / {totalPages}\r\n </span>\r\n <button\r\n class=\"pagination-btn\"\r\n disabled={currentPage >= totalPages}\r\n onClick={() => this.handlePageChange(currentPage + 1, this.pagination.size)}\r\n >\r\n 下一页\r\n </button>\r\n <select\r\n class=\"pagination-size-select\"\r\n onChange={(e) => this.handlePageChange(1, parseInt((e.target as HTMLSelectElement).value))}\r\n >\r\n <option value=\"10\" selected={this.pagination.size === 10}>10条/页</option>\r\n <option value=\"20\" selected={this.pagination.size === 20}>20条/页</option>\r\n <option value=\"50\" selected={this.pagination.size === 50}>50条/页</option>\r\n </select>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n private renderMessage() {\r\n if (!this.showMessage) return null;\r\n\r\n return (\r\n <div class={`message message-${this.messageType}`}>\r\n {this.messageText}\r\n </div>\r\n );\r\n }\r\n\r\n render() {\r\n if (!this.open) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div class=\"modal-overlay\" onClick={() => this.cancel.emit()}>\r\n <div class=\"modal-container\" onClick={(e) => e.stopPropagation()}>\r\n <div class=\"modal-header\">\r\n <div class=\"modal-title\">\r\n <span>导出任务列表</span>\r\n {this.renderButton(\r\n '🔄 刷新',\r\n this.handleRefresh,\r\n 'default',\r\n 'small'\r\n )}\r\n </div>\r\n <button class=\"modal-close\" onClick={() => this.cancel.emit()}>\r\n ✕\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n {this.renderTable()}\r\n {this.renderPagination()}\r\n </div>\r\n {this.renderMessage()}\r\n </div>\r\n </div>\r\n );\r\n }\r\n}","/* 输入模式切换 */\r\n.input-mode-toggle {\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 16px;\r\n}\r\n \r\n.input-mode-toggle span {\r\n color: #333;\r\n margin-right: 12px;\r\n}\r\n \r\n.toggle-button {\r\n display: flex;\r\n align-items: center;\r\n background: none;\r\n border: none;\r\n color: #2E6EDF;\r\n cursor: pointer;\r\n font-size: 14px;\r\n padding: 4px 8px;\r\n}\r\n \r\n.toggle-button svg {\r\n margin-right: 4px;\r\n}\r\n\r\n/* 自由输入模式 */\r\n.free-input {\r\n width: 100%;\r\n}\r\n\r\n.textarea-container {\r\n margin-bottom: 16px;\r\n}\r\n\r\n.textarea-container label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.textarea-container textarea {\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n resize: vertical;\r\n background-color: #f9f9f9;\r\n min-height: 150px;\r\n width: 100%;\r\n padding: 12px 16px;\r\n margin-bottom: 20px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n word-wrap: break-word;\r\n}\r\n\r\n.textarea-container textarea:focus {\r\n outline: none;\r\n border-color: #2E6EDF;\r\n box-shadow: 0 0 0 2px rgba(46, 110, 223, 0.2);\r\n}\r\n\r\n.required {\r\n color: #f56c6c;\r\n}\r\n\r\n.input-guide {\r\n background-color: #f5f7fa;\r\n border-radius: 4px;\r\n padding: 12px 16px;\r\n margin-bottom: 20px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n word-wrap: break-word;\r\n}\r\n\r\n.guide-title {\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.guide-content {\r\n color: #666;\r\n font-size: 13px;\r\n max-width: 100%;\r\n word-wrap: break-word;\r\n}\r\n\r\n.guide-content div {\r\n margin-bottom: 4px;\r\n}\r\n\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { Message } from '../../services/message.service';\r\n\r\n/**\r\n * 劳动合同卫士\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-htws-modal',\r\n styleUrls: ['pcm-htws-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class HtwsModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '劳动合同卫士';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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 /**\r\n * 自定义输入参数,传入customInputs.input时,会自动切换到自由输入模式<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历(仅PC端生效)\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端输入合同内容(仅PC端生效)\r\n */\r\n @Prop() mobileInputAble: boolean = false;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() isSubmitting: boolean = false;\r\n\r\n // 添加输入模式状态\r\n @State() inputMode: 'upload' | 'free' = 'upload';\r\n\r\n // 自由输入模式的文本\r\n @State() freeInputText: string = '';\r\n\r\n \r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n private pcmUploadRef;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n \r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n\r\n\r\n // 添加切换输入模式的方法\r\n private handleToggleInput = () => {\r\n this.inputMode = this.inputMode === 'upload' ? 'free' : 'upload';\r\n };\r\n\r\n // 添加自由输入文本变更处理方法\r\n private handleFreeInputChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.freeInputText = textarea.value;\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n if (this.inputMode === 'upload' && !this.uploadedFileInfo) {\r\n Message.info('请上传合同文件');\r\n return;\r\n }\r\n\r\n if (this.inputMode === 'free' && !this.freeInputText.trim()) {\r\n Message.info('请输入合同内容');\r\n return;\r\n }\r\n\r\n // 判断文件是否正在上传\r\n if (this.inputMode === 'upload' && await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n this.isSubmitting = false;\r\n };\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\r\n this.freeInputText = '';\r\n this.inputMode = 'upload'; // 重置为默认上传模式\r\n } else {\r\n if (this.customInputs && this.customInputs.input) {\r\n // 如果有 input,直接切换到自由输入模式并填充内容\r\n this.inputMode = 'free';\r\n this.freeInputText = this.customInputs.input;\r\n }\r\n await verifyApiKey(this.token);\r\n\r\n if (this.conversationId) {\r\n // 如果有会话ID,直接显示聊天模态框\r\n this.showChatModal = true;\r\n }\r\n }\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\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 <div>{this.modalTitle}</div>\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 {/* 输入界面 - 仅在不显示聊天模态框且没有会话ID时显示 */}\r\n {!this.showChatModal && !this.conversationId && (\r\n <div class=\"input-container\">\r\n {/* 输入模式切换 */}\r\n <div class=\"input-mode-toggle\">\r\n <span>合同内容</span>\r\n <button\r\n class=\"toggle-button\"\r\n onClick={this.handleToggleInput}\r\n >\r\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\r\n </svg>\r\n 切换输入\r\n </button>\r\n </div>\r\n\r\n {/* 上传模式 */}\r\n {this.inputMode === 'upload' && (\r\n <div class=\"resume-upload-section\">\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={25 * 1024 * 1024}\r\n multiple={false}\r\n mobileUploadAble={this.mobileUploadAble}\r\n uploadText=\"点击上传合同\"\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['other'],\r\n }}\r\n onUploadChange={(e) => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 自由输入模式 */}\r\n {this.inputMode === 'free' && (\r\n <div class=\"free-input\">\r\n {\r\n !!this.mobileInputAble && (\r\n <pcm-mobile-input-btn\r\n name=\"合同内容\"\r\n onOk={(e) => {\r\n this.freeInputText = e.detail;\r\n }}\r\n />\r\n )\r\n }\r\n <div class=\"textarea-container\">\r\n <textarea\r\n id=\"free-input-text\"\r\n placeholder=\"请输入合同内容\"\r\n rows={8}\r\n value={this.freeInputText}\r\n onInput={this.handleFreeInputChange}\r\n ></textarea>\r\n </div>\r\n\r\n <div class=\"input-guide\">\r\n <div class=\"guide-title\">输入提示:</div>\r\n <div class=\"guide-content\">\r\n <div>• 请输入完整的劳动合同内容</div>\r\n <div>• 包括甲方(公司)、乙方(员工)信息</div>\r\n <div>• 合同期限、工作内容、工作地点</div>\r\n <div>• 工作时间、休息休假、劳动报酬</div>\r\n <div>• 社会保险、劳动保护、劳动条件</div>\r\n <div>• 合同变更、解除和终止条件等</div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(this.inputMode === 'upload' && !this.uploadedFileInfo) ||\r\n (this.inputMode === 'free' && !this.freeInputText.trim()) ||\r\n this.isUploading ||\r\n this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始分析'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div>\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018882\"\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.inputMode === 'upload' ? this.uploadedFileInfo?.cos_key : undefined,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n input: this.inputMode === 'free' ? this.freeInputText : undefined\r\n }}\r\n interviewMode=\"text\"\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",null,"/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { uploadFileToBackend, FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { SentryReporter } from '../../utils/sentry-reporter';\r\n\r\n/**\r\n * 会议总结助手\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-hyzj-modal',\r\n styleUrls: ['pcm-hyzj-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class HyzjModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '会议总结助手';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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 /**\r\n * 自定义输入参数<br>\r\n * 传入customInputs.file_url时,会直接开始聊天。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() isSubmitting: boolean = false;\r\n\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.clearSelectedFile();\r\n this.showChatModal = false;\r\n } else {\r\n await verifyApiKey(this.token);\r\n \r\n // 如果有会话ID或者有file_url参数,直接显示聊天模态框\r\n if (this.conversationId || this.customInputs?.file_url) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n\r\n componentWillLoad() {\r\n\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleFileChange = (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\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 = null;\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 private async uploadFile() {\r\n if (!this.selectedFile) return;\r\n\r\n this.isUploading = true;\r\n\r\n try {\r\n // 使用 uploadFileToBackend 工具函数上传文件\r\n const result = await uploadFileToBackend(this.selectedFile, {\r\n }, {\r\n 'tags': ['other']\r\n });\r\n\r\n this.uploadedFileInfo = result;\r\n this.uploadSuccess.emit(result);\r\n } catch (error) {\r\n console.error('文件上传错误:', error);\r\n this.clearSelectedFile();\r\n SentryReporter.captureError(error, {\r\n action: 'uploadFile',\r\n component: 'pcm-hyzj-modal',\r\n title: '文件上传失败'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '文件上传失败,请重试'\r\n });\r\n } finally {\r\n this.isUploading = false;\r\n }\r\n }\r\n\r\n private handleStartInterview = async () => {\r\n if (!this.selectedFile) {\r\n alert('请上传面试内容');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n\r\n try {\r\n // 如果还没上传,先上传文件\r\n if (!this.uploadedFileInfo) {\r\n await this.uploadFile();\r\n if (!this.uploadedFileInfo) {\r\n this.isSubmitting = false;\r\n return; // 上传失败\r\n }\r\n }\r\n\r\n // 直接显示聊天模态框\r\n this.showChatModal = true;\r\n } catch (error) {\r\n console.error('开始面试时出错:', error);\r\n SentryReporter.captureError(error, {\r\n action: 'handleStartInterview',\r\n component: 'pcm-hyzj-modal',\r\n title: '开始面试时出错'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '开始面试时出错,请重试'\r\n });\r\n } finally {\r\n this.isSubmitting = false;\r\n }\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\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen,\r\n 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 判断是否隐藏文件上传区域\r\n const hideFileUpload = Boolean(this.customInputs && this.customInputs.file_url);\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 <div>{this.modalTitle}</div>\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 {/* 上传界面 - 仅在不显示聊天模态框且没有会话ID且没有customInputs.file_url时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hideFileUpload && (\r\n <div class=\"input-container\">\r\n {/* 上传会议纪要上传区域 */}\r\n <div class=\"resume-upload-section\">\r\n <label>上传会议纪要</label>\r\n <div class=\"upload-area\" onClick={this.handleUploadClick}>\r\n {this.selectedFile ? (\r\n <div class=\"file-item\">\r\n <div class=\"file-item-content\">\r\n <span class=\"file-icon\">📝</span>\r\n <span class=\"file-name\">{this.selectedFile.name}</span>\r\n </div>\r\n <button class=\"remove-file\" onClick={(e) => {\r\n e.stopPropagation();\r\n this.clearSelectedFile();\r\n }}>×</button>\r\n </div>\r\n ) : (\r\n <div class=\"upload-placeholder\">\r\n <img src='https://pub.pincaimao.com/static/web/images/home/i_upload.png'></img>\r\n <p class='upload-text'>点击上传会议纪要</p>\r\n <p class=\"upload-hint\">支持 mp3、markdown、pdf、docx、doc、md 格式</p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={!this.selectedFile || this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始分析'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n onChange={this.handleFileChange}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018885\"\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name\r\n }}\r\n interviewMode=\"text\"\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ","/* 输入模式切换 */\r\n.input-mode-toggle {\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 16px;\r\n}\r\n \r\n.input-mode-toggle span {\r\n color: #333;\r\n margin-right: 12px;\r\n}\r\n \r\n.toggle-button {\r\n display: flex;\r\n align-items: center;\r\n background: none;\r\n border: none;\r\n color: #2E6EDF;\r\n cursor: pointer;\r\n font-size: 14px;\r\n padding: 4px 8px;\r\n}\r\n \r\n.toggle-button svg {\r\n margin-right: 4px;\r\n}\r\n \r\n.toggle-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}\r\n \r\n/* 结构化输入模式 */\r\n.structured-input {\r\n width: 100%;\r\n}\r\n \r\n.job-name-input {\r\n margin-bottom: 20px;\r\n}\r\n \r\n.job-name-input label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n \r\n.job-name-input input {\r\n width: 95%;\r\n padding: 10px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n background-color: #f9f9f9;\r\n}\r\n\r\n.job-name-input input:focus {\r\n outline: none;\r\n border-color: #2E6EDF;\r\n box-shadow: 0 0 0 2px rgba(46, 110, 223, 0.2);\r\n}\r\n\r\n.required {\r\n color: #f56c6c;\r\n}\r\n\r\n/* 按钮容器 */\r\n.button-container {\r\n display: flex;\r\n justify-content: center;\r\n margin-top: 24px;\r\n gap: 12px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n flex-wrap: wrap;\r\n}\r\n\r\n\r\n.next-button {\r\n background-color: #2E6EDF;\r\n color: white;\r\n}\r\n\r\n.next-button:hover {\r\n background-color: #2457b8;\r\n}\r\n\r\n.next-button:disabled {\r\n background-color: #a0c0e8;\r\n cursor: not-allowed;\r\n}\r\n\r\n.prev-button {\r\n background-color: #f0f0f0 !important;\r\n color: #333 !important;\r\n}\r\n\r\n.prev-button:hover {\r\n background-color: #e0e0e0;\r\n}\r\n\r\n/* 标签选择 */\r\n.tag-selection {\r\n width: 100%;\r\n}\r\n\r\n.tag-selection-content {\r\n width: 100%;\r\n}\r\n\r\n.section-title {\r\n font-weight: 600;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 16px;\r\n}\r\n\r\n.ai-tags-section, .basic-tags-section {\r\n margin-bottom: 24px;\r\n}\r\n\r\n.tag-group {\r\n margin-bottom: 16px;\r\n}\r\n\r\n.tag-title {\r\n color: #555;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n}\r\n\r\n.tag-container {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n}\r\n\r\n.tag {\r\n display: inline-flex;\r\n align-items: center;\r\n padding: 6px 12px;\r\n border-radius: 4px;\r\n background-color: #f5f5f5;\r\n border: 1px solid #e0e0e0;\r\n color: #333;\r\n font-size: 13px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.tag:hover {\r\n background-color: #e8e8e8;\r\n}\r\n\r\n.tag-selected {\r\n background-color: #e6f0ff;\r\n border-color: #2E6EDF;\r\n color: #2E6EDF;\r\n}\r\n\r\n/* 加载状态 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px 0;\r\n background-color: #f9f9f9;\r\n border-radius: 8px;\r\n margin: 20px 0;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n}\r\n\r\n.loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 3px solid rgba(46, 110, 223, 0.2);\r\n border-radius: 50%;\r\n border-top-color: #2E6EDF;\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n}\r\n\r\n@keyframes spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n.loading-text {\r\n text-align: center;\r\n color: #333;\r\n font-weight: 500;\r\n}\r\n\r\n.loading-subtext {\r\n color: #888;\r\n font-size: 14px;\r\n margin-top: 4px;\r\n}\r\n\r\n/* 自由输入模式 */\r\n.free-input {\r\n width: 100%;\r\n}\r\n\r\n.textarea-container {\r\n margin-bottom: 16px;\r\n}\r\n\r\n.textarea-container label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.textarea-container textarea {\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n resize: vertical;\r\n background-color: #f9f9f9;\r\n min-height: 150px;\r\n width: 100%;\r\n padding: 12px 16px;\r\n margin-bottom: 20px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n word-wrap: break-word;\r\n}\r\n\r\n.textarea-container textarea:focus {\r\n outline: none;\r\n border-color: #2E6EDF;\r\n box-shadow: 0 0 0 2px rgba(46, 110, 223, 0.2);\r\n}\r\n\r\n.input-guide {\r\n background-color: #f5f7fa;\r\n border-radius: 4px;\r\n padding: 12px 16px;\r\n margin-bottom: 20px;\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n word-wrap: break-word;\r\n}\r\n\r\n.guide-title {\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.guide-content {\r\n color: #666;\r\n font-size: 13px;\r\n max-width: 100%;\r\n word-wrap: break-word;\r\n}\r\n\r\n.guide-content div {\r\n margin-bottom: 4px;\r\n}\r\n\r\n\r\n/* 响应式调整 */\r\n@media (max-width: 768px) {\r\n \r\n .tag-container {\r\n gap: 7px;\r\n }\r\n \r\n .tag {\r\n padding: 4px 8px;\r\n font-size: 12px;\r\n }\r\n}\r\n\r\n@media (max-width: 480px) {\r\n .button-container {\r\n flex-direction: column;\r\n align-items: center;\r\n }\r\n \r\n .next-button, .prev-button, .submit-button {\r\n width: 100%;\r\n margin-bottom: 8px;\r\n }\r\n \r\n .tag {\r\n max-width: calc(50% - 8px);\r\n }\r\n}\r\n\r\n.tag-selection, \r\n.tag-selection-content,\r\n.ai-tags-section, \r\n.basic-tags-section,\r\n.structured-input,\r\n.free-input {\r\n max-width: 100%;\r\n box-sizing: border-box;\r\n}","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { sendHttpRequest, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { SentryReporter } from '../../utils/sentry-reporter';\r\n\r\n/**\r\n * 职位生成组件\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-jd-modal',\r\n styleUrls: ['pcm-jd-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmJdModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '职位生成';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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 /**\r\n * 自定义输入参数,传入customInputs.job_info时,会隐藏JD输入区域<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 是否显示“保存职位”按钮(仅JD助手智能体生效)\r\n */\r\n @Prop() showSaveJdButton: boolean = false;\r\n\r\n /**\r\n * 保存职位按钮文本\r\n */\r\n @Prop() saveJdButtonText: string = '保存职位';\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n // 输入模式:structured(点选模式) 或 free(表单模式)\r\n @State() inputMode: 'structured' | 'free' = 'structured';\r\n\r\n // 步骤:input(输入职位名称) 或 review(选择标签)\r\n @State() step: 'input' | 'review' = 'input';\r\n\r\n // 职位名称\r\n @State() jobName: string = '';\r\n\r\n // 自由输入模式的文本\r\n @State() freeInputText: string = '';\r\n\r\n // 是否正在加载标签\r\n @State() isLoading: boolean = false;\r\n\r\n // 是否正在提交\r\n @State() isSubmitting: boolean = false;\r\n\r\n // 标签组\r\n @State() tagGroups: { dimensionName: string; defaultTags: string[]; optionalTags: string[] }[] = [];\r\n\r\n // 洗牌后的标签组\r\n @State() shuffledTagGroups: { dimensionName: string; tags: string[] }[] = [];\r\n\r\n // 选中的AI标签\r\n @State() selectedAITags: { [key: string]: string[] } = {};\r\n\r\n // 选中的基础标签\r\n @State() selectedTags: {\r\n salary: string;\r\n benefits: string[];\r\n education: string;\r\n } = {\r\n salary: '',\r\n benefits: [],\r\n education: ''\r\n };\r\n\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n\r\n // 薪资范围选项\r\n private salaryRanges = [\r\n { text: '3k-5k', value: '3k_5k' },\r\n { text: '5k-8k', value: '5k_8k' },\r\n { text: '8k-12k', value: '8k_12k' },\r\n { text: '12k-15k', value: '12k_15k' },\r\n { text: '15k-20k', value: '15k_20k' },\r\n { text: '20k以上', value: 'above_20k' },\r\n ];\r\n\r\n // 福利待遇选项\r\n private benefits = [\r\n { text: '五险一金', value: '五险一金' },\r\n { text: '年终奖', value: '年终奖' },\r\n { text: '带薪年假', value: '带薪年假' },\r\n { text: '加班补贴', value: '加班补贴' },\r\n { text: '餐补', value: '餐补' },\r\n { text: '交通补贴', value: '交通补贴' },\r\n { text: '节日福利', value: '节日福利' },\r\n { text: '团队建设', value: '团队建设' },\r\n ];\r\n\r\n // 学历要求选项\r\n private educationRequirements = [\r\n { text: '大专', value: '大专' },\r\n { text: '本科', value: '本科' },\r\n { text: '硕士', value: '硕士' },\r\n { text: '博士', value: '博士' },\r\n { text: '学历不限', value: '学历不限' },\r\n ];\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleToggleInput = () => {\r\n this.inputMode = this.inputMode === 'structured' ? 'free' : 'structured';\r\n };\r\n\r\n private handleJobNameChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.jobName = input.value;\r\n };\r\n\r\n private handleFreeInputChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.freeInputText = textarea.value;\r\n };\r\n\r\n private handleNextStep = async () => {\r\n if (!this.jobName.trim()) {\r\n alert('请输入职位名称');\r\n return;\r\n }\r\n\r\n this.step = 'review';\r\n await this.handlePositionAnalysis(this.jobName);\r\n };\r\n\r\n private handlePrevStep = () => {\r\n this.step = 'input';\r\n };\r\n\r\n private async handlePositionAnalysis(jobName: string) {\r\n if (!jobName.trim()) return;\r\n\r\n this.isLoading = true;\r\n\r\n try {\r\n const response = await sendHttpRequest({\r\n url: '/sdk/v1/chat/workflow/block-run',\r\n method: 'POST',\r\n data: {\r\n inputs: {\r\n input_info: jobName,\r\n\r\n },\r\n bot_id: \"59322522667307008\",\r\n workflow_code: \"generate_jd_tags\"\r\n }\r\n });\r\n\r\n if (response.success && response.data?.data.outputs?.text) {\r\n try {\r\n // 兼容纯JSON和Markdown格式的JSON (```json ... ```)\r\n let jsonText = response.data.data.outputs.text.trim();\r\n const markdownJsonMatch = jsonText.match(/```json\\s*([\\s\\S]*?)\\s*```/);\r\n if (markdownJsonMatch) {\r\n jsonText = markdownJsonMatch[1].trim();\r\n }\r\n const parsedOutput = JSON.parse(jsonText);\r\n this.tagGroups = parsedOutput.tagGroup || [];\r\n\r\n // 自动选中所有默认标签\r\n const initialSelectedTags: { [key: string]: string[] } = {};\r\n\r\n // 洗牌处理标签\r\n const shuffled = (parsedOutput.tagGroup || []).map(group => {\r\n // 将默认标签和可选标签合并\r\n const allTags = [...(group.defaultTags || []), ...(group.optionalTags || [])];\r\n\r\n // Fisher-Yates 洗牌算法打乱标签顺序\r\n for (let i = allTags.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n [allTags[i], allTags[j]] = [allTags[j], allTags[i]];\r\n }\r\n\r\n // 设置默认选中的标签\r\n if (group.defaultTags && group.defaultTags.length > 0) {\r\n initialSelectedTags[group.dimensionName] = [...group.defaultTags];\r\n }\r\n\r\n return {\r\n dimensionName: group.dimensionName,\r\n tags: allTags\r\n };\r\n });\r\n\r\n this.shuffledTagGroups = shuffled;\r\n this.selectedAITags = initialSelectedTags;\r\n } catch (error) {\r\n SentryReporter.captureError(error, {\r\n action: 'handlePositionAnalysis',\r\n component: 'pcm-jd-modal',\r\n title: '解析前置标签时错误'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '解析前置标签时错误'\r\n });\r\n }\r\n }\r\n } catch (error) {\r\n console.error('工作流运行错误:', error);\r\n } finally {\r\n this.isLoading = false;\r\n }\r\n }\r\n\r\n private handleTagClick = (category: 'salary' | 'benefits' | 'education', value: string) => {\r\n if (category === 'benefits') {\r\n const currentTags = [...this.selectedTags.benefits];\r\n const newTags = currentTags.includes(value)\r\n ? currentTags.filter(t => t !== value)\r\n : [...currentTags, value];\r\n\r\n this.selectedTags = {\r\n ...this.selectedTags,\r\n benefits: newTags\r\n };\r\n } else {\r\n this.selectedTags = {\r\n ...this.selectedTags,\r\n [category]: this.selectedTags[category] === value ? '' : value\r\n };\r\n }\r\n };\r\n\r\n private handleAITagClick = (dimensionName: string, tag: string) => {\r\n const currentTags = this.selectedAITags[dimensionName] || [];\r\n const newTags = currentTags.includes(tag)\r\n ? currentTags.filter(t => t !== tag)\r\n : [...currentTags, tag];\r\n\r\n this.selectedAITags = {\r\n ...this.selectedAITags,\r\n [dimensionName]: newTags\r\n };\r\n };\r\n\r\n private handleSubmitStructured = async () => {\r\n this.isSubmitting = true;\r\n\r\n try {\r\n // 处理薪资范围标签\r\n let salaryRange = '';\r\n if (this.selectedTags.salary) {\r\n const range = this.salaryRanges.find(r => r.value === this.selectedTags.salary);\r\n if (range) {\r\n salaryRange = range.text;\r\n }\r\n }\r\n\r\n // 处理福利待遇标签\r\n const selectedBenefits = this.selectedTags.benefits.join('、');\r\n\r\n // 处理学历要求标签\r\n let education = '';\r\n if (this.selectedTags.education) {\r\n const edu = this.educationRequirements.find(e => e.value === this.selectedTags.education);\r\n if (edu) {\r\n education = edu.text;\r\n }\r\n }\r\n\r\n // 构建职位描述\r\n let jobInfo = `职位名称:${this.jobName}\\n`;\r\n\r\n if (salaryRange) {\r\n jobInfo += `薪资范围:${salaryRange}\\n`;\r\n }\r\n\r\n if (selectedBenefits) {\r\n jobInfo += `福利待遇:${selectedBenefits}\\n`;\r\n }\r\n\r\n if (education) {\r\n jobInfo += `学历要求:${education}\\n`;\r\n }\r\n\r\n // 添加AI标签\r\n Object.entries(this.selectedAITags).forEach(([dimension, tags]) => {\r\n if (tags.length > 0) {\r\n jobInfo += `${dimension}:${tags.join('、')}\\n`;\r\n }\r\n });\r\n\r\n // 显示聊天模态框\r\n this.showChatModal = true;\r\n this.jobDescription = jobInfo;\r\n } catch (error) {\r\n console.error('提交结构化数据时出错:', error);\r\n SentryReporter.captureError(error, {\r\n action: 'handleSubmitStructured',\r\n component: 'pcm-jd-modal',\r\n title: '提交数据时出错'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '提交数据时出错,请重试'\r\n });\r\n } finally {\r\n this.isSubmitting = false;\r\n }\r\n };\r\n\r\n private handleSubmitFree = async () => {\r\n if (!this.freeInputText.trim()) {\r\n alert('请输入职位需求信息');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n\r\n try {\r\n // 直接使用自由输入的文本作为职位描述\r\n this.jobDescription = this.freeInputText;\r\n\r\n // 显示聊天模态框\r\n this.showChatModal = true;\r\n } catch (error) {\r\n console.error('提交自由输入数据时出错:', error);\r\n SentryReporter.captureError(error, {\r\n action: 'handleSubmitFree',\r\n component: 'pcm-jd-modal',\r\n title: '提交数据时出错'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '提交数据时出错,请重试'\r\n });\r\n } finally {\r\n this.isSubmitting = false;\r\n }\r\n };\r\n\r\n @State() jobDescription: string = '';\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n this.jobName = '';\r\n this.freeInputText = '';\r\n this.step = 'input';\r\n this.inputMode = 'structured';\r\n this.tagGroups = [];\r\n this.shuffledTagGroups = [];\r\n this.selectedAITags = {};\r\n this.selectedTags = {\r\n salary: '',\r\n benefits: [],\r\n education: ''\r\n };\r\n } else {\r\n if (this.customInputs && this.customInputs.job_info) {\r\n this.jobDescription = this.customInputs.job_info;\r\n // 如果有 job_info,直接切换到自由输入模式并填充内容\r\n this.inputMode = 'free';\r\n this.freeInputText = this.customInputs.job_info;\r\n }\r\n await verifyApiKey(this.token);\r\n if (this.conversationId) {\r\n // 如果有会话ID,直接显示聊天模态框\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n\r\n // 渲染标签组\r\n private renderTagGroup(title: string, options: { text: string, value: string }[], category: 'salary' | 'benefits' | 'education') {\r\n return (\r\n <div class=\"tag-group\">\r\n <div class=\"tag-title\">{title}</div>\r\n <div class=\"tag-container\">\r\n {options.map(option => {\r\n const isSelected = category === 'benefits'\r\n ? this.selectedTags.benefits.includes(option.value)\r\n : this.selectedTags[category] === option.value;\r\n\r\n return (\r\n <div\r\n class={{\r\n 'tag': true,\r\n 'tag-selected': isSelected\r\n }}\r\n onClick={() => this.handleTagClick(category, option.value)}\r\n >\r\n {option.text}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染AI标签组\r\n private renderAITagGroups() {\r\n return (\r\n <div class=\"ai-tag-groups\">\r\n {this.shuffledTagGroups.map(group => (\r\n <div class=\"tag-group\">\r\n <div class=\"tag-title\">{group.dimensionName}</div>\r\n <div class=\"tag-container\">\r\n {group.tags.map(tag => {\r\n const isSelected = (this.selectedAITags[group.dimensionName] || []).includes(tag);\r\n return (\r\n <div\r\n class={{\r\n 'tag': true,\r\n 'tag-selected': isSelected\r\n }}\r\n onClick={() => this.handleAITagClick(group.dimensionName, tag)}\r\n >\r\n {tag}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n }\r\n\r\n // 渲染加载状态\r\n private renderLoadingState() {\r\n return (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <div class=\"loading-text\">\r\n <div>AI 正在分析职位信息</div>\r\n <div class=\"loading-subtext\">请稍候...</div>\r\n </div>\r\n </div>\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 修正这里的逻辑,确保当 customInputs.job_info 存在时不隐藏输入区域,而是显示自由输入模式\r\n const hideJdInput = false;\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 <div>{this.modalTitle}</div>\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 {/* 输入界面 - 仅在不显示聊天模态框且没有会话ID时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hideJdInput && (\r\n <div class=\"input-container\">\r\n {/* 输入模式切换 */}\r\n <div class=\"input-mode-toggle\">\r\n <span>职位需求信息</span>\r\n <button\r\n class=\"toggle-button\"\r\n onClick={this.handleToggleInput}\r\n disabled={this.isLoading}\r\n >\r\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" />\r\n </svg>\r\n 切换输入\r\n </button>\r\n </div>\r\n\r\n {/* 结构化输入模式 */}\r\n {this.inputMode === 'structured' && (\r\n <div class=\"structured-input\">\r\n {/* 第一步:输入职位名称 */}\r\n {this.step === 'input' && (\r\n <div class=\"job-name-input\">\r\n <label htmlFor=\"job-name\">\r\n 职位名称 <span class=\"required\">*</span>\r\n </label>\r\n <input\r\n id=\"job-name\"\r\n type=\"text\"\r\n placeholder=\"请输入职位名称\"\r\n value={this.jobName}\r\n onInput={this.handleJobNameChange}\r\n disabled={this.isLoading}\r\n />\r\n <div class=\"button-container\">\r\n <button\r\n class=\"submit-button next-button\"\r\n onClick={this.handleNextStep}\r\n disabled={!this.jobName.trim() || this.isLoading}\r\n >\r\n 下一步\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 第二步:选择标签 */}\r\n {this.step === 'review' && (\r\n <div class=\"tag-selection\">\r\n {this.isLoading ? (\r\n this.renderLoadingState()\r\n ) : (\r\n <div class=\"tag-selection-content\">\r\n {/* AI推荐标签 */}\r\n {this.tagGroups.length > 0 && (\r\n <div class=\"ai-tags-section\">\r\n <div class=\"section-title\">AI 推荐标签</div>\r\n {this.renderAITagGroups()}\r\n </div>\r\n )}\r\n\r\n {/* 基础标签 */}\r\n {this.tagGroups.length > 0 && (\r\n <div class=\"basic-tags-section\">\r\n {this.renderTagGroup('月薪范围', this.salaryRanges, 'salary')}\r\n {this.renderTagGroup('福利待遇', this.benefits, 'benefits')}\r\n {this.renderTagGroup('学历要求', this.educationRequirements, 'education')}\r\n </div>\r\n )}\r\n\r\n <div class=\"button-container\">\r\n <button\r\n class=\"submit-button prev-button\"\r\n onClick={this.handlePrevStep}\r\n >\r\n 上一步\r\n </button>\r\n <button\r\n class=\"submit-button\"\r\n onClick={this.handleSubmitStructured}\r\n disabled={this.isSubmitting}\r\n >\r\n {this.isSubmitting ? '处理中...' : '生成JD'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* 自由输入模式 */}\r\n {this.inputMode === 'free' && (\r\n <div class=\"free-input\">\r\n <div class=\"textarea-container\">\r\n <label htmlFor=\"free-input-text\">\r\n JD信息 <span class=\"required\">*</span>\r\n </label>\r\n <textarea\r\n id=\"free-input-text\"\r\n placeholder=\"请按照下方提示格式输入职位需求信息\"\r\n rows={8}\r\n value={this.freeInputText}\r\n onInput={this.handleFreeInputChange}\r\n ></textarea>\r\n </div>\r\n\r\n <div class=\"input-guide\">\r\n <div class=\"guide-title\">输入格式参考:</div>\r\n <div class=\"guide-content\">\r\n <div>• 职位名称 - 明确定义职位的名称</div>\r\n <div>• 薪资范围 - 明确该岗位的月薪或年薪</div>\r\n <div>• 福利待遇 - 该职位的福利待遇,如:五险一金、年休假、下午茶等</div>\r\n <div>• 工作职责 - 描述工作内容</div>\r\n <div>• 任职资格 - 包括学历、经验和技术要求</div>\r\n <div>• 工作地点与性质 - 全职/兼职、远程/办公室</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"button-container\">\r\n <button\r\n class=\"submit-button\"\r\n onClick={this.handleSubmitFree}\r\n disabled={!this.freeInputText.trim() || this.isSubmitting}\r\n >\r\n {this.isSubmitting ? '处理中...' : '生成JD'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div>\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018873\"\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n job_info: this.customInputs?.job_info || this.jobDescription\r\n }}\r\n interviewMode=\"text\"\r\n showSaveJdButton={this.showSaveJdButton}\r\n saveJdButtonText={this.saveJdButtonText}\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",null,"/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../interfaces/events';\r\nimport { ErrorEventDetail, ErrorEventBus } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { Message } from '../../services/message.service';\r\n\r\n/**\r\n * 简历匹配\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-jlpp-modal',\r\n styleUrls: ['pcm-jlpp-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class JlppModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '简历剖析助手';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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\r\n /**\r\n * 自定义输入参数,传入customInputs.job_info时,会隐藏JD输入区域<br>\r\n * 传入customInputs.file_url时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_url和customInputs.job_info时,会直接开始聊天。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历(仅PC端生效)\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端输入职位描述(仅PC端生效)\r\n */\r\n @Prop() mobileJdInputAble: boolean = false;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n private pcmUploadRef;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n\r\n } else {\r\n if (this.customInputs && this.customInputs.job_info) {\r\n this.jobDescription = this.customInputs.job_info;\r\n }\r\n await verifyApiKey(this.token);\r\n \r\n // 如果有会话ID或者同时有 file_url 和 job_info,直接显示聊天模态框\r\n if (this.conversationId || (this.customInputs?.file_url && this.customInputs?.job_info)) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n \r\n componentWillLoad() {\r\n\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n \r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n\r\n\r\n private handleJobDescriptionChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.jobDescription = textarea.value;\r\n };\r\n\r\n private handleStartAnalysis = async () => {\r\n // 既没有预设 file_url,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.uploadedFileInfo) {\r\n Message.info('请上传简历');\r\n return;\r\n }\r\n\r\n // 如果没有预设的job_info,则需要检查用户输入\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n Message.info('请输入职位描述');\r\n return;\r\n }\r\n\r\n // 判断文件是否正在上传\r\n if (await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n this.isSubmitting = false;\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 确保当 customInputs.job_info 存在时,hideJdInput 为 true\r\n const hideJdInput = Boolean(this.customInputs && this.customInputs.job_info);\r\n \r\n // 判断是否隐藏简历上传区域\r\n const hideResumeUpload = Boolean(this.customInputs && this.customInputs.file_url);\r\n \r\n // 判断是否同时提供了file_url和job_info\r\n const hasFileAndJob = Boolean(this.customInputs?.file_url && this.customInputs?.job_info);\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 <div>{this.modalTitle}</div>\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 {/* 输入界面 - 仅在不显示聊天模态框且没有会话ID且没有同时提供file_url和job_info时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hasFileAndJob && (\r\n <div class=\"input-container\">\r\n {/* JD输入区域 - 仅在没有parsedCustomInputs.job_info时显示 */}\r\n {!hideJdInput && (\r\n <div class=\"jd-input-section\">\r\n <label htmlFor=\"job-description\">请输入职位描述 (JD)</label>\r\n {\r\n !!this.mobileJdInputAble && (\r\n <pcm-mobile-input-btn\r\n name=\"职位描述\"\r\n onOk={(e) => {\r\n this.jobDescription = e.detail;\r\n }}\r\n />\r\n )\r\n }\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder=\"请输入职位描述,包括职责、要求等信息...\"\r\n rows={6}\r\n value={this.jobDescription}\r\n onInput={this.handleJobDescriptionChange}\r\n ></textarea>\r\n </div>\r\n )}\r\n\r\n {/* 简历上传区域 - 仅在没有customInputs.file_url时显示 */}\r\n {!hideResumeUpload && (\r\n <div class=\"resume-upload-section\">\r\n <label>上传简历</label>\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\r\n mobileUploadAble={this.mobileUploadAble}\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['resume'],\r\n }}\r\n onUploadChange={(e) => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(!hideResumeUpload && !this.uploadedFileInfo) || (!hideJdInput && !this.jobDescription.trim()) || this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartAnalysis}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始分析'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018881\"\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription\r\n }}\r\n interviewMode=\"text\"\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ","/* 任务界面专用样式 */\r\n.pc-layout{\r\n max-width:none;\r\n}\r\n/* 任务布局容器 */\r\n.task-layout {\r\n width: 90%;\r\n max-width: 1200px;\r\n min-width: 800px;\r\n}\r\n\r\n@media screen and (max-width: 1024px) {\r\n .task-layout {\r\n width: 95%;\r\n min-width: 320px;\r\n }\r\n}\r\n\r\n/* 任务容器 */\r\n.task-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n overflow-y: auto;\r\n gap: 20px;\r\n}\r\n\r\n.upload-area{\r\n max-height: 300px;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 步骤头部 */\r\n.step-header {\r\n text-align: center;\r\n margin-bottom: 24px;\r\n}\r\n\r\n.step-header h3 {\r\n margin: 0 0 8px 0;\r\n font-size: 20px;\r\n color: #333;\r\n}\r\n\r\n.step-description {\r\n margin: 0;\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n/* 步骤指示器 */\r\n.step-indicator {\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n margin-left: 8px;\r\n}\r\n\r\n/* 评分标准输入区域 */\r\n.criteria-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.criteria-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 任务信息展示区域 */\r\n.task-info-section {\r\n flex-shrink: 0;\r\n}\r\n\r\n.info-cards {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 16px;\r\n}\r\n\r\n@media screen and (max-width: 768px) {\r\n .info-cards {\r\n grid-template-columns: 1fr;\r\n }\r\n}\r\n\r\n.info-card {\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n background: #fff;\r\n}\r\n\r\n.card-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background: #fafafa;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.card-header:hover {\r\n background: #f0f0f0;\r\n}\r\n\r\n.card-title {\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.toggle-btn {\r\n background: transparent;\r\n border: none;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.toggle-btn:hover {\r\n background: rgba(24, 144, 255, 0.1);\r\n}\r\n\r\n.card-content {\r\n padding: 16px;\r\n border-top: 1px solid #e8e8e8;\r\n max-height: 120px;\r\n overflow-y: auto;\r\n}\r\n\r\n.card-content p {\r\n margin: 0;\r\n line-height: 1.6;\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n/* 卡片预览区域 */\r\n.card-preview {\r\n padding: 12px 16px;\r\n border-top: 1px solid #e8e8e8;\r\n}\r\n\r\n.preview-text {\r\n margin: 0;\r\n line-height: 1.5;\r\n color: #666;\r\n font-size: 14px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n/* 抽屉内容样式 */\r\n.drawer-text-content {\r\n line-height: 1.6;\r\n color: #333;\r\n font-size: 14px;\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n}\r\n\r\n/* 上传区域 */\r\n.upload-section {\r\n flex-shrink: 0;\r\n}\r\n\r\n.section-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin-bottom: 12px;\r\n flex-shrink: 0;\r\n}\r\n\r\n.section-header-side {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.export-actions {\r\n height: 32px;\r\n display: flex;\r\n border-radius: 6px;\r\n background-color: white;\r\n border: 1px solid #1890ff;\r\n overflow: hidden;\r\n margin-right: 16px;\r\n color: #1890ff;\r\n font-size: 14px;\r\n font-weight: bold;\r\n}\r\n\r\n.export-btn {\r\n width: 128px;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.export-btn:hover {\r\n background-color: #f5f5f5;\r\n cursor: pointer;\r\n}\r\n\r\n.export-divide {\r\n width: 1px;\r\n height: 100%;\r\n background-color: #1890ff;\r\n}\r\n\r\n.section-header h4 {\r\n margin: 0;\r\n font-size: 16px;\r\n color: #333;\r\n}\r\n\r\n.count-badge {\r\n background: #1890ff;\r\n color: white;\r\n padding: 2px 8px;\r\n border-radius: 12px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n}\r\n\r\n.analyze-btn {\r\n padding: 8px 16px;\r\n background: #52c41a;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n font-size: 14px;\r\n}\r\n\r\n.analyze-btn:hover {\r\n background: #73d13d;\r\n}\r\n\r\n.analyze-btn:disabled {\r\n background: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* 简历表格区域 */\r\n.resume-table-section {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 0;\r\n}\r\n\r\n.table-container {\r\n flex: 1;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n background: white;\r\n overflow-x: auto;\r\n min-height: 400px;\r\n}\r\n\r\n.resume-table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n font-size: 14px;\r\n}\r\n\r\n.resume-table th {\r\n background: #fafafa;\r\n padding: 12px 16px;\r\n text-align: left;\r\n font-weight: 500;\r\n color: #333;\r\n border-bottom: 1px solid #e8e8e8;\r\n}\r\n\r\n.resume-table td {\r\n padding: 12px 16px;\r\n vertical-align: middle;\r\n height: 60px;\r\n}\r\n\r\n.resume-table tr {\r\n border-bottom: 1px solid #f0f0f0;\r\n height: 60px;\r\n}\r\n.resume-table tr:hover {\r\n background: #f9f9f9;\r\n}\r\n\r\n/* 表格单元格样式 */\r\n.filename-cell {\r\n max-width: 200px;\r\n height: 100%;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.filename-cell span:last-child {\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.talent-info-cell {\r\n max-width: 180px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n\r\n.score-badge {\r\n display: inline-block;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n font-weight: 500;\r\n font-size: 12px;\r\n}\r\n\r\n.score-badge.excellent {\r\n background: #f6ffed;\r\n color: #52c41a;\r\n border: 1px solid #b7eb8f;\r\n}\r\n\r\n.score-badge.good {\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n border: 1px solid #91d5ff;\r\n}\r\n\r\n.score-badge.average {\r\n background: #fff7e6;\r\n color: #fa8c16;\r\n border: 1px solid #ffd591;\r\n}\r\n\r\n.score-badge.below-average {\r\n background: #fff1f0;\r\n color: #f5222d;\r\n border: 1px solid #ffa39e;\r\n}\r\n\r\n.score-badge.poor {\r\n background: #f5f5f5;\r\n color: #8c8c8c;\r\n border: 1px solid #d9d9d9;\r\n}\r\n\r\n\r\n.status-badge {\r\n display: inline-block;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n font-weight: 500;\r\n font-size: 12px;\r\n}\r\n\r\n.status-badge.status-pending {\r\n background: #f0f0f0;\r\n color: #8c8c8c;\r\n border: 1px solid #d9d9d9;\r\n}\r\n\r\n.status-badge.status-analyzing {\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n border: 1px solid #91d5ff;\r\n}\r\n\r\n.status-badge.status-completed {\r\n background: #f6ffed;\r\n color: #52c41a;\r\n border: 1px solid #b7eb8f;\r\n}\r\n\r\n.status-badge.status-failed {\r\n background: #fff1f0;\r\n color: #f5222d;\r\n border: 1px solid #ffa39e;\r\n}\r\n\r\n.detail-cell {\r\n max-width: 200px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.detail-content {\r\n cursor: pointer;\r\n transition: color 0.2s;\r\n}\r\n\r\n.detail-content:hover {\r\n color: #40a9ff;\r\n}\r\n\r\n.action-cell {\r\n display: flex;\r\n gap: 8px;\r\n position: relative;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n}\r\n\r\n.action-dropdown {\r\n position: relative;\r\n display: inline-block;\r\n}\r\n\r\n.dropdown-trigger {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 6px 12px;\r\n background: #f0f0f0;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 12px;\r\n color: #595959;\r\n transition: all 0.2s;\r\n min-width: 60px;\r\n justify-content: center;\r\n}\r\n\r\n.dropdown-trigger:hover {\r\n background: #e6e6e6;\r\n border-color: #bfbfbf;\r\n color: #333;\r\n}\r\n\r\n.dropdown-trigger svg {\r\n transition: transform 0.2s;\r\n margin-left: 4px;\r\n}\r\n\r\n.dropdown-menu {\r\n position: absolute;\r\n top: 100%;\r\n right: 0;\r\n z-index: 9999;\r\n min-width: 120px;\r\n background: white;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n overflow: hidden;\r\n margin-top: 4px;\r\n}\r\n\r\n.dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 12px;\r\n font-size: 14px;\r\n color: #333;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n border-bottom: 1px solid #f5f5f5;\r\n white-space: nowrap;\r\n}\r\n\r\n.dropdown-item:last-child {\r\n border-bottom: none;\r\n}\r\n\r\n.dropdown-item:hover {\r\n background: #f5f5f5;\r\n}\r\n\r\n.dropdown-item.danger {\r\n color: #f5222d;\r\n}\r\n\r\n.dropdown-item.danger:hover {\r\n background: #fff1f0;\r\n color: #cf1322;\r\n}\r\n\r\n.dropdown-item svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n.view-btn {\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n}\r\n\r\n.view-btn:hover {\r\n background: #bae7ff;\r\n}\r\n\r\n.delete-btn {\r\n background: #fff1f0;\r\n color: #f5222d;\r\n}\r\n\r\n.delete-btn:hover {\r\n background: #ffccc7;\r\n}\r\n\r\n/* 空状态 */\r\n.empty-row {\r\n text-align: center;\r\n padding: 40px 20px !important;\r\n border-bottom: none !important;\r\n}\r\n\r\n.empty-state {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 8px;\r\n color: #999;\r\n}\r\n\r\n.empty-state p {\r\n margin: 0;\r\n}\r\n\r\n.empty-hint {\r\n font-size: 12px;\r\n}\r\n\r\n/* 响应式表格 */\r\n@media screen and (max-width: 768px) {\r\n .task-container {\r\n padding: 16px;\r\n gap: 16px;\r\n }\r\n \r\n .resume-table {\r\n font-size: 12px;\r\n }\r\n \r\n .resume-table th,\r\n .resume-table td {\r\n padding: 8px 12px;\r\n }\r\n \r\n .filename-cell,\r\n .talent-info-cell,\r\n .detail-cell {\r\n max-width: 120px;\r\n }\r\n \r\n .action-cell {\r\n flex-direction: column;\r\n gap: 4px;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 80px;\r\n height: 100%;\r\n }\r\n \r\n .dropdown-trigger {\r\n min-width: 50px;\r\n padding: 4px 8px;\r\n font-size: 11px;\r\n }\r\n}\r\n\r\n/* 评分标准表格样式 */\r\n.criteria-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.criteria-header label {\r\n margin: 0;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.criteria-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.total-weight {\r\n font-size: 14px;\r\n color: #52c41a;\r\n font-weight: 500;\r\n}\r\n\r\n.total-weight.invalid {\r\n color: #f5222d;\r\n}\r\n\r\n.add-criteria-btn {\r\n padding: 6px 12px;\r\n background: #1890ff;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.add-criteria-btn:hover {\r\n background: #40a9ff;\r\n}\r\n\r\n.criteria-table-container {\r\n border: 1px solid #e8e8e8;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n background: white;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.criteria-table {\r\n width: 100%;\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n font-size: 14px;\r\n}\r\n\r\n.criteria-table th {\r\n background: #fafafa;\r\n padding: 12px 16px;\r\n text-align: left;\r\n font-weight: 500;\r\n color: #333;\r\n border-bottom: 1px solid #e8e8e8;\r\n border-right: 1px solid #e8e8e8;\r\n font-size: 13px;\r\n vertical-align: middle;\r\n}\r\n\r\n.criteria-table th:last-child {\r\n border-right: none;\r\n}\r\n\r\n.criteria-table td {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n border-right: 1px solid #f0f0f0;\r\n vertical-align: middle;\r\n}\r\n\r\n.criteria-table td:last-child {\r\n border-right: none;\r\n}\r\n\r\n.criteria-table tr:last-child td {\r\n border-bottom: none;\r\n}\r\n\r\n.criteria-name-input {\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n outline: none;\r\n transition: border-color 0.2s;\r\n box-sizing: border-box;\r\n}\r\n\r\n.criteria-name-input:focus {\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.criteria-value-input {\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n outline: none;\r\n transition: border-color 0.2s;\r\n text-align: center;\r\n box-sizing: border-box;\r\n}\r\n\r\n.criteria-value-input:focus {\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.criteria-description-input {\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n outline: none;\r\n resize: vertical;\r\n min-height: 80px;\r\n line-height: 1.5;\r\n transition: border-color 0.2s;\r\n box-sizing: border-box;\r\n}\r\n\r\n.criteria-description-input:focus {\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.remove-criteria-btn {\r\n width: 28px;\r\n height: 28px;\r\n background: #fff1f0;\r\n color: #f5222d;\r\n border: 1px solid #ffa39e;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 16px;\r\n font-weight: bold;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: all 0.2s;\r\n margin: 0 auto;\r\n}\r\n\r\n.remove-criteria-btn:hover:not(:disabled) {\r\n background: #ffccc7;\r\n border-color: #ff7875;\r\n}\r\n\r\n.remove-criteria-btn:disabled {\r\n background: #f5f5f5;\r\n color: #bfbfbf;\r\n border-color: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n.criteria-warning {\r\n color: #fa8c16;\r\n font-size: 13px;\r\n margin: 8px 0 0 0;\r\n padding: 8px 12px;\r\n background: #fff7e6;\r\n border: 1px solid #ffd591;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .criteria-header {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 8px;\r\n }\r\n \r\n .criteria-actions {\r\n width: 100%;\r\n justify-content: space-between;\r\n }\r\n \r\n .criteria-table th,\r\n .criteria-table td {\r\n padding: 10px 8px;\r\n font-size: 12px;\r\n vertical-align: middle;\r\n }\r\n \r\n .criteria-table th:nth-child(1) { width: 20%; }\r\n .criteria-table th:nth-child(2) { width: 15%; }\r\n .criteria-table th:nth-child(3) { width: 55%; }\r\n .criteria-table th:nth-child(4) { width: 10%; }\r\n \r\n .criteria-name-input,\r\n .criteria-value-input,\r\n .criteria-description-input {\r\n font-size: 12px;\r\n padding: 6px 8px;\r\n }\r\n \r\n .criteria-description-input {\r\n min-height: 60px;\r\n }\r\n \r\n .remove-criteria-btn {\r\n width: 24px;\r\n height: 24px;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n/* 表格排序样式 */\r\n.sortable-header {\r\n cursor: pointer !important;\r\n user-select: none;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.sortable-header:hover {\r\n background: #f0f0f0 !important;\r\n}\r\n\r\n.sortable-header.active {\r\n background: #e6f7ff !important;\r\n color: #1890ff;\r\n}\r\n\r\n.header-content {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: 100%;\r\n}\r\n\r\n.sort-icons {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 1px;\r\n margin-left: 8px;\r\n opacity: 0.6;\r\n}\r\n\r\n.sortable-header:hover .sort-icons {\r\n opacity: 1;\r\n}\r\n\r\n.sort-icon {\r\n transition: color 0.2s;\r\n color: #bfbfbf;\r\n}\r\n\r\n.sort-icon.active {\r\n color: #1890ff;\r\n}\r\n\r\n/* 分页样式 */\r\n.pagination {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 16px;\r\n padding: 20px 0;\r\n margin-top: 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.page-btn {\r\n padding: 8px 16px;\r\n background: #fff;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: #333;\r\n transition: all 0.2s;\r\n min-width: 80px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 36px;\r\n}\r\n\r\n.page-btn:hover:not(:disabled) {\r\n border-color: #40a9ff;\r\n color: #40a9ff;\r\n background: #f6f8ff;\r\n}\r\n\r\n.page-btn:disabled {\r\n background: #f5f5f5;\r\n border-color: #d9d9d9;\r\n color: #bfbfbf;\r\n cursor: not-allowed;\r\n}\r\n\r\n.page-info {\r\n font-size: 14px;\r\n color: #666;\r\n padding: 0 16px;\r\n display: flex;\r\n align-items: center;\r\n height: 36px;\r\n white-space: nowrap;\r\n}\r\n\r\n/* 移动端分页适配 */\r\n@media screen and (max-width: 768px) {\r\n .pagination {\r\n gap: 12px;\r\n padding: 16px 0;\r\n flex-wrap: wrap;\r\n }\r\n \r\n .page-btn {\r\n min-width: 70px;\r\n padding: 6px 12px;\r\n font-size: 13px;\r\n height: 32px;\r\n }\r\n \r\n .page-info {\r\n font-size: 13px;\r\n padding: 0 8px;\r\n height: 32px;\r\n order: 3;\r\n width: 100%;\r\n justify-content: center;\r\n margin-top: 8px;\r\n }\r\n}\r\n\r\n/* 任务管理相关样式 */\r\n.step-indicator.clickable {\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.step-indicator.clickable:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n/* 任务历史抽屉内容 */\r\n.task-history-drawer-content {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n}\r\n\r\n.task-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px 0;\r\n}\r\n\r\n.loading-tasks,\r\n.empty-tasks {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px 20px;\r\n color: #666;\r\n}\r\n\r\n.loading-spinner-small {\r\n width: 24px;\r\n height: 24px;\r\n border: 2px solid #f0f0f0;\r\n border-top: 2px solid #1890ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 12px;\r\n}\r\n\r\n@keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n}\r\n\r\n.task-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 16px;\r\n margin-bottom: 8px;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n background: #fff;\r\n}\r\n\r\n.task-item:hover {\r\n border-color: #1890ff;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n.task-item.active {\r\n border-color: #1890ff;\r\n background: #f6ffed;\r\n box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);\r\n}\r\n\r\n.task-info {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.task-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.task-id {\r\n font-weight: 600;\r\n color: #333;\r\n font-size: 14px;\r\n}\r\n\r\n.task-time {\r\n font-size: 12px;\r\n color: #666;\r\n}\r\n\r\n.task-job-info {\r\n font-size: 14px;\r\n color: #333;\r\n margin-bottom: 8px;\r\n line-height: 1.4;\r\n word-break: break-word;\r\n}\r\n\r\n.task-meta {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.resume-count {\r\n font-size: 12px;\r\n color: #666;\r\n background: #f5f5f5;\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n}\r\n\r\n.current-task-indicator {\r\n flex-shrink: 0;\r\n margin-left: 12px;\r\n color: #52c41a;\r\n}\r\n\r\n.current-task-indicator svg {\r\n width: 16px;\r\n height: 16px;\r\n}\r\n\r\n/* 任务分页 */\r\n.task-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 16px;\r\n padding: 16px;\r\n border-top: 1px solid #e8e8e8;\r\n background: #fafafa;\r\n flex-shrink: 0;\r\n}\r\n\r\n.task-pagination .page-btn {\r\n background: #fff;\r\n border: 1px solid #d9d9d9;\r\n color: #333;\r\n padding: 6px 12px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.task-pagination .page-btn:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n}\r\n\r\n.task-pagination .page-btn:disabled {\r\n background: #f5f5f5;\r\n color: #bfbfbf;\r\n cursor: not-allowed;\r\n border-color: #e8e8e8;\r\n}\r\n\r\n.task-pagination .page-info {\r\n font-size: 14px;\r\n color: #666;\r\n}\r\n\r\n/* 响应式设计 */\r\n@media screen and (max-width: 768px) {\r\n .task-item {\r\n padding: 12px;\r\n }\r\n \r\n .task-header {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 4px;\r\n }\r\n \r\n .task-job-info {\r\n font-size: 13px;\r\n margin-bottom: 6px;\r\n }\r\n \r\n .task-pagination {\r\n padding: 12px;\r\n gap: 12px;\r\n }\r\n \r\n .task-pagination .page-btn {\r\n padding: 8px 12px;\r\n font-size: 13px;\r\n }\r\n \r\n .task-pagination .page-info {\r\n font-size: 13px;\r\n }\r\n}\r\n\r\n.pcm-jlsx-card {\r\n margin-bottom: 20px;\r\n background-color: #ffffff;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.pcm-jlsx-card-header {\r\n padding: 12px 20px;\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: #333;\r\n border-bottom: 1px solid #e9ecef;\r\n}\r\n\r\n.pcm-jlsx-card-body {\r\n padding: 20px;\r\n font-size: 14px;\r\n color: #333;\r\n line-height: 1.6;\r\n white-space: pre-wrap;\r\n word-wrap: break-word;\r\n}\r\n\r\n.out-important-conditions {\r\n margin-top: 8px;\r\n color: #666;\r\n font-size: 12px;\r\n}\r\n","\r\n.markdown-body {\r\n --base-size-4: 4px;\r\n --base-size-8: 8px;\r\n --base-size-16: 16px;\r\n --base-size-24: 24px;\r\n --base-size-40: 40px;\r\n --base-text-weight-normal: 400;\r\n --base-text-weight-medium: 500;\r\n --base-text-weight-semibold: 600;\r\n --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;\r\n --fgColor-accent: Highlight;\r\n }\r\n \r\n @media (prefers-color-scheme: dark) {\r\n \r\n .markdown-body,\r\n [data-theme=\"dark\"] {\r\n /* dark */\r\n color-scheme: dark;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n @media (prefers-color-scheme: light) {\r\n \r\n .markdown-body,\r\n [data-theme=\"light\"] {\r\n /* light */\r\n color-scheme: light;\r\n --focus-outlineColor: #0969da;\r\n --fgColor-default: #1f2328;\r\n --fgColor-muted: #59636e;\r\n --fgColor-accent: #0969da;\r\n --fgColor-success: #1a7f37;\r\n --fgColor-attention: #9a6700;\r\n --fgColor-danger: #d1242f;\r\n --fgColor-done: #8250df;\r\n --bgColor-default: #ffffff;\r\n --bgColor-muted: #f6f8fa;\r\n --bgColor-neutral-muted: #818b981f;\r\n --bgColor-attention-muted: #fff8c5;\r\n --borderColor-default: #d1d9e0;\r\n --borderColor-muted: #d1d9e0b3;\r\n --borderColor-neutral-muted: #d1d9e0b3;\r\n --borderColor-accent-emphasis: #0969da;\r\n --borderColor-success-emphasis: #1a7f37;\r\n --borderColor-attention-emphasis: #9a6700;\r\n --borderColor-danger-emphasis: #cf222e;\r\n --borderColor-done-emphasis: #8250df;\r\n --color-prettylights-syntax-comment: #59636e;\r\n --color-prettylights-syntax-constant: #0550ae;\r\n --color-prettylights-syntax-constant-other-reference-link: #0a3069;\r\n --color-prettylights-syntax-entity: #6639ba;\r\n --color-prettylights-syntax-storage-modifier-import: #1f2328;\r\n --color-prettylights-syntax-entity-tag: #0550ae;\r\n --color-prettylights-syntax-keyword: #cf222e;\r\n --color-prettylights-syntax-string: #0a3069;\r\n --color-prettylights-syntax-variable: #953800;\r\n --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;\r\n --color-prettylights-syntax-brackethighlighter-angle: #59636e;\r\n --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;\r\n --color-prettylights-syntax-invalid-illegal-bg: #82071e;\r\n --color-prettylights-syntax-carriage-return-text: #f6f8fa;\r\n --color-prettylights-syntax-carriage-return-bg: #cf222e;\r\n --color-prettylights-syntax-string-regexp: #116329;\r\n --color-prettylights-syntax-markup-list: #3b2300;\r\n --color-prettylights-syntax-markup-heading: #0550ae;\r\n --color-prettylights-syntax-markup-italic: #1f2328;\r\n --color-prettylights-syntax-markup-bold: #1f2328;\r\n --color-prettylights-syntax-markup-deleted-text: #82071e;\r\n --color-prettylights-syntax-markup-deleted-bg: #ffebe9;\r\n --color-prettylights-syntax-markup-inserted-text: #116329;\r\n --color-prettylights-syntax-markup-inserted-bg: #dafbe1;\r\n --color-prettylights-syntax-markup-changed-text: #953800;\r\n --color-prettylights-syntax-markup-changed-bg: #ffd8b5;\r\n --color-prettylights-syntax-markup-ignored-text: #d1d9e0;\r\n --color-prettylights-syntax-markup-ignored-bg: #0550ae;\r\n --color-prettylights-syntax-meta-diff-range: #8250df;\r\n --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;\r\n }\r\n }\r\n \r\n .markdown-body {\r\n -ms-text-size-adjust: 100%;\r\n -webkit-text-size-adjust: 100%;\r\n margin: 0;\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Noto Sans\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\";\r\n font-size: 16px;\r\n line-height: 1.5;\r\n word-wrap: break-word;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n fill: currentColor;\r\n vertical-align: text-bottom;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link:before,\r\n .markdown-body h2:hover .anchor .octicon-link:before,\r\n .markdown-body h3:hover .anchor .octicon-link:before,\r\n .markdown-body h4:hover .anchor .octicon-link:before,\r\n .markdown-body h5:hover .anchor .octicon-link:before,\r\n .markdown-body h6:hover .anchor .octicon-link:before {\r\n width: 16px;\r\n height: 16px;\r\n content: ' ';\r\n display: inline-block;\r\n background-color: currentColor;\r\n -webkit-mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n mask-image: url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>\");\r\n }\r\n \r\n .markdown-body details,\r\n .markdown-body figcaption,\r\n .markdown-body figure {\r\n display: block;\r\n }\r\n \r\n .markdown-body summary {\r\n display: list-item;\r\n }\r\n \r\n .markdown-body [hidden] {\r\n display: none !important;\r\n }\r\n \r\n .markdown-body a {\r\n background-color: transparent;\r\n color: var(--fgColor-accent);\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body abbr[title] {\r\n border-bottom: none;\r\n -webkit-text-decoration: underline dotted;\r\n text-decoration: underline dotted;\r\n }\r\n \r\n .markdown-body b,\r\n .markdown-body strong {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dfn {\r\n font-style: italic;\r\n }\r\n \r\n .markdown-body h1 {\r\n margin: .67em 0;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.5em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body mark {\r\n background-color: var(--bgColor-attention-muted);\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body small {\r\n font-size: 90%;\r\n }\r\n \r\n .markdown-body sub,\r\n .markdown-body sup {\r\n font-size: 75%;\r\n line-height: 0;\r\n position: relative;\r\n vertical-align: baseline;\r\n }\r\n \r\n .markdown-body sub {\r\n bottom: -0.25em;\r\n }\r\n \r\n .markdown-body sup {\r\n top: -0.5em;\r\n }\r\n \r\n .markdown-body img {\r\n border-style: none;\r\n max-width: 100%;\r\n box-sizing: content-box;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body kbd,\r\n .markdown-body pre,\r\n .markdown-body samp {\r\n font-family: monospace;\r\n font-size: 1em;\r\n }\r\n \r\n .markdown-body figure {\r\n margin: 1em var(--base-size-40);\r\n }\r\n \r\n .markdown-body hr {\r\n box-sizing: content-box;\r\n overflow: hidden;\r\n background: transparent;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n height: .25em;\r\n padding: 0;\r\n margin: var(--base-size-24) 0;\r\n background-color: var(--borderColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body input {\r\n font: inherit;\r\n margin: 0;\r\n overflow: visible;\r\n font-family: inherit;\r\n font-size: inherit;\r\n line-height: inherit;\r\n }\r\n \r\n .markdown-body [type=button],\r\n .markdown-body [type=reset],\r\n .markdown-body [type=submit] {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n }\r\n \r\n .markdown-body [type=checkbox],\r\n .markdown-body [type=radio] {\r\n box-sizing: border-box;\r\n padding: 0;\r\n }\r\n \r\n .markdown-body [type=number]::-webkit-inner-spin-button,\r\n .markdown-body [type=number]::-webkit-outer-spin-button {\r\n height: auto;\r\n }\r\n \r\n .markdown-body [type=search]::-webkit-search-cancel-button,\r\n .markdown-body [type=search]::-webkit-search-decoration {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body ::-webkit-input-placeholder {\r\n color: inherit;\r\n opacity: .54;\r\n }\r\n \r\n .markdown-body ::-webkit-file-upload-button {\r\n -webkit-appearance: button;\r\n appearance: button;\r\n font: inherit;\r\n }\r\n \r\n .markdown-body a:hover {\r\n text-decoration: underline;\r\n }\r\n \r\n .markdown-body ::placeholder {\r\n color: var(--fgColor-muted);\r\n opacity: 1;\r\n }\r\n \r\n .markdown-body hr::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body hr::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body table {\r\n border-spacing: 0;\r\n border-collapse: collapse;\r\n display: block;\r\n width: max-content;\r\n max-width: 100%;\r\n overflow: auto;\r\n font-variant: tabular-nums;\r\n }\r\n \r\n .markdown-body td,\r\n .markdown-body th {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body details summary {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body a:focus,\r\n .markdown-body [role=button]:focus,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=checkbox]:focus {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:focus:not(:focus-visible),\r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body input[type=radio]:focus:not(:focus-visible),\r\n .markdown-body input[type=checkbox]:focus:not(:focus-visible) {\r\n outline: solid 1px transparent;\r\n }\r\n \r\n .markdown-body a:focus-visible,\r\n .markdown-body [role=button]:focus-visible,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline: 2px solid var(--focus-outlineColor);\r\n outline-offset: -2px;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body a:not([class]):focus,\r\n .markdown-body a:not([class]):focus-visible,\r\n .markdown-body input[type=radio]:focus,\r\n .markdown-body input[type=radio]:focus-visible,\r\n .markdown-body input[type=checkbox]:focus,\r\n .markdown-body input[type=checkbox]:focus-visible {\r\n outline-offset: 0;\r\n }\r\n \r\n .markdown-body kbd {\r\n display: inline-block;\r\n padding: var(--base-size-4);\r\n font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n line-height: 10px;\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n background-color: var(--bgColor-muted);\r\n border: solid 1px var(--borderColor-neutral-muted);\r\n border-bottom-color: var(--borderColor-neutral-muted);\r\n border-radius: 6px;\r\n box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted);\r\n }\r\n \r\n .markdown-body h1,\r\n .markdown-body h2,\r\n .markdown-body h3,\r\n .markdown-body h4,\r\n .markdown-body h5,\r\n .markdown-body h6 {\r\n margin-top: var(--base-size-24);\r\n margin-bottom: var(--base-size-16);\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n line-height: 1.25;\r\n }\r\n \r\n .markdown-body h2 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n padding-bottom: .3em;\r\n font-size: 1.2em;\r\n border-bottom: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body h3 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 1.05em;\r\n }\r\n \r\n .markdown-body h4 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: 0.875em;\r\n }\r\n \r\n .markdown-body h5 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .85em;\r\n }\r\n \r\n .markdown-body h6 {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n font-size: .80em;\r\n color: var(--fgColor-muted);\r\n }\r\n \r\n .markdown-body p {\r\n margin-top: 0;\r\n margin-bottom: 10px;\r\n }\r\n \r\n .markdown-body blockquote {\r\n margin: 0;\r\n padding: 0 1em;\r\n color: var(--fgColor-muted);\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body ul,\r\n .markdown-body ol {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n padding-left: 2em;\r\n }\r\n \r\n .markdown-body ol ol,\r\n .markdown-body ul ol {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ul ul ol,\r\n .markdown-body ul ol ol,\r\n .markdown-body ol ul ol,\r\n .markdown-body ol ol ol {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body dd {\r\n margin-left: 0;\r\n }\r\n \r\n .markdown-body tt,\r\n .markdown-body code,\r\n .markdown-body samp {\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n }\r\n \r\n .markdown-body pre {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);\r\n font-size: 12px;\r\n word-wrap: normal;\r\n }\r\n \r\n .markdown-body .octicon {\r\n display: inline-block;\r\n overflow: visible !important;\r\n vertical-align: text-bottom;\r\n fill: currentColor;\r\n }\r\n \r\n .markdown-body input::-webkit-outer-spin-button,\r\n .markdown-body input::-webkit-inner-spin-button {\r\n margin: 0;\r\n appearance: none;\r\n }\r\n \r\n .markdown-body .mr-2 {\r\n margin-right: var(--base-size-8, 8px) !important;\r\n }\r\n \r\n .markdown-body::before {\r\n display: table;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body::after {\r\n display: table;\r\n clear: both;\r\n content: \"\";\r\n }\r\n \r\n .markdown-body>*:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body>*:last-child {\r\n margin-bottom: 0 !important;\r\n }\r\n \r\n .markdown-body a:not([href]) {\r\n color: inherit;\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body .absent {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body .anchor {\r\n float: left;\r\n padding-right: var(--base-size-4);\r\n margin-left: -20px;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .anchor:focus {\r\n outline: none;\r\n }\r\n \r\n .markdown-body p,\r\n .markdown-body blockquote,\r\n .markdown-body ul,\r\n .markdown-body ol,\r\n .markdown-body dl,\r\n .markdown-body table,\r\n .markdown-body pre,\r\n .markdown-body details {\r\n margin-top: 0;\r\n margin-bottom: var(--base-size-16);\r\n font-size: 16px;\r\n font-weight: 400;\r\n }\r\n \r\n .markdown-body blockquote>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body blockquote>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body h1 .octicon-link,\r\n .markdown-body h2 .octicon-link,\r\n .markdown-body h3 .octicon-link,\r\n .markdown-body h4 .octicon-link,\r\n .markdown-body h5 .octicon-link,\r\n .markdown-body h6 .octicon-link {\r\n color: var(--fgColor-default);\r\n vertical-align: middle;\r\n visibility: hidden;\r\n }\r\n \r\n .markdown-body h1:hover .anchor,\r\n .markdown-body h2:hover .anchor,\r\n .markdown-body h3:hover .anchor,\r\n .markdown-body h4:hover .anchor,\r\n .markdown-body h5:hover .anchor,\r\n .markdown-body h6:hover .anchor {\r\n text-decoration: none;\r\n }\r\n \r\n .markdown-body h1:hover .anchor .octicon-link,\r\n .markdown-body h2:hover .anchor .octicon-link,\r\n .markdown-body h3:hover .anchor .octicon-link,\r\n .markdown-body h4:hover .anchor .octicon-link,\r\n .markdown-body h5:hover .anchor .octicon-link,\r\n .markdown-body h6:hover .anchor .octicon-link {\r\n visibility: visible;\r\n }\r\n \r\n .markdown-body h1 tt,\r\n .markdown-body h1 code,\r\n .markdown-body h2 tt,\r\n .markdown-body h2 code,\r\n .markdown-body h3 tt,\r\n .markdown-body h3 code,\r\n .markdown-body h4 tt,\r\n .markdown-body h4 code,\r\n .markdown-body h5 tt,\r\n .markdown-body h5 code,\r\n .markdown-body h6 tt,\r\n .markdown-body h6 code {\r\n padding: 0 .2em;\r\n font-size: inherit;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2,\r\n .markdown-body summary h3,\r\n .markdown-body summary h4,\r\n .markdown-body summary h5,\r\n .markdown-body summary h6 {\r\n display: inline-block;\r\n }\r\n \r\n .markdown-body summary h1 .anchor,\r\n .markdown-body summary h2 .anchor,\r\n .markdown-body summary h3 .anchor,\r\n .markdown-body summary h4 .anchor,\r\n .markdown-body summary h5 .anchor,\r\n .markdown-body summary h6 .anchor {\r\n margin-left: -40px;\r\n }\r\n \r\n .markdown-body summary h1,\r\n .markdown-body summary h2 {\r\n padding-bottom: 0;\r\n border-bottom: 0;\r\n }\r\n \r\n .markdown-body ul.no-list,\r\n .markdown-body ol.no-list {\r\n padding: 0;\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body ol[type=\"a s\"] {\r\n list-style-type: lower-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"A s\"] {\r\n list-style-type: upper-alpha;\r\n }\r\n \r\n .markdown-body ol[type=\"i s\"] {\r\n list-style-type: lower-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"I s\"] {\r\n list-style-type: upper-roman;\r\n }\r\n \r\n .markdown-body ol[type=\"1\"] {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body div>ol:not([type]) {\r\n list-style-type: decimal;\r\n }\r\n \r\n .markdown-body ul ul,\r\n .markdown-body ul ol,\r\n .markdown-body ol ol,\r\n .markdown-body ol ul {\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body li>p {\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body li+li {\r\n margin-top: .25em;\r\n }\r\n \r\n .markdown-body dl {\r\n padding: 0;\r\n }\r\n \r\n .markdown-body dl dt {\r\n padding: 0;\r\n margin-top: var(--base-size-16);\r\n font-size: 1em;\r\n font-style: italic;\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body dl dd {\r\n padding: 0 var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body table th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n }\r\n \r\n .markdown-body table th,\r\n .markdown-body table td {\r\n padding: 6px 13px;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body table td>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body table tr {\r\n background-color: var(--bgColor-default);\r\n border-top: 1px solid var(--borderColor-muted);\r\n }\r\n \r\n .markdown-body table tr:nth-child(2n) {\r\n background-color: var(--bgColor-muted);\r\n }\r\n \r\n .markdown-body table img {\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body img[align=right] {\r\n padding-left: 20px;\r\n }\r\n \r\n .markdown-body img[align=left] {\r\n padding-right: 20px;\r\n }\r\n \r\n .markdown-body .emoji {\r\n max-width: none;\r\n vertical-align: text-top;\r\n background-color: transparent;\r\n }\r\n \r\n .markdown-body span.frame {\r\n display: block;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.frame>span {\r\n display: block;\r\n float: left;\r\n width: auto;\r\n padding: 7px;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n border: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body span.frame span img {\r\n display: block;\r\n float: left;\r\n }\r\n \r\n .markdown-body span.frame span span {\r\n display: block;\r\n padding: 5px 0 0;\r\n clear: both;\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body span.align-center {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-center>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-center span img {\r\n margin: 0 auto;\r\n text-align: center;\r\n }\r\n \r\n .markdown-body span.align-right {\r\n display: block;\r\n overflow: hidden;\r\n clear: both;\r\n }\r\n \r\n .markdown-body span.align-right>span {\r\n display: block;\r\n margin: 13px 0 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.align-right span img {\r\n margin: 0;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body span.float-left {\r\n display: block;\r\n float: left;\r\n margin-right: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-left span {\r\n margin: 13px 0 0;\r\n }\r\n \r\n .markdown-body span.float-right {\r\n display: block;\r\n float: right;\r\n margin-left: 13px;\r\n overflow: hidden;\r\n }\r\n \r\n .markdown-body span.float-right>span {\r\n display: block;\r\n margin: 13px auto 0;\r\n overflow: hidden;\r\n text-align: right;\r\n }\r\n \r\n .markdown-body code,\r\n .markdown-body tt {\r\n padding: .2em .4em;\r\n margin: 0;\r\n font-size: 85%;\r\n white-space: break-spaces;\r\n background-color: var(--bgColor-neutral-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body code br,\r\n .markdown-body tt br {\r\n display: none;\r\n }\r\n \r\n .markdown-body del code {\r\n text-decoration: inherit;\r\n }\r\n \r\n .markdown-body samp {\r\n font-size: 85%;\r\n }\r\n \r\n .markdown-body pre code {\r\n font-size: 100%;\r\n }\r\n \r\n .markdown-body pre>code {\r\n padding: 0;\r\n margin: 0;\r\n word-break: normal;\r\n white-space: pre;\r\n background: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .highlight {\r\n margin-bottom: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .highlight pre {\r\n margin-bottom: 0;\r\n word-break: normal;\r\n }\r\n \r\n .markdown-body .highlight pre,\r\n .markdown-body pre {\r\n padding: var(--base-size-16);\r\n overflow: auto;\r\n font-size: 85%;\r\n line-height: 1.45;\r\n color: var(--fgColor-default);\r\n background-color: var(--bgColor-muted);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body pre code,\r\n .markdown-body pre tt {\r\n display: inline;\r\n max-width: auto;\r\n padding: 0;\r\n margin: 0;\r\n overflow: visible;\r\n line-height: inherit;\r\n word-wrap: normal;\r\n background-color: transparent;\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data td,\r\n .markdown-body .csv-data th {\r\n padding: 5px;\r\n overflow: hidden;\r\n font-size: 12px;\r\n line-height: 1;\r\n text-align: left;\r\n white-space: nowrap;\r\n }\r\n \r\n .markdown-body .csv-data .blob-num {\r\n padding: 10px var(--base-size-8) 9px;\r\n text-align: right;\r\n background: var(--bgColor-default);\r\n border: 0;\r\n }\r\n \r\n .markdown-body .csv-data tr {\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body .csv-data th {\r\n font-weight: var(--base-text-weight-semibold, 600);\r\n background: var(--bgColor-muted);\r\n border-top: 0;\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::before {\r\n content: \"[\";\r\n }\r\n \r\n .markdown-body [data-footnote-ref]::after {\r\n content: \"]\";\r\n }\r\n \r\n .markdown-body .footnotes {\r\n font-size: 12px;\r\n color: var(--fgColor-muted);\r\n border-top: 1px solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .footnotes ol {\r\n padding-left: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes ol ul {\r\n display: inline-block;\r\n padding-left: var(--base-size-16);\r\n margin-top: var(--base-size-16);\r\n }\r\n \r\n .markdown-body .footnotes li {\r\n position: relative;\r\n }\r\n \r\n .markdown-body .footnotes li:target::before {\r\n position: absolute;\r\n top: calc(var(--base-size-8)*-1);\r\n right: calc(var(--base-size-8)*-1);\r\n bottom: calc(var(--base-size-8)*-1);\r\n left: calc(var(--base-size-24)*-1);\r\n pointer-events: none;\r\n content: \"\";\r\n border: 2px solid var(--borderColor-accent-emphasis);\r\n border-radius: 6px;\r\n }\r\n \r\n .markdown-body .footnotes li:target {\r\n color: var(--fgColor-default);\r\n }\r\n \r\n .markdown-body .footnotes .data-footnote-backref g-emoji {\r\n font-family: monospace;\r\n }\r\n \r\n .markdown-body body:has(:modal) {\r\n padding-right: var(--dialog-scrollgutter) !important;\r\n }\r\n \r\n .markdown-body .pl-c {\r\n color: var(--color-prettylights-syntax-comment);\r\n }\r\n \r\n .markdown-body .pl-c1,\r\n .markdown-body .pl-s .pl-v {\r\n color: var(--color-prettylights-syntax-constant);\r\n }\r\n \r\n .markdown-body .pl-e,\r\n .markdown-body .pl-en {\r\n color: var(--color-prettylights-syntax-entity);\r\n }\r\n \r\n .markdown-body .pl-smi,\r\n .markdown-body .pl-s .pl-s1 {\r\n color: var(--color-prettylights-syntax-storage-modifier-import);\r\n }\r\n \r\n .markdown-body .pl-ent {\r\n color: var(--color-prettylights-syntax-entity-tag);\r\n }\r\n \r\n .markdown-body .pl-k {\r\n color: var(--color-prettylights-syntax-keyword);\r\n }\r\n \r\n .markdown-body .pl-s,\r\n .markdown-body .pl-pds,\r\n .markdown-body .pl-s .pl-pse .pl-s1,\r\n .markdown-body .pl-sr,\r\n .markdown-body .pl-sr .pl-cce,\r\n .markdown-body .pl-sr .pl-sre,\r\n .markdown-body .pl-sr .pl-sra {\r\n color: var(--color-prettylights-syntax-string);\r\n }\r\n \r\n .markdown-body .pl-v,\r\n .markdown-body .pl-smw {\r\n color: var(--color-prettylights-syntax-variable);\r\n }\r\n \r\n .markdown-body .pl-bu {\r\n color: var(--color-prettylights-syntax-brackethighlighter-unmatched);\r\n }\r\n \r\n .markdown-body .pl-ii {\r\n color: var(--color-prettylights-syntax-invalid-illegal-text);\r\n background-color: var(--color-prettylights-syntax-invalid-illegal-bg);\r\n }\r\n \r\n .markdown-body .pl-c2 {\r\n color: var(--color-prettylights-syntax-carriage-return-text);\r\n background-color: var(--color-prettylights-syntax-carriage-return-bg);\r\n }\r\n \r\n .markdown-body .pl-sr .pl-cce {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-string-regexp);\r\n }\r\n \r\n .markdown-body .pl-ml {\r\n color: var(--color-prettylights-syntax-markup-list);\r\n }\r\n \r\n .markdown-body .pl-mh,\r\n .markdown-body .pl-mh .pl-en,\r\n .markdown-body .pl-ms {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-heading);\r\n }\r\n \r\n .markdown-body .pl-mi {\r\n font-style: italic;\r\n color: var(--color-prettylights-syntax-markup-italic);\r\n }\r\n \r\n .markdown-body .pl-mb {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-markup-bold);\r\n }\r\n \r\n .markdown-body .pl-md {\r\n color: var(--color-prettylights-syntax-markup-deleted-text);\r\n background-color: var(--color-prettylights-syntax-markup-deleted-bg);\r\n }\r\n \r\n .markdown-body .pl-mi1 {\r\n color: var(--color-prettylights-syntax-markup-inserted-text);\r\n background-color: var(--color-prettylights-syntax-markup-inserted-bg);\r\n }\r\n \r\n .markdown-body .pl-mc {\r\n color: var(--color-prettylights-syntax-markup-changed-text);\r\n background-color: var(--color-prettylights-syntax-markup-changed-bg);\r\n }\r\n \r\n .markdown-body .pl-mi2 {\r\n color: var(--color-prettylights-syntax-markup-ignored-text);\r\n background-color: var(--color-prettylights-syntax-markup-ignored-bg);\r\n }\r\n \r\n .markdown-body .pl-mdr {\r\n font-weight: bold;\r\n color: var(--color-prettylights-syntax-meta-diff-range);\r\n }\r\n \r\n .markdown-body .pl-ba {\r\n color: var(--color-prettylights-syntax-brackethighlighter-angle);\r\n }\r\n \r\n .markdown-body .pl-sg {\r\n color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);\r\n }\r\n \r\n .markdown-body .pl-corl {\r\n text-decoration: underline;\r\n color: var(--color-prettylights-syntax-constant-other-reference-link);\r\n }\r\n \r\n .markdown-body [role=button]:focus:not(:focus-visible),\r\n .markdown-body [role=tabpanel][tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body button:focus:not(:focus-visible),\r\n .markdown-body summary:focus:not(:focus-visible),\r\n .markdown-body a:focus:not(:focus-visible) {\r\n outline: none;\r\n box-shadow: none;\r\n }\r\n \r\n .markdown-body [tabindex=\"0\"]:focus:not(:focus-visible),\r\n .markdown-body details-dialog:focus:not(:focus-visible) {\r\n outline: none;\r\n }\r\n \r\n .markdown-body g-emoji {\r\n display: inline-block;\r\n min-width: 1ch;\r\n font-family: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\r\n font-size: 1em;\r\n font-style: normal !important;\r\n font-weight: var(--base-text-weight-normal, 400);\r\n line-height: 1;\r\n vertical-align: -0.075em;\r\n }\r\n \r\n .markdown-body g-emoji img {\r\n width: 1em;\r\n height: 1em;\r\n }\r\n \r\n .markdown-body .task-list-item {\r\n list-style-type: none;\r\n }\r\n \r\n .markdown-body .task-list-item label {\r\n font-weight: var(--base-text-weight-normal, 400);\r\n }\r\n \r\n .markdown-body .task-list-item.enabled label {\r\n cursor: pointer;\r\n }\r\n \r\n .markdown-body .task-list-item+.task-list-item {\r\n margin-top: var(--base-size-4);\r\n }\r\n \r\n .markdown-body .task-list-item .handle {\r\n display: none;\r\n }\r\n \r\n .markdown-body .task-list-item-checkbox {\r\n margin: 0 .2em .25em -1.4em;\r\n vertical-align: middle;\r\n }\r\n \r\n .markdown-body ul:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body ol:dir(rtl) .task-list-item-checkbox {\r\n margin: 0 -1.6em .25em .2em;\r\n }\r\n \r\n .markdown-body .contains-task-list:hover .task-list-item-convert-container,\r\n .markdown-body .contains-task-list:focus-within .task-list-item-convert-container {\r\n display: block;\r\n width: auto;\r\n height: 24px;\r\n overflow: visible;\r\n clip: auto;\r\n }\r\n \r\n .markdown-body ::-webkit-calendar-picker-indicator {\r\n filter: invert(50%);\r\n }\r\n \r\n .markdown-body .markdown-alert {\r\n padding: var(--base-size-8) var(--base-size-16);\r\n margin-bottom: var(--base-size-16);\r\n color: inherit;\r\n border-left: .25em solid var(--borderColor-default);\r\n }\r\n \r\n .markdown-body .markdown-alert>:first-child {\r\n margin-top: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert>:last-child {\r\n margin-bottom: 0;\r\n }\r\n \r\n .markdown-body .markdown-alert .markdown-alert-title {\r\n display: flex;\r\n font-weight: var(--base-text-weight-medium, 500);\r\n align-items: center;\r\n line-height: 1;\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note {\r\n border-left-color: var(--borderColor-accent-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title {\r\n color: var(--fgColor-accent);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important {\r\n border-left-color: var(--borderColor-done-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title {\r\n color: var(--fgColor-done);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning {\r\n border-left-color: var(--borderColor-attention-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title {\r\n color: var(--fgColor-attention);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip {\r\n border-left-color: var(--borderColor-success-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title {\r\n color: var(--fgColor-success);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution {\r\n border-left-color: var(--borderColor-danger-emphasis);\r\n }\r\n \r\n .markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title {\r\n color: var(--fgColor-danger);\r\n }\r\n \r\n .markdown-body>*:first-child>.heading-element:first-child {\r\n margin-top: 0 !important;\r\n }\r\n \r\n .markdown-body .highlight pre:has(+.zeroclipboard-container) {\r\n min-height: 52px;\r\n }",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",".pcm-message {\r\n position: fixed;\r\n top: 20px;\r\n left: 50%;\r\n transform: translateX(-50%) translateY(-100%);\r\n background-color: #fff;\r\n padding: 10px 16px;\r\n border-radius: 4px;\r\n box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);\r\n pointer-events: all;\r\n z-index: 1010;\r\n opacity: 0;\r\n transition: all 0.3s;\r\n}\r\n\r\n.pcm-message-visible {\r\n transform: translateX(-50%) translateY(0);\r\n opacity: 1;\r\n}\r\n\r\n.pcm-message-content {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.pcm-message-icon {\r\n margin-right: 8px;\r\n font-size: 16px;\r\n line-height: 1;\r\n}\r\n\r\n.pcm-message-success .pcm-message-icon {\r\n color: #52c41a;\r\n}\r\n\r\n.pcm-message-error .pcm-message-icon {\r\n color: #ff4d4f;\r\n}\r\n\r\n.pcm-message-warning .pcm-message-icon {\r\n color: #faad14;\r\n}\r\n\r\n.pcm-message-info .pcm-message-icon {\r\n color: #1890ff;\r\n}\r\n\r\n.pcm-message-text {\r\n font-size: 14px;\r\n line-height: 1.5;\r\n}\r\n\r\n.pcm-message-container {\r\n position: fixed;\r\n top: 20px;\r\n left: 0;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n pointer-events: none;\r\n z-index: 1010;\r\n} \r\n\r\n",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, h, Prop, State, Element, Method } from '@stencil/core';\r\n\r\n@Component({\r\n tag: 'pcm-message',\r\n styleUrls: ['pcm-message.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmMessage {\r\n @Element() el: HTMLElement;\r\n @Prop() content: string = '';\r\n @Prop() type: 'success' | 'error' | 'info' | 'warning' = 'info';\r\n @Prop() duration: number = 3000;\r\n @State() visible: boolean = false;\r\n\r\n private timer: number;\r\n\r\n componentWillLoad() {\r\n if (this.content) {\r\n this.visible = true;\r\n }\r\n }\r\n\r\n componentDidLoad() {\r\n if (this.visible && this.duration > 0) {\r\n this.timer = window.setTimeout(() => {\r\n this.close();\r\n }, this.duration);\r\n }\r\n }\r\n\r\n disconnectedCallback() {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n }\r\n }\r\n\r\n @Method()\r\n async show() {\r\n this.visible = true;\r\n \r\n if (this.duration > 0) {\r\n this.timer = window.setTimeout(() => {\r\n this.close();\r\n }, this.duration);\r\n }\r\n }\r\n\r\n @Method()\r\n async close() {\r\n this.visible = false;\r\n \r\n // 等待动画结束后移除元素\r\n setTimeout(() => {\r\n if (this.el && this.el.parentNode) {\r\n this.el.parentNode.removeChild(this.el);\r\n }\r\n }, 300);\r\n }\r\n\r\n render() {\r\n return (\r\n <div class={{\r\n 'pcm-message': true,\r\n 'pcm-message-visible': this.visible,\r\n [`pcm-message-${this.type}`]: true\r\n }}>\r\n <div class=\"pcm-message-content\">\r\n <span class=\"pcm-message-icon\">\r\n {this.renderIcon()}\r\n </span>\r\n <span class=\"pcm-message-text\">{this.content}</span>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n private renderIcon() {\r\n switch (this.type) {\r\n case 'success':\r\n return <svg viewBox=\"64 64 896 896\" width=\"16px\" height=\"16px\" fill=\"currentColor\"><path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z\"></path></svg>;\r\n case 'error':\r\n return <svg viewBox=\"64 64 896 896\" width=\"16px\" height=\"16px\" fill=\"currentColor\"><path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z\"></path></svg>;\r\n case 'warning':\r\n return <svg viewBox=\"64 64 896 896\" width=\"16px\" height=\"16px\" fill=\"currentColor\"><path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z\"></path></svg>;\r\n default: // info\r\n return <svg viewBox=\"64 64 896 896\" width=\"16px\" height=\"16px\" fill=\"currentColor\"><path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 664c-30.9 0-56-25.1-56-56 0-30.9 25.1-56 56-56s56 25.1 56 56c0 30.9-25.1 56-56 56zm32-296c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V248c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v184z\"></path></svg>;\r\n }\r\n }\r\n} ","\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { uploadFileToBackend, FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { SentryReporter } from '../../utils/sentry-reporter';\r\n\r\n/**\r\n * 模拟出题大师\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-mnct-modal',\r\n styleUrls: ['pcm-mnct-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MnctModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '面试出题大师';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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 /**\r\n * 自定义输入参数<br>\r\n * 传入customInputs.job_info时,会隐藏JD输入区域。<br>\r\n * 传入customInputs.file_url时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_url和customInputs.job_info时,会直接开始聊天。<br>\r\n * 传入customInputs.question_number时,会设置面试题数量。<br>\r\n * 传入customInputs.can_outputAnalysis时,会设置是否需要参考答案。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 面试题数量,默认6题(范围:3-20题)\r\n */\r\n @Prop({ mutable: true }) questionNumber: number = 6;\r\n\r\n /**\r\n * 是否需要参考答案,默认开启\r\n */\r\n @Prop({ mutable: true }) canOutputAnalysis: boolean = true;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.clearSelectedFile();\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n\r\n } else {\r\n if (this.customInputs && this.customInputs.job_info) {\r\n this.jobDescription = this.customInputs.job_info;\r\n }\r\n\r\n await verifyApiKey(this.token);\r\n\r\n // 如果有会话ID或者同时有file_url和job_info,直接显示聊天模态框\r\n if (this.conversationId || (this.customInputs?.file_url && this.customInputs?.job_info)) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleFileChange = (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\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 = null;\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 private async uploadFile() {\r\n if (!this.selectedFile) return;\r\n\r\n this.isUploading = true;\r\n\r\n try {\r\n // 使用 uploadFileToBackend 工具函数上传文件\r\n const result = await uploadFileToBackend(this.selectedFile, {\r\n }, {\r\n 'tags': ['resume']\r\n });\r\n\r\n this.uploadedFileInfo = result;\r\n this.uploadSuccess.emit(result);\r\n } catch (error) {\r\n console.error('文件上传错误:', error);\r\n this.clearSelectedFile();\r\n SentryReporter.captureError(error, {\r\n action: 'uploadFile',\r\n component: 'pcm-mnct-modal',\r\n title: '文件上传失败'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '文件上传失败,请重试'\r\n });\r\n } finally {\r\n this.isUploading = false;\r\n }\r\n }\r\n\r\n private handleJobDescriptionChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.jobDescription = textarea.value;\r\n };\r\n\r\n private handleQuestionNumberChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n const value = parseInt(input.value);\r\n this.questionNumber = (value >= 3 && value <= 20) ? value : 6;\r\n };\r\n\r\n private handleAnalysisToggle = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.canOutputAnalysis = input.checked;\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n if (!this.selectedFile) {\r\n alert('请上传简历');\r\n return;\r\n }\r\n\r\n // 如果没有预设的job_info,则需要检查用户输入\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n alert('请输入职位描述');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n\r\n try {\r\n // 如果还没上传,先上传文件\r\n if (!this.uploadedFileInfo) {\r\n await this.uploadFile();\r\n if (!this.uploadedFileInfo) {\r\n this.isSubmitting = false;\r\n return; // 上传失败\r\n }\r\n }\r\n\r\n // 直接显示聊天模态框\r\n this.showChatModal = true;\r\n } catch (error) {\r\n console.error('开始面试时出错:', error);\r\n SentryReporter.captureError(error, {\r\n action: 'handleStartInterview',\r\n component: 'pcm-mnct-modal',\r\n title: '开始面试时出错'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '开始面试时出错,请重试'\r\n });\r\n } finally {\r\n this.isSubmitting = false;\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 判断是否隐藏JD输入区域\r\n const hideJdInput = Boolean(this.customInputs && this.customInputs.job_info);\r\n \r\n // 判断是否隐藏简历上传区域\r\n const hideResumeUpload = Boolean(this.customInputs && this.customInputs.file_url);\r\n \r\n // 判断是否同时提供了file_url和job_info\r\n const hasFileAndJob = Boolean(this.customInputs?.file_url && this.customInputs?.job_info);\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 <div>{this.modalTitle}</div>\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 {/* 上传界面 - 仅在不显示聊天模态框且没有会话ID且没有同时提供file_url和job_info时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hasFileAndJob && (\r\n <div class=\"input-container\">\r\n {/* JD输入区域 - 仅在没有customInputs.job_info时显示 */}\r\n {!hideJdInput && (\r\n <div class=\"jd-input-section\">\r\n <label htmlFor=\"job-description\">请输入职位描述 (JD)</label>\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder=\"请输入职位描述,包括职责、要求等信息...\"\r\n rows={6}\r\n value={this.jobDescription}\r\n onInput={this.handleJobDescriptionChange}\r\n ></textarea>\r\n </div>\r\n )}\r\n\r\n {/* 简历上传区域 - 仅在没有customInputs.file_url时显示 */}\r\n {!hideResumeUpload && (\r\n <div class=\"resume-upload-section\">\r\n <label>上传简历</label>\r\n <div class=\"upload-area\" onClick={this.handleUploadClick}>\r\n {this.selectedFile ? (\r\n <div class=\"file-item\">\r\n <div class=\"file-item-content\">\r\n <span class=\"file-icon\">📝</span>\r\n <span class=\"file-name\">{this.selectedFile.name}</span>\r\n </div>\r\n <button class=\"remove-file\" onClick={(e) => {\r\n e.stopPropagation();\r\n this.clearSelectedFile();\r\n }}>×</button>\r\n </div>\r\n ) : (\r\n <div class=\"upload-placeholder\">\r\n <img src='https://pub.pincaimao.com/static/web/images/home/i_upload.png'></img>\r\n <p class='upload-text'>点击上传简历</p>\r\n <p class=\"upload-hint\">支持 txt、markdown、pdf、docx、doc、md 格式</p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 面试设置区域 */}\r\n <div class=\"interview-settings-section\">\r\n <div class=\"settings-row\">\r\n <div class=\"question-number-section\">\r\n <label class=\"settings-label\">面试题数量:</label>\r\n <div class=\"slider-container\">\r\n <input\r\n type=\"range\"\r\n min=\"3\"\r\n max=\"20\"\r\n value={this.questionNumber}\r\n class=\"question-slider\"\r\n onInput={this.handleQuestionNumberChange}\r\n />\r\n <div class=\"slider-value\">{this.questionNumber}题</div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"settings-row\">\r\n <div class=\"analysis-toggle-section\">\r\n <label class=\"settings-label\">是否需要参考答案:</label>\r\n <div class=\"toggle-container\">\r\n <label class=\"toggle-switch\">\r\n <input\r\n type=\"checkbox\"\r\n checked={this.canOutputAnalysis}\r\n onChange={this.handleAnalysisToggle}\r\n />\r\n <span class=\"toggle-slider\"></span>\r\n </label>\r\n <span class=\"toggle-text\">{this.canOutputAnalysis ? '开启' : '关闭'}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={((!hideResumeUpload && !this.selectedFile) || \r\n (!hideJdInput && !this.jobDescription.trim())) || \r\n this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始分析'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n onChange={this.handleFileChange}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div>\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018876\"\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n question_number: this.questionNumber,\r\n can_outputAnalysis: this.canOutputAnalysis ? 'true' : 'false',\r\n }}\r\n interviewMode=\"text\"\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",null,"/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport {\r\n StreamCompleteEventData,\r\n ConversationStartEventData,\r\n InterviewCompleteEventData,\r\n RecordingErrorEventData,\r\n} from '../../interfaces/events';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { Message } from '../../services/message.service';\r\n\r\n/**\r\n * 模拟面试(招聘)\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-mnms-zp-modal',\r\n styleUrls: ['pcm-mnms-zp-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MnmsZpModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '模拟面试';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '请开始模拟面试';\r\n\r\n /**\r\n * 视频录制最大时长(秒)默认120\r\n */\r\n @Prop() maxRecordingTime: number = 120;\r\n\r\n /**\r\n * 等待录制时间(秒)默认10\r\n */\r\n @Prop() waitingTime: number = 10;\r\n\r\n /**\r\n * 是否以全屏模式打开,移动端建议设置为true\r\n */\r\n @Prop() fullscreen: boolean = false;\r\n\r\n /**\r\n * 自定义输入参数,可传入以下参数:<br>\r\n * customInputs.job_info时,会隐藏JD输入区域。<br>\r\n * customInputs.file_url或customInputs.resume_content时,会隐藏简历上传区域。<br>\r\n * customInputs.file_url(或customInputs.resume_content)和customInputs.job_info时,会直接开始聊天。<br>\r\n * customInputs.resume_content:可传入json字符串,或纯文本字符串,字符串内容为简历内容。<br>\r\n * customInputs.url_callback:可传入url字符串,当报告生成后,会调用该url进行回调。该url请使用post请求,接收报告字段为report_content,会话id字段为conversation_id。<br>\r\n * customInputs.interview_type:可传入数字,传入 1 时,开启题目连续模式,一次性生成所有题目。不传入或传入其他值时,题目将逐个生成。<br>\r\n * customInputs.question_number时,会设置面试题总数量, 默认5题。<br>\r\n * customInputs.question_list:可传入字符串数组形式的JSON字符串,自定义面试问题列表。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传JD(仅PC端生效)\r\n */\r\n @Prop() mobileJdInputAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历(仅PC端生效)\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 虚拟数字人ID,指定则开启虚拟数字人功能</br>\r\n * 智琪:79202506752 </br>\r\n * 艾綝:79402522624 </br>\r\n * 艾姮:79597885440 </br>\r\n */\r\n @Prop() digitalId?: string;\r\n\r\n /**\r\n * 数字人开场白索引,用于选择开场白和开场视频(可选:0, 1, 2)\r\n * 0、您好,我是聘才猫 AI 面试助手。很高兴为你主持这场面试!在开始前,请确保:身处安静、光线充足的环境。网络顺畅,摄像头和麦克风工作正常。现在我正在查看本次面试的相关信息,为您生成专属面试题,马上就好,请稍等片刻。</br>\r\n * 1、您好,我是您的 AI 面试助手。欢迎参加本次AI面试!为了获得最佳效果,请确认:您在安静、明亮的环境中。您的网络稳定,摄像头和麦克风已开启。我们正在后台为您准备本次专属面试内容,很快开始,请稍候。<br>\r\n * 2、您好,我是您的 AI 面试助手。面试马上开始。趁此片刻,请快速确认:周围安静吗?光线足够吗?网络没问题?摄像头和麦克风准备好了吗?我们正在为您加载个性化的面试环节,稍等就好!\r\n */\r\n @Prop() openingIndex: number = 0;\r\n\r\n /**\r\n * 是否启用全屏数字人模式,此模式下面试报告只会通过url_callback回调返回\r\n */\r\n @Prop() enableVirtualHuman: boolean = false;\r\n\r\n /**\r\n * 是否显示结束面试按钮\r\n */\r\n @Prop() showEndInterviewButton: boolean = false;\r\n\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n\r\n /**\r\n * 面试模式:text - 文本模式,video - 视频模式\r\n */\r\n @Prop() interviewMode: 'text' | 'video' = 'text';\r\n\r\n /**\r\n * 录制错误事件\r\n */\r\n @Event() recordingError: EventEmitter<RecordingErrorEventData>;\r\n\r\n /**\r\n * 是否显示复制按钮\r\n */\r\n @Prop() showCopyButton: boolean = true;\r\n\r\n /**\r\n * 是否显示点赞点踩按钮\r\n */\r\n @Prop() showFeedbackButtons: boolean = true;\r\n\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n // 添加对子组件的引用\r\n private virtualChatModalRef: HTMLPcmVirtualChatModalElement | null = null;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 当模态框关闭时,调用子组件方法停止所有活动\r\n if (this.virtualChatModalRef) {\r\n await this.virtualChatModalRef.setComponentActive(false);\r\n }\r\n // 重置状态\r\n this.resetState();\r\n\r\n } else {\r\n if (this.customInputs && this.customInputs.job_info) {\r\n this.jobDescription = this.customInputs.job_info;\r\n }\r\n\r\n await verifyApiKey(this.token);\r\n\r\n // 如果同时有 file_url 和 job_info,或者有会话ID,直接显示聊天模态框\r\n if (((this.customInputs?.file_url || this.customInputs?.resume_content) && this.customInputs?.job_info) || this.conversationId) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n /**\r\n * 重置组件状态\r\n */\r\n private resetState() {\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n this.isSubmitting = false;\r\n this.selectedFile = null;\r\n this.isUploading = false;\r\n this.uploadedFileInfo = null;\r\n }\r\n\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleJobDescriptionChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.jobDescription = textarea.value;\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n // 如果没有预设的job_info,则需要检查用户输入\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n alert('请输入职位描述');\r\n return;\r\n }\r\n // 判断文件是否正在上传\r\n if (await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n };\r\n\r\n private pcmUploadRef;\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\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen,\r\n 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 修正这里的逻辑,确保当 customInputs.job_info 存在时,hideJdInput 为 true\r\n const hideJdInput = Boolean(this.customInputs && this.customInputs.job_info);\r\n\r\n // 判断是否隐藏简历上传区域 - 当有file_url或resume_content时都隐藏\r\n const hideResumeUpload = Boolean(this.customInputs && (this.customInputs.file_url || this.customInputs.resume_content));\r\n\r\n // 判断是否同时提供了(file_url或resume_content)和job_info\r\n const hasFileAndJob = Boolean((this.customInputs?.file_url || this.customInputs?.resume_content) && this.customInputs?.job_info);\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 <div>{this.modalTitle}</div>\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 {/* 上传界面 - 仅在不显示聊天模态框且没有会话ID且没有同时提供file_url和job_info时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hasFileAndJob && (\r\n <div class=\"input-container\">\r\n {/* JD输入区域 - 仅在没有customInputs.job_info时显示 */}\r\n {!hideJdInput && (\r\n <div class=\"jd-input-section\">\r\n <label htmlFor=\"job-description\">请输入职位描述 (JD)</label>\r\n {\r\n !!this.mobileJdInputAble && (\r\n <pcm-mobile-input-btn\r\n name=\"职位描述\"\r\n onOk={(e) => {\r\n this.jobDescription = e.detail;\r\n }}\r\n />\r\n )\r\n }\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder=\"请输入职位描述,包括职责、要求等信息...\"\r\n rows={6}\r\n value={this.jobDescription}\r\n onInput={this.handleJobDescriptionChange}\r\n ></textarea>\r\n </div>\r\n )}\r\n\r\n {/* 简历上传区域 - 仅在没有customInputs.file_url或customInputs.resume_content时显示 */}\r\n {\r\n !hideResumeUpload && (\r\n <div class=\"jd-input-section\">\r\n <label>上传简历(选填)</label>\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\r\n mobileUploadAble={this.mobileUploadAble}\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['resume'],\r\n }}\r\n onUploadChange={(e) => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(!hideJdInput && !this.jobDescription.trim()) || this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始面试'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n {this.enableVirtualHuman && this.digitalId ? (\r\n <pcm-virtual-chat-modal\r\n ref={el => this.virtualChatModalRef = el}\r\n isOpen={true}\r\n fullscreen={this.fullscreen}\r\n botId=\"3022316191018907\"\r\n digitalId={this.digitalId}\r\n openingIndex={this.openingIndex}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n waitingTime={this.waitingTime}\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n question_number: this.customInputs?.question_number || 5,\r\n interview_type:\"1\"\r\n }}\r\n ></pcm-virtual-chat-modal>\r\n ) : (\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018907\"\r\n digitalId={this.digitalId}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n maxRecordingTime={this.maxRecordingTime}\r\n waitingTime={this.waitingTime}\r\n showCopyButton={this.showCopyButton}\r\n showFeedbackButtons={this.showFeedbackButtons}\r\n showEndInterviewButton={this.showEndInterviewButton}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription,\r\n question_number: this.customInputs?.question_number || 5\r\n }}\r\n interviewMode={this.interviewMode}\r\n ></pcm-app-chat-modal>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module Charset\n */\nconst VALUES_TO_CHARSET = new Map();\nfunction fromCharsetValue(value) {\n const charset = VALUES_TO_CHARSET.get(value);\n if (charset != null) {\n return charset;\n }\n throw Error('illegal charset value');\n}\nclass Charset {\n #label;\n #values;\n // See: https://en.wikipedia.org/wiki/Extended_Channel_Interpretation\n static CP437 = new Charset('cp437', 2, 0);\n static ISO_8859_1 = new Charset('iso-8859-1', 3, 1);\n static ISO_8859_2 = new Charset('iso-8859-2', 4);\n static ISO_8859_3 = new Charset('iso-8859-3', 5);\n static ISO_8859_4 = new Charset('iso-8859-4', 6);\n static ISO_8859_5 = new Charset('iso-8859-5', 7);\n static ISO_8859_6 = new Charset('iso-8859-6', 8);\n static ISO_8859_7 = new Charset('iso-8859-7', 9);\n static ISO_8859_8 = new Charset('iso-8859-8', 10);\n static ISO_8859_9 = new Charset('iso-8859-9', 11);\n static ISO_8859_10 = new Charset('iso-8859-10', 12);\n static ISO_8859_11 = new Charset('iso-8859-11', 13);\n static ISO_8859_13 = new Charset('iso-8859-13', 15);\n static ISO_8859_14 = new Charset('iso-8859-14', 16);\n static ISO_8859_15 = new Charset('iso-8859-15', 17);\n static ISO_8859_16 = new Charset('iso-8859-16', 18);\n static SHIFT_JIS = new Charset('shift-jis', 20);\n static CP1250 = new Charset('cp1250', 21);\n static CP1251 = new Charset('cp1251', 22);\n static CP1252 = new Charset('cp1252', 23);\n static CP1256 = new Charset('cp1256', 24);\n static UTF_16BE = new Charset('utf-16be', 25);\n static UTF_8 = new Charset('utf-8', 26);\n static ASCII = new Charset('ascii', 27);\n static BIG5 = new Charset('big5', 28);\n static GB2312 = new Charset('gb2312', 29);\n static EUC_KR = new Charset('euc-kr', 30);\n static GBK = new Charset('gbk', 31);\n static GB18030 = new Charset('gb18030', 32);\n static UTF_16LE = new Charset('utf-16le', 33);\n static UTF_32BE = new Charset('utf-32be', 34);\n static UTF_32LE = new Charset('utf-32le', 35);\n static ISO_646_INV = new Charset('iso-646-inv', 170);\n static BINARY = new Charset('binary', 899);\n /**\n * @constructor\n * @param label The label of charset.\n * @param values The values of charset.\n */\n constructor(label, ...values) {\n this.#label = label;\n this.#values = Object.freeze(values);\n for (const value of values) {\n if (value >= 0 && value <= 999999 && Number.isInteger(value)) {\n VALUES_TO_CHARSET.set(value, this);\n } else {\n throw new Error('illegal extended channel interpretation value');\n }\n }\n }\n /**\n * @property label\n * @description Get the label of charset.\n */\n get label() {\n return this.#label;\n }\n /**\n * @property values\n * @description Get the values of charset.\n */\n get values() {\n return this.#values;\n }\n}\n\nexport { Charset, fromCharsetValue };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module utils\n */\nfunction toBit(value) {\n return value & 0x01;\n}\nfunction toInt32(value) {\n return value | 0;\n}\nfunction round(value) {\n return toInt32(value + (value < 0 ? -0.5 : 0.5));\n}\nfunction getBitMask(value) {\n return 1 << getBitOffset(value);\n}\nfunction getBitOffset(value) {\n return value & 0x1f;\n}\nfunction charAt(value, index) {\n const character = value.at(index);\n return character != null ? character : '';\n}\n// Get hamming weight of int32.\nfunction hammingWeight(value) {\n // HD, Figure 5-2.\n value = value - ((value >> 1) & 0x55555555);\n value = (value & 0x33333333) + ((value >> 2) & 0x33333333);\n return (((value + (value >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;\n}\n// Return the position of the most significant bit set (to one) in the \"value\". The most\n// significant bit is position 32. If there is no bit set, return 0. Examples:\n// - findMSBSet(0) => 0\n// - findMSBSet(1) => 1\n// - findMSBSet(255) => 8\nfunction findMSBSet(value) {\n return 32 - Math.clz32(value);\n}\n// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for \"value\" using polynomial \"poly\". The BCH\n// code is used for encoding type information and version information.\n// Example: Calculation of version information of 7.\n// f(x) is created from 7.\n// - 7 = 000111 in 6 bits\n// - f(x) = x^2 + x^1 + x^0\n// g(x) is given by the standard (p. 67)\n// - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1\n// Multiply f(x) by x^(18 - 6)\n// - f'(x) = f(x) * x^(18 - 6)\n// - f'(x) = x^14 + x^13 + x^12\n// Calculate the remainder of f'(x) / g(x)\n// x^2\n// __________________________________________________\n// g(x) )x^14 + x^13 + x^12\n// x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2\n// --------------------------------------------------\n// x^11 + x^10 + x^7 + x^4 + x^2\n//\n// The remainder is x^11 + x^10 + x^7 + x^4 + x^2\n// Encode it in binary: 110010010100\n// The return value is 0xc94 (1100 1001 0100)\n//\n// Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit\n// operations. We don't care if coefficients are positive or negative.\nfunction calculateBCHCode(value, poly) {\n // If poly is \"1 1111 0010 0101\" (version info poly), msbSetInPoly is 13. We'll subtract 1\n // from 13 to make it 12.\n const msbSetInPoly = findMSBSet(poly);\n value <<= msbSetInPoly - 1;\n // Do the division business using exclusive-or operations.\n while (findMSBSet(value) >= msbSetInPoly) {\n value ^= poly << (findMSBSet(value) - msbSetInPoly);\n }\n // Now the \"value\" is the remainder (i.e. the BCH code).\n return value;\n}\nfunction accumulate(array, start = 0, end = array.length) {\n let total = 0;\n for (let i = start; i < end; i++) {\n total += array[i];\n }\n return total;\n}\n\nexport { accumulate, calculateBCHCode, charAt, findMSBSet, getBitMask, getBitOffset, hammingWeight, round, toBit, toInt32 };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module Mode\n */\nconst VALUES_TO_MODE = new Map();\nfunction fromModeBits(bits) {\n const mode = VALUES_TO_MODE.get(bits);\n if (mode != null) {\n return mode;\n }\n throw new Error('illegal mode bits');\n}\nclass Mode {\n #bits;\n #characterCountBitsSet;\n static TERMINATOR = new Mode([0, 0, 0], 0x00);\n static NUMERIC = new Mode([10, 12, 14], 0x01);\n static ALPHANUMERIC = new Mode([9, 11, 13], 0x02);\n static STRUCTURED_APPEND = new Mode([0, 0, 0], 0x03);\n static BYTE = new Mode([8, 16, 16], 0x04);\n static ECI = new Mode([0, 0, 0], 0x07);\n static KANJI = new Mode([8, 10, 12], 0x08);\n static FNC1_FIRST_POSITION = new Mode([0, 0, 0], 0x05);\n static FNC1_SECOND_POSITION = new Mode([0, 0, 0], 0x09);\n static HANZI = new Mode([8, 10, 12], 0x0d);\n constructor(characterCountBitsSet, bits) {\n this.#bits = bits;\n this.#characterCountBitsSet = new Int32Array(characterCountBitsSet);\n VALUES_TO_MODE.set(bits, this);\n }\n get bits() {\n return this.#bits;\n }\n getCharacterCountBits({ version }) {\n let offset;\n if (version <= 9) {\n offset = 0;\n } else if (version <= 26) {\n offset = 1;\n } else {\n offset = 2;\n }\n return this.#characterCountBitsSet[offset];\n }\n}\n\nexport { Mode, fromModeBits };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { toInt32 } from './utils.js';\n\n/**\n * @module mask\n */\n// Penalty weights.\nconst N1 = 3;\nconst N2 = 3;\nconst N3 = 40;\nconst N4 = 10;\n// Is dark point.\nfunction isDark(matrix, x, y) {\n return matrix.get(x, y) === 1;\n}\n// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both\n// horizontal and vertical orders respectively.\nfunction applyMaskPenaltyRule1Internal(matrix, isVertical) {\n let penalty = 0;\n const { size } = matrix;\n for (let y = 0; y < size; y++) {\n let prevBit = -1;\n let numSameBitCells = 0;\n for (let x = 0; x < size; x++) {\n const bit = isVertical ? matrix.get(y, x) : matrix.get(x, y);\n if (bit === prevBit) {\n numSameBitCells++;\n } else {\n if (numSameBitCells >= 5) {\n penalty += N1 + (numSameBitCells - 5);\n }\n // set prev bit.\n prevBit = bit;\n // include the cell itself.\n numSameBitCells = 1;\n }\n }\n if (numSameBitCells >= 5) {\n penalty += N1 + (numSameBitCells - 5);\n }\n }\n return penalty;\n}\n// Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and\n// give penalty to them. Example: 00000 or 11111.\nfunction applyMaskPenaltyRule1(matrix) {\n return applyMaskPenaltyRule1Internal(matrix) + applyMaskPenaltyRule1Internal(matrix, true);\n}\n// Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give\n// penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a\n// penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.\nfunction applyMaskPenaltyRule2(matrix) {\n let penalty = 0;\n const size = matrix.size - 1;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n const bit = matrix.get(x, y);\n if (\n // Find 2x2 blocks with the same color.\n bit === matrix.get(x + 1, y) &&\n bit === matrix.get(x, y + 1) &&\n bit === matrix.get(x + 1, y + 1)\n ) {\n penalty += N2;\n }\n }\n }\n return penalty;\n}\n// Is is four white, check on horizontal and vertical.\nfunction isFourWhite(matrix, offset, from, to, isVertical) {\n if (from < 0 || to > matrix.size) {\n return false;\n }\n for (let i = from; i < to; i++) {\n if (isVertical ? isDark(matrix, offset, i) : isDark(matrix, i, offset)) {\n return false;\n }\n }\n return true;\n}\n// Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4\n// starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we\n// find patterns like 000010111010000, we give penalty once.\nfunction applyMaskPenaltyRule3(matrix) {\n let numPenalties = 0;\n const { size } = matrix;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (\n // Find consecutive runs of 1:1:3:1:1:4 or 4:1:1:3:1:1, patterns like 000010111010000.\n x + 6 < size &&\n isDark(matrix, x, y) &&\n !isDark(matrix, x + 1, y) &&\n isDark(matrix, x + 2, y) &&\n isDark(matrix, x + 3, y) &&\n isDark(matrix, x + 4, y) &&\n !isDark(matrix, x + 5, y) &&\n isDark(matrix, x + 6, y) &&\n (isFourWhite(matrix, y, x - 4, x) || isFourWhite(matrix, y, x + 7, x + 11))\n ) {\n numPenalties++;\n }\n if (\n // Find consecutive runs of 1:1:3:1:1:4 or 4:1:1:3:1:1, patterns like 000010111010000.\n y + 6 < size &&\n isDark(matrix, x, y) &&\n !isDark(matrix, x, y + 1) &&\n isDark(matrix, x, y + 2) &&\n isDark(matrix, x, y + 3) &&\n isDark(matrix, x, y + 4) &&\n !isDark(matrix, x, y + 5) &&\n isDark(matrix, x, y + 6) &&\n (isFourWhite(matrix, x, y - 4, y, true) || isFourWhite(matrix, x, y + 7, y + 11, true))\n ) {\n numPenalties++;\n }\n }\n }\n return numPenalties * N3;\n}\n// Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give\n// penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.\nfunction applyMaskPenaltyRule4(matrix) {\n let numDarkCells = 0;\n const { size } = matrix;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (isDark(matrix, x, y)) {\n numDarkCells++;\n }\n }\n }\n const numTotalCells = size * size;\n const fivePercentVariances = toInt32((Math.abs(numDarkCells * 2 - numTotalCells) * 10) / numTotalCells);\n return fivePercentVariances * N4;\n}\n// The mask penalty calculation is complicated. See Table 11 of ISO/IEC 18004:2015(E)(p.54) for details.\n// Basically it applies four rules and summate all penalties.\nfunction calculateMaskPenalty(matrix) {\n return (\n applyMaskPenaltyRule1(matrix) +\n applyMaskPenaltyRule2(matrix) +\n applyMaskPenaltyRule3(matrix) +\n applyMaskPenaltyRule4(matrix)\n );\n}\n// Return is apply mask at \"x\" and \"y\". See 7.8 of ISO/IEC 18004:2015(E)(p.50) for mask pattern conditions.\nfunction isApplyMask(mask, x, y) {\n let temporary;\n let intermediate;\n switch (mask) {\n case 0:\n intermediate = (y + x) & 0x01;\n break;\n case 1:\n intermediate = y & 0x01;\n break;\n case 2:\n intermediate = x % 3;\n break;\n case 3:\n intermediate = (y + x) % 3;\n break;\n case 4:\n intermediate = (toInt32(y / 2) + toInt32(x / 3)) & 0x01;\n break;\n case 5:\n temporary = y * x;\n intermediate = (temporary & 0x01) + (temporary % 3);\n break;\n case 6:\n temporary = y * x;\n intermediate = ((temporary & 0x01) + (temporary % 3)) & 0x01;\n break;\n case 7:\n intermediate = (((y * x) % 3) + ((y + x) & 0x01)) & 0x01;\n break;\n default:\n throw new Error(`illegal mask: ${mask}`);\n }\n return intermediate === 0;\n}\n\nexport { calculateMaskPenalty, isApplyMask };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module ECLevel\n */\nconst VALUES_TO_ECLEVEL = new Map();\nfunction fromECLevelBits(bits) {\n const ecLevel = VALUES_TO_ECLEVEL.get(bits);\n if (ecLevel != null) {\n return ecLevel;\n }\n throw new Error('illegal error correction bits');\n}\nclass ECLevel {\n #name;\n #bits;\n #level;\n // L = ~7% correction.\n static L = new ECLevel('L', 0, 0x01);\n // L = ~15% correction.\n static M = new ECLevel('M', 1, 0x00);\n // L = ~25% correction.\n static Q = new ECLevel('Q', 2, 0x03);\n // L = ~30% correction.\n static H = new ECLevel('H', 3, 0x02);\n constructor(name, level, bits) {\n this.#bits = bits;\n this.#name = name;\n this.#level = level;\n VALUES_TO_ECLEVEL.set(bits, this);\n }\n get bits() {\n return this.#bits;\n }\n get name() {\n return this.#name;\n }\n get level() {\n return this.#level;\n }\n}\n\nexport { ECLevel, fromECLevelBits };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module ECB\n */\nclass ECB {\n #count;\n #numDataCodewords;\n constructor(count, numDataCodewords) {\n this.#count = count;\n this.#numDataCodewords = numDataCodewords;\n }\n get count() {\n return this.#count;\n }\n get numDataCodewords() {\n return this.#numDataCodewords;\n }\n}\n\nexport { ECB };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module ECBlocks\n */\nclass ECBlocks {\n #ecBlocks;\n #numTotalCodewords;\n #numTotalECCodewords;\n #numTotalDataCodewords;\n #numECCodewordsPerBlock;\n constructor(numECCodewordsPerBlock, ...ecBlocks) {\n let numBlocks = 0;\n let numTotalDataCodewords = 0;\n for (const { count, numDataCodewords } of ecBlocks) {\n numBlocks += count;\n numTotalDataCodewords += numDataCodewords * count;\n }\n const numTotalECCodewords = numECCodewordsPerBlock * numBlocks;\n this.#ecBlocks = ecBlocks;\n this.#numTotalECCodewords = numTotalECCodewords;\n this.#numTotalDataCodewords = numTotalDataCodewords;\n this.#numECCodewordsPerBlock = numECCodewordsPerBlock;\n this.#numTotalCodewords = numTotalDataCodewords + numTotalECCodewords;\n }\n get ecBlocks() {\n return this.#ecBlocks;\n }\n get numTotalCodewords() {\n return this.#numTotalCodewords;\n }\n get numTotalECCodewords() {\n return this.#numTotalECCodewords;\n }\n get numTotalDataCodewords() {\n return this.#numTotalDataCodewords;\n }\n get numECCodewordsPerBlock() {\n return this.#numECCodewordsPerBlock;\n }\n}\n\nexport { ECBlocks };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { ECB } from './ECB.js';\nimport { ECBlocks } from './ECBlocks.js';\nimport { BitMatrix } from './BitMatrix.js';\nimport { hammingWeight } from './utils.js';\n\n/**\n * @module Version\n */\nconst MIN_VERSION_SIZE = 21;\nconst MAX_VERSION_SIZE = 177;\nconst VERSION_DECODE_TABLE = [\n // Version 7 - 11.\n 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6,\n // Version 12 - 16.\n 0x0c762, 0x0d847, 0x0e60d, 0x0f928, 0x10b78,\n // Version 17 - 21.\n 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683,\n // Version 22 - 26.\n 0x168c9, 0x177ec, 0x18ec4, 0x191e1, 0x1afab,\n // Version 27 - 31.\n 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 0x1f250,\n // Version 32 - 36.\n 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b,\n // Version 37 - 40.\n 0x2542e, 0x26a64, 0x27541, 0x28c69\n];\n// Version > 2 has alignment patterns.\nconst MIN_VERSION_SIZE_WITH_ALIGNMENTS = 25;\nclass Version {\n #size;\n #version;\n #ecBlocks;\n #alignmentPatterns;\n constructor(version, alignmentPatterns, ...ecBlocks) {\n this.#version = version;\n this.#ecBlocks = ecBlocks;\n this.#size = 17 + 4 * version;\n this.#alignmentPatterns = alignmentPatterns;\n }\n get size() {\n return this.#size;\n }\n get version() {\n return this.#version;\n }\n get alignmentPatterns() {\n return this.#alignmentPatterns;\n }\n getECBlocks({ level }) {\n return this.#ecBlocks[level];\n }\n}\nconst VERSIONS = [\n new Version(\n 1,\n [],\n new ECBlocks(7, new ECB(1, 19)),\n new ECBlocks(10, new ECB(1, 16)),\n new ECBlocks(13, new ECB(1, 13)),\n new ECBlocks(17, new ECB(1, 9))\n ),\n new Version(\n 2,\n [6, 18],\n new ECBlocks(10, new ECB(1, 34)),\n new ECBlocks(16, new ECB(1, 28)),\n new ECBlocks(22, new ECB(1, 22)),\n new ECBlocks(28, new ECB(1, 16))\n ),\n new Version(\n 3,\n [6, 22],\n new ECBlocks(15, new ECB(1, 55)),\n new ECBlocks(26, new ECB(1, 44)),\n new ECBlocks(18, new ECB(2, 17)),\n new ECBlocks(22, new ECB(2, 13))\n ),\n new Version(\n 4,\n [6, 26],\n new ECBlocks(20, new ECB(1, 80)),\n new ECBlocks(18, new ECB(2, 32)),\n new ECBlocks(26, new ECB(2, 24)),\n new ECBlocks(16, new ECB(4, 9))\n ),\n new Version(\n 5,\n [6, 30],\n new ECBlocks(26, new ECB(1, 108)),\n new ECBlocks(24, new ECB(2, 43)),\n new ECBlocks(18, new ECB(2, 15), new ECB(2, 16)),\n new ECBlocks(22, new ECB(2, 11), new ECB(2, 12))\n ),\n new Version(\n 6,\n [6, 34],\n new ECBlocks(18, new ECB(2, 68)),\n new ECBlocks(16, new ECB(4, 27)),\n new ECBlocks(24, new ECB(4, 19)),\n new ECBlocks(28, new ECB(4, 15))\n ),\n new Version(\n 7,\n [6, 22, 38],\n new ECBlocks(20, new ECB(2, 78)),\n new ECBlocks(18, new ECB(4, 31)),\n new ECBlocks(18, new ECB(2, 14), new ECB(4, 15)),\n new ECBlocks(26, new ECB(4, 13), new ECB(1, 14))\n ),\n new Version(\n 8,\n [6, 24, 42],\n new ECBlocks(24, new ECB(2, 97)),\n new ECBlocks(22, new ECB(2, 38), new ECB(2, 39)),\n new ECBlocks(22, new ECB(4, 18), new ECB(2, 19)),\n new ECBlocks(26, new ECB(4, 14), new ECB(2, 15))\n ),\n new Version(\n 9,\n [6, 26, 46],\n new ECBlocks(30, new ECB(2, 116)),\n new ECBlocks(22, new ECB(3, 36), new ECB(2, 37)),\n new ECBlocks(20, new ECB(4, 16), new ECB(4, 17)),\n new ECBlocks(24, new ECB(4, 12), new ECB(4, 13))\n ),\n new Version(\n 10,\n [6, 28, 50],\n new ECBlocks(18, new ECB(2, 68), new ECB(2, 69)),\n new ECBlocks(26, new ECB(4, 43), new ECB(1, 44)),\n new ECBlocks(24, new ECB(6, 19), new ECB(2, 20)),\n new ECBlocks(28, new ECB(6, 15), new ECB(2, 16))\n ),\n new Version(\n 11,\n [6, 30, 54],\n new ECBlocks(20, new ECB(4, 81)),\n new ECBlocks(30, new ECB(1, 50), new ECB(4, 51)),\n new ECBlocks(28, new ECB(4, 22), new ECB(4, 23)),\n new ECBlocks(24, new ECB(3, 12), new ECB(8, 13))\n ),\n new Version(\n 12,\n [6, 32, 58],\n new ECBlocks(24, new ECB(2, 92), new ECB(2, 93)),\n new ECBlocks(22, new ECB(6, 36), new ECB(2, 37)),\n new ECBlocks(26, new ECB(4, 20), new ECB(6, 21)),\n new ECBlocks(28, new ECB(7, 14), new ECB(4, 15))\n ),\n new Version(\n 13,\n [6, 34, 62],\n new ECBlocks(26, new ECB(4, 107)),\n new ECBlocks(22, new ECB(8, 37), new ECB(1, 38)),\n new ECBlocks(24, new ECB(8, 20), new ECB(4, 21)),\n new ECBlocks(22, new ECB(12, 11), new ECB(4, 12))\n ),\n new Version(\n 14,\n [6, 26, 46, 66],\n new ECBlocks(30, new ECB(3, 115), new ECB(1, 116)),\n new ECBlocks(24, new ECB(4, 40), new ECB(5, 41)),\n new ECBlocks(20, new ECB(11, 16), new ECB(5, 17)),\n new ECBlocks(24, new ECB(11, 12), new ECB(5, 13))\n ),\n new Version(\n 15,\n [6, 26, 48, 70],\n new ECBlocks(22, new ECB(5, 87), new ECB(1, 88)),\n new ECBlocks(24, new ECB(5, 41), new ECB(5, 42)),\n new ECBlocks(30, new ECB(5, 24), new ECB(7, 25)),\n new ECBlocks(24, new ECB(11, 12), new ECB(7, 13))\n ),\n new Version(\n 16,\n [6, 26, 50, 74],\n new ECBlocks(24, new ECB(5, 98), new ECB(1, 99)),\n new ECBlocks(28, new ECB(7, 45), new ECB(3, 46)),\n new ECBlocks(24, new ECB(15, 19), new ECB(2, 20)),\n new ECBlocks(30, new ECB(3, 15), new ECB(13, 16))\n ),\n new Version(\n 17,\n [6, 30, 54, 78],\n new ECBlocks(28, new ECB(1, 107), new ECB(5, 108)),\n new ECBlocks(28, new ECB(10, 46), new ECB(1, 47)),\n new ECBlocks(28, new ECB(1, 22), new ECB(15, 23)),\n new ECBlocks(28, new ECB(2, 14), new ECB(17, 15))\n ),\n new Version(\n 18,\n [6, 30, 56, 82],\n new ECBlocks(30, new ECB(5, 120), new ECB(1, 121)),\n new ECBlocks(26, new ECB(9, 43), new ECB(4, 44)),\n new ECBlocks(28, new ECB(17, 22), new ECB(1, 23)),\n new ECBlocks(28, new ECB(2, 14), new ECB(19, 15))\n ),\n new Version(\n 19,\n [6, 30, 58, 86],\n new ECBlocks(28, new ECB(3, 113), new ECB(4, 114)),\n new ECBlocks(26, new ECB(3, 44), new ECB(11, 45)),\n new ECBlocks(26, new ECB(17, 21), new ECB(4, 22)),\n new ECBlocks(26, new ECB(9, 13), new ECB(16, 14))\n ),\n new Version(\n 20,\n [6, 34, 62, 90],\n new ECBlocks(28, new ECB(3, 107), new ECB(5, 108)),\n new ECBlocks(26, new ECB(3, 41), new ECB(13, 42)),\n new ECBlocks(30, new ECB(15, 24), new ECB(5, 25)),\n new ECBlocks(28, new ECB(15, 15), new ECB(10, 16))\n ),\n new Version(\n 21,\n [6, 28, 50, 72, 94],\n new ECBlocks(28, new ECB(4, 116), new ECB(4, 117)),\n new ECBlocks(26, new ECB(17, 42)),\n new ECBlocks(28, new ECB(17, 22), new ECB(6, 23)),\n new ECBlocks(30, new ECB(19, 16), new ECB(6, 17))\n ),\n new Version(\n 22,\n [6, 26, 50, 74, 98],\n new ECBlocks(28, new ECB(2, 111), new ECB(7, 112)),\n new ECBlocks(28, new ECB(17, 46)),\n new ECBlocks(30, new ECB(7, 24), new ECB(16, 25)),\n new ECBlocks(24, new ECB(34, 13))\n ),\n new Version(\n 23,\n [6, 30, 54, 78, 102],\n new ECBlocks(30, new ECB(4, 121), new ECB(5, 122)),\n new ECBlocks(28, new ECB(4, 47), new ECB(14, 48)),\n new ECBlocks(30, new ECB(11, 24), new ECB(14, 25)),\n new ECBlocks(30, new ECB(16, 15), new ECB(14, 16))\n ),\n new Version(\n 24,\n [6, 28, 54, 80, 106],\n new ECBlocks(30, new ECB(6, 117), new ECB(4, 118)),\n new ECBlocks(28, new ECB(6, 45), new ECB(14, 46)),\n new ECBlocks(30, new ECB(11, 24), new ECB(16, 25)),\n new ECBlocks(30, new ECB(30, 16), new ECB(2, 17))\n ),\n new Version(\n 25,\n [6, 32, 58, 84, 110],\n new ECBlocks(26, new ECB(8, 106), new ECB(4, 107)),\n new ECBlocks(28, new ECB(8, 47), new ECB(13, 48)),\n new ECBlocks(30, new ECB(7, 24), new ECB(22, 25)),\n new ECBlocks(30, new ECB(22, 15), new ECB(13, 16))\n ),\n new Version(\n 26,\n [6, 30, 58, 86, 114],\n new ECBlocks(28, new ECB(10, 114), new ECB(2, 115)),\n new ECBlocks(28, new ECB(19, 46), new ECB(4, 47)),\n new ECBlocks(28, new ECB(28, 22), new ECB(6, 23)),\n new ECBlocks(30, new ECB(33, 16), new ECB(4, 17))\n ),\n new Version(\n 27,\n [6, 34, 62, 90, 118],\n new ECBlocks(30, new ECB(8, 122), new ECB(4, 123)),\n new ECBlocks(28, new ECB(22, 45), new ECB(3, 46)),\n new ECBlocks(30, new ECB(8, 23), new ECB(26, 24)),\n new ECBlocks(30, new ECB(12, 15), new ECB(28, 16))\n ),\n new Version(\n 28,\n [6, 26, 50, 74, 98, 122],\n new ECBlocks(30, new ECB(3, 117), new ECB(10, 118)),\n new ECBlocks(28, new ECB(3, 45), new ECB(23, 46)),\n new ECBlocks(30, new ECB(4, 24), new ECB(31, 25)),\n new ECBlocks(30, new ECB(11, 15), new ECB(31, 16))\n ),\n new Version(\n 29,\n [6, 30, 54, 78, 102, 126],\n new ECBlocks(30, new ECB(7, 116), new ECB(7, 117)),\n new ECBlocks(28, new ECB(21, 45), new ECB(7, 46)),\n new ECBlocks(30, new ECB(1, 23), new ECB(37, 24)),\n new ECBlocks(30, new ECB(19, 15), new ECB(26, 16))\n ),\n new Version(\n 30,\n [6, 26, 52, 78, 104, 130],\n new ECBlocks(30, new ECB(5, 115), new ECB(10, 116)),\n new ECBlocks(28, new ECB(19, 47), new ECB(10, 48)),\n new ECBlocks(30, new ECB(15, 24), new ECB(25, 25)),\n new ECBlocks(30, new ECB(23, 15), new ECB(25, 16))\n ),\n new Version(\n 31,\n [6, 30, 56, 82, 108, 134],\n new ECBlocks(30, new ECB(13, 115), new ECB(3, 116)),\n new ECBlocks(28, new ECB(2, 46), new ECB(29, 47)),\n new ECBlocks(30, new ECB(42, 24), new ECB(1, 25)),\n new ECBlocks(30, new ECB(23, 15), new ECB(28, 16))\n ),\n new Version(\n 32,\n [6, 34, 60, 86, 112, 138],\n new ECBlocks(30, new ECB(17, 115)),\n new ECBlocks(28, new ECB(10, 46), new ECB(23, 47)),\n new ECBlocks(30, new ECB(10, 24), new ECB(35, 25)),\n new ECBlocks(30, new ECB(19, 15), new ECB(35, 16))\n ),\n new Version(\n 33,\n [6, 30, 58, 86, 114, 142],\n new ECBlocks(30, new ECB(17, 115), new ECB(1, 116)),\n new ECBlocks(28, new ECB(14, 46), new ECB(21, 47)),\n new ECBlocks(30, new ECB(29, 24), new ECB(19, 25)),\n new ECBlocks(30, new ECB(11, 15), new ECB(46, 16))\n ),\n new Version(\n 34,\n [6, 34, 62, 90, 118, 146],\n new ECBlocks(30, new ECB(13, 115), new ECB(6, 116)),\n new ECBlocks(28, new ECB(14, 46), new ECB(23, 47)),\n new ECBlocks(30, new ECB(44, 24), new ECB(7, 25)),\n new ECBlocks(30, new ECB(59, 16), new ECB(1, 17))\n ),\n new Version(\n 35,\n [6, 30, 54, 78, 102, 126, 150],\n new ECBlocks(30, new ECB(12, 121), new ECB(7, 122)),\n new ECBlocks(28, new ECB(12, 47), new ECB(26, 48)),\n new ECBlocks(30, new ECB(39, 24), new ECB(14, 25)),\n new ECBlocks(30, new ECB(22, 15), new ECB(41, 16))\n ),\n new Version(\n 36,\n [6, 24, 50, 76, 102, 128, 154],\n new ECBlocks(30, new ECB(6, 121), new ECB(14, 122)),\n new ECBlocks(28, new ECB(6, 47), new ECB(34, 48)),\n new ECBlocks(30, new ECB(46, 24), new ECB(10, 25)),\n new ECBlocks(30, new ECB(2, 15), new ECB(64, 16))\n ),\n new Version(\n 37,\n [6, 28, 54, 80, 106, 132, 158],\n new ECBlocks(30, new ECB(17, 122), new ECB(4, 123)),\n new ECBlocks(28, new ECB(29, 46), new ECB(14, 47)),\n new ECBlocks(30, new ECB(49, 24), new ECB(10, 25)),\n new ECBlocks(30, new ECB(24, 15), new ECB(46, 16))\n ),\n new Version(\n 38,\n [6, 32, 58, 84, 110, 136, 162],\n new ECBlocks(30, new ECB(4, 122), new ECB(18, 123)),\n new ECBlocks(28, new ECB(13, 46), new ECB(32, 47)),\n new ECBlocks(30, new ECB(48, 24), new ECB(14, 25)),\n new ECBlocks(30, new ECB(42, 15), new ECB(32, 16))\n ),\n new Version(\n 39,\n [6, 26, 54, 82, 110, 138, 166],\n new ECBlocks(30, new ECB(20, 117), new ECB(4, 118)),\n new ECBlocks(28, new ECB(40, 47), new ECB(7, 48)),\n new ECBlocks(30, new ECB(43, 24), new ECB(22, 25)),\n new ECBlocks(30, new ECB(10, 15), new ECB(67, 16))\n ),\n new Version(\n 40,\n [6, 30, 58, 86, 114, 142, 170],\n new ECBlocks(30, new ECB(19, 118), new ECB(6, 119)),\n new ECBlocks(28, new ECB(18, 47), new ECB(31, 48)),\n new ECBlocks(30, new ECB(34, 24), new ECB(34, 25)),\n new ECBlocks(30, new ECB(20, 15), new ECB(61, 16))\n )\n];\nfunction decodeVersion(version1, version2) {\n let bestDiff = 32;\n let bestVersion = 0;\n const { length } = VERSION_DECODE_TABLE;\n for (let i = 0; i < length; i++) {\n const maskedVersion = VERSION_DECODE_TABLE[i];\n // Do the version info bits match exactly done?\n if (version1 === maskedVersion || version2 === maskedVersion) {\n return VERSIONS[i + 6];\n }\n // Otherwise see if this is the closest to a real version info bit string we have seen so far.\n let bitsDiff = hammingWeight(version1 ^ maskedVersion);\n if (bitsDiff < bestDiff) {\n bestDiff = bitsDiff;\n bestVersion = i + 7;\n }\n if (version1 !== version2) {\n // Also try the other option.\n bitsDiff = hammingWeight(version2 ^ maskedVersion);\n if (bitsDiff < bestDiff) {\n bestDiff = bitsDiff;\n bestVersion = i + 7;\n }\n }\n }\n // We can tolerate up to 3 bits of error since no two version info codewords will differ in less than 8 bits.\n if (bestDiff <= 3 && bestVersion >= 7) {\n return VERSIONS[bestVersion - 1];\n }\n // If we didn't find a close enough match, fail.\n throw new Error('unable to decode version');\n}\n// See ISO 18004:2006 Annex E\nfunction buildFunctionPattern({ size, version, alignmentPatterns }) {\n // Alignment patterns\n const { length } = alignmentPatterns;\n const matrix = new BitMatrix(size);\n const max = length - 1;\n // Top left finder pattern + separator + format.\n matrix.setRegion(0, 0, 9, 9);\n // Top right finder pattern + separator + format.\n matrix.setRegion(size - 8, 0, 8, 9);\n // Bottom left finder pattern + separator + format.\n matrix.setRegion(0, size - 8, 9, 8);\n for (let x = 0; x < length; x++) {\n const top = alignmentPatterns[x] - 2;\n for (let y = 0; y < length; y++) {\n if ((x !== 0 || (y !== 0 && y !== max)) && (x !== max || y !== 0)) {\n matrix.setRegion(alignmentPatterns[y] - 2, top, 5, 5);\n }\n // Else no o alignment patterns near the three finder patterns.\n }\n }\n // Vertical timing pattern.\n matrix.setRegion(6, 9, 1, size - 17);\n // Horizontal timing pattern.\n matrix.setRegion(9, 6, size - 17, 1);\n if (version > 6) {\n // Version info, top right.\n matrix.setRegion(size - 11, 0, 3, 6);\n // Version info, bottom left.\n matrix.setRegion(0, size - 11, 6, 3);\n }\n return matrix;\n}\n\nexport {\n MAX_VERSION_SIZE,\n MIN_VERSION_SIZE,\n MIN_VERSION_SIZE_WITH_ALIGNMENTS,\n VERSIONS,\n Version,\n buildFunctionPattern,\n decodeVersion\n};\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module Polynomial\n */\nclass Polynomial {\n #field;\n #coefficients;\n constructor(field, coefficients) {\n const { length } = coefficients;\n if (length <= 0) {\n throw new Error('polynomial coefficients cannot empty');\n }\n this.#field = field;\n if (length > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\".\n let firstNonZero = 1;\n while (firstNonZero < length && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === length) {\n this.#coefficients = new Int32Array([0]);\n } else {\n const array = new Int32Array(length - firstNonZero);\n array.set(coefficients.subarray(firstNonZero));\n this.#coefficients = array;\n }\n } else {\n this.#coefficients = coefficients;\n }\n }\n get coefficients() {\n return this.#coefficients;\n }\n isZero() {\n return this.#coefficients[0] === 0;\n }\n getDegree() {\n return this.#coefficients.length - 1;\n }\n getCoefficient(degree) {\n const coefficients = this.#coefficients;\n return coefficients[coefficients.length - 1 - degree];\n }\n evaluate(a) {\n if (a === 0) {\n // Just return the x^0 coefficient.\n return this.getCoefficient(0);\n }\n let result;\n const coefficients = this.#coefficients;\n if (a === 1) {\n // Just the sum of the coefficients.\n result = 0;\n for (const coefficient of coefficients) {\n result ^= coefficient;\n }\n return result;\n }\n [result] = coefficients;\n const field = this.#field;\n const { length } = coefficients;\n for (let i = 1; i < length; i++) {\n result = field.multiply(a, result) ^ coefficients[i];\n }\n return result;\n }\n multiply(other) {\n const field = this.#field;\n const coefficients = this.#coefficients;\n const { length } = coefficients;\n if (other instanceof Polynomial) {\n if (this.isZero() || other.isZero()) {\n return field.zero;\n }\n const otherCoefficients = other.#coefficients;\n const otherLength = otherCoefficients.length;\n const product = new Int32Array(length + otherLength - 1);\n for (let i = 0; i < length; i++) {\n const coefficient = coefficients[i];\n for (let j = 0; j < otherLength; j++) {\n product[i + j] ^= field.multiply(coefficient, otherCoefficients[j]);\n }\n }\n return new Polynomial(field, product);\n }\n if (other === 0) {\n return field.zero;\n }\n if (other === 1) {\n return this;\n }\n const product = new Int32Array(length);\n for (let i = 0; i < length; i++) {\n product[i] = field.multiply(coefficients[i], other);\n }\n return new Polynomial(field, product);\n }\n multiplyByMonomial(degree, coefficient) {\n const field = this.#field;\n if (coefficient === 0) {\n return field.zero;\n }\n const coefficients = this.#coefficients;\n const { length } = coefficients;\n const product = new Int32Array(length + degree);\n for (let i = 0; i < length; i++) {\n product[i] = field.multiply(coefficients[i], coefficient);\n }\n return new Polynomial(field, product);\n }\n addOrSubtract(other) {\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n let largerCoefficients = other.#coefficients;\n let largerLength = largerCoefficients.length;\n let smallerCoefficients = this.#coefficients;\n let smallerLength = smallerCoefficients.length;\n if (largerLength < smallerLength) {\n [largerLength, smallerLength] = [smallerLength, largerLength];\n [largerCoefficients, smallerCoefficients] = [smallerCoefficients, largerCoefficients];\n }\n // Diff index offset.\n const offset = largerLength - smallerLength;\n const coefficients = new Int32Array(largerLength);\n // Copy high-order terms only found in higher-degree polynomial's coefficients.\n coefficients.set(largerCoefficients.subarray(0, offset));\n for (let i = offset; i < largerLength; i++) {\n coefficients[i] = smallerCoefficients[i - offset] ^ largerCoefficients[i];\n }\n return new Polynomial(this.#field, coefficients);\n }\n divide(other) {\n const field = this.#field;\n let quotient = field.zero;\n let remainder = this;\n const denominatorLeadingTerm = other.getCoefficient(other.getDegree());\n const invertDenominatorLeadingTerm = field.invert(denominatorLeadingTerm);\n while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n const remainderDegree = remainder.getDegree();\n const degreeDiff = remainderDegree - other.getDegree();\n const scale = field.multiply(remainder.getCoefficient(remainderDegree), invertDenominatorLeadingTerm);\n const term = other.multiplyByMonomial(degreeDiff, scale);\n const iterationQuotient = field.buildPolynomial(degreeDiff, scale);\n quotient = quotient.addOrSubtract(iterationQuotient);\n remainder = remainder.addOrSubtract(term);\n }\n return [quotient, remainder];\n }\n}\n\nexport { Polynomial };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Polynomial } from './Polynomial.js';\n\n/**\n * @module GaloisField\n */\nclass GaloisField {\n #size;\n #one;\n #zero;\n #generator;\n #expTable;\n #logTable;\n constructor(primitive, size, generator) {\n let x = 1;\n const expTable = new Int32Array(size);\n for (let i = 0; i < size; i++) {\n expTable[i] = x;\n // We're assuming the generator alpha is 2.\n x *= 2;\n if (x >= size) {\n x ^= primitive;\n x &= size - 1;\n }\n }\n const logTable = new Int32Array(size);\n for (let i = 0, length = size - 1; i < length; i++) {\n logTable[expTable[i]] = i;\n }\n this.#size = size;\n this.#expTable = expTable;\n this.#logTable = logTable;\n this.#generator = generator;\n this.#one = new Polynomial(this, new Int32Array([1]));\n this.#zero = new Polynomial(this, new Int32Array([0]));\n }\n get size() {\n return this.#size;\n }\n get one() {\n return this.#one;\n }\n get zero() {\n return this.#zero;\n }\n get generator() {\n return this.#generator;\n }\n exp(a) {\n return this.#expTable[a];\n }\n log(a) {\n return this.#logTable[a];\n }\n invert(a) {\n return this.#expTable[this.#size - this.#logTable[a] - 1];\n }\n multiply(a, b) {\n if (a === 0 || b === 0) {\n return 0;\n }\n const logTable = this.#logTable;\n return this.#expTable[(logTable[a] + logTable[b]) % (this.#size - 1)];\n }\n buildPolynomial(degree, coefficient) {\n if (coefficient === 0) {\n return this.#zero;\n }\n const coefficients = new Int32Array(degree + 1);\n coefficients[0] = coefficient;\n return new Polynomial(this, coefficients);\n }\n}\nconst QR_CODE_FIELD_256 = new GaloisField(0x011d, 256, 0);\n\nexport { GaloisField, QR_CODE_FIELD_256 };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Charset } from '../Charset.js';\n\n/**\n * @module index\n */\nfunction getUnicodeCodes(content, maxCode) {\n const bytes = [];\n for (const character of content) {\n const code = character.codePointAt(0);\n // If gt max code, push \"?\".\n bytes.push(code == null || code > maxCode ? 63 : code);\n }\n return new Uint8Array(bytes);\n}\nfunction encode(content, charset) {\n switch (charset) {\n case Charset.ASCII:\n return getUnicodeCodes(content, 0x7f);\n case Charset.ISO_8859_1:\n return getUnicodeCodes(content, 0xff);\n case Charset.UTF_8:\n return new TextEncoder().encode(content);\n default:\n throw Error(`built-in encode not support charset: ${charset.label}`);\n }\n}\nfunction decode(bytes, charset) {\n try {\n return new TextDecoder(charset.label).decode(bytes);\n } catch {\n throw Error(`built-in decode not support charset: ${charset.label}`);\n }\n}\n\nexport { decode, encode };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { getBitMask, toBit, getBitOffset, toInt32 } from './utils.js';\n\n/**\n * @module BitArray\n */\nconst LOAD_FACTOR = 0.75;\nfunction offset(index) {\n return toInt32(index / 32);\n}\nfunction makeArray(length) {\n return new Int32Array(Math.ceil(length / 32));\n}\nclass BitArray {\n #length;\n #bits;\n constructor(length = 0) {\n this.#length = length;\n this.#bits = makeArray(length);\n }\n #alloc(length) {\n const bits = this.#bits;\n if (length > bits.length * 32) {\n const array = makeArray(Math.ceil(length / LOAD_FACTOR));\n array.set(bits);\n this.#bits = array;\n }\n this.#length = length;\n }\n get length() {\n return this.#length;\n }\n get byteLength() {\n return Math.ceil(this.#length / 8);\n }\n set(index) {\n this.#bits[offset(index)] |= getBitMask(index);\n }\n get(index) {\n return toBit(this.#bits[offset(index)] >>> getBitOffset(index));\n }\n xor(mask) {\n const bits = this.#bits;\n const maskBits = mask.#bits;\n const length = Math.min(this.#length, mask.#length);\n for (let i = 0; i < length; i++) {\n // The last int could be incomplete (i.e. not have 32 bits in\n // it) but there is no problem since 0 XOR 0 == 0.\n bits[i] ^= maskBits[i];\n }\n }\n append(value, length = 1) {\n let index = this.#length;\n if (value instanceof BitArray) {\n length = value.#length;\n this.#alloc(index + length);\n for (let i = 0; i < length; i++) {\n if (value.get(i) !== 0) {\n this.set(index);\n }\n index++;\n }\n } else {\n this.#alloc(index + length);\n for (let i = length - 1; i >= 0; i--) {\n if (toBit(value >>> i) !== 0) {\n this.set(index);\n }\n index++;\n }\n }\n }\n writeToUint8Array(bitOffset, target, byteOffset, byteLength) {\n for (let i = 0; i < byteLength; i++) {\n let byte = 0;\n for (let j = 0; j < 8; j++) {\n if (this.get(bitOffset++) !== 0) {\n byte |= 1 << (7 - j);\n }\n }\n target[byteOffset + i] = byte;\n }\n }\n clear() {\n this.#bits.fill(0);\n }\n}\n\nexport { BitArray };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module ByteMatrix\n */\nclass ByteMatrix {\n #size;\n #bytes;\n constructor(size) {\n this.#size = size;\n this.#bytes = new Int8Array(size * size);\n }\n get size() {\n return this.#size;\n }\n set(x, y, value) {\n this.#bytes[y * this.#size + x] = value;\n }\n get(x, y) {\n return this.#bytes[y * this.#size + x];\n }\n clear(value) {\n this.#bytes.fill(value);\n }\n}\n\nexport { ByteMatrix };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { isApplyMask } from '../../common/mask.js';\nimport { BitArray } from '../../common/BitArray.js';\nimport { ByteMatrix } from '../../common/ByteMatrix.js';\nimport { calculateBCHCode } from '../../common/utils.js';\nimport { VERSIONS } from '../../common/Version.js';\n\n/**\n * @module matrix\n */\n// Format information poly: 101 0011 0111.\nconst FORMAT_INFO_POLY = 0x537;\n// Format information mask.\nconst FORMAT_INFO_MASK = 0x5412;\n// Version information poly: 1 1111 0010 0101.\nconst VERSION_INFO_POLY = 0x1f25;\n// Finder pattern shape.\nconst FINDER_PATTERN_SHAPE = [\n [1, 1, 1, 1, 1, 1, 1],\n [1, 0, 0, 0, 0, 0, 1],\n [1, 0, 1, 1, 1, 0, 1],\n [1, 0, 1, 1, 1, 0, 1],\n [1, 0, 1, 1, 1, 0, 1],\n [1, 0, 0, 0, 0, 0, 1],\n [1, 1, 1, 1, 1, 1, 1]\n];\n// Alignment pattern shape.\nconst ALIGNMENT_PATTERN_SHAPE = [\n [1, 1, 1, 1, 1],\n [1, 0, 0, 0, 1],\n [1, 0, 1, 0, 1],\n [1, 0, 0, 0, 1],\n [1, 1, 1, 1, 1]\n];\n// Format information coordinates.\nconst FORMAT_INFO_COORDINATES = [\n [8, 0],\n [8, 1],\n [8, 2],\n [8, 3],\n [8, 4],\n [8, 5],\n [8, 7],\n [8, 8],\n [7, 8],\n [5, 8],\n [4, 8],\n [3, 8],\n [2, 8],\n [1, 8],\n [0, 8]\n];\n// Is empty point.\nfunction isEmpty(matrix, x, y) {\n return matrix.get(x, y) === -1;\n}\nfunction embedFinderPattern(matrix, x, y) {\n for (let i = 0; i < 7; i++) {\n const pattern = FINDER_PATTERN_SHAPE[i];\n for (let j = 0; j < 7; j++) {\n matrix.set(x + j, y + i, pattern[j]);\n }\n }\n}\nfunction embedHorizontalSeparator(matrix, x, y) {\n for (let j = 0; j < 8; j++) {\n matrix.set(x + j, y, 0);\n }\n}\nfunction embedVerticalSeparator(matrix, x, y) {\n for (let i = 0; i < 7; i++) {\n matrix.set(x, y + i, 0);\n }\n}\n// Embed finder patterns and surrounding vertical/horizontal separators.\nfunction embedFinderPatternsAndSeparators(matrix) {\n // Embed three big squares at corners.\n const pdpWidth = 7;\n // Embed horizontal separation patterns around the squares.\n const hspWidth = 8;\n // Embed vertical separation patterns around the squares.\n const vspHeight = 7;\n // Matrix width\n const { size } = matrix;\n // Left top corner.\n embedFinderPattern(matrix, 0, 0);\n // Right top corner.\n embedFinderPattern(matrix, size - pdpWidth, 0);\n // Left bottom corner.\n embedFinderPattern(matrix, 0, size - pdpWidth);\n // Left top corner.\n embedHorizontalSeparator(matrix, 0, hspWidth - 1);\n // Right top corner.\n embedHorizontalSeparator(matrix, size - hspWidth, hspWidth - 1);\n // Left bottom corner.\n embedHorizontalSeparator(matrix, 0, size - hspWidth);\n // Left top corner.\n embedVerticalSeparator(matrix, vspHeight, 0);\n // Right top corner.\n embedVerticalSeparator(matrix, size - vspHeight - 1, 0);\n // Left bottom corner.\n embedVerticalSeparator(matrix, vspHeight, size - vspHeight);\n}\nfunction embedTimingPatterns(matrix) {\n const size = matrix.size - 8;\n // -8 is for skipping position detection patterns (7: size)\n // separation patterns (1: size). Thus, 8 = 7 + 1.\n for (let x = 8; x < size; x++) {\n const bit = (x + 1) & 0x01;\n // Horizontal line.\n if (isEmpty(matrix, x, 6)) {\n matrix.set(x, 6, bit);\n }\n }\n // -8 is for skipping position detection patterns (7: size)\n // separation patterns (1: size). Thus, 8 = 7 + 1.\n for (let y = 8; y < size; y++) {\n const bit = (y + 1) & 0x01;\n // Vertical line.\n if (isEmpty(matrix, 6, y)) {\n matrix.set(6, y, bit);\n }\n }\n}\nfunction embedAlignmentPattern(matrix, x, y) {\n for (let i = 0; i < 5; i++) {\n const pattern = ALIGNMENT_PATTERN_SHAPE[i];\n for (let j = 0; j < 5; j++) {\n matrix.set(x + j, y + i, pattern[j]);\n }\n }\n}\n// Embed position alignment patterns if need be.\nfunction embedAlignmentPatterns(matrix, { version }) {\n if (version >= 2) {\n const { alignmentPatterns } = VERSIONS[version - 1];\n const { length } = alignmentPatterns;\n for (let i = 0; i < length; i++) {\n const y = alignmentPatterns[i];\n for (let j = 0; j < length; j++) {\n const x = alignmentPatterns[j];\n if (isEmpty(matrix, x, y)) {\n // If the cell is unset, we embed the position alignment pattern here.\n // -2 is necessary since the x/y coordinates point to the center of the pattern, not the\n // left top corner.\n embedAlignmentPattern(matrix, x - 2, y - 2);\n }\n }\n }\n }\n}\n// Embed the lonely dark dot at left bottom corner. ISO/IEC 18004:2015(E)(p.56)\nfunction embedDarkModule(matrix) {\n matrix.set(8, matrix.size - 8, 1);\n}\n// Make bit vector of format information. On success, store the result in \"bits\".\n// Encode error correction level and mask pattern. See 8.9 of\n// ISO/IEC 18004:2015(E)(p.55) for details.\nfunction makeFormatInfoBits(bits, ecLevel, mask) {\n const formatInfo = (ecLevel.bits << 3) | mask;\n bits.append(formatInfo, 5);\n const bchCode = calculateBCHCode(formatInfo, FORMAT_INFO_POLY);\n bits.append(bchCode, 10);\n const maskBits = new BitArray();\n maskBits.append(FORMAT_INFO_MASK, 15);\n bits.xor(maskBits);\n}\n// Embed format information. On success, modify the matrix.\nfunction embedFormatInfo(matrix, ecLevel, mask) {\n const formatInfoBits = new BitArray();\n makeFormatInfoBits(formatInfoBits, ecLevel, mask);\n const { size } = matrix;\n const { length } = formatInfoBits;\n for (let i = 0; i < length; i++) {\n // Type info bits at the left top corner.\n const [x, y] = FORMAT_INFO_COORDINATES[i];\n // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in formatInfoBits.\n const bit = formatInfoBits.get(length - 1 - i);\n matrix.set(x, y, bit);\n if (i < 8) {\n // Right top corner.\n matrix.set(size - i - 1, 8, bit);\n } else {\n // Left bottom corner.\n matrix.set(8, size - 7 + (i - 8), bit);\n }\n }\n // Then, embed the dark dot at the left bottom corner.\n embedDarkModule(matrix);\n}\n// Make bit vector of version information. On success, store the result in \"bits\".\n// See 7.10 of ISO/IEC 18004:2015(E)(p.58) for details.\nfunction makeVersionInfoBits(bits, version) {\n bits.append(version, 6);\n const bchCode = calculateBCHCode(version, VERSION_INFO_POLY);\n bits.append(bchCode, 12);\n}\n// Embed version information if need be. On success, modify the matrix.\n// See 7.10 of ISO/IEC 18004:2015(E)(p.58) for how to embed version information.\nfunction embedVersionInfo(matrix, { version }) {\n if (version >= 7) {\n const versionInfoBits = new BitArray();\n makeVersionInfoBits(versionInfoBits, version);\n // It will decrease from 17 to 0.\n let bitIndex = 6 * 3 - 1;\n const { size } = matrix;\n for (let i = 0; i < 6; i++) {\n for (let j = 0; j < 3; j++) {\n // Place bits in LSB (least significant bit) to MSB order.\n const bit = versionInfoBits.get(bitIndex--);\n // Left bottom corner.\n matrix.set(i, size - 11 + j, bit);\n // Right bottom corner.\n matrix.set(size - 11 + j, i, bit);\n }\n }\n }\n}\n// Embed \"codewords\". On success, modify the matrix.\n// See 7.7.3 of ISO/IEC 18004:2015(E)(p.46) for how to embed codewords.\nfunction embedCodewords(matrix, codewords, mask) {\n let bitIndex = 0;\n const { size } = matrix;\n const { length } = codewords;\n // Start from the right bottom cell.\n for (let x = size - 1; x >= 1; x -= 2) {\n // Skip the vertical timing pattern.\n if (x === 6) {\n x = 5;\n }\n for (let y = 0; y < size; y++) {\n for (let i = 0; i < 2; i++) {\n const offsetX = x - i;\n const upward = ((x + 1) & 2) === 0;\n const offsetY = upward ? size - 1 - y : y;\n // Skip the cell if it's not empty.\n if (isEmpty(matrix, offsetX, offsetY)) {\n // Padding bit. If there is no bit left, we'll fill the left cells with 0.\n let bit = 0;\n if (bitIndex < length) {\n bit = codewords.get(bitIndex++);\n }\n // Is apply mask.\n if (isApplyMask(mask, offsetX, offsetY)) {\n bit ^= 1;\n }\n matrix.set(offsetX, offsetY, bit);\n }\n }\n }\n }\n}\n// Embed function patterns. On success, modify the matrix.\n// The function patterns are:\n// - Finder patterns and separators\n// - Alignment patterns, if version >= 2\n// - Timing patterns\nfunction embedFunctionPatterns(matrix, version) {\n // Let's get started with embedding big squares at corners.\n embedFinderPatternsAndSeparators(matrix);\n // Alignment patterns appear if version >= 2.\n embedAlignmentPatterns(matrix, version);\n // Timing patterns should be embedded after position adj. patterns.\n embedTimingPatterns(matrix);\n}\n// Embed encoding region. On success, modify the matrix.\n// The encoding region are:\n// - Format Info\n// - Version Info, if version >= 7\n// - Data with correction\nfunction embedEncodingRegion(matrix, codewords, version, ecLevel, mask) {\n // Type information appear with any version.\n embedFormatInfo(matrix, ecLevel, mask);\n // Version info appear if version >= 7.\n embedVersionInfo(matrix, version);\n // Data should be embedded at end.\n embedCodewords(matrix, codewords, mask);\n}\n// Build 2D matrix of QR Code from \"codewords\" with \"ecLevel\", \"version\" and \"getMaskPattern\". On\n// success, store the result in \"matrix\".\nfunction buildMatrix(codewords, version, ecLevel, mask) {\n const matrix = new ByteMatrix(version.size);\n // Clear matrix.\n matrix.clear(-1);\n // Embed function patterns.\n embedFunctionPatterns(matrix, version);\n // Embed encoding region.\n embedEncodingRegion(matrix, codewords, version, ecLevel, mask);\n return matrix;\n}\n\nexport { buildMatrix };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module BlockPair\n */\nclass BlockPair {\n #ecCodewords;\n #dataCodewords;\n constructor(dataCodewords, ecCodewords) {\n this.#ecCodewords = ecCodewords;\n this.#dataCodewords = dataCodewords;\n }\n get ecCodewords() {\n return this.#ecCodewords;\n }\n get dataCodewords() {\n return this.#dataCodewords;\n }\n}\n\nexport { BlockPair };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Polynomial } from './Polynomial.js';\nimport { QR_CODE_FIELD_256 } from './GaloisField.js';\n\n/**\n * @module Encoder\n */\nfunction buildGenerator(field, generators, degree) {\n const { length } = generators;\n if (degree >= length) {\n const { generator } = field;\n let lastGenerator = generators[length - 1];\n for (let i = length; i <= degree; i++) {\n const coefficients = new Int32Array([1, field.exp(i - 1 + generator)]);\n const nextGenerator = lastGenerator.multiply(new Polynomial(field, coefficients));\n generators.push(nextGenerator);\n lastGenerator = nextGenerator;\n }\n }\n return generators[degree];\n}\nclass Encoder {\n #field;\n #generators;\n constructor(field = QR_CODE_FIELD_256) {\n this.#field = field;\n this.#generators = [new Polynomial(field, new Int32Array([1]))];\n }\n encode(received, ecLength) {\n const dataBytes = received.length - ecLength;\n const infoCoefficients = new Int32Array(dataBytes);\n const generator = buildGenerator(this.#field, this.#generators, ecLength);\n infoCoefficients.set(received.subarray(0, dataBytes));\n const base = new Polynomial(this.#field, infoCoefficients);\n const info = base.multiplyByMonomial(ecLength, 1);\n const [, remainder] = info.divide(generator);\n const { coefficients } = remainder;\n const numZeroCoefficients = ecLength - coefficients.length;\n const zeroCoefficientsOffset = dataBytes + numZeroCoefficients;\n received.fill(0, dataBytes, zeroCoefficientsOffset);\n received.set(coefficients, zeroCoefficientsOffset);\n }\n}\n\nexport { Encoder };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Mode } from '../../common/Mode.js';\nimport { buildMatrix } from './matrix.js';\nimport { BitArray } from '../../common/BitArray.js';\nimport { BlockPair } from '../BlockPair.js';\nimport { VERSIONS } from '../../common/Version.js';\nimport { calculateMaskPenalty } from '../../common/mask.js';\nimport { Encoder } from '../../common/reedsolomon/Encoder.js';\n\n/**\n * @module encoder\n */\nfunction generateECCodewords(codewords, numECCodewords) {\n const numDataCodewords = codewords.length;\n const buffer = new Int32Array(numDataCodewords + numECCodewords);\n // Copy data codewords.\n buffer.set(codewords);\n // Reed solomon encode.\n new Encoder().encode(buffer, numECCodewords);\n // Get ec codewords.\n return new Uint8Array(buffer.subarray(numDataCodewords));\n}\nfunction injectECCodewords(bits, { ecBlocks, numECCodewordsPerBlock }) {\n // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll\n // store the divided data bytes blocks and error correction bytes blocks into \"blocks\".\n let maxNumECCodewords = 0;\n let maxNumDataCodewords = 0;\n let dataCodewordsOffset = 0;\n // Block pair.\n const blocks = [];\n for (const { count, numDataCodewords } of ecBlocks) {\n for (let i = 0; i < count; i++) {\n const dataCodewords = new Uint8Array(numDataCodewords);\n bits.writeToUint8Array(dataCodewordsOffset * 8, dataCodewords, 0, numDataCodewords);\n const ecCodewords = generateECCodewords(dataCodewords, numECCodewordsPerBlock);\n blocks.push(new BlockPair(dataCodewords, ecCodewords));\n dataCodewordsOffset += numDataCodewords;\n maxNumECCodewords = Math.max(maxNumECCodewords, ecCodewords.length);\n maxNumDataCodewords = Math.max(maxNumDataCodewords, numDataCodewords);\n }\n }\n const codewords = new BitArray();\n // First, place data blocks.\n for (let i = 0; i < maxNumDataCodewords; i++) {\n for (const { dataCodewords } of blocks) {\n if (i < dataCodewords.length) {\n codewords.append(dataCodewords[i], 8);\n }\n }\n }\n // Then, place error correction blocks.\n for (let i = 0; i < maxNumECCodewords; i++) {\n for (const { ecCodewords } of blocks) {\n if (i < ecCodewords.length) {\n codewords.append(ecCodewords[i], 8);\n }\n }\n }\n return codewords;\n}\nfunction appendTerminator(bits, numDataCodewords) {\n const capacity = numDataCodewords * 8;\n // Append terminator if there is enough space (value is 0000).\n for (let i = 0; i < 4 && bits.length < capacity; i++) {\n bits.append(0);\n }\n // Append terminator. See 7.4.9 of ISO/IEC 18004:2015(E)(p.32) for details.\n // If the last byte isn't 8-bit aligned, we'll add padding bits.\n const numBitsInLastByte = bits.length & 0x07;\n if (numBitsInLastByte > 0) {\n for (let i = numBitsInLastByte; i < 8; i++) {\n bits.append(0);\n }\n }\n // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).\n const numPaddingCodewords = numDataCodewords - bits.byteLength;\n for (let i = 0; i < numPaddingCodewords; i++) {\n bits.append(i & 0x01 ? 0x11 : 0xec, 8);\n }\n}\nfunction isByteMode(segment) {\n return segment.mode === Mode.BYTE;\n}\nfunction isHanziMode(segment) {\n return segment.mode === Mode.HANZI;\n}\nfunction appendModeInfo(bits, mode) {\n bits.append(mode.bits, 4);\n}\nfunction appendECI(bits, segment, currentECIValue) {\n if (isByteMode(segment)) {\n const [value] = segment.charset.values;\n if (value !== currentECIValue) {\n bits.append(Mode.ECI.bits, 4);\n // See 7.4.2.2 of ISO/IEC 18004:2015(E)(p.24) for details.\n if (value <= 127) {\n bits.append(value, 8);\n } else if (value <= 16383) {\n bits.append(0x8000 | value, 16);\n } else {\n bits.append(0xc00000 | value, 24);\n }\n return value;\n }\n }\n return currentECIValue;\n}\nfunction appendFNC1Info(bits, fnc1) {\n const [mode, indicator] = fnc1;\n // Append FNC1 if applicable.\n switch (mode) {\n case 'GS1':\n // GS1 formatted codes are prefixed with a FNC1 in first position mode header.\n appendModeInfo(bits, Mode.FNC1_FIRST_POSITION);\n break;\n case 'AIM':\n // AIM formatted codes are prefixed with a FNC1 in first position mode header.\n appendModeInfo(bits, Mode.FNC1_SECOND_POSITION);\n // Append AIM application indicator.\n bits.append(indicator, 8);\n break;\n }\n}\nfunction getSegmentLength(segment, bits) {\n // Byte segment use byte Length.\n if (isByteMode(segment)) {\n return bits.byteLength;\n }\n // Other segments use the real length of characters.\n // All rest segments content codePointAt at 0x0000 to 0xffff, so use length directly.\n return segment.content.length;\n}\nfunction appendLengthInfo(bits, mode, version, numLetters) {\n bits.append(numLetters, mode.getCharacterCountBits(version));\n}\nfunction willFit(numInputBits, version, ecLevel) {\n // In the following comments, we use numbers of Version 7-H.\n const ecBlocks = version.getECBlocks(ecLevel);\n const numInputCodewords = Math.ceil(numInputBits / 8);\n return ecBlocks.numTotalDataCodewords >= numInputCodewords;\n}\nfunction chooseVersion(numInputBits, ecLevel) {\n for (const version of VERSIONS) {\n if (willFit(numInputBits, version, ecLevel)) {\n return version;\n }\n }\n throw new Error('data too big for all versions');\n}\nfunction calculateBitsNeeded(segmentBlocks, version) {\n let bitsNeeded = 0;\n for (const { mode, head, body } of segmentBlocks) {\n bitsNeeded += head.length + mode.getCharacterCountBits(version) + body.length;\n }\n return bitsNeeded;\n}\nfunction chooseRecommendVersion(segmentBlocks, ecLevel) {\n // Hard part: need to know version to know how many bits length takes. But need to know how many\n // bits it takes to know version. First we take a guess at version by assuming version will be\n // the minimum, 1:\n const provisionalBitsNeeded = calculateBitsNeeded(segmentBlocks, VERSIONS[0]);\n const provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel);\n // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.\n const bitsNeeded = calculateBitsNeeded(segmentBlocks, provisionalVersion);\n return chooseVersion(bitsNeeded, ecLevel);\n}\nfunction chooseBestMaskAndMatrix(codewords, version, ecLevel) {\n let bestMask = 0;\n let bestMatrix = buildMatrix(codewords, version, ecLevel, bestMask);\n let minPenalty = calculateMaskPenalty(bestMatrix);\n // We try all rest mask patterns to choose the best one.\n for (let mask = 1; mask < 8; mask++) {\n const matrix = buildMatrix(codewords, version, ecLevel, mask);\n const penalty = calculateMaskPenalty(matrix);\n // Lower penalty is better.\n if (penalty < minPenalty) {\n bestMask = mask;\n bestMatrix = matrix;\n minPenalty = penalty;\n }\n }\n return [bestMask, bestMatrix];\n}\n\nexport {\n appendECI,\n appendFNC1Info,\n appendLengthInfo,\n appendModeInfo,\n appendTerminator,\n calculateBitsNeeded,\n chooseBestMaskAndMatrix,\n chooseRecommendVersion,\n getSegmentLength,\n injectECCodewords,\n isByteMode,\n isHanziMode,\n willFit\n};\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module Dict\n * @see https://github.com/google/dart-gif-encoder\n */\n// The highest code that can be defined in the CodeBook.\nconst MAX_CODE = (1 << 12) - 1;\n/**\n * A dict contains codes defined during LZW compression. It's a mapping from a string\n * of pixels to the code that represents it. The codes are stored in a trie which is\n * represented as a map. Codes may be up to 12 bits. The size of the codebook is always\n * the minimum power of 2 needed to represent all the codes and automatically increases\n * as new codes are defined.\n */\nclass Dict {\n #bof;\n #eof;\n #bits;\n #depth;\n #size;\n #unused;\n #codes;\n constructor(depth) {\n const bof = 1 << depth;\n const eof = bof + 1;\n this.#bof = bof;\n this.#eof = eof;\n this.#depth = depth;\n this.reset();\n }\n get bof() {\n return this.#bof;\n }\n get eof() {\n return this.#eof;\n }\n get bits() {\n return this.#bits;\n }\n get depth() {\n return this.#depth;\n }\n reset() {\n const bits = this.#depth + 1;\n this.#bits = bits;\n this.#size = 1 << bits;\n this.#codes = new Map();\n this.#unused = this.#eof + 1;\n }\n add(code, index) {\n let unused = this.#unused;\n if (unused > MAX_CODE) {\n return false;\n }\n this.#codes.set((code << 8) | index, unused++);\n let bits = this.#bits;\n let size = this.#size;\n if (unused > size) {\n size = 1 << ++bits;\n }\n this.#bits = bits;\n this.#size = size;\n this.#unused = unused;\n return true;\n }\n get(code, index) {\n return this.#codes.get((code << 8) | index);\n }\n}\n\nexport { Dict };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module DictStream\n * @see https://github.com/google/dart-gif-encoder\n */\nclass DictStream {\n #bits = 0;\n #dict;\n #buffer = 0;\n #bytes = [];\n constructor(dict) {\n this.#dict = dict;\n }\n write(code) {\n let bits = this.#bits;\n let buffer = this.#buffer | (code << bits);\n bits += this.#dict.bits;\n const bytes = this.#bytes;\n while (bits >= 8) {\n bytes.push(buffer & 0xff);\n buffer >>= 8;\n bits -= 8;\n }\n this.#bits = bits;\n this.#buffer = buffer;\n }\n pipe(stream) {\n const bytes = this.#bytes;\n // Add the remaining bits. (Unused bits are set to zero.)\n if (this.#bits > 0) {\n bytes.push(this.#buffer);\n }\n stream.writeByte(this.#dict.depth);\n // Divide it up into blocks with a size in front of each block.\n const { length } = bytes;\n for (let i = 0; i < length; ) {\n const remain = length - i;\n if (remain >= 255) {\n stream.writeByte(0xff);\n stream.writeBytes(bytes, i, 255);\n i += 255;\n } else {\n stream.writeByte(remain);\n stream.writeBytes(bytes, i, remain);\n i = length;\n }\n }\n stream.writeByte(0);\n }\n}\n\nexport { DictStream };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Dict } from './Dict.js';\nimport { DictStream } from './DictStream.js';\n\n/**\n * @module index\n * @see https://github.com/google/dart-gif-encoder\n */\nfunction compress(pixels, depth, stream) {\n const dict = new Dict(depth);\n const buffer = new DictStream(dict);\n buffer.write(dict.bof);\n if (pixels.length > 0) {\n let code = pixels[0];\n const { length } = pixels;\n for (let i = 1; i < length; i++) {\n const pixelIndex = pixels[i];\n const nextCode = dict.get(code, pixelIndex);\n if (nextCode != null) {\n code = nextCode;\n } else {\n buffer.write(code);\n // Reset dict when full.\n if (!dict.add(code, pixelIndex)) {\n buffer.write(dict.bof);\n dict.reset();\n }\n code = pixelIndex;\n }\n }\n buffer.write(code);\n }\n buffer.write(dict.eof);\n buffer.pipe(stream);\n}\n\nexport { compress };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\n/**\n * @module ByteStream\n */\nclass ByteStream {\n #bytes = [];\n get bytes() {\n return this.#bytes;\n }\n writeByte(value) {\n this.#bytes.push(value & 0xff);\n }\n writeInt16(value) {\n this.#bytes.push(value & 0xff, (value >> 8) & 0xff);\n }\n writeBytes(bytes, offset = 0, length = bytes.length) {\n const buffer = this.#bytes;\n for (let i = 0; i < length; i++) {\n buffer.push(bytes[offset + i] & 0xff);\n }\n }\n}\n\nexport { ByteStream };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { ByteStream } from './ByteStream.js';\n\n/**\n * @module Base64Stream\n */\nconst { fromCharCode } = String;\nfunction encode(byte) {\n byte &= 0x3f;\n if (byte >= 0) {\n if (byte < 26) {\n // A.\n return 0x41 + byte;\n } else if (byte < 52) {\n // a.\n return 0x61 + (byte - 26);\n } else if (byte < 62) {\n // 0.\n return 0x30 + (byte - 52);\n } else if (byte === 62) {\n // +.\n return 0x2b;\n } else if (byte === 63) {\n // /.\n return 0x2f;\n }\n }\n throw new Error(`illegal char: ${fromCharCode(byte)}`);\n}\nclass Base64Stream {\n #bits = 0;\n #buffer = 0;\n #length = 0;\n #stream = new ByteStream();\n get bytes() {\n return this.#stream.bytes;\n }\n write(byte) {\n let bits = this.#bits + 8;\n const stream = this.#stream;\n const buffer = (this.#buffer << 8) | (byte & 0xff);\n while (bits >= 6) {\n stream.writeByte(encode(buffer >>> (bits - 6)));\n bits -= 6;\n }\n this.#length++;\n this.#bits = bits;\n this.#buffer = buffer;\n }\n close() {\n const bits = this.#bits;\n const stream = this.#stream;\n if (bits > 0) {\n stream.writeByte(encode(this.#buffer << (6 - bits)));\n this.#bits = 0;\n this.#buffer = 0;\n }\n const length = this.#length;\n if (length % 3 != 0) {\n // Padding.\n const pad = 3 - (length % 3);\n for (let i = 0; i < pad; i++) {\n // =.\n stream.writeByte(0x3d);\n }\n }\n }\n}\n\nexport { Base64Stream, fromCharCode };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { compress } from './utils/lzw/index.js';\nimport { ByteStream } from './utils/ByteStream.js';\nimport { Base64Stream, fromCharCode } from './utils/Base64Stream.js';\n\n/**\n * @module GIFImage\n */\nclass GIFImage {\n #width;\n #height;\n #foreground;\n #background;\n #pixels = [];\n constructor(width, height, { foreground = [0x00, 0x00, 0x00], background = [0xff, 0xff, 0xff] } = {}) {\n this.#width = width;\n this.#height = height;\n this.#foreground = foreground;\n this.#background = background;\n }\n #encode() {\n const width = this.#width;\n const height = this.#height;\n const stream = new ByteStream();\n const background = this.#background;\n const foreground = this.#foreground;\n // GIF signature: GIF89a.\n stream.writeBytes([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]);\n // Logical screen descriptor.\n stream.writeInt16(width);\n stream.writeInt16(height);\n stream.writeBytes([0x80, 0, 0]);\n // Global background color palette.\n stream.writeBytes([background[0], background[1], background[2]]);\n // Global foreground color palette.\n stream.writeBytes([foreground[0], foreground[1], foreground[2]]);\n // Image descriptor.\n stream.writeByte(0x2c);\n stream.writeInt16(0);\n stream.writeInt16(0);\n stream.writeInt16(width);\n stream.writeInt16(height);\n stream.writeByte(0);\n // Compress pixels to stream.\n compress(this.#pixels, 2, stream);\n // GIF terminator.\n stream.writeByte(0x3b);\n return stream.bytes;\n }\n set(x, y, color) {\n this.#pixels[y * this.#width + x] = color;\n }\n toDataURL() {\n const bytes = this.#encode();\n const stream = new Base64Stream();\n for (const byte of bytes) {\n stream.write(byte);\n }\n stream.close();\n const base64 = stream.bytes;\n let url = 'data:image/gif;base64,';\n for (const byte of base64) {\n url += fromCharCode(byte);\n }\n return url;\n }\n}\n\nexport { GIFImage };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { toInt32 } from '../common/utils.js';\nimport { GIFImage } from '../common/image/GIFImage.js';\n\n/**\n * @module Encoded\n */\nclass Encoded {\n #mask;\n #level;\n #version;\n #matrix;\n constructor(matrix, version, level, mask) {\n this.#mask = mask;\n this.#level = level;\n this.#matrix = matrix;\n this.#version = version;\n }\n /**\n * @property matrix\n * @description Get the size of qrcode.\n */\n get size() {\n return this.#matrix.size;\n }\n /**\n * @property mask\n * @description Get the mask of qrcode.\n */\n get mask() {\n return this.#mask;\n }\n /**\n * @property level\n * @description Get the error correction level of qrcode.\n */\n get level() {\n return this.#level.name;\n }\n /**\n * @property version\n * @description Get the version of qrcode.\n */\n get version() {\n return this.#version.version;\n }\n /**\n * @method get\n * @description Get the bit value of the specified coordinate of qrcode.\n */\n get(x, y) {\n const { size } = this.#matrix;\n if (x < 0 || y < 0 || x >= size || y >= size) {\n throw new Error(`illegal coordinate: [${x}, ${y}]`);\n }\n return this.#matrix.get(x, y);\n }\n /**\n * @method toDataURL\n * @param moduleSize The size of one qrcode module\n * @param options Set rest options of gif, like margin, foreground and background.\n */\n toDataURL(moduleSize = 2, { margin = moduleSize * 4, ...colors } = {}) {\n moduleSize = Math.max(1, moduleSize >> 0);\n margin = Math.max(0, margin >> 0);\n const matrix = this.#matrix;\n const matrixSize = matrix.size;\n const size = moduleSize * matrixSize + margin * 2;\n const gif = new GIFImage(size, size, colors);\n const max = size - margin;\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n if (x >= margin && x < max && y >= margin && y < max) {\n const offsetX = toInt32((x - margin) / moduleSize);\n const offsetY = toInt32((y - margin) / moduleSize);\n gif.set(x, y, matrix.get(offsetX, offsetY));\n } else {\n // Margin pixels.\n gif.set(x, y, 0);\n }\n }\n }\n return gif.toDataURL();\n }\n}\n\nexport { Encoded };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Charset } from '../../common/Charset.js';\n\n/**\n * @module asserts\n */\nfunction assertContent(content) {\n if (content === '') {\n throw new Error('segment content should be at least 1 character');\n }\n}\nfunction assertCharset(charset) {\n if (!(charset instanceof Charset)) {\n throw new Error('illegal charset');\n }\n}\nfunction assertHints(hints) {\n const { fnc1 } = hints;\n // FNC1.\n if (fnc1 != null) {\n const [mode] = fnc1;\n if (mode !== 'GS1' && mode !== 'AIM') {\n throw new Error('illegal fn1 hint');\n }\n if (mode === 'AIM') {\n const [, indicator] = fnc1;\n if (indicator < 0 || indicator > 0xff || !Number.isInteger(indicator)) {\n throw new Error('illegal fn1 application indicator');\n }\n }\n }\n}\nfunction assertLevel(level) {\n if (['L', 'M', 'Q', 'H'].indexOf(level) < 0) {\n throw new Error('illegal error correction level');\n }\n}\nfunction assertVersion(version) {\n if (version !== 'Auto') {\n if (version < 1 || version > 40 || !Number.isInteger(version)) {\n throw new Error('illegal version');\n }\n }\n}\n\nexport { assertCharset, assertContent, assertHints, assertLevel, assertVersion };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport {\n getSegmentLength,\n appendECI,\n appendFNC1Info,\n appendModeInfo,\n isHanziMode,\n chooseRecommendVersion,\n calculateBitsNeeded,\n willFit,\n appendLengthInfo,\n appendTerminator,\n injectECCodewords,\n chooseBestMaskAndMatrix\n} from './utils/encoder.js';\nimport { Encoded } from './Encoded.js';\nimport { Charset } from '../common/Charset.js';\nimport { ECLevel } from '../common/ECLevel.js';\nimport { BitArray } from '../common/BitArray.js';\nimport { VERSIONS } from '../common/Version.js';\nimport { encode } from '../common/encoding/index.js';\nimport { assertHints, assertLevel, assertVersion } from './utils/asserts.js';\n\n/**\n * @module Encoder\n */\nclass Encoder {\n #hints;\n #level;\n #encode;\n #version;\n /**\n * @constructor\n * @param options The options of encoder.\n */\n constructor({ hints = {}, level = 'L', version = 'Auto', encode: encode$1 = encode } = {}) {\n assertHints(hints);\n assertLevel(level);\n assertVersion(version);\n this.#hints = hints;\n this.#encode = encode$1;\n this.#version = version;\n this.#level = ECLevel[level];\n }\n /**\n * @method encode\n * @description Encode the segments.\n * @param segments The segments.\n */\n encode(...segments) {\n const ecLevel = this.#level;\n const encode = this.#encode;\n const { fnc1 } = this.#hints;\n const versionNumber = this.#version;\n const segmentBlocks = [];\n // Only append FNC1 once.\n let isFNC1Appended = false;\n // Current ECI value.\n let [currentECIValue] = Charset.ISO_8859_1.values;\n // Init segments.\n for (const segment of segments) {\n const { mode } = segment;\n const head = new BitArray();\n const body = segment.encode(encode);\n const length = getSegmentLength(segment, body);\n // Append ECI segment if applicable.\n currentECIValue = appendECI(head, segment, currentECIValue);\n // Append FNC1 if applicable.\n if (fnc1 != null && !isFNC1Appended) {\n isFNC1Appended = true;\n appendFNC1Info(head, fnc1);\n }\n // With ECI in place, Write the mode marker.\n appendModeInfo(head, mode);\n // If is Hanzi mode append GB2312 subset.\n if (isHanziMode(segment)) {\n head.append(1, 4);\n }\n // Push segment block.\n segmentBlocks.push({ mode, head, body, length });\n }\n let version;\n if (versionNumber === 'Auto') {\n version = chooseRecommendVersion(segmentBlocks, ecLevel);\n } else {\n version = VERSIONS[versionNumber - 1];\n const bitsNeeded = calculateBitsNeeded(segmentBlocks, version);\n if (!willFit(bitsNeeded, version, ecLevel)) {\n throw new Error('data too big for requested version');\n }\n }\n const buffer = new BitArray();\n for (const { mode, head, body, length } of segmentBlocks) {\n buffer.append(head);\n appendLengthInfo(buffer, mode, version, length);\n buffer.append(body);\n }\n const ecBlocks = version.getECBlocks(ecLevel);\n appendTerminator(buffer, ecBlocks.numTotalDataCodewords);\n const codewords = injectECCodewords(buffer, ecBlocks);\n const [mask, matrix] = chooseBestMaskAndMatrix(codewords, version, ecLevel);\n return new Encoded(matrix, version, ecLevel, mask);\n }\n}\n\nexport { Encoder };\n","/**\n * @module QRCode\n * @package @nuintun/qrcode\n * @license MIT\n * @version 5.0.2\n * @author nuintun <nuintun@qq.com>\n * @description A pure JavaScript QRCode encode and decode library.\n * @see https://github.com/nuintun/qrcode#readme\n */\n\nimport { Mode } from '../../common/Mode.js';\nimport { Charset } from '../../common/Charset.js';\nimport { BitArray } from '../../common/BitArray.js';\nimport { assertContent, assertCharset } from '../utils/asserts.js';\n\n/**\n * @module Byte\n */\nclass Byte {\n #content;\n #charset;\n /**\n * @constructor\n * @param content The content to encode.\n * @param charset The charset of the content.\n */\n constructor(content, charset = Charset.ISO_8859_1) {\n assertContent(content);\n assertCharset(charset);\n this.#content = content;\n this.#charset = charset;\n }\n /**\n * @property mode\n * @description The mode of the segment.\n */\n get mode() {\n return Mode.BYTE;\n }\n /**\n * @property content\n * @description The content of the segment.\n */\n get content() {\n return this.#content;\n }\n /**\n * @property charset\n * @description The charset of the content.\n */\n get charset() {\n return this.#charset;\n }\n /**\n * @method encode\n * @description Encode the segment.\n * @param encode The text encode function.\n */\n encode(encode) {\n const bits = new BitArray();\n const bytes = encode(this.#content, this.#charset);\n for (const byte of bytes) {\n bits.append(byte, 8);\n }\n return bits;\n }\n}\n\nexport { Byte };\n","import { sendHttpRequest } from \"../../utils/utils\";\r\n\r\n// 文件上传流水号SDK\r\nconst uploadNumberSDK = {\r\n number: '',\r\n isWorking: false,\r\n close: async function (params?: {\r\n onOk?: () => void;\r\n onError?: () => void;\r\n }) {\r\n const { onOk, onError } = params ?? {};\r\n const { number } = this;\r\n if (number) {\r\n const result = await sendHttpRequest({\r\n url: `/resource/update_id/${number}`,\r\n method: 'delete',\r\n });\r\n if (result.success) {\r\n this.number = '';\r\n onOk?.();\r\n } else {\r\n onError?.();\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport default uploadNumberSDK;",".mobile-upload {\r\n display: flex;\r\n justify-content: flex-end;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.btn {\r\n position: relative;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n overflow: hidden;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n white-space: nowrap;\r\n}\r\n\r\n.btn::after {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.btn:hover::after {\r\n background-color: rgba(0,0,0,0.04);\r\n}\r\n\r\n.btn-link {\r\n color: #0D75FB;\r\n}\r\n\r\n.btn-default {\r\n background-color: #ffffff;\r\n color: #0D75FB;\r\n border: 1px solid #0D75FB;\r\n}\r\n\r\n.btn-primary {\r\n background-color: #0D75FB;\r\n color: #ffffff;\r\n}\r\n\r\n\r\n.loading {\r\n font-size: 12px;\r\n color: #999999;\r\n}\r\n\r\n.mask {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: rgba(0,0,0,0.5);\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n z-index: 10000;\r\n}\r\n\r\n.mask .upload-wrapper {\r\n width: 540px;\r\n max-width: 80%;\r\n max-height: 80%;\r\n background-color: #ffffff;\r\n padding: 32px 24px;\r\n border-radius: 16px;\r\n overflow-y: auto;\r\n}\r\n\r\n.mask .upload-wrapper .upload-box {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n.time-expire {\r\n margin: 8px 0;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #555555;\r\n}\r\n\r\n.time-count-down {\r\n margin-left: 8px;\r\n color: #0D75FB;\r\n}\r\n\r\n.alert-tip {\r\n margin-top: 8px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999999;\r\n}\r\n\r\n.qrcode-wrapper {\r\n width: 160px;\r\n height: 160px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n border: 1px solid #e5e5e5;\r\n border-radius: 4px;\r\n padding: 1px;\r\n}\r\n\r\n.qrcode-wrapper .qrcode {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.modal-footer {\r\n margin-top: 32px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.modal-footer .btn {\r\n min-width: 100px;\r\n}\r\n\r\n.qrcode-textarea {\r\n width: calc(100% - 16px);\r\n min-height: 120px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, State, Event, h, EventEmitter } from \"@stencil/core\";\r\nimport { Byte, Encoder } from '@nuintun/qrcode'\r\nimport { isMobile, sendHttpRequest, PCM_DOMAIN } from \"../../utils/utils\";\r\nimport { Message } from \"../../services/message.service\";\r\nimport uploadNumberSDK from \"./uploadNumberSDK\";\r\n\r\n@Component({\r\n tag: 'pcm-mobile-input-btn',\r\n styleUrls: ['pcm-mobile-input-btn.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MobileUploadBtn {\r\n // 标题\r\n @Prop() name: string = '';\r\n /**\r\n * 最大文件数\r\n */\r\n @Prop() rows: number = 8;\r\n /**\r\n * 最大文件大小\r\n */\r\n @Prop() maxLength: number = undefined;\r\n /**\r\n * 填写请求头\r\n */\r\n @Prop() uploadHeaders?: Record<string, any>;\r\n /**\r\n * 填写请求参数\r\n */\r\n @Prop() uploadParams?: Record<string, any>;\r\n\r\n @State() QR_CODE_VALID_TIME: number = 0;\r\n @State() open: boolean = false;\r\n @State() mobileUrl: string = '';\r\n @State() setStartMobileUpload: boolean = false;\r\n @State() startMobileUploadLoading: boolean = false;\r\n @State() qrcodeStatus: 'active' | 'expired' | 'loading' | undefined = 'loading';\r\n @State() value: string = '';\r\n @State() expireTime: string = ''; // 过期时间\r\n\r\n @Event() ok: EventEmitter<string>;\r\n\r\n private setStartMobileUploadWrapper = (e: boolean) => {\r\n uploadNumberSDK.isWorking = e;\r\n this.setStartMobileUpload = e;\r\n }\r\n\r\n @State() qrcodeUrl: string = '';\r\n private setMobileUrlWrapper = (e: string) => {\r\n this.mobileUrl = e;\r\n if (e) {\r\n const encoder = new Encoder();\r\n const qrcode = encoder.encode(new Byte(e));\r\n this.qrcodeUrl = qrcode.toDataURL();\r\n } else {\r\n this.qrcodeUrl = '';\r\n }\r\n }\r\n\r\n // 轮询流水号数据\r\n private pollingQueryNumberInfo = async (num: any) => {\r\n const res = await sendHttpRequest({\r\n url: `/sdk/v1/update_id/${num}/status`,\r\n method: 'get',\r\n });\r\n if (res?.success) {\r\n const resData: {\r\n update_id?: any;\r\n tags?: any;\r\n status?: any;\r\n file_list?: any;\r\n user_id?: any;\r\n cfg?: any;\r\n iat?: any;\r\n exp?: any;\r\n custom_data?: any;\r\n } = res.data ?? {};\r\n const { custom_data } = resData;\r\n this.value = custom_data ?? '';\r\n }\r\n if (uploadNumberSDK.isWorking) {\r\n setTimeout(() => {\r\n this.pollingQueryNumberInfo(num);\r\n }, 3000);\r\n }\r\n }\r\n\r\n private handleStartMobileUpload = async () => {\r\n const that = this;\r\n this.qrcodeStatus = 'loading';\r\n this.startMobileUploadLoading = true;\r\n const params = this.uploadParams ?? {};\r\n const reqData: {\r\n cfg?: Record<string, any>;\r\n } = {\r\n cfg: {\r\n fromUserName: '',\r\n fromUserId: '',\r\n upload: that.uploadParams,\r\n name: that.name,\r\n rows: that.rows,\r\n maxLength: that.maxLength,\r\n params,\r\n },\r\n }\r\n const res = await sendHttpRequest({\r\n url: `/sdk/v1/update_id`,\r\n method: 'post',\r\n data: reqData,\r\n });\r\n if (res?.success) {\r\n const resData: {\r\n update_id?: any;\r\n tags?: any;\r\n status?: any;\r\n file_list?: any;\r\n user_id?: any;\r\n cfg?: any;\r\n iat?: any;\r\n exp?: any;\r\n now?: any;\r\n } = res.data ?? {};\r\n uploadNumberSDK.number = resData.update_id;\r\n // 计算过期时间:创建后+1小时\r\n const expireDate = new Date(Date.now() + 3600 * 1000);\r\n this.expireTime = `${expireDate.getHours().toString().padStart(2, '0')}:${expireDate.getMinutes().toString().padStart(2, '0')}`;\r\n const theMobileUrl = `${PCM_DOMAIN}/agents/inputByCode?num=${uploadNumberSDK.number}`;\r\n this.setMobileUrlWrapper(theMobileUrl)\r\n this.setStartMobileUploadWrapper(true);\r\n this.qrcodeStatus = 'active';\r\n // 开启轮询\r\n this.pollingQueryNumberInfo(uploadNumberSDK.number);\r\n }\r\n this.startMobileUploadLoading = false;\r\n }\r\n\r\n // 取消手机填写\r\n @State() cancelLoading = false;\r\n private cancelMobileUpload = async () => {\r\n this.cancelLoading = true;\r\n await uploadNumberSDK.close({\r\n onError() {\r\n Message.info('取消失败');\r\n }\r\n })\r\n this.cancelLoading = false;\r\n this.QR_CODE_VALID_TIME = 0;\r\n this.expireTime = '';\r\n this.setStartMobileUploadWrapper(false);\r\n this.setMobileUrlWrapper('');\r\n this.qrcodeStatus = 'expired';\r\n this.value = '';\r\n this.open = false;\r\n }\r\n\r\n\r\n render() {\r\n const mobile = isMobile();\r\n if (mobile) {\r\n return null\r\n } else {\r\n return (\r\n <div>\r\n <div class=\"mobile-upload\">\r\n <div\r\n class=\"btn btn-link\"\r\n onClick={() => {\r\n this.open = true;\r\n this.handleStartMobileUpload();\r\n }}\r\n >扫码填写</div>\r\n </div>\r\n {\r\n this.open && <div class=\"mask\">\r\n <div class=\"upload-wrapper\">\r\n {\r\n this.setStartMobileUpload ? <div class=\"upload-box\">\r\n <div class=\"qrcode-wrapper\">\r\n {\r\n this.qrcodeStatus === 'active' && <img class=\"qrcode\" src={this.qrcodeUrl} />\r\n }\r\n {\r\n this.qrcodeStatus === 'loading' && <span class=\"loading\">加载中...</span>\r\n }\r\n {\r\n this.qrcodeStatus === 'expired' && <div\r\n class=\"btn btn-link\"\r\n onClick={this.handleStartMobileUpload}\r\n >重新获取</div>\r\n }\r\n </div>\r\n <div class=\"time-expire\">\r\n 二维码有效期至 {this.expireTime}\r\n </div>\r\n <div class=\"alert-tip\">\r\n 填写过程中请不要关闭此弹窗\r\n </div>\r\n {\r\n this.qrcodeStatus === 'active' && <div\r\n style={{ marginTop: '12px', fontSize: '12px' }}\r\n class=\"btn btn-link\"\r\n onClick={() => {\r\n navigator.clipboard\r\n .writeText(this.mobileUrl)\r\n .then(() => {\r\n Message.success(\"已复制到剪贴板\");\r\n })\r\n .catch(() => {\r\n Message.error(\"复制失败\");\r\n });\r\n }}\r\n >复制二维码地址</div>\r\n }\r\n </div> : (this.startMobileUploadLoading && <span class=\"loading\">加载中...</span>)\r\n }\r\n {/* 填写文件列表 */}\r\n <div style={{ marginTop: '12px' }}>\r\n {\r\n !!this.value?.length && <textarea\r\n readOnly\r\n class=\"qrcode-textarea\"\r\n value={this.value}\r\n onChange={(e: any) => {\r\n this.value = e.target.value;\r\n }}\r\n />\r\n }\r\n </div>\r\n <div class=\"modal-footer\">\r\n <div class=\"btn btn-default\" onClick={this.cancelMobileUpload}>取消</div>\r\n <div class=\"btn btn-primary\" onClick={() => {\r\n if (!this.value) {\r\n Message.info(`请输入内容`);\r\n return;\r\n }\r\n if (this.value.length > this.maxLength) {\r\n Message.info(`输入内容不能超过${this.maxLength}个字符`);\r\n return;\r\n }\r\n this.ok.emit(this.value);\r\n this.cancelMobileUpload();\r\n }}>完成</div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n )\r\n }\r\n }\r\n}","import { sendHttpRequest } from \"../../utils/utils\";\r\n\r\n// 文件上传流水号SDK\r\nconst uploadNumberSDK = {\r\n number: '',\r\n isWorking: false,\r\n close: async function (params?: {\r\n onOk?: () => void;\r\n onError?: () => void;\r\n }) {\r\n const { onOk, onError } = params ?? {};\r\n const { number } = this;\r\n if (number) {\r\n const result = await sendHttpRequest({\r\n url: `/resource/update_id/${number}`,\r\n method: 'delete',\r\n });\r\n if (result.success) {\r\n this.number = '';\r\n onOk?.();\r\n } else {\r\n onError?.();\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport default uploadNumberSDK;",".mobile-upload {\r\n display: flex;\r\n justify-content: flex-end;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.btn {\r\n position: relative;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n overflow: hidden;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n white-space: nowrap;\r\n}\r\n\r\n.btn::after {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.btn:hover::after {\r\n background-color: rgba(0,0,0,0.04);\r\n}\r\n\r\n.btn-link {\r\n color: #0D75FB;\r\n}\r\n\r\n.btn-default {\r\n background-color: #ffffff;\r\n color: #0D75FB;\r\n border: 1px solid #0D75FB;\r\n}\r\n\r\n.btn-primary {\r\n background-color: #0D75FB;\r\n color: #ffffff;\r\n}\r\n\r\n\r\n.loading {\r\n font-size: 12px;\r\n color: #999999;\r\n}\r\n\r\n.mask {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background-color: rgba(0,0,0,0.5);\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n z-index: 10000;\r\n}\r\n\r\n.mask .upload-wrapper {\r\n width: 540px;\r\n max-width: 80%;\r\n max-height: 80%;\r\n background-color: #ffffff;\r\n padding: 32px 24px;\r\n border-radius: 16px;\r\n overflow-y: auto;\r\n}\r\n\r\n.mask .upload-wrapper .upload-box {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n.time-expire {\r\n margin: 8px 0;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #555555;\r\n}\r\n\r\n.time-count-down {\r\n margin-left: 8px;\r\n color: #0D75FB;\r\n}\r\n\r\n.alert-tip {\r\n margin-top: 8px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999999;\r\n}\r\n\r\n.qrcode-wrapper {\r\n width: 160px;\r\n height: 160px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n border: 1px solid #e5e5e5;\r\n border-radius: 4px;\r\n padding: 1px;\r\n}\r\n\r\n.qrcode-wrapper .qrcode {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.modal-footer {\r\n margin-top: 32px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.modal-footer .btn {\r\n min-width: 100px;\r\n}","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, State, Event, h, EventEmitter } from \"@stencil/core\";\r\nimport { isMobile, sendHttpRequest, PCM_DOMAIN } from \"../../utils/utils\";\r\nimport uploadNumberSDK from \"./uploadNumberSDK\";\r\nimport { Message } from \"../../services/message.service\";\r\nimport { Byte, Encoder } from '@nuintun/qrcode'\r\n\r\n@Component({\r\n tag: 'pcm-mobile-upload-btn',\r\n styleUrls: ['pcm-mobile-upload-btn.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MobileUploadBtn {\r\n /**\r\n * 是否支持多文件上传\r\n */\r\n @Prop() multiple: boolean = false;\r\n /**\r\n * 支持的文件后缀列表(需要带上小数点.)\r\n */\r\n @Prop() acceptFileSuffixList: string[] = [];\r\n /**\r\n * 最大文件数\r\n */\r\n @Prop() maxFileCount: number = Infinity;\r\n /**\r\n * 最大文件大小\r\n */\r\n @Prop() maxFileSize: number = Infinity;\r\n /**\r\n * 上传请求头\r\n */\r\n @Prop() uploadHeaders?: Record<string, any>;\r\n /**\r\n * 上传请求参数\r\n */\r\n @Prop() uploadParams?: Record<string, any>;\r\n @State() QR_CODE_VALID_TIME: number = 0;\r\n @State() open: boolean = false;\r\n @State() mobileUrl: string = '';\r\n @State() setStartMobileUpload: boolean = false;\r\n @State() startMobileUploadLoading: boolean = false;\r\n @State() qrcodeStatus: 'active' | 'expired' | 'loading' | undefined = 'loading';\r\n @State() value: any[] = [];\r\n @State() expireTime: string = ''; // 过期时间\r\n\r\n @Event() ok: EventEmitter<any[]>;\r\n\r\n private setStartMobileUploadWrapper = (e: boolean) => {\r\n uploadNumberSDK.isWorking = e;\r\n this.setStartMobileUpload = e;\r\n }\r\n\r\n @State() qrcodeUrl: string = '';\r\n private setMobileUrlWrapper = (e: string) => {\r\n this.mobileUrl = e;\r\n if (e) {\r\n const encoder = new Encoder();\r\n const qrcode = encoder.encode(new Byte(e));\r\n this.qrcodeUrl = qrcode.toDataURL();\r\n } else {\r\n this.qrcodeUrl = '';\r\n }\r\n }\r\n\r\n // 轮询流水号数据\r\n private pollingQueryNumberInfo = async (num: any) => {\r\n const res = await sendHttpRequest({\r\n url: `/sdk/v1/update_id/${num}/status`,\r\n method: 'get',\r\n });\r\n if (res?.success) {\r\n const resData: {\r\n update_id?: any;\r\n tags?: any;\r\n status?: any;\r\n file_list?: any;\r\n user_id?: any;\r\n cfg?: any;\r\n iat?: any;\r\n exp?: any;\r\n } = res.data ?? {};\r\n const { file_list } = resData;\r\n this.value = file_list ?? [];\r\n }\r\n if (uploadNumberSDK.isWorking) {\r\n setTimeout(() => {\r\n this.pollingQueryNumberInfo(num);\r\n }, 3000);\r\n }\r\n }\r\n\r\n private handleStartMobileUpload = async () => {\r\n const that = this;\r\n this.qrcodeStatus = 'loading';\r\n this.startMobileUploadLoading = true;\r\n const params = this.uploadParams ?? {};\r\n const reqData: {\r\n tags?: string[];\r\n cfg?: Record<string, any>;\r\n is_knowledge_doc?: boolean,\r\n } = {\r\n is_knowledge_doc: false,\r\n tags: params.tags,\r\n cfg: {\r\n maxSize: that.maxFileSize,\r\n maxCount: that.multiple ? that.maxFileCount : 1,\r\n fromUserName: '',\r\n fromUserId: '',\r\n customAccept: that.acceptFileSuffixList.join(','),\r\n upload: that.uploadParams,\r\n },\r\n }\r\n const res = await sendHttpRequest({\r\n url: `/sdk/v1/update_id`,\r\n method: 'post',\r\n data: reqData,\r\n });\r\n if (res?.success) {\r\n const resData: {\r\n update_id?: any;\r\n tags?: any;\r\n status?: any;\r\n file_list?: any;\r\n user_id?: any;\r\n cfg?: any;\r\n iat?: any;\r\n exp?: any;\r\n now?: any;\r\n custom_data?: any;\r\n } = res.data ?? {};\r\n uploadNumberSDK.number = resData.update_id;\r\n // 计算过期时间:创建后+1小时\r\n const expireDate = new Date(Date.now() + 3600 * 1000);\r\n this.expireTime = `${expireDate.getHours().toString().padStart(2, '0')}:${expireDate.getMinutes().toString().padStart(2, '0')}`;\r\n const theMobileUrl = `${PCM_DOMAIN}/agents/uploadFileByCode?num=${uploadNumberSDK.number}`;\r\n this.setMobileUrlWrapper(theMobileUrl)\r\n this.setStartMobileUploadWrapper(true);\r\n this.qrcodeStatus = 'active';\r\n // 开启轮询\r\n this.pollingQueryNumberInfo(uploadNumberSDK.number);\r\n }\r\n this.startMobileUploadLoading = false;\r\n }\r\n\r\n // 取消手机上传\r\n @State() cancelLoading = false;\r\n private cancelMobileUpload = async () => {\r\n this.cancelLoading = true;\r\n await uploadNumberSDK.close({\r\n onError() {\r\n Message.info('取消失败');\r\n }\r\n })\r\n this.cancelLoading = false;\r\n this.QR_CODE_VALID_TIME = 0;\r\n this.expireTime = '';\r\n this.setStartMobileUploadWrapper(false);\r\n this.setMobileUrlWrapper('');\r\n this.qrcodeStatus = 'expired';\r\n this.value = [];\r\n this.open = false;\r\n }\r\n\r\n // 删除文件\r\n private handleDelete = async (cos_key: any) => {\r\n const res = await sendHttpRequest({\r\n url: `/sdk/v1/update_id/${uploadNumberSDK.number}/file`,\r\n method: 'delete',\r\n params: {\r\n update_id: uploadNumberSDK.number,\r\n cos_key,\r\n }\r\n });\r\n if (res?.success) {\r\n this.value = this.value.filter(it => it.cos_key !== cos_key);\r\n }\r\n }\r\n\r\n\r\n render() {\r\n const mobile = isMobile();\r\n if (mobile) {\r\n return null\r\n } else {\r\n return (\r\n <div>\r\n <div class=\"mobile-upload\">\r\n <div\r\n class=\"btn btn-link\"\r\n onClick={() => {\r\n if (this.maxFileCount < 1) {\r\n Message.info('文件数量已达到上限!');\r\n return;\r\n }\r\n this.open = true;\r\n this.handleStartMobileUpload();\r\n }}\r\n >扫码上传</div>\r\n </div>\r\n {\r\n this.open && <div class=\"mask\">\r\n <div class=\"upload-wrapper\">\r\n {\r\n this.setStartMobileUpload ? <div class=\"upload-box\">\r\n <div class=\"qrcode-wrapper\">\r\n {\r\n this.qrcodeStatus === 'active' && <img class=\"qrcode\" src={this.qrcodeUrl} />\r\n }\r\n {\r\n this.qrcodeStatus === 'loading' && <span class=\"loading\">加载中...</span>\r\n }\r\n {\r\n this.qrcodeStatus === 'expired' && <div\r\n class=\"btn btn-link\"\r\n onClick={this.handleStartMobileUpload}\r\n >重新获取</div>\r\n }\r\n </div>\r\n <div class=\"time-expire\">\r\n 二维码有效期至 {this.expireTime}\r\n </div>\r\n <div class=\"alert-tip\">\r\n 上传过程中请不要关闭此弹窗\r\n </div>\r\n {\r\n this.qrcodeStatus === 'active' && <div\r\n style={{ marginTop: '12px', fontSize: '12px' }}\r\n class=\"btn btn-link\"\r\n onClick={() => {\r\n navigator.clipboard\r\n .writeText(this.mobileUrl)\r\n .then(() => {\r\n Message.success(\"已复制到剪贴板\");\r\n })\r\n .catch(() => {\r\n Message.error(\"复制失败\");\r\n });\r\n }}\r\n >复制二维码地址</div>\r\n }\r\n </div> : (this.startMobileUploadLoading && <span class=\"loading\">加载中...</span>)\r\n }\r\n {/* 上传文件列表 */}\r\n <div style={{ marginTop: '12px' }}>\r\n {\r\n this.value?.map?.((item, index) => {\r\n return <div class=\"file-item\" key={index}>\r\n <div class=\"file-item-content\">\r\n <span class=\"file-icon\">📝</span>\r\n <span class=\"file-name\">{item?.file_name}</span>\r\n </div>\r\n <button class=\"remove-file\" onClick={(e) => {\r\n e.stopPropagation();\r\n this.handleDelete(item.cos_key)\r\n }}>×</button>\r\n </div>\r\n })\r\n }\r\n </div>\r\n <div class=\"modal-footer\">\r\n <div class=\"btn btn-default\" onClick={this.cancelMobileUpload}>取消</div>\r\n <div class=\"btn btn-primary\" onClick={() => {\r\n if (this.value.length > this.maxFileCount) {\r\n Message.info(`最多只能选择${this.maxFileCount}个文件,请删除多余文件!`);\r\n return;\r\n }\r\n this.ok.emit(this.value);\r\n this.cancelMobileUpload();\r\n }}>完成</div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n )\r\n }\r\n }\r\n}",null,"/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { uploadFileToBackend, FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, InterviewCompleteEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus,ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store';\r\nimport { configStore } from '../../../store/config.store';\r\nimport { SentryReporter } from '../../utils/sentry-reporter';\r\n\r\n/**\r\n * 面试报告\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-msbg-modal',\r\n styleUrls: ['pcm-msbg-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MsbgModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '面试报告';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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 /**\r\n * 自定义输入参数,传入customInputs.job_info时,会隐藏JD输入区域<br>\r\n * 传入customInputs.file_urls时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_urls和customInputs.job_info时,会直接开始聊天。<br>\r\n */\r\n @Prop() customInputs: Record<string, string>= {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() selectedFile: File | null = null;\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.clearSelectedFile();\r\n this.showChatModal = false;\r\n this.jobDescription = '';\r\n } else {\r\n if (this.customInputs && this.customInputs.job_info) {\r\n this.jobDescription = this.customInputs.job_info;\r\n }\r\n\r\n await verifyApiKey(this.token);\r\n\r\n // 如果有会话ID或者同时有file_urls和job_info,直接显示聊天模态框\r\n if (this.conversationId || (this.customInputs?.file_urls && this.customInputs?.job_info)) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n\r\n componentWillLoad() {\r\n \r\n \r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handleFileChange = (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\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 = null;\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 private async uploadFile() {\r\n if (!this.selectedFile) return;\r\n\r\n this.isUploading = true;\r\n\r\n try {\r\n // 使用 uploadFileToBackend 工具函数上传文件\r\n const result = await uploadFileToBackend(this.selectedFile, {\r\n }, {\r\n 'tags': ['other']\r\n });\r\n\r\n this.uploadedFileInfo = result;\r\n this.uploadSuccess.emit(result);\r\n } catch (error) {\r\n console.error('文件上传错误:', error);\r\n this.clearSelectedFile();\r\n SentryReporter.captureError(error, {\r\n action: 'uploadFile',\r\n component: 'pcm-msbg-modal',\r\n title: '文件上传失败'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '文件上传失败,请重试'\r\n });\r\n } finally {\r\n this.isUploading = false;\r\n }\r\n }\r\n\r\n private handleJobDescriptionChange = (event: Event) => {\r\n const textarea = event.target as HTMLTextAreaElement;\r\n this.jobDescription = textarea.value;\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n if (!this.selectedFile) {\r\n alert('请上传面试内容');\r\n return;\r\n }\r\n\r\n // 如果没有预设的job_info,则需要检查用户输入\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n alert('请输入职位描述');\r\n return;\r\n }\r\n\r\n this.isSubmitting = true;\r\n\r\n try {\r\n // 如果还没上传,先上传文件\r\n if (!this.uploadedFileInfo) {\r\n await this.uploadFile();\r\n if (!this.uploadedFileInfo) {\r\n this.isSubmitting = false;\r\n return; // 上传失败\r\n }\r\n }\r\n\r\n // 直接显示聊天模态框\r\n this.showChatModal = true;\r\n } catch (error) {\r\n console.error('开始面试时出错:', error);\r\n SentryReporter.captureError(error, {\r\n action: 'handleStartInterview',\r\n component: 'pcm-msbg-modal',\r\n title: '开始面试时出错'\r\n });\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: '开始面试时出错,请重试'\r\n });\r\n } finally {\r\n this.isSubmitting = false;\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\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen,\r\n 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 确保当 customInputs.job_info 存在时,hideJdInput 为 true\r\n const hideJdInput = Boolean(this.customInputs && this.customInputs.job_info);\r\n \r\n // 判断是否隐藏面试内容上传区域\r\n const hideFileUpload = Boolean(this.customInputs && this.customInputs.file_urls);\r\n \r\n // 判断是否同时提供了file_urls和job_info\r\n const hasFileAndJob = Boolean(this.customInputs?.file_urls && this.customInputs?.job_info);\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 <div>{this.modalTitle}</div>\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 {/* 上传界面 - 仅在不显示聊天模态框且没有会话ID且没有同时提供file_urls和job_info时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hasFileAndJob && (\r\n <div class=\"input-container\">\r\n {/* JD输入区域 - 仅在没有parsedCustomInputs.job_info时显示 */}\r\n {!hideJdInput && (\r\n <div class=\"jd-input-section\">\r\n <label htmlFor=\"job-description\">请输入职位描述 (JD)</label>\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder=\"请输入职位描述,包括职责、要求等信息...\"\r\n rows={6}\r\n value={this.jobDescription}\r\n onInput={this.handleJobDescriptionChange}\r\n ></textarea>\r\n </div>\r\n )}\r\n\r\n {/* 上传面试内容上传区域 - 仅在没有customInputs.file_urls时显示 */}\r\n {!hideFileUpload && (\r\n <div class=\"resume-upload-section\">\r\n <label>上传面试内容</label>\r\n <div class=\"upload-area\" onClick={this.handleUploadClick}>\r\n {this.selectedFile ? (\r\n <div class=\"file-item\">\r\n <div class=\"file-item-content\">\r\n <span class=\"file-icon\">📝</span>\r\n <span class=\"file-name\">{this.selectedFile.name}</span>\r\n </div>\r\n <button class=\"remove-file\" onClick={(e) => {\r\n e.stopPropagation();\r\n this.clearSelectedFile();\r\n }}>×</button>\r\n </div>\r\n ) : (\r\n <div class=\"upload-placeholder\">\r\n <img src='https://pub.pincaimao.com/static/web/images/home/i_upload.png'></img>\r\n <p class='upload-text'>点击上传面试内容</p>\r\n <p class=\"upload-hint\">支持 mp3、markdown、pdf、docx、doc、md 格式</p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(!hideFileUpload && !this.selectedFile) || (!hideJdInput && !this.jobDescription.trim()) || this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始分析'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n onChange={this.handleFileChange}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div >\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018877\"\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_urls: this.customInputs?.file_urls || this.uploadedFileInfo?.cos_key,\r\n file_names: this.customInputs?.file_names || this.uploadedFileInfo?.file_name,\r\n job_info: this.customInputs?.job_info || this.jobDescription\r\n }}\r\n interviewMode=\"text\"\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} ",".iframe-container {\r\n width: 100%;\r\n height: 85vh;\r\n}\r\n\r\n.iframe-container iframe {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",".upload-area{\r\n max-height: 300px;\r\n overflow-y: auto;\r\n}\r\n.upload-actions {\r\n display: flex;\r\n gap: 12px;\r\n margin-top: 12px;\r\n width: 100%;\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, h, State, Element, Prop, Event, EventEmitter, Method } from \"@stencil/core\";\r\nimport { FileUploadResponse, FileUploadResponseWithState, FileUploadState, formatFileSize, uploadFileToBackend } from \"../../utils/utils\";\r\nimport { Message } from \"../../services/message.service\";\r\nimport { SentryReporter } from \"../../utils/sentry-reporter\";\r\n\r\n\r\nexport type UploadFailedEvent = {\r\n error: Error;\r\n message: string;\r\n}\r\n\r\n@Component({\r\n tag: 'pcm-upload',\r\n styleUrls: ['pcm-upload.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class PcmUpload {\r\n /**\r\n * 是否支持多文件上传\r\n */\r\n @Prop() multiple: boolean = false;\r\n /**\r\n * 是否开启移动端上传(仅PC端生效)\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 支持的文件后缀列表(需要带上小数点.)\r\n */\r\n @Prop() acceptFileSuffixList: string[] = [];\r\n /**\r\n * 最大文件数\r\n */\r\n @Prop() maxFileCount: number = Infinity;\r\n /**\r\n * 最大文件大小\r\n */\r\n @Prop() maxFileSize: number = Infinity;\r\n /**\r\n * 上传请求头\r\n */\r\n @Prop() uploadHeaders?: Record<string, any>;\r\n /**\r\n * 上传请求参数\r\n */\r\n @Prop() uploadParams?: Record<string, any>;\r\n /**\r\n * 自定义上传文本\r\n */\r\n @Prop() uploadText: string = '点击上传简历';\r\n /**\r\n * 默认文件列表(预填充文件)\r\n */\r\n @Prop() defaultFileList?: FileUploadResponse[];\r\n /**\r\n * 是否禁用上传(禁用时只显示文件,不允许修改)\r\n */\r\n @Prop() disabled: boolean = false;\r\n /**\r\n * 上传失败监听\r\n */\r\n @Event() uploadFailed: EventEmitter<UploadFailedEvent>;\r\n /**\r\n * 上传文件变化监听\r\n */\r\n @Event() uploadChange: EventEmitter<FileUploadResponse[]>;\r\n\r\n\r\n @Element() hostElement: HTMLElement;\r\n @State() selectedFiles: FileUploadResponseWithState[] | null = null;\r\n\r\n componentWillLoad() {\r\n // 如果有默认文件列表,则初始化 selectedFiles\r\n if (this.defaultFileList && this.defaultFileList.length > 0) {\r\n this.selectedFiles = this.defaultFileList.map(file => ({\r\n ...file,\r\n state: FileUploadState.Success,\r\n }));\r\n }\r\n }\r\n\r\n @Method()\r\n async getIsUploading() {\r\n return !!this.selectedFiles?.some(item => item.state === FileUploadState.Uploading);\r\n }\r\n\r\n /**\r\n * 清除已选择的文件\r\n */\r\n @Method()\r\n async clearSelectedFiles() {\r\n this.selectedFiles = null;\r\n this.clearSelectedFile(); // 同时清除input的值\r\n }\r\n\r\n private handleUploadClick = () => {\r\n if (this.disabled) return;\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 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 private async uploadFile(file: File): Promise<FileUploadResponseWithState> {\r\n try {\r\n const result = await uploadFileToBackend(file, this.uploadHeaders || {}, this.uploadParams || {});\r\n return {\r\n ...result,\r\n file,\r\n file_name: file.name,\r\n file_size: file.size,\r\n state: FileUploadState.Success,\r\n }\r\n } catch (error) {\r\n this.clearSelectedFile();\r\n SentryReporter.captureError(error, {\r\n action: 'uploadFile',\r\n component: 'pcm-mnms-modal',\r\n title: '文件上传失败'\r\n });\r\n this.uploadFailed.emit({\r\n error: error,\r\n message: '文件上传失败,请重试'\r\n });\r\n return {\r\n file,\r\n error,\r\n state: FileUploadState.Failed,\r\n }\r\n }\r\n }\r\n\r\n private handleFileChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n\r\n if (this.multiple) {\r\n // 多选\r\n const files = Array.from(input.files || []);\r\n if (files.length === 0) return;\r\n\r\n // 验证文件数量限制\r\n const currentFileCount = this.selectedFiles?.length || 0;\r\n const remainingSlots = this.maxFileCount - currentFileCount;\r\n if (files.length > remainingSlots) {\r\n Message.info(`最多只能上传 ${this.maxFileCount} 个文件,当前已选择 ${currentFileCount} 个`);\r\n return;\r\n }\r\n\r\n const validFiles: File[] = [];\r\n const invalidFiles: string[] = [];\r\n\r\n // 验证每个文件\r\n files.forEach(file => {\r\n // 检测文件后缀名\r\n if (this.acceptFileSuffixList?.length) {\r\n const suffix = '.' + file.name.split('.').pop()?.toLowerCase();\r\n if (!this.acceptFileSuffixList.includes(suffix)) {\r\n invalidFiles.push(`${file.name}(格式不支持)`);\r\n return;\r\n }\r\n }\r\n // 检测文件大小\r\n if (this.maxFileSize < file.size) {\r\n invalidFiles.push(`${file.name}(文件过大)`);\r\n return;\r\n }\r\n validFiles.push(file);\r\n });\r\n\r\n // 提示无效文件\r\n if (invalidFiles.length > 0) {\r\n const supportedFormats = this.acceptFileSuffixList?.length ? this.acceptFileSuffixList.join('、') : '';\r\n const maxSizeText = this.maxFileSize !== Infinity ? formatFileSize(this.maxFileSize) : '';\r\n Message.info(`以下文件无法上传:${invalidFiles.join('、')}。${supportedFormats ? `支持格式:${supportedFormats}。` : ''}${maxSizeText ? `最大文件大小:${maxSizeText}。` : ''}`);\r\n }\r\n\r\n if (validFiles.length === 0) {\r\n this.clearSelectedFile();\r\n return;\r\n }\r\n\r\n // 为有效文件创建初始状态\r\n const newFileItems: FileUploadResponseWithState[] = validFiles.map(file => ({\r\n file,\r\n file_name: file.name,\r\n file_size: file.size,\r\n state: FileUploadState.Uploading,\r\n cos_key: '',\r\n error: undefined,\r\n }));\r\n\r\n // 添加到现有文件列表\r\n this.selectedFiles = [\r\n ...(this.selectedFiles || []),\r\n ...newFileItems\r\n ];\r\n\r\n // 依次上传文件\r\n for (let i = 0; i < validFiles.length; i++) {\r\n const file = validFiles[i];\r\n const uploadResult = await this.uploadFile(file);\r\n\r\n // 更新对应文件的状态\r\n if (this.selectedFiles) {\r\n const currentFileCount = this.selectedFiles.length;\r\n const targetIndex = currentFileCount - validFiles.length + i;\r\n if (targetIndex >= 0 && targetIndex < this.selectedFiles.length) {\r\n this.selectedFiles[targetIndex] = uploadResult;\r\n // 触发重新渲染\r\n this.selectedFiles = [...this.selectedFiles];\r\n }\r\n }\r\n }\r\n\r\n this.clearSelectedFile();\r\n this.emitUploadChange();\r\n } else {\r\n // 单选\r\n const file = input.files?.[0];\r\n if (!file) return;\r\n // 检测文件是否符合后缀名\r\n if (this.acceptFileSuffixList?.length) {\r\n const suffix = '.' + file.name.split('.').pop()?.toLowerCase();\r\n if (!this.acceptFileSuffixList.includes(suffix)) {\r\n Message.info(`请上传 ${this.acceptFileSuffixList.join('、')} 格式的文件`);\r\n return;\r\n }\r\n }\r\n // 检测文件大小是否超出限制\r\n if (this.maxFileSize < file.size) {\r\n Message.info(`文件大小不能超过 ${formatFileSize(this.maxFileSize) ?? '-'}`);\r\n return;\r\n }\r\n this.selectedFiles = [{\r\n file,\r\n file_name: file.name,\r\n file_size: file.size,\r\n state: FileUploadState.Uploading,\r\n cos_key: '',\r\n error: undefined,\r\n }];\r\n const uploadResult = await this.uploadFile(file);\r\n this.selectedFiles = [uploadResult];\r\n this.clearSelectedFile();\r\n this.emitUploadChange();\r\n }\r\n };\r\n\r\n private emitUploadChange = () => {\r\n this.uploadChange.emit(this.selectedFiles?.filter(item => item.state === FileUploadState.Success).map?.(item => ({\r\n cos_key: item.cos_key,\r\n file_name: item.file_name,\r\n file_size: item.file_size,\r\n ext: item.ext,\r\n })));\r\n }\r\n\r\n private uploadBtn() {\r\n return <div style={{ width: '100%' }}>\r\n {\r\n !!this.mobileUploadAble && <pcm-mobile-upload-btn\r\n multiple={this.multiple}\r\n acceptFileSuffixList={this.acceptFileSuffixList}\r\n maxFileCount={this.maxFileCount}\r\n maxFileSize={this.maxFileSize}\r\n uploadHeaders={this.uploadHeaders}\r\n uploadParams={this.uploadParams}\r\n onOk={e => {\r\n this.selectedFiles = [\r\n ...(this.selectedFiles ?? []),\r\n ...(e.detail ?? []).map(item => ({\r\n ...item,\r\n state: FileUploadState.Success,\r\n }))\r\n ]\r\n this.emitUploadChange();\r\n }}\r\n />\r\n }\r\n <div class=\"upload-placeholder\" onClick={this.handleUploadClick}>\r\n <img src='https://pub.pincaimao.com/static/web/images/home/i_upload.png'></img>\r\n <p class='upload-text'>{this.uploadText}</p>\r\n {\r\n !!this.acceptFileSuffixList?.length && <p class=\"upload-hint\">支持 {this.acceptFileSuffixList.join('、')} 格式。</p>\r\n }\r\n {\r\n !!this.maxFileSize && this.maxFileSize !== Infinity && <p class=\"upload-hint\">文件大小不能超过 {formatFileSize(this.maxFileSize) ?? ''}。</p>\r\n }\r\n {\r\n !!this.maxFileCount && this.maxFileCount !== Infinity && <p class=\"upload-hint\">最多上传 {this.maxFileCount} 个文件。</p>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n render() {\r\n return (\r\n <div>\r\n <div class=\"resume-upload-section\">\r\n <div class=\"upload-area\">\r\n <div>\r\n {\r\n this.selectedFiles?.map?.((item, index) => {\r\n return <div class=\"file-item\">\r\n <div class=\"file-item-content\">\r\n <span class=\"file-icon\">📝</span>\r\n <span class=\"file-name\" style={item.state === FileUploadState.Failed ? { color: 'red', textDecoration: 'line-through' } : undefined}>{item?.file_name}</span>\r\n {\r\n item.state === FileUploadState.Failed && <span style={{ color: 'red', marginLeft: '4px' }}>({item.error?.message ?? '上传失败'})</span>\r\n }\r\n </div>\r\n {!this.disabled && <button class=\"remove-file\" onClick={(e) => {\r\n e.stopPropagation();\r\n this.selectedFiles = this.selectedFiles?.filter((_, itemIndex) => index !== itemIndex);\r\n this.emitUploadChange();\r\n }}>×</button>}\r\n </div>\r\n })\r\n }\r\n </div>\r\n\r\n </div>\r\n {\r\n !this.disabled && (this.multiple ? <div class=\"upload-actions\">\r\n {\r\n (this.selectedFiles?.length ?? 0) < this.maxFileCount && this.uploadBtn()\r\n }\r\n </div> : <div class=\"upload-actions\">\r\n {\r\n !this.selectedFiles?.length && this.uploadBtn()\r\n }\r\n </div>)\r\n }\r\n </div>\r\n <input\r\n type=\"file\"\r\n class=\"file-input\"\r\n multiple={this.multiple}\r\n onChange={this.handleFileChange}\r\n />\r\n </div>\r\n )\r\n }\r\n}",":host {\r\n display: block;\r\n font-size: 16px;\r\n}\r\n\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n overflow: hidden;\r\n padding: 0;\r\n z-index: 1000;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.modal-container {\r\n background: #fff;\r\n border-radius: 0;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: 0;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* 数字人视频背景层 */\r\n.digital-human-background {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 1;\r\n overflow: hidden;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n\r\n.digital-human-background-video {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n object-position: center;\r\n max-width: 1200px;\r\n}\r\n\r\n/* 当没有数字人时的默认背景 */\r\n.modal-container:not(.digital-human-mode) {\r\n background: white;\r\n border-radius: 8px;\r\n width: 100%;\r\n max-width: 900px;\r\n height: 90vh;\r\n max-height: 800px;\r\n}\r\n\r\n/* 内容层 */\r\n.modal-content-layer {\r\n position: relative;\r\n z-index: 10;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n background: linear-gradient(\r\n 180deg,\r\n rgba(0, 0, 0, 0.3) 0%,\r\n rgba(0, 0, 0, 0.1) 20%,\r\n rgba(0, 0, 0, 0.1) 80%,\r\n rgba(0, 0, 0, 0.4) 100%\r\n );\r\n}\r\n\r\n.main-content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center; /* 水平居中 */\r\n overflow: hidden;\r\n padding: 24px 24px 40px 24px; /* 增加底部间距 */\r\n position: absolute;\r\n bottom: 0px;\r\n width: -webkit-fill-available;\r\n}\r\n\r\n.chat-history-section {\r\n width: 100%;\r\n max-width: 800px;\r\n text-align: center;\r\n color: white;\r\n}\r\n\r\n.ai-message-item {\r\n padding: 12px 20px;\r\n border-radius: 12px;\r\n margin-bottom: 12px;\r\n animation: fadeIn 0.5s ease-in-out;\r\n}\r\n\r\n.recording-preview-top-right {\r\n position: absolute;\r\n top: 20px;\r\n right: 20px;\r\n width: 180px;\r\n height: 120px;\r\n border-radius: 12px;\r\n overflow: hidden;\r\n border: 2px solid rgba(255, 255, 255, 0.5);\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\r\n background-color: #000;\r\n z-index: 10;\r\n}\r\n\r\n.user-video-preview {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n.recording-status-bar {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n background-color: white;\r\n padding: 8px 12px;\r\n border-radius: 999px;\r\n margin-top: 4px;\r\n width: 100%;\r\n max-width: 400px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n animation: slideInUp 0.5s ease-out;\r\n line-height: 40px;\r\n}\r\n\r\n.audio-waveform {\r\n display: flex;\r\n align-items: center;\r\n height: 24px;\r\n}\r\n\r\n.waveform-bar {\r\n width: 4px;\r\n margin: 0 2px;\r\n background-color: #16a34a; /* A vibrant green */\r\n border-radius: 2px;\r\n height: 6px;\r\n animation: waveform-animation 1.2s infinite ease-in-out;\r\n}\r\n\r\n.waveform-bar:nth-child(1) {\r\n animation-delay: 0.1s;\r\n}\r\n.waveform-bar:nth-child(2) {\r\n animation-delay: 0.3s;\r\n}\r\n.waveform-bar:nth-child(3) {\r\n animation-delay: 0.5s;\r\n}\r\n.waveform-bar:nth-child(4) {\r\n animation-delay: 0.2s;\r\n}\r\n.waveform-bar:nth-child(5) {\r\n animation-delay: 0.4s;\r\n}\r\n.waveform-bar:nth-child(6) {\r\n animation-delay: 0.1s;\r\n}\r\n.waveform-bar:nth-child(7) {\r\n animation-delay: 0.3s;\r\n}\r\n.waveform-bar:nth-child(8) {\r\n animation-delay: 0.5s;\r\n}\r\n\r\n@keyframes waveform-animation {\r\n 0%,\r\n 100% {\r\n height: 6px;\r\n }\r\n 50% {\r\n height: 35px;\r\n }\r\n}\r\n\r\n.recording-timer {\r\n font-size: 14px;\r\n color: #595959;\r\n font-family: 'Courier New', Courier, monospace;\r\n}\r\n\r\n.finish-recording-btn {\r\n background-color: #16a34a; /* A vibrant green */\r\n border: none;\r\n border-radius: 50%;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n transition:\r\n background-color 0.3s,\r\n transform 0.2s;\r\n}\r\n\r\n.finish-recording-btn:hover {\r\n background-color: #148a3f;\r\n}\r\n\r\n.finish-recording-btn:active {\r\n transform: scale(0.95);\r\n}\r\n\r\n@keyframes fadeIn {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n@keyframes slideInUp {\r\n from {\r\n transform: translateY(20px);\r\n opacity: 0;\r\n }\r\n to {\r\n transform: translateY(0);\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.status-indicator-text {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 14px;\r\n color: #595959;\r\n width: 100%;\r\n justify-content: center;\r\n}\r\n\r\n.status-indicator-text.loading .loading-spinner-small {\r\n width: 16px;\r\n height: 16px;\r\n border: 2px solid rgba(0, 0, 0, 0.1);\r\n border-top-color: #595959;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n.status-indicator-text.error {\r\n color: #ff4d4f;\r\n}\r\n\r\n.status-indicator-text.ready {\r\n color: #16a34a;\r\n}\r\n\r\n@keyframes spin {\r\n from {\r\n transform: rotate(0deg);\r\n }\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n.loading-spinner-small {\r\n width: 20px;\r\n height: 20px;\r\n border: 2px solid #e5e7eb;\r\n border-top-color: #6b7280;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n/* 添加上传按钮样式 */\r\n.upload-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #666;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.upload-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.upload-button svg {\r\n width: 20px;\r\n height: 20px;\r\n}\r\n\r\n/* 隐藏原生文件输入框 */\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n/* 添加文件名显示区域样式 */\r\n.selected-file {\r\n font-size: 12px;\r\n color: #666;\r\n margin-left: 8px;\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n padding: 0 4px;\r\n background: white;\r\n}\r\n\r\n.input-wrapper input {\r\n border: none;\r\n flex: 1;\r\n padding: 8px;\r\n outline: none;\r\n}\r\n\r\n.input-wrapper:focus-within {\r\n border-color: #bbb;\r\n}\r\n\r\n/* 文件预览区域样式 */\r\n.file-preview {\r\n padding: 8px 16px;\r\n border-top: 1px solid #eee;\r\n background-color: #f9f9f9;\r\n}\r\n\r\n.recording-section {\r\n border-top: 1px solid #eee;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 10px 20px 0px 20px;\r\n border-radius: 14px 14px 0 0;\r\n flex: 0 0 auto;\r\n}\r\n\r\n.recording-section .video-preview {\r\n width: 100%;\r\n height: 200px;\r\n max-width: 400px;\r\n position: relative;\r\n margin-bottom: 10px;\r\n border: 1px solid #ddd;\r\n border-radius: 12px;\r\n overflow: hidden;\r\n}\r\n\r\n.recording-section video {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n/* 修改 recording-status 样式 */\r\n.recording-status {\r\n position: absolute;\r\n top: 10px;\r\n left: 10px;\r\n background-color: rgba(0, 0, 0, 0.6);\r\n color: white;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n font-size: 14px;\r\n z-index: 0;\r\n}\r\n\r\n.recording-status .recording-dot {\r\n display: inline-block;\r\n width: 10px;\r\n height: 10px;\r\n background-color: red;\r\n border-radius: 50%;\r\n margin-right: 5px;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n.recording-status.warning {\r\n color: #ff4d4f;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n@keyframes blink {\r\n 0% {\r\n opacity: 1;\r\n }\r\n\r\n 50% {\r\n opacity: 0.5;\r\n }\r\n\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.recording-section .stop-recording-button {\r\n background-color: #f44336;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-weight: bold;\r\n}\r\n\r\n.recording-section .stop-recording-button:hover {\r\n background-color: #d32f2f;\r\n}\r\n\r\n.fullscreen {\r\n width: 100vw;\r\n border-radius: 0;\r\n height: 100vh;\r\n display: flex;\r\n flex-direction: column;\r\n overflow-y: auto;\r\n}\r\n\r\n.recording-controls {\r\n margin-top: 10px;\r\n height: 53px;\r\n width: 100%;\r\n max-width: 400px;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n\r\n.recording-controls .waiting-message {\r\n text-align: center;\r\n color: white;\r\n font-size: 16px;\r\n background-color: #0d75fb;\r\n border-radius: 6px;\r\n width: 95%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n}\r\n\r\n.recording-controls .waiting-message.loading {\r\n background: #faad14;\r\n}\r\n\r\n.recording-controls .waiting-message p {\r\n margin: 0;\r\n font-size: 16px;\r\n color: white;\r\n font-weight: 500;\r\n}\r\n\r\n.recording-controls .stop-recording-button {\r\n background-color: #dc3545;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-size: 16px;\r\n}\r\n\r\n.recording-controls .stop-recording-button:hover {\r\n background-color: #c82333;\r\n}\r\n\r\n/* 添加禁用状态的样式 */\r\n.recording-controls .stop-recording-button.disabled {\r\n background: #ccc;\r\n cursor: not-allowed;\r\n}\r\n\r\n.recording-controls .stop-recording-button.disabled:hover {\r\n background: #ccc;\r\n}\r\n\r\n/* 添加进度条和数字进度的样式 */\r\n.progress-container {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n width: 100%;\r\n max-width: 400px;\r\n margin-top: 10px;\r\n padding: 0 5px;\r\n}\r\n\r\n.progress-bar-container {\r\n height: 4px;\r\n background-color: #e5e5e5;\r\n border-radius: 2px;\r\n overflow: hidden;\r\n margin-right: 10px;\r\n width: 75px;\r\n}\r\n\r\n.progress-bar {\r\n height: 100%;\r\n background-image: linear-gradient(111deg, #4a9fff 0%, #1058ff 100%);\r\n border-radius: 2px;\r\n transition: width 0.3s ease;\r\n}\r\n\r\n.progress-text {\r\n font-size: 14px;\r\n color: #666;\r\n white-space: nowrap;\r\n}\r\n\r\n/* 重新设计文本输入区域样式 */\r\n.text-input-area {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n padding: 0px 16px 16px 16px;\r\n border-radius: 8px;\r\n border: none;\r\n /* 确保容器本身没有边框 */\r\n}\r\n\r\n/* 修改文本输入框样式 */\r\n.text-answer-input {\r\n flex: 1;\r\n min-height: 80px;\r\n padding: 12px 12px 0px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 8px 8px 0 0;\r\n resize: none;\r\n font-size: 16px;\r\n background-color: #fff;\r\n border-bottom: none;\r\n outline: none;\r\n /* 移除默认的焦点轮廓 */\r\n}\r\n\r\n/* 修改工具栏样式 */\r\n.input-toolbar {\r\n display: flex;\r\n justify-content: end;\r\n align-items: center;\r\n padding: 8px 12px;\r\n background-color: #fff;\r\n border: 1px solid #ddd;\r\n border-top: none;\r\n border-radius: 0 0 8px 8px;\r\n}\r\n\r\n/* 当输入框获得焦点时,修改边框颜色 */\r\n.text-answer-input:focus {\r\n border-color: rgb(74, 144, 226);\r\n border-bottom: none;\r\n}\r\n\r\n.text-answer-input:focus + .input-toolbar {\r\n border-color: rgb(74, 144, 226);\r\n border-top: none;\r\n}\r\n\r\n/* 左侧工具按钮区域 */\r\n.toolbar-actions {\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n margin-right: 10px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n}\r\n\r\n.toolbar-actions:hover {\r\n background-color: #f0f0f0;\r\n}\r\n\r\n/* 修改工具按钮样式,确保居中 */\r\n.toolbar-button {\r\n background: transparent;\r\n border: none;\r\n color: #666;\r\n cursor: pointer;\r\n padding: 0;\r\n margin: 0;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n/* 确保按钮内部的内容也居中 */\r\n.toolbar-button > div,\r\n.toolbar-button > svg {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n/* 发送按钮样式 */\r\n.submit-text-button {\r\n padding: 6px 16px;\r\n background-color: #4a90e2;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.submit-text-button:hover:not(.disabled) {\r\n background-color: #3a7bc8;\r\n}\r\n\r\n.submit-text-button.disabled {\r\n background-color: #b3b3b3;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* 语音输入按钮样式 */\r\n.toolbar-button.recording {\r\n background-color: rgba(255, 0, 0, 0.1);\r\n color: #ff3b30;\r\n animation: pulse 1.5s infinite;\r\n}\r\n\r\n.toolbar-button.converting {\r\n background-color: rgba(0, 122, 255, 0.1);\r\n color: #007aff;\r\n}\r\n\r\n.toolbar-button .recording-time {\r\n font-size: 12px;\r\n margin-left: 4px;\r\n}\r\n\r\n.converting-indicator {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.converting-indicator svg {\r\n animation: spin 1.5s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@keyframes pulse {\r\n 0% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.4);\r\n }\r\n\r\n 70% {\r\n box-shadow: 0 0 0 6px rgba(255, 0, 0, 0);\r\n }\r\n\r\n 100% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0);\r\n }\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 0;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 工作区样式 */\r\n.workspace-section {\r\n width: 100%;\r\n padding: 0px 16px 16px;\r\n}\r\n\r\n.workspace-toolbar {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: end;\r\n gap: 12px;\r\n position: relative;\r\n}\r\n\r\n.workspace-button {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 8px 16px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: white;\r\n color: #666;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\r\n}\r\n\r\n.workspace-button:hover {\r\n border-color: #4096ff;\r\n color: #4096ff;\r\n box-shadow: 0 2px 4px rgba(64, 150, 255, 0.1);\r\n}\r\n\r\n.workspace-button svg {\r\n flex-shrink: 0;\r\n}\r\n\r\n/* 数字人容器样式 */\r\n.digital-human-wrapper {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 120px;\r\n height: 80px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 8px;\r\n background: #fafafa;\r\n overflow: hidden;\r\n position: absolute;\r\n right: 0px;\r\n}\r\n\r\n\r\n/* 历史会话抽屉样式 */\r\n.history-drawer-content {\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.conversation-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 8px 0;\r\n}\r\n\r\n.loading-conversations,\r\n.empty-conversations {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px 20px;\r\n color: #999;\r\n}\r\n\r\n.loading-conversations .loading-spinner-small {\r\n margin-bottom: 12px;\r\n}\r\n\r\n.conversation-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 12px 16px;\r\n margin: 0 8px 4px 8px;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n border: 1px solid transparent;\r\n}\r\n\r\n.conversation-item:hover {\r\n background: #f5f5f5;\r\n}\r\n\r\n.conversation-item.active {\r\n background: #e6f7ff;\r\n border-color: #1890ff;\r\n}\r\n\r\n.conversation-info {\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n.conversation-title {\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: #262626;\r\n margin-bottom: 4px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.conversation-meta {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 12px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.conversation-time {\r\n flex-shrink: 0;\r\n}\r\n\r\n.message-count {\r\n flex-shrink: 0;\r\n}\r\n\r\n.conversation-status {\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n font-size: 11px;\r\n font-weight: 500;\r\n}\r\n\r\n.conversation-status.completed {\r\n background: #f6ffed;\r\n color: #52c41a;\r\n}\r\n\r\n.conversation-status.running {\r\n background: #fff7e6;\r\n color: #fa8c16;\r\n}\r\n\r\n.current-indicator {\r\n flex-shrink: 0;\r\n color: #1890ff;\r\n margin-left: 8px;\r\n}\r\n\r\n/* AI消息显示样式 */\r\n.ai-message-item {\r\n margin-bottom: 0;\r\n animation: messageSlideIn 0.3s ease-out;\r\n width: 100%;\r\n padding: 20px;\r\n}\r\n\r\n.ai-message-item.streaming {\r\n position: relative;\r\n}\r\n\r\n@keyframes messageSlideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n}\r\n\r\n.ai-message-content {\r\n color: #fff;\r\n padding: 20px 24px;\r\n border-radius: 16px;\r\n font-size: 16px;\r\n line-height: 1.6;\r\n word-wrap: break-word;\r\n backdrop-filter: blur(100px);\r\n border: 1px solid rgba(255, 255, 255, 0.2);\r\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);\r\n margin-bottom: 8px;\r\n max-width: 100%;\r\n text-align: left;\r\n}\r\n\r\n/* 打字指示器 */\r\n.typing-indicator {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 8px 24px;\r\n margin-top: -8px;\r\n}\r\n\r\n.typing-indicator span {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n background: #4facfe;\r\n animation: typingPulse 1.4s ease-in-out infinite;\r\n opacity: 0.6;\r\n}\r\n\r\n.typing-indicator span:nth-child(1) { animation-delay: 0s; }\r\n.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }\r\n.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }\r\n\r\n@keyframes typingPulse {\r\n 0%, 60%, 100% {\r\n transform: scale(1);\r\n opacity: 0.4;\r\n }\r\n 30% {\r\n transform: scale(1.3);\r\n opacity: 1;\r\n }\r\n}\r\n\r\n/* 响应式适配 */\r\n@media screen and (max-width: 768px) {\r\n .ai-message-content {\r\n padding: 14px 18px;\r\n font-size: 15px;\r\n }\r\n}\r\n\r\n@media screen and (max-width: 480px) {\r\n .ai-message-content {\r\n padding: 12px 16px;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n }\r\n\r\n .typing-indicator {\r\n padding: 6px 16px;\r\n }\r\n\r\n .typing-indicator span {\r\n width: 6px;\r\n height: 6px;\r\n }\r\n}\r\n\r\n/* 响应式适配 */\r\n@media screen and (max-width: 768px) {\r\n\r\n .ai-message-item {\r\n padding: 15px;\r\n }\r\n\r\n .ai-message-content {\r\n padding: 16px 20px;\r\n font-size: 15px;\r\n }\r\n\r\n .typing-indicator {\r\n padding: 6px 20px;\r\n }\r\n}\r\n\r\n@media screen and (max-width: 480px) {\r\n\r\n .ai-message-item {\r\n padding: 0px;\r\n }\r\n\r\n .ai-message-content {\r\n padding: 14px 18px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n }\r\n\r\n .typing-indicator {\r\n padding: 5px 18px;\r\n }\r\n\r\n .typing-indicator span {\r\n width: 6px;\r\n height: 6px;\r\n }\r\n\r\n\r\n}\r\n\r\n\r\n.waveform-bar {\r\n width: 3px;\r\n background: #4facfe;\r\n border-radius: 2px;\r\n min-height: 2px;\r\n animation: waveformAnimation 1.2s ease-in-out infinite alternate;\r\n transform-origin: bottom;\r\n}\r\n\r\n@keyframes waveformAnimation {\r\n 0% { transform: scaleY(0.2); }\r\n 100% { transform: scaleY(1); }\r\n}\r\n\r\n.recording-timer {\r\n font-size: 14px;\r\n color: #666;\r\n white-space: nowrap;\r\n}\r\n\r\n.close-button{\r\n position: absolute;\r\n top: 16px;\r\n left: 16px;\r\n z-index: 20;\r\n background: rgba(255, 255, 255, 0.9);\r\n backdrop-filter: blur(4px);\r\n border: 1px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 8px;\r\n width: 40px;\r\n height: 40px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n.close-button:hover {\r\n background: rgba(255, 255, 255, 1);\r\n border-color: rgba(0, 0, 0, 0.15);\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n transform: translateY(-1px);\r\n}\r\n\r\n.close-button:active {\r\n transform: translateY(0);\r\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n.close-button svg {\r\n color: #666;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.close-button:hover svg {\r\n color: #333;\r\n}\r\n\r\n/* 结束面试按钮容器 */\r\n.end-interview-button-container {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-start;\r\n width: 100%;\r\n max-width: 400px;\r\n margin-bottom: 4px;\r\n padding-left: 0;\r\n}\r\n\r\n/* 结束面试按钮 */\r\n.end-interview-button {\r\n padding: 5px 10px;\r\n background-color: #ff4d4f;\r\n color: white;\r\n border: none;\r\n border-radius: 20px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n box-shadow: 0 2px 8px rgba(255, 77, 79, 0.3);\r\n white-space: nowrap;\r\n}\r\n\r\n.end-interview-button:hover {\r\n background-color: #ff7875;\r\n box-shadow: 0 4px 12px rgba(255, 77, 79, 0.4);\r\n transform: translateY(-1px);\r\n}\r\n\r\n.end-interview-button:active {\r\n transform: translateY(0);\r\n box-shadow: 0 2px 8px rgba(255, 77, 79, 0.3);\r\n}\r\n\r\n.end-interview-button:disabled {\r\n background-color: #f0f0f0;\r\n color: #bfbfbf;\r\n cursor: not-allowed;\r\n box-shadow: none;\r\n transform: none;\r\n}\r\n\r\n\r\n",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}",":host {\r\n display: block;\r\n font-size: 16px;\r\n}\r\n\r\n \r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n -webkit-overflow-scrolling: touch; /* 增强iOS滚动体验 */\r\n}\r\n\r\n/* 全屏模式下的overlay样式 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n\r\n.modal-container {\r\n background: white;\r\n border-radius: 8px;\r\n width: 100%;\r\n max-width: 900px;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* 确保内容区域也使用 flex 布局并占满剩余空间 */\r\n.modal-container.fullscreen > div:not(.modal-header):not(.initial-upload) {\r\n display: flex;\r\n flex-direction: column;\r\n flex: 1;\r\n overflow: hidden; /* 防止内容溢出 */\r\n height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 800px;\r\n /* height: 80vh; */\r\n /* max-height: 700px; */\r\n min-width: 320px;\r\n min-height: 400px;\r\n}\r\n\r\n\r\n\r\n.video-preview.placeholder {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n background: #EAEAEA;\r\n}\r\n\r\n.placeholder-status {\r\n color: #00000066;\r\n}\r\n\r\n.waiting-message p {\r\n margin: 0;\r\n font-size: 16px;\r\n color: white;\r\n font-weight: 500;\r\n}\r\n\r\n.recording-container {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n\r\n\r\n.video-area {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n}\r\n\r\n.stop-recording-button {\r\n width: 100%;\r\n height: 100%;\r\n font-size: 16px;\r\n background: #f44336;\r\n border-radius: 6px;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n}\r\n\r\n.stop-recording-button:hover {\r\n background: #d32f2f;\r\n}\r\n\r\n.play-audio-container {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0; /* 防止头部被压缩 */\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n.chat-container{\r\n background-image: url(https://pub.pincaimao.com/static/web/images/login/bg_login_m.png);\r\n background-size: 100%;\r\n height: 100%;\r\n border-radius:0px 0px 8px 8px;\r\n}\r\n\r\n.chat-history {\r\n position: relative;\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 20px;\r\n scroll-behavior: smooth;\r\n height: 400px;\r\n}\r\n\r\n/* 添加全屏模式下的样式 */\r\n.fullscreen .chat-history {\r\n height: auto;\r\n flex: 1 1 auto;\r\n}\r\n\r\n\r\n.message-input {\r\n padding: 16px;\r\n border-top: 1px solid #eee;\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.message-input input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n outline: none;\r\n transition: border-color 0.2s ease;\r\n}\r\n\r\n.message-input input:focus {\r\n border-color: #bbb;\r\n}\r\n\r\n/* 消息样式 */\r\n.message {\r\n margin-bottom: 16px;\r\n opacity: 1;\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.message-content {\r\n max-width: 70%;\r\n padding: 8px 12px;\r\n border-radius: 8px;\r\n word-break: break-word;\r\n}\r\n\r\n.message-content p {\r\n margin: 0;\r\n word-break: break-word;\r\n}\r\n\r\n.user-message {\r\n display: flex;\r\n justify-content: flex-end;\r\n}\r\n\r\n.agent-message {\r\n display: flex;\r\n justify-content: flex-start;\r\n}\r\n\r\n.user-message .message-content {\r\n background-color: #007bff;\r\n color: white;\r\n}\r\n\r\n.agent-message .message-content {\r\n background-color: #f1f1f1;\r\n}\r\n\r\n.message-time {\r\n font-size: 12px;\r\n color: #999;\r\n margin-top: 4px;\r\n display: block;\r\n}\r\n\r\n/* 发送按钮样式 */\r\n.send-button {\r\n width: 38px;\r\n height: 38px;\r\n border-radius: 16px;\r\n background: #0d75fb;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: background-color 0.2s ease;\r\n}\r\n\r\n.send-button img {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.send-button:hover {\r\n background: #0a62d6;\r\n}\r\n\r\n.send-button.disabled {\r\n background: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n.empty-state {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n color: #999;\r\n text-align: center;\r\n}\r\n\r\n.loading-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: center;\r\n align-items: center;\r\n background-color: rgba(255, 255, 255, 0.98);\r\n z-index: 1;\r\n opacity: 1;\r\n transition: opacity 0.3s ease;\r\n}\r\n\r\n.loading-container p {\r\n margin-top: 16px;\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 3px solid #f3f3f3;\r\n border-top: 3px solid #1890ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n/* 修改 messages-wrapper 的样式 */\r\n.messages-wrapper {\r\n width: 100%;\r\n min-height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n /* 当内容少时,将内容放在底部 */\r\n justify-content: flex-end;\r\n}\r\n\r\n/* 当有很多消息时,取消固定在底部 */\r\n.messages-wrapper.has-overflow {\r\n justify-content: flex-start;\r\n}\r\n\r\n.suggested-questions {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n padding: 16px;\r\n}\r\n\r\n.suggested-question {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background-color: #f3f4f6;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: #374151;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.suggested-question:hover {\r\n background-color: #e5e7eb;\r\n}\r\n\r\n.arrow-right {\r\n margin-left: 8px;\r\n}\r\n\r\n.loading-suggestions {\r\n display: flex;\r\n justify-content: center;\r\n padding: 16px;\r\n}\r\n\r\n.loading-spinner-small {\r\n width: 20px;\r\n height: 20px;\r\n border: 2px solid #e5e7eb;\r\n border-top-color: #6b7280;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n/* 添加上传按钮样式 */\r\n.upload-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #666;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.upload-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.upload-button svg {\r\n width: 20px;\r\n height: 20px;\r\n}\r\n\r\n/* 隐藏原生文件输入框 */\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n/* 添加文件名显示区域样式 */\r\n.selected-file {\r\n font-size: 12px;\r\n color: #666;\r\n margin-left: 8px;\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.input-wrapper {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n padding: 0 4px;\r\n background: white;\r\n}\r\n\r\n.input-wrapper input {\r\n border: none;\r\n flex: 1;\r\n padding: 8px;\r\n outline: none;\r\n}\r\n\r\n.input-wrapper:focus-within {\r\n border-color: #bbb;\r\n}\r\n\r\n/* 文件预览区域样式 */\r\n.file-preview {\r\n padding: 8px 16px;\r\n border-top: 1px solid #eee;\r\n background-color: #f9f9f9;\r\n}\r\n\r\n\r\n.recording-section {\r\n border-top: 1px solid #eee;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 10px 20px 0px 20px;\r\n border-radius: 14px 14px 0 0;\r\n flex: 0 0 auto;\r\n}\r\n\r\n.recording-section .video-preview {\r\n width: 100%;\r\n height: 200px;\r\n max-width: 400px;\r\n position: relative;\r\n margin-bottom: 10px;\r\n border: 1px solid #ddd;\r\n border-radius: 12px;\r\n overflow: hidden;\r\n}\r\n\r\n.recording-section video {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n/* 修改 recording-status 样式 */\r\n.recording-status {\r\n position: absolute;\r\n top: 10px;\r\n left: 10px;\r\n background-color: rgba(0, 0, 0, 0.6);\r\n color: white;\r\n padding: 4px 8px;\r\n border-radius: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 5px;\r\n font-size: 14px;\r\n z-index: 2;\r\n}\r\n\r\n.recording-status .recording-dot {\r\n display: inline-block;\r\n width: 10px;\r\n height: 10px;\r\n background-color: red;\r\n border-radius: 50%;\r\n margin-right: 5px;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n.recording-status.warning {\r\n color: #ff4d4f;\r\n animation: blink 1s infinite;\r\n}\r\n\r\n@keyframes blink {\r\n 0% {\r\n opacity: 1;\r\n }\r\n\r\n 50% {\r\n opacity: 0.5;\r\n }\r\n\r\n 100% {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n.recording-section .stop-recording-button {\r\n background-color: #f44336;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-weight: bold;\r\n}\r\n\r\n.recording-section .stop-recording-button:hover {\r\n background-color: #d32f2f;\r\n}\r\n\r\n.fullscreen {\r\n width: 100vw;\r\n border-radius: 0;\r\n height: 100vh;\r\n display: flex;\r\n flex-direction: column;\r\n overflow-y: auto;\r\n}\r\n\r\n.recording-controls {\r\n margin-top: 10px;\r\n height: 53px;\r\n width: 100%;\r\n max-width: 400px;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n\r\n.recording-controls .waiting-message {\r\n text-align: center;\r\n color: white;\r\n font-size: 16px;\r\n background-image: linear-gradient(100deg, #4A9FFF 0%, #1058FF 100%);\r\n border-radius: 6px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\r\n width: 95%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n cursor: pointer;\r\n}\r\n\r\n.recording-controls .waiting-message.loading {\r\n background: #faad14;\r\n}\r\n\r\n.recording-controls .waiting-message p {\r\n margin: 0;\r\n font-size: 16px;\r\n color: white;\r\n font-weight: 500;\r\n}\r\n\r\n.recording-controls .stop-recording-button {\r\n background-color: #dc3545;\r\n color: white;\r\n border: none;\r\n cursor: pointer;\r\n font-size: 16px;\r\n}\r\n\r\n.recording-controls .stop-recording-button:hover {\r\n background-color: #c82333;\r\n}\r\n\r\n/* 添加禁用状态的样式 */\r\n.recording-controls .stop-recording-button.disabled {\r\n background: #ccc;\r\n cursor: not-allowed;\r\n}\r\n\r\n.recording-controls .stop-recording-button.disabled:hover {\r\n background: #ccc;\r\n}\r\n\r\n/* 添加进度条和数字进度的样式 */\r\n.progress-container {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n width: 100%;\r\n max-width: 400px;\r\n margin-top: 10px;\r\n padding: 0 5px;\r\n}\r\n\r\n.progress-bar-container {\r\n height: 4px;\r\n background-color: #E5E5E5;\r\n border-radius: 2px;\r\n overflow: hidden;\r\n margin-right: 10px;\r\n width: 75px;\r\n}\r\n\r\n.progress-bar {\r\n height: 100%;\r\n background-image: linear-gradient(111deg, #4A9FFF 0%, #1058FF 100%);\r\n border-radius: 2px;\r\n transition: width 0.3s ease;\r\n}\r\n\r\n.progress-text {\r\n font-size: 14px;\r\n color: #666;\r\n white-space: nowrap;\r\n}\r\n\r\n/* 重新设计文本输入区域样式 */\r\n.text-input-area {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n padding: 0px 16px 16px 16px;\r\n border-radius: 8px;\r\n border: none; /* 确保容器本身没有边框 */\r\n}\r\n\r\n/* 修改文本输入框样式 */\r\n.text-answer-input {\r\n flex: 1;\r\n min-height: 80px;\r\n padding: 12px 12px 0px 12px;\r\n border: 1px solid #ddd;\r\n border-radius: 8px 8px 0 0;\r\n resize: none;\r\n font-size: 16px;\r\n background-color: #fff;\r\n border-bottom: none;\r\n outline: none; /* 移除默认的焦点轮廓 */\r\n}\r\n\r\n/* 修改工具栏样式 */\r\n.input-toolbar {\r\n display: flex;\r\n justify-content: end;\r\n align-items: center;\r\n padding: 8px 12px;\r\n background-color: #fff;\r\n border: 1px solid #ddd;\r\n border-top: none;\r\n border-radius: 0 0 8px 8px;\r\n}\r\n\r\n/* 当输入框获得焦点时,修改边框颜色 */\r\n.text-answer-input:focus {\r\n border-color: rgb(74, 144, 226);\r\n border-bottom: none;\r\n}\r\n\r\n.text-answer-input:focus+.input-toolbar {\r\n border-color: rgb(74, 144, 226);\r\n border-top: none;\r\n}\r\n\r\n/* 左侧工具按钮区域 */\r\n.toolbar-actions {\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n margin-right: 10px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n}\r\n\r\n.toolbar-actions:hover {\r\n background-color: #f0f0f0;\r\n}\r\n\r\n\r\n.toolbar-button {\r\n background: transparent;\r\n border: none;\r\n color: #666;\r\n cursor: pointer;\r\n padding: 0;\r\n margin: 0;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n/* 确保按钮内部的内容也居中 */\r\n.toolbar-button > div,\r\n.toolbar-button > svg {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.toolbar-button img {\r\n width: 16px;\r\n height: 16px;\r\n}\r\n\r\n/* 发送按钮样式 */\r\n.submit-text-button {\r\n padding: 6px 16px;\r\n background-color: #4a90e2;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.submit-text-button:hover:not(.disabled) {\r\n background-color: #3a7bc8;\r\n}\r\n\r\n.submit-text-button.disabled {\r\n background-color: #b3b3b3;\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n/* 语音输入按钮样式 */\r\n.toolbar-button.recording {\r\n background-color: rgba(255, 0, 0, 0.1);\r\n color: #ff3b30;\r\n animation: pulse 1.5s infinite;\r\n}\r\n\r\n.toolbar-button.converting {\r\n background-color: rgba(0, 122, 255, 0.1);\r\n color: #007aff;\r\n}\r\n\r\n.toolbar-button .recording-time {\r\n font-size: 12px;\r\n margin-left: 4px;\r\n}\r\n\r\n.converting-indicator {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.converting-indicator svg {\r\n animation: spin 1.5s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n 0% {\r\n transform: rotate(0deg);\r\n }\r\n 100% {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@keyframes pulse {\r\n 0% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.4);\r\n }\r\n 70% {\r\n box-shadow: 0 0 0 6px rgba(255, 0, 0, 0);\r\n }\r\n 100% {\r\n box-shadow: 0 0 0 0 rgba(255, 0, 0, 0);\r\n }\r\n}\r\n\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n\r\n\r\n}\r\n\r\n/* 修改引用文档样式 */\r\n.references-section {\r\n margin-top: 30px;\r\n padding: 12px;\r\n background-color: #f9f9f9;\r\n border-radius: 8px;\r\n border: 1px solid #e8e8e8;\r\n}\r\n\r\n.references-title {\r\n font-size: 14px;\r\n color: #666;\r\n margin: 0 0 8px 0;\r\n font-weight: 500;\r\n}\r\n\r\n.references-list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.reference-item {\r\n background-color: #fff;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 6px;\r\n padding: 10px;\r\n cursor: pointer;\r\n transition: background-color 0.2s, box-shadow 0.2s;\r\n}\r\n\r\n.reference-item:hover {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n.reference-header {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n position: relative;\r\n}\r\n\r\n.reference-icon {\r\n color: #1890ff;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.reference-name {\r\n font-size: 13px;\r\n font-weight: 500;\r\n color: #333;\r\n flex: 1;\r\n}\r\n\r\n.download-icon {\r\n color: #1890ff;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n/* 移除不再需要的引用内容样式 */\r\n.reference-content {\r\n display: none;\r\n}\r\n\r\n/* 推荐问题样式 */\r\n.suggested-questions {\r\n margin-top: 20px;\r\n padding: 12px;\r\n background-color: #f0f7ff;\r\n border-radius: 8px;\r\n border: 1px solid #d6e8ff;\r\n}\r\n\r\n.suggested-title {\r\n font-size: 14px;\r\n color: #1890ff;\r\n margin: 0 0 8px 0;\r\n font-weight: 500;\r\n}\r\n\r\n.suggested-question {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 12px;\r\n background-color: #fff;\r\n border: 1px solid #e6f7ff;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: #1890ff;\r\n transition: all 0.3s;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.suggested-question:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.suggested-question:hover {\r\n background-color: #e6f7ff;\r\n border-color: #91d5ff;\r\n}\r\n\r\n.arrow-right {\r\n color: #1890ff;\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.loading-suggestions {\r\n display: flex;\r\n justify-content: center;\r\n padding: 16px;\r\n}\r\n\r\n.loading-spinner-small {\r\n width: 20px;\r\n height: 20px;\r\n border: 2px solid #e6f7ff;\r\n border-top-color: #1890ff;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n}\r\n\r\n",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: calc(100% - 10px);\r\n}\r\n\r\n.modal-container {\r\n background-color: #fff;\r\n border-radius: 8px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n position: relative;\r\n margin: auto;\r\n transition: all 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n/* 全屏模式样式 - 改为基于父组件 */\r\n.modal-container.fullscreen {\r\n width: 100%;\r\n max-width: none;\r\n height: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n max-height: 100%;\r\n}\r\n\r\n/* PC端布局 */\r\n.pc-layout {\r\n width: 80%;\r\n max-width: 600px;\r\n min-width: 320px;\r\n}\r\n\r\n/* 响应式布局 */\r\n@media screen and (max-width: 768px) {\r\n .pc-layout {\r\n width: 95%;\r\n }\r\n\r\n .modal-overlay {\r\n padding: 10px 0px 0px 0px;\r\n }\r\n\r\n .modal-container.fullscreen {\r\n /* 移动端也基于父组件尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n max-height: 100%;\r\n border-radius: 16px 16px 0 0;\r\n /* 保留安全区域支持 */\r\n padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);\r\n }\r\n}\r\n\r\n/* 模态框头部样式 */\r\n.modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 4px 16px;\r\n height: 50px;\r\n border-bottom: 1px solid #e8e8e8;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.header-icon {\r\n width: 24px;\r\n height: 24px;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 4px;\r\n}\r\n\r\n.close-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.close-button span {\r\n font-size: 24px;\r\n line-height: 1;\r\n color: #999;\r\n}\r\n\r\n.close-button:hover span {\r\n color: #666;\r\n}\r\n\r\n\r\n/* 文件上传区域通用样式 */\r\n.upload-area {\r\n cursor: pointer;\r\n width: 100%;\r\n}\r\n\r\n\r\n.upload-placeholder {\r\n transition: all 0.3s ease;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n background: rgba(0, 0, 0, 0.02);\r\n border: 1px dashed #d9d9d9;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder:hover {\r\n border: 1px dashed #1890ff;\r\n}\r\n\r\n.upload-placeholder img {\r\n margin-top: 8px;\r\n width: 50px;\r\n height: 50px;\r\n}\r\n\r\n.upload-placeholder .upload-text {\r\n margin: 4px 0;\r\n color: #332F39;\r\n font-size: 14px;\r\n}\r\n\r\n.upload-placeholder .upload-hint {\r\n font-size: 14px;\r\n color: #949AA5;\r\n margin-top: 8px;\r\n padding: 0px 10px;\r\n text-align: center;\r\n white-space: normal;\r\n word-wrap: break-word;\r\n word-break: break-all;\r\n line-height: 1.4;\r\n}\r\n\r\n\r\n/* 文件项样式 */\r\n.file-item {\r\n position: relative;\r\n padding: 16px;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 8px;\r\n transition: border-color 0.3s;\r\n cursor: pointer;\r\n margin-bottom: 16px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.file-item:hover {\r\n border-color: #0D75FB;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.file-icon {\r\n color: #0D75FB;\r\n flex-shrink: 0;\r\n}\r\n\r\n.file-name {\r\n font-weight: 500;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n max-width: calc(100% - 50px);\r\n}\r\n\r\n.remove-file {\r\n background: transparent;\r\n border: none;\r\n color: #94a3b8;\r\n cursor: pointer;\r\n font-size: 18px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px;\r\n margin-left: 8px;\r\n border-radius: 4px;\r\n transition: all 0.2s;\r\n min-width: 30px;\r\n min-height: 30px;\r\n}\r\n\r\n.remove-file:hover {\r\n background-color: #f1f5f9;\r\n color: #475569;\r\n}\r\n\r\n.file-input {\r\n display: none;\r\n}\r\n\r\n\r\n\r\n/* 输入容器样式 */\r\n.input-container {\r\n padding: 20px;\r\n display: flex;\r\n flex-direction: column;\r\n height: calc(100% - 50px);\r\n background: linear-gradient(150deg, #2a6ee933, #0000 50%) 0 0 / 400px 200px no-repeat, #fff;\r\n /* 减去header高度 */\r\n overflow-y: auto;\r\n}\r\n\r\n.input-container h3 {\r\n margin-top: 0;\r\n margin-bottom: 20px;\r\n font-size: 18px;\r\n color: #333;\r\n text-align: center;\r\n}\r\n\r\n/* JD输入区域样式 */\r\n.jd-input-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.jd-input-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.job-description-textarea {\r\n width: calc(100% - 16px);\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n resize: vertical;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n padding: 8px;\r\n}\r\n\r\n.job-description-textarea:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 简历上传区域样式 */\r\n.resume-upload-section {\r\n margin-bottom: 20px;\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.resume-upload-section label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n/* 面试设置区域 */\r\n.interview-settings-section {\r\n margin-bottom: 24px;\r\n padding: 20px;\r\n background-color: #f8f9fa;\r\n border-radius: 8px;\r\n border: 1px solid #e9ecef;\r\n}\r\n\r\n.settings-row {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.settings-row:last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-label {\r\n display: block;\r\n font-weight: 500;\r\n color: #333;\r\n margin-bottom: 12px;\r\n font-size: 14px;\r\n}\r\n\r\n/* 题目数量滑块样式 */\r\n.question-number-section {\r\n width: 100%;\r\n}\r\n\r\n.slider-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.question-slider {\r\n flex: 1;\r\n height: 6px;\r\n background: #ddd;\r\n outline: none;\r\n border-radius: 3px;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n}\r\n\r\n.question-slider::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.question-slider::-moz-range-thumb {\r\n width: 20px;\r\n height: 20px;\r\n background: #0D75FB;\r\n cursor: pointer;\r\n border-radius: 50%;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\n.slider-value {\r\n font-weight: 600;\r\n color: #0D75FB;\r\n font-size: 14px;\r\n min-width: 30px;\r\n text-align: center;\r\n}\r\n\r\n/* 开关样式 */\r\n.analysis-toggle-section {\r\n width: 100%;\r\n}\r\n\r\n.toggle-container {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toggle-switch {\r\n position: relative;\r\n display: inline-block;\r\n width: 44px;\r\n height: 24px;\r\n}\r\n\r\n.toggle-switch input {\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n}\r\n\r\n.toggle-slider {\r\n position: absolute;\r\n cursor: pointer;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: #ccc;\r\n transition: 0.3s;\r\n border-radius: 24px;\r\n}\r\n\r\n.toggle-slider:before {\r\n position: absolute;\r\n content: \"\";\r\n height: 18px;\r\n width: 18px;\r\n left: 3px;\r\n bottom: 3px;\r\n background-color: white;\r\n transition: 0.3s;\r\n border-radius: 50%;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n\r\ninput:checked + .toggle-slider {\r\n background-color: #0D75FB;\r\n}\r\n\r\ninput:checked + .toggle-slider:before {\r\n transform: translateX(20px);\r\n}\r\n\r\n.toggle-text {\r\n font-size: 14px;\r\n color: #666;\r\n font-weight: 500;\r\n}\r\n\r\n/* 提交按钮通用样式 */\r\n.submit-button {\r\n margin-top: 10px;\r\n padding: 10px 30px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 16px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n width: 100%;\r\n max-width: 400px;\r\n align-self: center;\r\n}\r\n\r\n.submit-button:hover {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.submit-button:disabled {\r\n background-color: rgba(0,0,0,0.04);\r\n color: rgba(0,0,0,0.25);\r\n cursor: not-allowed;\r\n}\r\n\r\n\r\n\r\n/* AI免责声明和备案信息样式 */\r\n.ai-disclaimer {\r\n margin-top: 16px;\r\n text-align: center;\r\n font-size: 12px;\r\n color: #999;\r\n line-height: 1.5;\r\n}\r\n\r\n.ai-disclaimer p {\r\n margin: 4px 0;\r\n}\r\n\r\n.beian-info {\r\n display: flex;\r\n justify-content: center;\r\n flex-wrap: wrap;\r\n gap: 4px;\r\n}\r\n\r\n.ai-disclaimer a {\r\n color: #666;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n}\r\n\r\n.ai-disclaimer a:hover {\r\n color: #1890ff;\r\n text-decoration: underline;\r\n}\r\n\r\n/* 添加加载状态的样式 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n padding: 24px;\r\n }\r\n \r\n .loading-spinner {\r\n width: 40px;\r\n height: 40px;\r\n border: 4px solid rgba(0, 0, 0, 0.1);\r\n border-radius: 50%;\r\n border-top-color: var(--pcm-primary-color, #1890ff);\r\n animation: spin 1s linear infinite;\r\n margin-bottom: 16px;\r\n }\r\n \r\n .loading-text {\r\n font-size: 16px;\r\n color: var(--pcm-text-color, #333);\r\n }\r\n \r\n @keyframes spin {\r\n 0% { transform: rotate(0deg); }\r\n 100% { transform: rotate(360deg); }\r\n }\r\n \r\n ",".plan-type-section {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n margin-bottom: 20px;\r\n}\r\n\r\n.plan-type-section label {\r\n font-weight: 600;\r\n color: #333;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.plan-type-options {\r\n display: flex;\r\n gap: 15px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.plan-type-option {\r\n flex: 1;\r\n min-width: 120px;\r\n border: 1px solid #e8e8e8;\r\n border-radius: 8px;\r\n padding: 15px;\r\n cursor: pointer;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n transition: all 0.3s;\r\n}\r\n\r\n.plan-type-option:hover {\r\n border-color: #1890ff;\r\n background-color: #f0f7ff;\r\n}\r\n\r\n.plan-type-option.selected {\r\n border-color: #1890ff;\r\n background-color: #e6f7ff;\r\n box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.option-icon {\r\n font-size: 24px;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.option-label {\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: #333;\r\n}\r\n\r\n.resume-upload-section {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.resume-upload-section label {\r\n font-weight: 600;\r\n color: #333;\r\n margin-bottom: 8px;\r\n}\r\n\r\n\r\n\r\n",":host {\r\n /* 字体相关属性 */\r\n font-size: 16px;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\r\n font-weight: normal;\r\n font-style: normal;\r\n font-variant: normal;\r\n line-height: 1.5;\r\n letter-spacing: normal;\r\n word-spacing: normal;\r\n \r\n /* 文本相关属性 */\r\n color: #333; /* 重置文字颜色,避免继承外部的red */\r\n text-align: left;\r\n text-indent: 0;\r\n text-transform: none;\r\n white-space: normal;\r\n word-wrap: normal;\r\n word-break: normal;\r\n \r\n /* 可见性 */\r\n visibility: visible;\r\n \r\n /* 列表相关 */\r\n list-style: none;\r\n list-style-image: none;\r\n list-style-position: outside;\r\n list-style-type: disc;\r\n \r\n /* 表格相关 */\r\n border-collapse: separate;\r\n border-spacing: 0;\r\n caption-side: top;\r\n empty-cells: show;\r\n table-layout: auto;\r\n \r\n /* 引用 */\r\n quotes: auto;\r\n \r\n /* 光标 */\r\n cursor: auto;\r\n \r\n /* 文本方向 */\r\n direction: ltr;\r\n \r\n /* 打印相关 */\r\n orphans: 2;\r\n widows: 2;\r\n page-break-inside: auto;\r\n \r\n /* 其他可能被继承的属性 */\r\n text-decoration: none;\r\n text-shadow: none;\r\n \r\n /* 确保组件有独立的盒模型 */\r\n box-sizing: border-box;\r\n \r\n /* 重置一些可能影响布局的继承属性 */\r\n writing-mode: horizontal-tb;\r\n text-orientation: mixed;\r\n}","import { Component, Prop, h, State, Element, Event, EventEmitter, Watch } from '@stencil/core';\r\nimport { FileUploadResponse, verifyApiKey } from '../../utils/utils';\r\nimport { ConversationStartEventData, StreamCompleteEventData } from '../../components';\r\nimport { ErrorEventBus, ErrorEventDetail } from '../../utils/error-event';\r\nimport { authStore } from '../../../store/auth.store'; // 导入 authStore\r\nimport { configStore } from '../../../store/config.store';\r\nimport { Message } from '../../services/message.service';\r\n\r\n/**\r\n * 职业规划助手\r\n */\r\n\r\nexport type CareerPlanType = '长期规划' | '转行建议' | '晋升路径';\r\n\r\n@Component({\r\n tag: 'pcm-zygh-modal',\r\n styleUrls: ['../../global/global.css', 'pcm-zygh-modal.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ZyghModal {\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '职业规划助手';\r\n\r\n /**\r\n * SDK鉴权密钥\r\n */\r\n @Prop({ attribute: 'token' }) token!: 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 @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({ mutable: true }) conversationId?: string;\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\r\n /**\r\n * 自定义输入参数,传入customInputs.type则可以指定规划类型,可传入\"长期规划\"、\"转行建议\"、\"晋升路径\"<br>\r\n * 传入customInputs.file_url时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_url和customInputs.type时,会直接开始聊天。<br>\r\n */\r\n @Prop() customInputs: Record<string, string> = {};\r\n\r\n /**\r\n * 是否显示工作区历史会话按钮\r\n */\r\n @Prop() showWorkspaceHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历(仅PC端生效)\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n\r\n /**\r\n * 上传成功事件\r\n */\r\n @Event() uploadSuccess: EventEmitter<FileUploadResponse>;\r\n\r\n /**\r\n * 流式输出完成事件\r\n */\r\n @Event() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 新会话开始的回调,只会在一轮对话开始时触发一次\r\n */\r\n @Event() conversationStart: EventEmitter<ConversationStartEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() planningComplete: EventEmitter<{\r\n conversation_id: string;\r\n type: CareerPlanType;\r\n }>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'window';\r\n\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n @State() isSubmitting: boolean = false;\r\n @State() selectedPlanType: CareerPlanType = '长期规划';\r\n\r\n // 使用 @Element 装饰器获取组件的 host 元素\r\n @Element() hostElement: HTMLElement;\r\n\r\n private tokenInvalidListener: () => void;\r\n private removeErrorListener: () => void;\r\n private pcmUploadRef;\r\n\r\n @Watch('token')\r\n handleTokenChange(newToken: string) {\r\n // 当传入的 token 变化时,更新 authStore 中的 token\r\n if (newToken && newToken !== authStore.getToken()) {\r\n authStore.setToken(newToken);\r\n }\r\n }\r\n\r\n \r\n @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\r\n\r\n } else {\r\n if (this.customInputs && this.customInputs.type) {\r\n // 检查是否是有效的 CareerPlanType 值\r\n const type = this.customInputs.type;\r\n if (type === '长期规划' || type === '转行建议' || type === '晋升路径') {\r\n this.selectedPlanType = type;\r\n }\r\n }\r\n\r\n await verifyApiKey(this.token);\r\n\r\n // 如果有会话ID或者有file_url参数,直接显示聊天模态框\r\n if (this.conversationId || (this.customInputs?.file_url && this.customInputs?.type)) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n \r\n\r\n componentWillLoad() {\r\n\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener((errorDetail) => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handlePlanTypeChange = (type: CareerPlanType) => {\r\n this.selectedPlanType = type;\r\n };\r\n\r\n private handleStartPlanning = async () => {\r\n // 既没有预设 file_url,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.uploadedFileInfo) {\r\n Message.info('请上传简历');\r\n return;\r\n }\r\n // 判断文件是否正在上传\r\n if (await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n this.isSubmitting = false;\r\n };\r\n\r\n\r\n // 处理规划完成事件\r\n private handlePlanningComplete = (event: CustomEvent) => {\r\n this.planningComplete.emit({\r\n ...event.detail,\r\n type: this.selectedPlanType\r\n });\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 'pc-layout': true,\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 // 显示加载状态\r\n const isLoading = this.conversationId && !this.showChatModal;\r\n\r\n // 判断是否隐藏简历上传区域\r\n const hideResumeUpload = Boolean(this.customInputs && this.customInputs.file_url);\r\n\r\n // 判断是否同时提供了 file_url 和 type\r\n const hasFileAndType = Boolean(this.customInputs?.file_url && this.customInputs?.type);\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 <div>{this.modalTitle}</div>\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\r\n {/* 输入界面 - 仅在不显示聊天模态框且没有会话ID且没有预设file_url和type时显示 */}\r\n {!this.showChatModal && !this.conversationId && !hasFileAndType && (\r\n <div class=\"input-container\">\r\n\r\n {/* 规划类型选择 */}\r\n <div class=\"plan-type-section\">\r\n <label>选择规划类型</label>\r\n <div class=\"plan-type-options\">\r\n <div\r\n class={`plan-type-option ${this.selectedPlanType === '长期规划' ? 'selected' : ''}`}\r\n onClick={() => this.handlePlanTypeChange('长期规划')}\r\n >\r\n <div class=\"option-icon\">📈</div>\r\n <div class=\"option-label\">长期规划</div>\r\n </div>\r\n <div\r\n class={`plan-type-option ${this.selectedPlanType === '转行建议' ? 'selected' : ''}`}\r\n onClick={() => this.handlePlanTypeChange('转行建议')}\r\n >\r\n <div class=\"option-icon\">🔄</div>\r\n <div class=\"option-label\">转行建议</div>\r\n </div>\r\n <div\r\n class={`plan-type-option ${this.selectedPlanType === '晋升路径' ? 'selected' : ''}`}\r\n onClick={() => this.handlePlanTypeChange('晋升路径')}\r\n >\r\n <div class=\"option-icon\">🚀</div>\r\n <div class=\"option-label\">晋升路径</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* 简历上传区域 */}\r\n {!hideResumeUpload && (\r\n <div class=\"resume-upload-section\">\r\n <label>上传简历</label>\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\r\n mobileUploadAble={this.mobileUploadAble}\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['resume'],\r\n }}\r\n onUploadChange={(e) => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(!this.customInputs?.file_url && !this.uploadedFileInfo) || this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartPlanning}\r\n >\r\n {this.isUploading ? '上传中...' : this.isSubmitting ? '处理中...' : '开始规划'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">Hunan-PinCaiMao-202412310003</a>\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 加载状态 - 在有会话ID但聊天模态框尚未显示时展示 */}\r\n {isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">正在加载对话...</p>\r\n </div>\r\n )}\r\n\r\n {/* 聊天界面 - 在显示聊天模态框时显示 */}\r\n {this.showChatModal && (\r\n <div>\r\n <pcm-app-chat-modal\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isShowHeader}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId=\"3022316191018898\"\r\n fullscreen={this.fullscreen}\r\n conversationId={this.conversationId}\r\n defaultQuery={this.defaultQuery}\r\n filePreviewMode={this.filePreviewMode}\r\n customInputs={{\r\n ...this.customInputs,\r\n file_url: this.customInputs?.file_url || this.uploadedFileInfo?.cos_key,\r\n file_name: this.customInputs?.file_name || this.uploadedFileInfo?.file_name,\r\n type: this.selectedPlanType\r\n }}\r\n interviewMode=\"text\"\r\n onInterviewComplete={this.handlePlanningComplete}\r\n ></pcm-app-chat-modal>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n} "],"mappings":"4YAAA,MAAMA,EAAgC,iiKCAtC,MAAMC,EAAY,g/M,uxQCAlB,MAAMC,EAAkB,+iECAxB,MAAMD,EAAY,g/MCAlB,MAAME,EAAU,4wB,kqNCAhB,MAAMC,EAAkB,q0FCAxB,MAAMH,EAAY,g/MCAlB,MAAME,EAAU,4wB,MCsBHE,EAAY,M,iYAIbC,WAAqB,OAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,UAKvBC,iBAA2B,IAK3BC,YAAsB,GAKtBC,WAAsB,MAWtBC,aAAuC,GAKvCC,qBAAgC,MAKhCC,MAQAC,UAQAC,aAAuB,EAKvBC,mBAA8B,MAK9BC,uBAAkC,MAMjCC,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODC,cAAkC,OAKjCC,eAKDC,eAA0B,KAK1BC,oBAA+B,KAG9BC,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,MAGzBC,YAAsB,GACtBC,iBAA2B,GAC3BC,cAAyB,MACzBC,UAAoB,EACpBC,gBAA2B,MAG3BC,qBAAgC,M,iCAKhCC,eAAyB,GACzBC,aAAwB,MAEzBC,qBACAC,oBAGAC,oBAA6D,KAGrE,iBAAAC,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAM3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEX,GAAIC,KAAKR,oBAAqB,OACpBQ,KAAKR,oBAAoBS,mBAAmB,M,CAGtDD,KAAKE,Y,KACF,OACGC,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,eAAgB,CACrB4C,KAAKnB,cAAgB,I,GAOjC,iBAAAuB,GAEI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAI7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAI5BmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAI5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAGzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,CAGT,GAAIS,KAAKe,eAAgB,CACrBC,cAAchB,KAAKe,gBACnBf,KAAKe,eAAiB,I,EAOtB,UAAAb,GACJF,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,GACtBY,KAAKX,aAAe,MACpBW,KAAKtB,aAAe,KACpBsB,KAAKrB,YAAc,MACnBqB,KAAKpB,iBAAmB,KAExBoB,KAAKlB,YAAc,GACnBkB,KAAKjB,iBAAmB,GACxBiB,KAAKhB,cAAgB,MACrBgB,KAAKd,gBAAkB,MACvBc,KAAKf,UAAY,EACjB,GAAIe,KAAKe,eAAgB,CACrBC,cAAchB,KAAKe,gBACnBf,KAAKe,eAAiB,I,EAItBE,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnBW,2BAA8BC,IAClC,MAAMC,EAAWD,EAAME,OACvBrB,KAAKZ,eAAiBgC,EAASE,KAAK,EAGhCC,wBAA2BJ,IAC/B,MAAMK,EAAQL,EAAME,OACpBrB,KAAKlB,YAAc0C,EAAMF,KAAK,EAG1BG,6BAAgCN,IACpC,MAAMK,EAAQL,EAAME,OACpBrB,KAAKjB,iBAAmByC,EAAMF,KAAK,EAG/BP,eAAwC,KAExCW,eAAiB,KACrB1B,KAAKf,UAAY,GACjB,GAAIe,KAAKe,eAAgB,CACrBC,cAAchB,KAAKe,e,CAEvBf,KAAKe,eAAiBY,aAAY,KAC9B3B,KAAKf,YACL,GAAIe,KAAKf,WAAa,EAAG,CACrB,GAAIe,KAAKe,eAAgB,CACrBC,cAAchB,KAAKe,gBACnBf,KAAKe,eAAiB,I,KAG/B,IAAK,EAGJa,eAAiBC,UACrB,IAAK7B,KAAKlB,YAAYgD,OAAQ,CAC1BC,EAAQC,MAAM,UACd,M,CAIJ,MAAMC,EAAa,gBACnB,IAAKA,EAAWC,KAAKlC,KAAKlB,YAAYgD,QAAS,CAC3CC,EAAQC,MAAM,aACd,M,CAGJhC,KAAKhB,cAAgB,KACrB,IACI,MAAMmD,QAAeC,EAAYpC,KAAKlB,YAAYgD,OAAQ,GAC1D,GAAIK,EAAOE,QAAS,CAChBN,EAAQM,QAAQ,UAChBrC,KAAK0B,gB,KACF,CACHK,EAAQC,MAAMG,EAAOG,SAAW,U,EAEtC,MAAON,GACLD,EAAQC,MAAM,U,SAEdhC,KAAKhB,cAAgB,K,GAIrBuD,2BAA6B,KACjC,IAAKvC,KAAKrC,MAAO,CACboE,EAAQS,KAAK,oBACb,M,CAEJxC,KAAKb,qBAAuB,IAAI,EAG5BsD,4BAA8B,KAClCzC,KAAKb,qBAAuB,KAAK,EAG7BuD,uBAA0BvB,IAC9B,MAAMwB,EAAWxB,EAAMyB,OAEvB5C,KAAKZ,eAAiBuD,EAASE,gBAAkB,GACjD7C,KAAKb,qBAAuB,MAC5B4C,EAAQM,QAAQ,UAAU,EAGtBS,qBAAuBjB,UAE3B,IAAK7B,KAAKvC,cAAcsF,WAAa/C,KAAKZ,eAAe0C,OAAQ,CAC7DC,EAAQC,MAAM,WACd,M,CAIJ,GAAIhC,KAAKlB,YAAYgD,OAAQ,CAEzB,MAAMG,EAAa,gBACnB,IAAKA,EAAWC,KAAKlC,KAAKlB,YAAYgD,QAAS,CAC3CC,EAAQC,MAAM,aACd,M,CAIJ,IAAKhC,KAAKjB,iBAAiB+C,OAAQ,CAC/BC,EAAQC,MAAM,UACd,M,CAIJhC,KAAKd,gBAAkB,KACvB,IACI,MAAMiD,QAAea,EAAchD,KAAKlB,YAAYgD,OAAQ9B,KAAKjB,iBAAiB+C,OAAQ,GAC1F,IAAKK,EAAOE,QAAS,CACjBN,EAAQC,MAAMG,EAAOH,MAAMY,QAAU,SACrC5C,KAAKd,gBAAkB,MACvB,M,EAEN,MAAO8C,GACLD,EAAQC,MAAM,WACdhC,KAAKd,gBAAkB,MACvB,M,CAEJc,KAAKd,gBAAkB,K,CAI3B,SAAUc,KAAKiD,cAAcC,oBAAoB,CAC7CnB,EAAQS,KAAK,aACb,M,CAEJxC,KAAKX,aAAe,KACpBW,KAAKnB,cAAgB,IAAI,EAGrBoE,aAER,MAAAE,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAIxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM4E,EAAiBC,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAasF,UAGtE,MAAMY,EAAsBD,QAAQ1D,KAAKvC,eAAiBuC,KAAKvC,aAAamG,UAAY5D,KAAKvC,aAAaoG,iBAE1G,OACIC,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,gBAC1B0G,EAAK,OAAAC,MAAM,mBAEPD,EAAK,OAAAC,MAAM,oBACPD,EAAK,OAAAC,MAAM,qBACPD,EAAO,SAAAM,QAAQ,mBAAsC,iBACnDX,GACEK,EAAK,OAAAC,MAAM,gBACN/D,KAAKrC,OACFmG,EACI,UAAAC,MAAM,2BACNI,QAASnE,KAAKuC,2BACd8B,KAAK,UAAQ,QAKrBP,EACI,wBAAAQ,KAAK,OACLC,KAAOC,IACHxE,KAAKZ,eAAiBoF,EAAE5B,MAAM,MAMlDkB,EAAA,YACIW,GAAG,kBACHV,MAAM,2BACNW,YAAY,wBACZC,KAAM,EACNrD,MAAOtB,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC3CwF,QAAS5E,KAAKkB,2BACd2D,SAAUpB,KAKlBK,EAAK,OAAAC,MAAM,oBACPD,EAAuB,yBACvBA,EAAA,cACIgB,IAAKC,GAAM/E,KAAKiD,aAAe8B,EAC/BC,YAAa,GAAK,KAAO,KACzBC,SAAU,MACVC,iBAAkB,KAClBC,qBAAsB,CAAC,OAAQ,MAAO,OAAQ,QAAS,QACvDC,aAAc,CACVC,KAAM,CAAC,WAEXC,gBAAiBtF,KAAKvC,cAAcmG,SAAW,CAAC,CAC5C2B,QAASvF,KAAKvC,aAAamG,SAC3B4B,UAAWxF,KAAKvC,cAAc+H,WAAa,OAC3CC,UAAW,EACXC,IAAK,KACJC,UACLd,SAAUlB,EACViC,eAAiBpB,IACb,MAAMrC,EAA+BqC,EAAE5B,QAAU,GACjD5C,KAAKpB,iBAAmBuD,EAAO,GAC/BnC,KAAKhC,cAAcuC,KAAKP,KAAKpB,iBAAiB,KAM1DkF,EAAK,OAAAC,MAAM,oBACPD,EAAqC,uCACrCA,EAAA,SACIO,KAAK,MACLN,MAAM,cACNW,YAAY,SACZmB,UAAW,GACXvE,MAAOtB,KAAKlB,YACZ8F,QAAS5E,KAAKuB,2BAKrBvB,KAAKlB,YAAYgD,OAAOgE,SAAW,IAChChC,EAAK,OAAAC,MAAM,oBACPD,EAAkB,oBAClBA,EAAK,OAAAC,MAAM,+BACPD,EACI,SAAAO,KAAK,OACLN,MAAM,0BACNW,YAAY,SACZmB,UAAW,EACXvE,MAAOtB,KAAKjB,iBACZ6F,QAAS5E,KAAKyB,+BAElBqC,EAAA,UACIC,MAAM,mBACNc,SAAU7E,KAAKhB,eAAiBgB,KAAKf,UAAY,IAAMe,KAAKlB,YAAYgD,OACxEqC,QAASnE,KAAK4B,gBAEb5B,KAAKhB,cAAgB,SAAWgB,KAAKf,UAAY,EAAI,GAAGe,KAAKf,aAAe,WAM7F6E,EAAA,UACIC,MAAM,gBACNc,WAAY7E,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAAe0C,SAAW9B,KAAKrB,aAAeqB,KAAKX,cAAgBW,KAAKd,gBACxHiF,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKd,gBAAkB,SAAWc,KAAKX,aAAe,SAAW,QAGpGyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO5FxC,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACK9D,KAAKlC,oBAAsBkC,KAAKpC,UAC7BkG,EAAA,0BACIgB,IAAKC,GAAM/E,KAAKR,oBAAsBuF,EACtCjI,OAAQ,KACRU,WAAYwC,KAAKxC,WACjByI,MAAM,mBACNrI,UAAWoC,KAAKpC,UAChBC,aAAcmC,KAAKnC,aACnBT,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBE,YAAayC,KAAKzC,YAClBQ,uBAAwBiC,KAAKjC,uBAC7BN,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C8G,gBAAiBlG,KAAKvC,cAAcyI,iBAAmB,EACvDC,eAAe,IACfC,MAAOpG,KAAKlB,YAAYgD,QAAU6D,aAI1C7B,EACI,sBAAAhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACNrI,UAAWoC,KAAKpC,UAChBR,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBC,iBAAkB0C,KAAK1C,iBACvBC,YAAayC,KAAKzC,YAClBiB,eAAgBwB,KAAKxB,eACrBC,oBAAqBuB,KAAKvB,oBAC1BV,uBAAwBiC,KAAKjC,uBAC7BN,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C8G,gBAAiBlG,KAAKvC,cAAcyI,iBAAmB,EACvDE,MAAOpG,KAAKlB,YAAYgD,QAAU6D,WAEtCrH,cAAe0B,KAAK1B,kBAQvC0B,KAAKb,sBACF2E,EAAK,OAAAC,MAAM,mCACPD,EAAK,OAAAC,MAAM,2BACPD,EAAK,OAAAC,MAAM,kCACPD,EAAa,kBACbA,EAAQ,UAAAC,MAAM,8BAA8BI,QAASnE,KAAKyC,6BAA2B,MAIzFqB,EAAK,OAAAC,MAAM,gCACPD,EACI,gCAAAnG,MAAOqC,KAAKrC,MACZsH,SAAU,MACVoB,mBAAoBrG,KAAK0C,4B,2GC/qB7D,MAAM4D,EAA0B,GCAhC,MAAM/J,EAAY,g/MCAlB,MAAME,EAAU,4wB,MCqBH8J,EAAgB,M,iYAIjB3J,WAAqB,OAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,UAKvBC,iBAA2B,IAK3BC,YAAsB,GAKtBC,WAAsB,MAKtBC,aAAuC,GAKvCG,UAQAC,aAAuB,EAKvBC,mBAA8B,MAK9BC,uBAAkC,MAKjCC,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAKAE,eAEAG,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBO,eAAyB,GACzBC,aAAwB,MAEzBC,qBACAC,oBAGAC,oBAA6D,KAGrE,iBAAAC,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAM3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEX,GAAIC,KAAKR,oBAAqB,OACpBQ,KAAKR,oBAAoBS,mBAAmB,M,CAGtDD,KAAKE,Y,KACF,OACGC,EAAaH,KAAKnD,OACxBmD,KAAKnB,cAAgB,I,EAI7B,iBAAAuB,GAGI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAG7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAI5BmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAG5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAEzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAOL,UAAAW,GACJF,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,GACtBY,KAAKX,aAAe,MACpBW,KAAKtB,aAAe,KACpBsB,KAAKrB,YAAc,MACnBqB,KAAKpB,iBAAmB,I,CAGpBqC,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAO3B,MAAA4C,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,OACIiF,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,mBAO7BN,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACK9D,KAAKlC,mBACFgG,EAAA,0BACIgB,IAAKC,GAAM/E,KAAKR,oBAAsBuF,EACtCjI,OAAQ,KACRU,WAAYwC,KAAKxC,WACjByI,MAAM,mBACNrI,UAAWoC,KAAKpC,UAChBC,aAAcmC,KAAKnC,aACnBT,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBU,uBAAwBiC,KAAKjC,uBAC7BR,YAAayC,KAAKzC,YAClBE,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C+G,eAAgB,OAIxBrC,EACI,sBAAAhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjByI,MAAM,mBACNlI,uBAAwBiC,KAAKjC,uBAC7BX,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBC,iBAAkB0C,KAAK1C,iBACvBC,YAAayC,KAAKzC,YAClBE,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKpB,kBAAkB2G,QACjCC,UAAWxF,KAAKpB,kBAAkB4G,WAEtClH,cAAc,Y,2GC3UlD,MAAMkI,EAAqB,+xZCA3B,MAAMC,EAAc,ixzBCApB,MAAMhK,EAAU,4wB,+ymCCAhB,MAAMiK,EAAe,0lFCArB,MAAMjK,EAAU,4wB,MCWHkK,EAAS,M,yBAKZtC,KAA2D,UAM3DuC,KAAqC,SAKrCC,QAAmB,MAKnBhC,SAAoB,MAMpB7H,KAAe,yDAOf8J,MAAwC,UAKxCC,gBAA0B,GAK1BC,UAAoB,GAKpBC,YAAsB,GAKtBC,aAAuB,KAKvBC,MAAgB,GAKhBC,MAAiB,MAMjBC,YAAsD,QAE9D,MAAAlE,GAEE,MAAMmE,EAAU,CACd,aAAc,KACd,CAAC,cAActH,KAAKqE,QAAS,KAC7B,CAAC,cAAcrE,KAAK4G,QAAS,KAC7B,CAAC,cAAc5G,KAAK8G,SAAU,KAC9B,qBAAsB9G,KAAK6G,QAC3B,sBAAuB7G,KAAK6E,SAC5B,mBAAoB7E,KAAKoH,OAI3B,MAAMG,EAAc,GACpB,GAAIvH,KAAK+G,gBAAiB,CACxBQ,EAAY,mBAAqBvH,KAAK+G,e,CAExC,GAAI/G,KAAKgH,UAAW,CAClBO,EAAY,SAAWvH,KAAKgH,S,CAE9B,GAAIhH,KAAKiH,YAAa,CACpBM,EAAY,eAAiBvH,KAAKiH,W,CAEpC,GAAIjH,KAAKkH,eAAiB,KAAM,CAC9BK,EAAY,gBAAkB,GAAGvH,KAAKkH,gB,CAExC,GAAIlH,KAAKmH,MAAO,CACdI,EAAY,SAAWvH,KAAKmH,K,CAE9B,GAAInH,KAAKqH,YAAa,CACpBE,EAAY,eAAiBvH,KAAKqH,W,CAGpC,OACEvD,EACE,UAAA0D,IAAA,2CAAAzD,MAAO0D,OAAOC,KAAKJ,GAASK,QAAOH,GAAOF,EAAQE,KAAMI,KAAK,KAC7D5D,MAAOuD,EACP1C,SAAU7E,KAAK6E,SACfR,KAAK,UAEJrE,KAAK6G,SACJ/C,EAAA,QAAA0D,IAAA,2CAAMzD,MAAM,iBAEb/D,KAAKhD,OAASgD,KAAK6G,SAClB/C,EAAA,QAAA0D,IAAA,2CAAMzD,MAAM,eACVD,EAAK,OAAA0D,IAAA,2CAAAvD,IAAKjE,KAAKhD,KAAMkH,IAAI,MAG7BJ,EAAQ,QAAA0D,IAAA,6C,eCnIhB,MAAMK,EAAa,2mJCAnB,MAAMpL,EAAU,4wB,MCaHqL,EAAO,M,kEAIcjL,MAItBkL,UAAoB,GAKpBC,YAAsB,GAKtBC,QAAkB,GAMlBC,OAAiB,GAKjBC,gBAA0B,GAK1BC,YAAuB,MAKvBC,cAAwB,GAKxBC,cAAwB,OAKxBrC,MAAgB,GAKfsC,QAAe,KAKf1B,QAAmB,MAKnB7E,MAAgB,GAKhB5D,aAEDkB,qBAMR,iBAAAkJ,CAAkBzI,GACd,GAAIA,EAAU,CACVC,KAAKyI,c,EAKb,iBAAAhJ,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAO3B,iBAAAU,GACI,GAAIJ,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5B,GAAImD,KAAKiG,MAAO,CACZjG,KAAKyI,c,CAGRzI,KAAKV,qBAAuB,KACzBU,KAAK5B,aAAamC,MAAM,EAE5BI,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,qB,CAOnD,kBAAMmJ,GACV,IAAKzI,KAAKiG,MAAO,OAEjBjG,KAAK6G,QAAU,KACf7G,KAAKgC,MAAQ,GAEb,IACI,MAAM0G,QAAiBC,EAAgB,CACnCC,IAAK,iBAAiB5I,KAAKiG,aAC3B4C,OAAQ,QAGZ,GAAIH,EAASrG,SAAWqG,EAASI,KAAM,CACnC9I,KAAKuI,QAAUG,EAASI,I,KACrB,CACH,MAAM,IAAIC,MAAML,EAASpG,SAAW,Y,EAE1C,MAAO0G,GACLhJ,KAAKgC,MAAQgH,EAAI1G,SAAW,YAC5B2G,QAAQjH,MAAM,aAAcgH,E,SAE5BhJ,KAAK6G,QAAU,K,EAIvB,MAAA1D,GAEI,MAAM+F,EAAQlJ,KAAK+H,YAAc/H,KAAKuI,SAASW,OAAS,IACxD,MAAMC,EAAOnJ,KAAKgI,cAAgBhI,KAAKuI,SAASP,aAAe,IAE/D,MAAMoB,EAAcpJ,KAAKuI,SAASvL,MAAQgD,KAAKuI,SAASN,SAAWjI,KAAKuI,SAASc,MAAQ,GACzF,MAAMrM,EAAOgD,KAAKiI,SAAWmB,EAE7B,MAAME,EAAatJ,KAAKkI,SAAWlI,KAAKuI,SAASgB,aAAe,IAChE,MAAMC,EAAexJ,KAAKmI,kBAAoBnI,KAAKuI,SAASkB,eAAiB,IAC7E,MAAMC,EAAa1J,KAAKqI,gBAAkBrI,KAAKuI,SAASoB,MAAQ,IAChE,MAAMC,EAAa5J,KAAKuI,SAASsB,WAAa,EAC9C,MAAMC,EAAa9J,KAAKuI,SAASwB,cAAgB,EACjD,MAAMC,EAAahK,KAAKuI,SAAS0B,YAAc,EAE/ChB,QAAQiB,IAAI,QAAS,CACjBhB,QACAlM,OACAoM,cACAe,YAAanK,KAAKiI,QAClBM,QAASvI,KAAKuI,QACde,aACAE,iBAGJ,OACI1F,EACI,OAAA0D,IAAA,2CAAAzD,MAAM,kBAEL/D,KAAK6G,QACF/C,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,sBAEJ9D,KAAKgC,MACL8B,EAAK,OAAAC,MAAM,mBACPD,EAAK,OAAAC,MAAM,cAAoB,KAC/BD,EAAA,OAAKC,MAAM,iBAAiB/D,KAAKgC,QAGrC8B,EAAA,WACIA,EAAK,OAAAC,MAAM,eACN/G,GACG8G,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAG,IAAKjH,EAAMkH,IAAKgF,KAG7BpF,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAC,MAAM,iBACPD,EAAA,OAAKC,MAAM,cAAcmF,IAE5BlJ,KAAKoI,aAAesB,GAAc5F,EAAA,OAAKC,MAAM,YAAY2F,IAG7DJ,GACGxF,EAAK,OAAAC,MAAM,cACNyF,GACG1F,EAAK,OAAAC,MAAM,gBAAgBE,IAAKuF,EAActF,IAAKoF,IAEvDxF,EAAA,OAAKC,MAAM,eAAeuF,IAIjCH,GACGrF,EAAA,OAAKC,MAAM,oBAAoBoF,KAK3CrF,EAAK,OAAAC,MAAM,eACPD,EAAK,OAAAC,MAAM,mBACPD,EAAK,OAAAC,MAAM,aACPD,EAAM,QAAAC,MAAM,wBACZD,EAAA,OAAKC,MAAM,cAAc6F,IAE7B9F,EAAK,OAAAC,MAAM,aACPD,EAAM,QAAAC,MAAM,wBACZD,EAAA,OAAKC,MAAM,cAAc+F,IAE7BhG,EAAK,OAAAC,MAAM,aACPD,EAAM,QAAAC,MAAM,yBACZD,EAAA,OAAKC,MAAM,cAAciG,KAGjClG,EAAA,OAAKC,MAAM,cAAc/D,KAAKsI,eAAiB,U,qGChP3E,MAAM7B,GAAc,ixzBCApB,MAAM2D,GAAoB,q9NCA1B,MAAM3N,GAAU,4wB,grSCAhB,MAAM4N,GAAqB,s/FCA3B,MAAM5N,GAAU,4wB,MCYH6N,GAAe,M,gLAIcxN,OAAkB,MAKlDF,WAAqB,KAKrB2N,OAAiB,KAKjBC,WAAqB,KAKrBC,OAA2C,UAK3CC,aAAwB,KAKxBC,KAAgB,KAKhBC,SAAoB,KAKnBC,GAKAC,OAKAC,OAKAC,UAKAC,W,iCAIAhO,OAAiB,IAElBiO,uBAAiC,GACjCC,qBAMR,UAAMC,GACJpL,KAAKlD,OAAS,I,CAOhB,WAAMuO,GACJrL,KAAKlD,OAAS,K,CAIhB,cAAAwO,CAAevL,GACb,GAAIA,EAAU,CAEZC,KAAKkL,uBAAyBvK,SAAS4K,KAAKvH,MAAMwH,SAClD7K,SAAS4K,KAAKvH,MAAMwH,SAAW,SAG/B,MAAMC,EAAQzL,KAAK0L,YAAYC,WAAWC,cAAc,kBACxD,GAAIH,EAAO,CACTzL,KAAKmL,qBAAuB,KAC1BnL,KAAKgL,UAAUzK,MAAM,EAEvBkL,EAAM7K,iBAAiB,gBAAiBZ,KAAKmL,qBAAsB,CAAEU,KAAM,M,MAExE,CAELlL,SAAS4K,KAAKvH,MAAMwH,SAAWxL,KAAKkL,uBAGpC,MAAMO,EAAQzL,KAAK0L,YAAYC,WAAWC,cAAc,kBACxD,GAAIH,EAAO,CACTzL,KAAKmL,qBAAuB,KAC1BnL,KAAKiL,WAAW1K,MAAM,EAExBkL,EAAM7K,iBAAiB,gBAAiBZ,KAAKmL,qBAAsB,CAAEU,KAAM,M,GAKjF,iBAAAzL,GAEE,MAAM0L,EAAezL,EAAY0L,QAAgB,gBACjD,GAAID,EAAc,CAChB9L,KAAK/C,OAAS6O,EAAe,G,EAIjC,oBAAAjL,GAEE,GAAIb,KAAKlD,OAAQ,CACf6D,SAAS4K,KAAKvH,MAAMwH,SAAWxL,KAAKkL,sB,CAItC,MAAMO,EAAQzL,KAAK0L,YAAYC,YAAYC,cAAc,kBACzD,GAAIH,GAASzL,KAAKmL,qBAAsB,CACtCM,EAAM3K,oBAAoB,gBAAiBd,KAAKmL,qB,EAI5Ca,gBAAkB,KACxB,GAAIhM,KAAK0K,aAAc,CACrB1K,KAAKiM,c,GAIDC,SAAW,KACjBlM,KAAK6K,GAAGtK,MAAM,EAGR0L,aAAe,KACrBjM,KAAK8K,OAAOvK,OACZP,KAAKlD,OAAS,MACdkD,KAAK+K,OAAOxK,MAAM,EAGpB,MAAA4C,GACE,MAAMC,EAAa,CACjBnG,OAAQ,GAAG+C,KAAK/C,OAAS,KAG3B,MAAMkP,EAAY,CAChBlP,OAAQ,GAAG+C,KAAK/C,UAGlB,MAAMqG,EAAiB,CACrB,0BAA2B,KAC3B,aAActD,KAAKlD,QAGrB,MAAMsP,EAAe,CACnB,wBAAyB,KACzB,wBAAyBpM,KAAKlD,OAC9B8N,SAAY5K,KAAK4K,UAGnB,MAAMyB,EAAgB,CACpB,eAAgB,KAChB,YAAa,KACb,CAAC,MAAMrM,KAAKyK,UAAW,MAGzB,OACE3G,EAAA,OAAA0D,IAAA,2CAAKzD,MAAOT,GACTtD,KAAK2K,MACJ7G,EACE,OAAA0D,IAAA,2CAAAzD,MAAO,CAAE,qBAAsB,KAAM,eAAgB/D,KAAKlD,QAC1DkH,MAAOmI,EACPhI,QAASnE,KAAKgM,kBAGlBlI,EAAA,OAAA0D,IAAA,2CACEzD,MAAOqI,EACPpI,MAAOZ,GAEPU,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,iBACTD,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,gBACTD,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,eAAe/D,KAAKpD,aAGjCkH,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,cACTD,EAAA,QAAA0D,IAAA,8CAGF1D,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,gBACTD,EAAA,UAAA0D,IAAA,2CACEzD,MAAM,6BACNI,QAASnE,KAAKiM,cAEbjM,KAAKwK,YAER1G,EAAA,UAAA0D,IAAA,2CACEzD,MAAOsI,EACPlI,QAASnE,KAAKkM,UAEblM,KAAKuK,W,0ECnOtB,MAAM+B,GAAqB,k4BCA3B,MAAM7P,GAAU,4wB,4rICAhB,MAAM8P,GAAe,u4CCArB,MAAM9P,GAAU,4wB,MCYH+P,GAAS,M,8HAIoB1P,OAAkB,MAKlD2P,YAAsB,GAKtBtF,MAAgB,QAKhBuF,OAAiB,QAKjBC,SAAoB,KAKpBjC,aAAwB,KAMvBK,OAKAC,UAKAC,W,iCAIAhO,OAAiB,KAElBiO,uBAAiC,GACjCC,qBAMR,UAAMC,GACJpL,KAAKlD,OAAS,I,CAOhB,WAAMuO,GACJrL,KAAKlD,OAAS,K,CAIhB,cAAAwO,CAAevL,GACb,GAAIA,EAAU,CAEZC,KAAKkL,uBAAyBvK,SAAS4K,KAAKvH,MAAMwH,SAClD7K,SAAS4K,KAAKvH,MAAMwH,SAAW,SAG/B,MAAMoB,EAAS5M,KAAK0L,YAAYC,WAAWC,cAAc,mBACzD,GAAIgB,EAAQ,CACV5M,KAAKmL,qBAAuB,KAC1BnL,KAAKgL,UAAUzK,MAAM,EAEvBqM,EAAOhM,iBAAiB,gBAAiBZ,KAAKmL,qBAAsB,CAAEU,KAAM,M,MAEzE,CAELlL,SAAS4K,KAAKvH,MAAMwH,SAAWxL,KAAKkL,uBAGpC,MAAM0B,EAAS5M,KAAK0L,YAAYC,WAAWC,cAAc,mBACzD,GAAIgB,EAAQ,CACV5M,KAAKmL,qBAAuB,KAC1BnL,KAAKiL,WAAW1K,MAAM,EAExBqM,EAAOhM,iBAAiB,gBAAiBZ,KAAKmL,qBAAsB,CAAEU,KAAM,M,GAKlF,iBAAAzL,GAEE,MAAM0L,EAAezL,EAAY0L,QAAgB,gBACjD,GAAID,EAAc,CAChB9L,KAAK/C,OAAS6O,EAAe,G,EAIjC,oBAAAjL,GAEE,GAAIb,KAAKlD,OAAQ,CACf6D,SAAS4K,KAAKvH,MAAMwH,SAAWxL,KAAKkL,sB,CAItC,MAAM0B,EAAS5M,KAAK0L,YAAYC,YAAYC,cAAc,mBAC1D,GAAIgB,GAAU5M,KAAKmL,qBAAsB,CACvCyB,EAAO9L,oBAAoB,gBAAiBd,KAAKmL,qB,EAI7Ca,gBAAkB,KACxB,GAAIhM,KAAK0K,aAAc,CACrB1K,KAAKiB,a,GAIDA,YAAc,KACpBjB,KAAKlD,OAAS,MACdkD,KAAK+K,OAAOxK,MAAM,EAGpB,MAAA4C,GACE,MAAM0J,EAAc,CAClB1F,MAAOnH,KAAKmH,MACZlK,OAAQ,GAAG+C,KAAK/C,OAAS,KAG3B,MAAMkP,EAAY,CAChBlP,OAAQ,GAAG+C,KAAK/C,UAGlB,OACE6G,EAAA,OAAA0D,IAAA,2CAAKzD,MAAO,CAAE,mBAAoB,KAAM,cAAe/D,KAAKlD,SAC1DgH,EACE,OAAA0D,IAAA,2CAAAzD,MAAO,CAAE,cAAe,KAAM,eAAgB/D,KAAKlD,QACnDkH,MAAOmI,EACPhI,QAASnE,KAAKgM,kBAEhBlI,EAAA,OAAA0D,IAAA,2CACEzD,MAAO,CAAE,iBAAkB,KAAM,yBAA0B/D,KAAKlD,QAChEkH,MAAO6I,GAEP/I,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,iBACR/D,KAAKyM,aAAe3I,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,gBAAgB/D,KAAKyM,aACpDzM,KAAK2M,UACJ7I,EAAQ,UAAA0D,IAAA,2CAAAzD,MAAM,eAAeI,QAASnE,KAAKiB,aACzC6C,EAAc,QAAA0D,IAAA,mDAIpB1D,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,eACTD,EAAA,QAAA0D,IAAA,+C,0EC9KZ,MAAMsF,GAA2B,wrJCiBjC,MAAMC,GAAqB,CACzBC,KAAM,EACNpG,KAAM,IAGR,MAAMqG,GAA2E,CAC/E,EAAK,CAAEC,KAAM,MAAOC,MAAO,WAC3B,EAAK,CAAED,KAAM,MAAOC,MAAO,WAC3B,KAAM,CAAED,KAAM,KAAMC,MAAO,Y,MAQhBC,GAAqB,M,sDACxBnH,MACAoH,SACAjC,KAAgB,MACfN,OAEAjE,QAAmB,KACnByG,WAA6BP,GAC7BjE,KAAuB,GACvByE,YAAuB,MACvBC,YAAsB,GACtBC,YAAmC,UAG5C,SAAAC,CAAU3N,GACR,GAAIA,EAAU,CACZC,KAAK2N,UAAU3N,KAAKsN,W,EAIhB,eAAMK,CAAUC,GACtB5N,KAAK6G,QAAU,KACf,IAEE,MAAM6B,QAAiBC,EAAgB,CACrCC,IAAK,4BACLC,OAAQ,MACRgF,OAAQ,CACNb,KAAMY,EAAEZ,KACRpG,KAAMgH,EAAEhH,KACRkH,OAAQ9N,KAAKiG,MACb8H,UAAW/N,KAAKqN,YAGpB,GAAI3E,EAASrG,SAAWqG,EAASI,KAAM,CACrC,MAAMkF,EAAUtF,GAAUI,MAAMkF,SAAW,GAC3ChO,KAAK8I,KAAOkF,EACZhO,KAAKsN,WAAa,IACbM,EACHK,MAAOvF,GAAUI,MAAMmF,OAAS,E,EAGpC,MAAOjM,GACPiH,QAAQjH,MAAM,wBAAyBA,E,SAEvChC,KAAK6G,QAAU,K,EAIX,oBAAMqH,CAAeC,GAC3B,IACE,MAAMC,QAAoBC,EAAmBF,EAAO5I,SACpD,MAAM+I,EAAWH,EAAO3I,UACxB,GAAI4I,EAAa,CACb,MAAMG,EAAO5N,SAAS6N,cAAc,KACpCD,EAAKxI,KAAOqI,EACZG,EAAKE,aAAa,WAAYH,GAC9B3N,SAAS4K,KAAKmD,YAAYH,GAC1BA,EAAKI,QACLJ,EAAKK,SACL5O,KAAK6O,iBAAiB,OAAQ,U,KAC3B,CACH7O,KAAK6O,iBAAiB,WAAY,Q,EAGtC,MAAO7M,GACPhC,KAAK6O,iBAAiB,OAAQ,Q,EAI1B,kBAAMC,CAAaX,GACzB,IACE,MAAMzF,QAAiBC,EAAgB,CACrCC,IAAK,+BAA+BuF,EAAO1J,KAC3CoE,OAAQ,WAEV,GAAIH,GAAUrG,QAAS,CACrBrC,KAAK6O,iBAAiB,OAAQ,WAC9BE,YAAW,KACT/O,KAAK2N,UAAU3N,KAAKsN,WAAW,GAC9B,I,EAEL,MAAOtL,GACPhC,KAAK6O,iBAAiB,SAAS7M,EAAMM,UAAW,Q,EAI5C,gBAAAuM,CAAiB3B,EAAc7I,GACrCrE,KAAKwN,YAAcN,EACnBlN,KAAKyN,YAAcpJ,EACnBrE,KAAKuN,YAAc,KACnBwB,YAAW,KACT/O,KAAKuN,YAAc,KAAK,GACvB,I,CAGGyB,cAAgB,KACtBhP,KAAK2N,UAAU3N,KAAKsN,WAAW,EAGzB2B,iBAAmB,CAACjC,EAAcpG,KACxC,MAAMsI,EAAgB,IACjBlP,KAAKsN,WACRN,OACApG,QAEF5G,KAAK2N,UAAUuB,EAAc,EAGvB,UAAAC,CAAWC,GACjB,MAAMC,EAAO,IAAIC,KAAKF,GACtB,OAAOC,EAAKE,eAAe,QAAS,CAClCC,KAAM,UACNC,MAAO,UACPC,IAAK,UACLC,KAAM,UACNC,OAAQ,UACRC,OAAQ,W,CAIJ,WAAAC,GACN,OACEhM,EAAA,OAAKC,MAAM,mBACTD,EAAK,OAAAC,MAAM,cAAqB,MAChCD,EAAA,OAAKC,MAAM,cAAuB,Q,CAKhC,SAAAgM,CAAUC,GAChB,MAAMC,EAAahD,GAAwB+C,EAAOE,aAAe,CAAEhD,KAAM,KAAMC,MAAO,WACtF,OACErJ,EAAA,QAAMC,MAAM,MAAMC,MAAO,CAAE+C,gBAAiBkJ,EAAW9C,QACpD8C,EAAW/C,K,CAKV,YAAAiD,CAAajD,EAAc/I,EAAqBiM,EAA4C,UAAWxJ,EAA2B,UACxI,OACE9C,EACE,UAAAC,MAAO,WAAWqM,SAAexJ,IACjCzC,QAASA,GAER+I,E,CAKC,WAAAmD,GACN,GAAIrQ,KAAK6G,QAAS,CAChB,OACE/C,EAAA,OAAKC,MAAM,qBACTD,EAAK,OAAAC,MAAM,oBACXD,EAAiB,qB,CAKvB,IAAK9D,KAAK8I,MAAQ9I,KAAK8I,KAAKhD,SAAW,EAAG,CACxC,OAAO9F,KAAK8P,a,CAGd,OACEhM,EAAA,OAAKC,MAAM,mBACTD,EAAO,SAAAC,MAAM,SACXD,EAAA,aACEA,EAAA,UACEA,EAAI,MAAAE,MAAO,CAAEmD,MAAO,QAASmJ,UAAW,WAAoB,OAC5DxM,EAAI,MAAAE,MAAO,CAAEmD,MAAO,QAASmJ,UAAW,WAAmB,MAC3DxM,EAAI,MAAAE,MAAO,CAAEmD,MAAO,QAASmJ,UAAW,WAAqB,QAC7DxM,EAAA,MAAIE,MAAO,CAAEmD,MAAO,QAASmJ,UAAW,SAAQ,QAGpDxM,EAAA,aACG9D,KAAK8I,KAAKyH,KAAKpC,GACdrK,EAAA,MAAI0D,IAAK2G,EAAO1J,IACdX,EAAI,MAAAE,MAAO,CAAEsM,UAAW,WAAanC,EAAO3I,WAC5C1B,EAAA,MAAIE,MAAO,CAAEsM,UAAW,WACrBtQ,KAAK+P,UAAU5B,EAAO6B,SAEzBlM,EAAA,MAAIE,MAAO,CAAEsM,UAAW,WACrBtQ,KAAKmP,WAAWhB,EAAOqC,aAE1B1M,EAAA,MAAIE,MAAO,CAAEsM,UAAW,SACtBxM,EAAK,OAAAC,MAAM,kBACRoK,EAAO6B,SAAW,GAAKhQ,KAAKmQ,aAC3B,MACA,IAAMnQ,KAAK8O,aAAaX,IACxB,SACA,SAEDA,EAAO5I,SAAWvF,KAAKmQ,aACtB,MACA,IAAMnQ,KAAKkO,eAAeC,IAC1B,UACA,gB,CAYZ,gBAAAsC,GACN,IAAKzQ,KAAKsN,WAAWW,OAASjO,KAAKsN,WAAWW,QAAU,EAAG,CACzD,OAAO,I,CAGT,MAAMyC,EAAaC,KAAKC,KAAK5Q,KAAKsN,WAAWW,MAAQjO,KAAKsN,WAAW1G,MACrE,MAAMiK,EAAc7Q,KAAKsN,WAAWN,KAEpC,OACElJ,EAAA,OAAKC,MAAM,wBACTD,EAAK,OAAAC,MAAM,mBAAiB,IACxB/D,KAAKsN,WAAWW,MACd,KACNnK,EAAK,OAAAC,MAAM,uBACTD,EAAA,UACEC,MAAM,iBACNc,SAAUgM,GAAe,EACzB1M,QAAS,IAAMnE,KAAKiP,iBAAiB4B,EAAc,EAAG7Q,KAAKsN,WAAW1G,OAG/D,OACT9C,EAAM,QAAAC,MAAM,sBACT8M,EAAW,MAAKH,GAEnB5M,EAAA,UACEC,MAAM,iBACNc,SAAUgM,GAAeH,EACzBvM,QAAS,IAAMnE,KAAKiP,iBAAiB4B,EAAc,EAAG7Q,KAAKsN,WAAW1G,OAG/D,OACT9C,EACE,UAAAC,MAAM,yBACN+M,SAAWtM,GAAMxE,KAAKiP,iBAAiB,EAAG8B,SAAUvM,EAAEnD,OAA6BC,SAEnFwC,EAAA,UAAQxC,MAAM,KAAK0P,SAAUhR,KAAKsN,WAAW1G,OAAS,IAAkB,SACxE9C,EAAA,UAAQxC,MAAM,KAAK0P,SAAUhR,KAAKsN,WAAW1G,OAAS,IAAkB,SACxE9C,EAAA,UAAQxC,MAAM,KAAK0P,SAAUhR,KAAKsN,WAAW1G,OAAS,IAAE,W,CAO1D,aAAAqK,GACN,IAAKjR,KAAKuN,YAAa,OAAO,KAE9B,OACEzJ,EAAA,OAAKC,MAAO,mBAAmB/D,KAAKyN,eACjCzN,KAAKwN,Y,CAKZ,MAAArK,GACE,IAAKnD,KAAKoL,KAAM,CACd,OAAO,I,CAGT,OACEtH,EAAK,OAAAC,MAAM,gBAAgBI,QAAS,IAAMnE,KAAK8K,OAAOvK,QACpDuD,EAAA,OAAKC,MAAM,kBAAkBI,QAAUK,GAAMA,EAAE0M,mBAC7CpN,EAAK,OAAAC,MAAM,gBACTD,EAAK,OAAAC,MAAM,eACTD,EAAmB,sBAClB9D,KAAKmQ,aACJ,QACAnQ,KAAKgP,cACL,UACA,UAGJlL,EAAA,UAAQC,MAAM,cAAcI,QAAS,IAAMnE,KAAK8K,OAAOvK,QAAM,MAI/DuD,EAAK,OAAAC,MAAM,cACR/D,KAAKqQ,cACLrQ,KAAKyQ,oBAEPzQ,KAAKiR,iB,gEClUhB,MAAME,GAAkB,ioCCAxB,MAAM5U,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBH2U,GAAS,M,oVAIVxU,WAAqB,SAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAKtBC,aAAuC,GAKvCC,qBAAgC,MAKhCwH,iBAA4B,MAK5BmM,gBAA2B,MAK1BrT,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtC3S,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBQ,aAAwB,MAGxBkS,UAA+B,SAG/BC,cAAwB,GAGzBlS,qBACAC,oBACA0D,aAGR,iBAAAxD,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAI3B,iBAAAU,GAGI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAI5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAGzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAIL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAMnBkR,kBAAoB,KACxBzR,KAAKuR,UAAYvR,KAAKuR,YAAc,SAAW,OAAS,QAAQ,EAI5DG,sBAAyBvQ,IAC7B,MAAMC,EAAWD,EAAME,OACvBrB,KAAKwR,cAAgBpQ,EAASE,KAAK,EAG/BwB,qBAAuBjB,UAC3B,GAAI7B,KAAKuR,YAAc,WAAavR,KAAKpB,iBAAkB,CACvDmD,EAAQS,KAAK,WACb,M,CAGJ,GAAIxC,KAAKuR,YAAc,SAAWvR,KAAKwR,cAAc1P,OAAQ,CACzDC,EAAQS,KAAK,WACb,M,CAIJ,GAAIxC,KAAKuR,YAAc,gBAAkBvR,KAAKiD,cAAcC,oBAAoB,CAC5EnB,EAAQS,KAAK,aACb,M,CAGJxC,KAAKX,aAAe,KACpBW,KAAKnB,cAAgB,KACrBmB,KAAKX,aAAe,KAAK,EAI7B,wBAAMS,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKnB,cAAgB,MACrBmB,KAAKwR,cAAgB,GACrBxR,KAAKuR,UAAY,Q,KACd,CACH,GAAIvR,KAAKvC,cAAgBuC,KAAKvC,aAAa+D,MAAO,CAE9CxB,KAAKuR,UAAY,OACjBvR,KAAKwR,cAAgBxR,KAAKvC,aAAa+D,K,OAErCrB,EAAaH,KAAKnD,OAExB,GAAImD,KAAK5C,eAAgB,CAErB4C,KAAKnB,cAAgB,I,GAMjC,MAAAsE,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAE/C,OACIiF,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,gBAC1B0G,EAAK,OAAAC,MAAM,mBAEPD,EAAK,OAAAC,MAAM,qBACPD,EAAiB,oBACjBA,EACI,UAAAC,MAAM,gBACNI,QAASnE,KAAKyR,mBAEd3N,EAAA,OAAK6N,QAAQ,YAAYxK,MAAM,KAAKuF,OAAO,KAAKkF,KAAK,OAAOC,OAAO,gBAC/D/N,EAAqB,iCAAwB,0BAAqB,mBAAIgO,EAAE,6BACtE,SAMb9R,KAAKuR,YAAc,UAChBzN,EAAA,OAAKC,MAAM,yBACPD,EACI,cAAAgB,IAAKC,GAAM/E,KAAKiD,aAAe8B,EAC/BC,YAAa,GAAK,KAAO,KACzBC,SAAU,MACVC,iBAAkBlF,KAAKkF,iBACvB6M,WAAW,SACX5M,qBAAsB,CAAC,OAAQ,MAAO,OAAQ,QAAS,QACvDC,aAAc,CACVC,KAAM,CAAC,UAEXO,eAAiBpB,IACb,MAAMrC,EAA+BqC,EAAE5B,QAAU,GACjD5C,KAAKpB,iBAAmBuD,EAAO,GAC/BnC,KAAKhC,cAAcuC,KAAKP,KAAKpB,iBAAiB,KAO7DoB,KAAKuR,YAAc,QAChBzN,EAAA,OAAKC,MAAM,gBAED/D,KAAKqR,iBACHvN,EACI,wBAAAQ,KAAK,OACLC,KAAOC,IACHxE,KAAKwR,cAAgBhN,EAAE5B,MAAM,IAK7CkB,EAAK,OAAAC,MAAM,sBACPD,EACI,YAAAW,GAAG,kBACHC,YAAY,UACZC,KAAM,EACNrD,MAAOtB,KAAKwR,cACZ5M,QAAS5E,KAAK0R,yBAItB5N,EAAK,OAAAC,MAAM,eACPD,EAAK,OAAAC,MAAM,eAAyB,SACpCD,EAAK,OAAAC,MAAM,iBACPD,EAAyB,6BACzBA,EAA8B,kCAC9BA,EAA2B,+BAC3BA,EAA2B,+BAC3BA,EAA2B,+BAC3BA,EAA0B,iCAM1CA,EAAA,UACIC,MAAM,gBACNc,SAAW7E,KAAKuR,YAAc,WAAavR,KAAKpB,kBAC3CoB,KAAKuR,YAAc,SAAWvR,KAAKwR,cAAc1P,QAClD9B,KAAKrB,aACLqB,KAAKX,aACT8E,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO3FxC,GACEM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACN7I,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKuR,YAAc,SAAWvR,KAAKpB,kBAAkB2G,QAAUI,UACzEH,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEhE,MAAOxB,KAAKuR,YAAc,OAASvR,KAAKwR,cAAgB7L,WAE5DrH,cAAc,W,+GCja9C,MAAM0T,GAAkB,GCAxB,MAAMzV,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBHwV,GAAS,M,oVAIVrV,WAAqB,SAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAMtBC,aAAuC,GAKvCC,qBAAgC,MAK/BM,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtC5S,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBQ,aAAwB,MAGzBC,qBACAC,oBAGR,iBAAAE,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAK3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKkS,oBACLlS,KAAKnB,cAAgB,K,KAClB,OACGsB,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,gBAAkB4C,KAAKvC,cAAcmG,SAAU,CACpD5D,KAAKnB,cAAgB,I,GAMjC,iBAAAuB,GAGI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAI5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAGzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAGvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAKL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnB4R,iBAAoBhR,IACxB,MAAMK,EAAQL,EAAME,OACpB,GAAIG,EAAM4Q,OAAS5Q,EAAM4Q,MAAMtM,OAAS,EAAG,CACvC9F,KAAKtB,aAAe8C,EAAM4Q,MAAM,E,GAIhCC,kBAAoB,KACxB,MAAMC,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D0G,GAAW3D,OAAO,EAGduD,kBAAoB,KACxBlS,KAAKtB,aAAe,KACpBsB,KAAKpB,iBAAmB,KACxB,MAAM0T,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D,GAAI0G,EAAW,CACXA,EAAUhR,MAAQ,E,GAIlB,gBAAMiR,GACV,IAAKvS,KAAKtB,aAAc,OAExBsB,KAAKrB,YAAc,KAEnB,IAEI,MAAMwD,QAAeqQ,EAAoBxS,KAAKtB,aAAc,GACzD,CACC2G,KAAQ,CAAC,WAGbrF,KAAKpB,iBAAmBuD,EACxBnC,KAAKhC,cAAcuC,KAAK4B,E,CAC1B,MAAOH,GACLiH,QAAQjH,MAAM,UAAWA,GACzBhC,KAAKkS,oBACLO,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,aACRC,UAAW,iBACX1J,MAAO,WAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,c,SAGbtC,KAAKrB,YAAc,K,EAInBmE,qBAAuBjB,UAC3B,IAAK7B,KAAKtB,aAAc,CACpBoU,MAAM,WACN,M,CAGJ9S,KAAKX,aAAe,KAEpB,IAEI,IAAKW,KAAKpB,iBAAkB,OAClBoB,KAAKuS,aACX,IAAKvS,KAAKpB,iBAAkB,CACxBoB,KAAKX,aAAe,MACpB,M,EAKRW,KAAKnB,cAAgB,I,CACvB,MAAOmD,GACLiH,QAAQjH,MAAM,WAAYA,GAC1ByQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,uBACRC,UAAW,iBACX1J,MAAO,YAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,e,SAGbtC,KAAKX,aAAe,K,GAK5B,MAAA8D,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAIxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAIhC,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAMkU,EAAiBrP,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAamG,UAErE,OACIE,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmB2V,GAC7CjP,EAAK,OAAAC,MAAM,mBAEPD,EAAK,OAAAC,MAAM,yBACPD,EAAqB,uBACrBA,EAAK,OAAAC,MAAM,cAAcI,QAASnE,KAAKqS,mBAClCrS,KAAKtB,aACFoF,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAC,MAAM,qBACPD,EAAM,QAAAC,MAAM,aAAqB,MACjCD,EAAM,QAAAC,MAAM,aAAa/D,KAAKtB,aAAa4F,OAE/CR,EAAQ,UAAAC,MAAM,cAAcI,QAAUK,IAClCA,EAAE0M,kBACFlR,KAAKkS,mBAAmB,GAC3B,MAGLpO,EAAA,OAAKC,MAAM,sBACPD,EAAK,OAAAG,IAAI,kEACTH,EAAG,KAAAC,MAAM,eAA0B,YACnCD,EAAA,KAAGC,MAAM,eAAa,yCAMtCD,EACI,UAAAC,MAAM,gBACNc,UAAW7E,KAAKtB,cAAgBsB,KAAKrB,aAAeqB,KAAKX,aACzD8E,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,kCAIrFlC,EAAA,SACIO,KAAK,OACLN,MAAM,aACN+M,SAAU9Q,KAAKmS,oBAMzB3O,GACEM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACN7I,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,WAEtElH,cAAc,W,+GC1Z9C,MAAM0U,GAAgB,ooHCAtB,MAAMzW,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBHwW,GAAU,M,ySAIXrW,WAAqB,OAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,YAKvBG,WAAsB,MAKtBC,aAAuC,GAKvCC,qBAAgC,MAKhCwV,iBAA4B,MAK5BC,iBAA2B,OAK1BlV,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtCzS,cAAyB,M,iCAMzB0S,UAAmC,aAGnC6B,KAA2B,QAG3BC,QAAkB,GAGlB7B,cAAwB,GAGxBhO,UAAqB,MAGrBnE,aAAwB,MAGxBiU,UAAwF,GAGxFC,kBAAiE,GAGjEC,eAA8C,GAG9CC,aAIL,CACIC,OAAQ,GACRC,SAAU,GACVC,UAAW,IAIXtU,qBACAC,oBAGR,iBAAAE,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAK3B,iBAAAU,GAEI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAI5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAEzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAGvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAMLsU,aAAe,CACnB,CAAE3G,KAAM,QAAS5L,MAAO,SACxB,CAAE4L,KAAM,QAAS5L,MAAO,SACxB,CAAE4L,KAAM,SAAU5L,MAAO,UACzB,CAAE4L,KAAM,UAAW5L,MAAO,WAC1B,CAAE4L,KAAM,UAAW5L,MAAO,WAC1B,CAAE4L,KAAM,QAAS5L,MAAO,cAIpBqS,SAAW,CACf,CAAEzG,KAAM,OAAQ5L,MAAO,QACvB,CAAE4L,KAAM,MAAO5L,MAAO,OACtB,CAAE4L,KAAM,OAAQ5L,MAAO,QACvB,CAAE4L,KAAM,OAAQ5L,MAAO,QACvB,CAAE4L,KAAM,KAAM5L,MAAO,MACrB,CAAE4L,KAAM,OAAQ5L,MAAO,QACvB,CAAE4L,KAAM,OAAQ5L,MAAO,QACvB,CAAE4L,KAAM,OAAQ5L,MAAO,SAInBwS,sBAAwB,CAC5B,CAAE5G,KAAM,KAAM5L,MAAO,MACrB,CAAE4L,KAAM,KAAM5L,MAAO,MACrB,CAAE4L,KAAM,KAAM5L,MAAO,MACrB,CAAE4L,KAAM,KAAM5L,MAAO,MACrB,CAAE4L,KAAM,OAAQ5L,MAAO,SAGnBL,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnBkR,kBAAoB,KACxBzR,KAAKuR,UAAYvR,KAAKuR,YAAc,aAAe,OAAS,YAAY,EAGpEwC,oBAAuB5S,IAC3B,MAAMK,EAAQL,EAAME,OACpBrB,KAAKqT,QAAU7R,EAAMF,KAAK,EAGtBoQ,sBAAyBvQ,IAC7B,MAAMC,EAAWD,EAAME,OACvBrB,KAAKwR,cAAgBpQ,EAASE,KAAK,EAG/B0S,eAAiBnS,UACrB,IAAK7B,KAAKqT,QAAQvR,OAAQ,CACtBgR,MAAM,WACN,M,CAGJ9S,KAAKoT,KAAO,eACNpT,KAAKiU,uBAAuBjU,KAAKqT,QAAQ,EAG3Ca,eAAiB,KACrBlU,KAAKoT,KAAO,OAAO,EAGf,4BAAMa,CAAuBZ,GACjC,IAAKA,EAAQvR,OAAQ,OAErB9B,KAAKwD,UAAY,KAEjB,IACI,MAAMkF,QAAiBC,EAAgB,CACnCC,IAAK,kCACLC,OAAQ,OACRC,KAAM,CACFqL,OAAQ,CACJC,WAAYf,GAGhBvF,OAAQ,oBACRuG,cAAe,sBAIvB,GAAI3L,EAASrG,SAAWqG,EAASI,MAAMA,KAAKwL,SAASpH,KAAM,CACvD,IAEI,IAAIqH,EAAW7L,EAASI,KAAKA,KAAKwL,QAAQpH,KAAKpL,OAC/C,MAAM0S,EAAoBD,EAASE,MAAM,8BACzC,GAAID,EAAmB,CACnBD,EAAWC,EAAkB,GAAG1S,M,CAEpC,MAAM4S,EAAeC,KAAKC,MAAML,GAChCvU,KAAKsT,UAAYoB,EAAaG,UAAY,GAG1C,MAAMC,EAAmD,GAGzD,MAAMC,GAAYL,EAAaG,UAAY,IAAItE,KAAIyE,IAE/C,MAAMC,EAAU,IAAKD,EAAME,aAAe,MAASF,EAAMG,cAAgB,IAGzE,IAAK,IAAIC,EAAIH,EAAQnP,OAAS,EAAGsP,EAAI,EAAGA,IAAK,CACzC,MAAMC,EAAI1E,KAAK2E,MAAM3E,KAAK4E,UAAYH,EAAI,KACzCH,EAAQG,GAAIH,EAAQI,IAAM,CAACJ,EAAQI,GAAIJ,EAAQG,G,CAIpD,GAAIJ,EAAME,aAAeF,EAAME,YAAYpP,OAAS,EAAG,CACnDgP,EAAoBE,EAAMQ,eAAiB,IAAIR,EAAME,Y,CAGzD,MAAO,CACHM,cAAeR,EAAMQ,cACrBnQ,KAAM4P,EACT,IAGLjV,KAAKuT,kBAAoBwB,EACzB/U,KAAKwT,eAAiBsB,C,CACxB,MAAO9S,GACLyQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,yBACRC,UAAW,eACX1J,MAAO,cAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,a,GAIvB,MAAON,GACLiH,QAAQjH,MAAM,WAAYA,E,SAE1BhC,KAAKwD,UAAY,K,EAIjBiS,eAAiB,CAACC,EAA+CpU,KACrE,GAAIoU,IAAa,WAAY,CACzB,MAAMC,EAAc,IAAI3V,KAAKyT,aAAaE,UAC1C,MAAMiC,EAAUD,EAAYE,SAASvU,GAC/BqU,EAAYhO,QAAOmO,GAAKA,IAAMxU,IAC9B,IAAIqU,EAAarU,GAEvBtB,KAAKyT,aAAe,IACbzT,KAAKyT,aACRE,SAAUiC,E,KAEX,CACH5V,KAAKyT,aAAe,IACbzT,KAAKyT,aACRiC,CAACA,GAAW1V,KAAKyT,aAAaiC,KAAcpU,EAAQ,GAAKA,E,GAK7DyU,iBAAmB,CAACP,EAAuBQ,KAC/C,MAAML,EAAc3V,KAAKwT,eAAegC,IAAkB,GAC1D,MAAMI,EAAUD,EAAYE,SAASG,GAC/BL,EAAYhO,QAAOmO,GAAKA,IAAME,IAC9B,IAAIL,EAAaK,GAEvBhW,KAAKwT,eAAiB,IACfxT,KAAKwT,eACRgC,CAACA,GAAgBI,EACpB,EAGGK,uBAAyBpU,UAC7B7B,KAAKX,aAAe,KAEpB,IAEI,IAAI6W,EAAc,GAClB,GAAIlW,KAAKyT,aAAaC,OAAQ,CAC1B,MAAMyC,EAAQnW,KAAK6T,aAAauC,MAAKC,GAAKA,EAAE/U,QAAUtB,KAAKyT,aAAaC,SACxE,GAAIyC,EAAO,CACPD,EAAcC,EAAMjJ,I,EAK5B,MAAMoJ,EAAmBtW,KAAKyT,aAAaE,SAAS/L,KAAK,KAGzD,IAAIgM,EAAY,GAChB,GAAI5T,KAAKyT,aAAaG,UAAW,CAC7B,MAAM2C,EAAMvW,KAAK8T,sBAAsBsC,MAAK5R,GAAKA,EAAElD,QAAUtB,KAAKyT,aAAaG,YAC/E,GAAI2C,EAAK,CACL3C,EAAY2C,EAAIrJ,I,EAKxB,IAAIsJ,EAAU,QAAQxW,KAAKqT,YAE3B,GAAI6C,EAAa,CACbM,GAAW,QAAQN,K,CAGvB,GAAII,EAAkB,CAClBE,GAAW,QAAQF,K,CAGvB,GAAI1C,EAAW,CACX4C,GAAW,QAAQ5C,K,CAIvBnM,OAAOgP,QAAQzW,KAAKwT,gBAAgBkD,SAAQ,EAAEC,EAAWtR,MACrD,GAAIA,EAAKS,OAAS,EAAG,CACjB0Q,GAAW,GAAGG,KAAatR,EAAKuC,KAAK,Q,KAK7C5H,KAAKnB,cAAgB,KACrBmB,KAAKZ,eAAiBoX,C,CACxB,MAAOxU,GACLiH,QAAQjH,MAAM,cAAeA,GAC7ByQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,yBACRC,UAAW,eACX1J,MAAO,YAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,e,SAGbtC,KAAKX,aAAe,K,GAIpBuX,iBAAmB/U,UACvB,IAAK7B,KAAKwR,cAAc1P,OAAQ,CAC5BgR,MAAM,aACN,M,CAGJ9S,KAAKX,aAAe,KAEpB,IAEIW,KAAKZ,eAAiBY,KAAKwR,cAG3BxR,KAAKnB,cAAgB,I,CACvB,MAAOmD,GACLiH,QAAQjH,MAAM,eAAgBA,GAC9ByQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,mBACRC,UAAW,eACX1J,MAAO,YAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,e,SAGbtC,KAAKX,aAAe,K,GAInBD,eAAyB,GAGlC,wBAAMU,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,GACtBY,KAAKqT,QAAU,GACfrT,KAAKwR,cAAgB,GACrBxR,KAAKoT,KAAO,QACZpT,KAAKuR,UAAY,aACjBvR,KAAKsT,UAAY,GACjBtT,KAAKuT,kBAAoB,GACzBvT,KAAKwT,eAAiB,GACtBxT,KAAKyT,aAAe,CAChBC,OAAQ,GACRC,SAAU,GACVC,UAAW,G,KAEZ,CACH,GAAI5T,KAAKvC,cAAgBuC,KAAKvC,aAAasF,SAAU,CACjD/C,KAAKZ,eAAiBY,KAAKvC,aAAasF,SAExC/C,KAAKuR,UAAY,OACjBvR,KAAKwR,cAAgBxR,KAAKvC,aAAasF,Q,OAErC5C,EAAaH,KAAKnD,OACxB,GAAImD,KAAK5C,eAAgB,CAErB4C,KAAKnB,cAAgB,I,GAOzB,cAAAgY,CAAe3N,EAAe4N,EAA4CpB,GAC9E,OACI5R,EAAA,OAAKC,MAAM,aACPD,EAAA,OAAKC,MAAM,aAAamF,GACxBpF,EAAK,OAAAC,MAAM,iBACN+S,EAAQvG,KAAIwG,IACT,MAAMC,EAAatB,IAAa,WAC1B1V,KAAKyT,aAAaE,SAASkC,SAASkB,EAAOzV,OAC3CtB,KAAKyT,aAAaiC,KAAcqB,EAAOzV,MAE7C,OACIwC,EACI,OAAAC,MAAO,CACHiS,IAAO,KACP,eAAgBgB,GAEpB7S,QAAS,IAAMnE,KAAKyV,eAAeC,EAAUqB,EAAOzV,QAEnDyV,EAAO7J,KACN,K,CAStB,iBAAA+J,GACJ,OACInT,EAAA,OAAKC,MAAM,iBACN/D,KAAKuT,kBAAkBhD,KAAIyE,GACxBlR,EAAK,OAAAC,MAAM,aACPD,EAAA,OAAKC,MAAM,aAAaiR,EAAMQ,eAC9B1R,EAAA,OAAKC,MAAM,iBACNiR,EAAM3P,KAAKkL,KAAIyF,IACZ,MAAMgB,GAAchX,KAAKwT,eAAewB,EAAMQ,gBAAkB,IAAIK,SAASG,GAC7E,OACIlS,EACI,OAAAC,MAAO,CACHiS,IAAO,KACP,eAAgBgB,GAEpB7S,QAAS,IAAMnE,KAAK+V,iBAAiBf,EAAMQ,cAAeQ,IAEzDA,EACC,Q,CAW9B,kBAAAkB,GACJ,OACIpT,EAAA,OAAKC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAK,OAAAC,MAAM,gBACPD,EAAsB,0BACtBA,EAAA,OAAKC,MAAM,mBAAiB,W,CAM5C,MAAAZ,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAK/C,OACIiF,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,gBAAkB,MAC5C0G,EAAK,OAAAC,MAAM,mBAEPD,EAAK,OAAAC,MAAM,qBACPD,EAAmB,sBACnBA,EAAA,UACIC,MAAM,gBACNI,QAASnE,KAAKyR,kBACd5M,SAAU7E,KAAKwD,WAEfM,EAAA,OAAK6N,QAAQ,YAAYxK,MAAM,KAAKuF,OAAO,KAAKkF,KAAK,OAAOC,OAAO,gBAC/D/N,EAAqB,iCAAwB,0BAAqB,mBAAIgO,EAAE,6BACtE,SAMb9R,KAAKuR,YAAc,cAChBzN,EAAA,OAAKC,MAAM,oBAEN/D,KAAKoT,OAAS,SACXtP,EAAA,OAAKC,MAAM,kBACPD,EAAO,SAAAM,QAAQ,YAAU,QAChBN,EAAA,QAAMC,MAAM,YAAU,MAE/BD,EAAA,SACIW,GAAG,WACHJ,KAAK,OACLK,YAAY,UACZpD,MAAOtB,KAAKqT,QACZzO,QAAS5E,KAAK+T,oBACdlP,SAAU7E,KAAKwD,YAEnBM,EAAK,OAAAC,MAAM,oBACPD,EACI,UAAAC,MAAM,4BACNI,QAASnE,KAAKgU,eACdnP,UAAW7E,KAAKqT,QAAQvR,QAAU9B,KAAKwD,WAAS,SAS/DxD,KAAKoT,OAAS,UACXtP,EAAK,OAAAC,MAAM,iBACN/D,KAAKwD,UACFxD,KAAKkX,qBAELpT,EAAK,OAAAC,MAAM,yBAEN/D,KAAKsT,UAAUxN,OAAS,GACrBhC,EAAA,OAAKC,MAAM,mBACPD,EAAK,OAAAC,MAAM,iBAA6B,WACvC/D,KAAKiX,qBAKbjX,KAAKsT,UAAUxN,OAAS,GACrBhC,EAAA,OAAKC,MAAM,sBACN/D,KAAK6W,eAAe,OAAQ7W,KAAK6T,aAAc,UAC/C7T,KAAK6W,eAAe,OAAQ7W,KAAK2T,SAAU,YAC3C3T,KAAK6W,eAAe,OAAQ7W,KAAK8T,sBAAuB,cAIjEhQ,EAAK,OAAAC,MAAM,oBACPD,EACI,UAAAC,MAAM,4BACNI,QAASnE,KAAKkU,gBAGT,OACTpQ,EAAA,UACIC,MAAM,gBACNI,QAASnE,KAAKiW,uBACdpR,SAAU7E,KAAKX,cAEdW,KAAKX,aAAe,SAAW,YAW/DW,KAAKuR,YAAc,QAChBzN,EAAA,OAAKC,MAAM,cACPD,EAAK,OAAAC,MAAM,sBACPD,EAAO,SAAAM,QAAQ,mBAAiB,QACvBN,EAAA,QAAMC,MAAM,YAAU,MAE/BD,EACI,YAAAW,GAAG,kBACHC,YAAY,oBACZC,KAAM,EACNrD,MAAOtB,KAAKwR,cACZ5M,QAAS5E,KAAK0R,yBAItB5N,EAAK,OAAAC,MAAM,eACPD,EAAK,OAAAC,MAAM,eAA2B,WACtCD,EAAK,OAAAC,MAAM,iBACPD,EAA6B,iCAC7BA,EAA+B,mCAC/BA,EAA4C,gDAC5CA,EAA0B,8BAC1BA,EAAgC,oCAChCA,EAAA,yCAIRA,EAAK,OAAAC,MAAM,oBACPD,EAAA,UACIC,MAAM,gBACNI,QAASnE,KAAK4W,iBACd/R,UAAW7E,KAAKwR,cAAc1P,QAAU9B,KAAKX,cAE5CW,KAAKX,aAAe,SAAW,UAMhDyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO5FxC,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACN7I,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRsF,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,gBAElDd,cAAc,OACd4U,iBAAkBlT,KAAKkT,iBACvBC,iBAAkBnT,KAAKmT,qB,+GC/xBvD,MAAMgE,GAAkB,GCAxB,MAAM5a,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBH2a,GAAS,M,oVAIVxa,WAAqB,SAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAQtBC,aAAuC,GAKvCC,qBAAgC,MAKhCwH,iBAA4B,MAK5BmS,kBAA6B,MAK5BrZ,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtC3S,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,MACzBO,eAAyB,GACzBC,aAAwB,M,iCAKzBC,qBACAC,oBACA0D,aAGR,iBAAAxD,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAO3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,E,KAEnB,CACH,GAAIY,KAAKvC,cAAgBuC,KAAKvC,aAAasF,SAAU,CACjD/C,KAAKZ,eAAiBY,KAAKvC,aAAasF,Q,OAEtC5C,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,gBAAmB4C,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcsF,SAAW,CACrF/C,KAAKnB,cAAgB,I,GAMjC,iBAAAuB,GAGI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAG5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAGzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAGvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAKL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAKnBW,2BAA8BC,IAClC,MAAMC,EAAWD,EAAME,OACvBrB,KAAKZ,eAAiBgC,EAASE,KAAK,EAGhCgW,oBAAsBzV,UAE1B,IAAK7B,KAAKvC,cAAcmG,WAAa5D,KAAKpB,iBAAkB,CACxDmD,EAAQS,KAAK,SACb,M,CAIJ,IAAKxC,KAAKvC,cAAcsF,WAAa/C,KAAKZ,eAAe0C,OAAQ,CAC7DC,EAAQS,KAAK,WACb,M,CAIJ,SAAUxC,KAAKiD,cAAcC,oBAAoB,CAC7CnB,EAAQS,KAAK,aACb,M,CAGJxC,KAAKX,aAAe,KACpBW,KAAKnB,cAAgB,KACrBmB,KAAKX,aAAe,KAAK,EAI7B,MAAA8D,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM0Y,EAAc7T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAasF,UAGnE,MAAMyU,EAAmB9T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAamG,UAGxE,MAAM6T,EAAgB/T,QAAQ1D,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcsF,UAEhF,OACIe,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmBqa,GAC7C3T,EAAK,OAAAC,MAAM,oBAELwT,GACEzT,EAAK,OAAAC,MAAM,oBACPD,EAAO,SAAAM,QAAQ,mBAAsC,kBAE/CpE,KAAKqX,mBACHvT,EACI,wBAAAQ,KAAK,OACLC,KAAOC,IACHxE,KAAKZ,eAAiBoF,EAAE5B,MAAM,IAK9CkB,EAAA,YACIW,GAAG,kBACHV,MAAM,2BACNW,YAAY,wBACZC,KAAM,EACNrD,MAAOtB,KAAKZ,eACZwF,QAAS5E,KAAKkB,+BAMxBsW,GACE1T,EAAK,OAAAC,MAAM,yBACPD,EAAmB,qBACnBA,EACI,cAAAgB,IAAKC,GAAM/E,KAAKiD,aAAe8B,EAC/BC,YAAa,GAAK,KAAO,KACzBC,SAAU,MACVC,iBAAkBlF,KAAKkF,iBACvBC,qBAAsB,CAAC,OAAQ,MAAO,OAAQ,QAAS,QACvDC,aAAc,CACVC,KAAM,CAAC,WAEXO,eAAiBpB,IACb,MAAMrC,EAA+BqC,EAAE5B,QAAU,GACjD5C,KAAKpB,iBAAmBuD,EAAO,GAC/BnC,KAAKhC,cAAcuC,KAAKP,KAAKpB,iBAAiB,KAM9DkF,EAAA,UACIC,MAAM,gBACNc,UAAY2S,IAAqBxX,KAAKpB,mBAAuB2Y,IAAgBvX,KAAKZ,eAAe0C,QAAW9B,KAAKrB,aAAeqB,KAAKX,aACrI8E,QAASnE,KAAKsX,qBAEbtX,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO5FxC,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBJ,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB5T,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACNxI,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,gBAElDd,cAAc,W,+GCvY9C,MAAM/B,GAAY,g/MCAlB,MAAMmb,GAAkB,0ncCAxB,MAAMjR,GAAc,ixzBCApB,MAAMhK,GAAU,4wB,6g9BCAhB,MAAMkb,GAAgB,+5BCAtB,MAAMlb,GAAU,4wB,MCOHmb,GAAU,M,iDAEbC,QAAkB,GAClBxT,KAAiD,OACjDyT,SAAmB,IAClBC,QAAmB,MAEpBC,MAER,iBAAA5X,GACE,GAAIJ,KAAK6X,QAAS,CAChB7X,KAAK+X,QAAU,I,EAInB,gBAAAE,GACE,GAAIjY,KAAK+X,SAAW/X,KAAK8X,SAAW,EAAG,CACrC9X,KAAKgY,MAAQE,OAAOnJ,YAAW,KAC7B/O,KAAKqL,OAAO,GACXrL,KAAK8X,S,EAIZ,oBAAAjX,GACE,GAAIb,KAAKgY,MAAO,CACdG,aAAanY,KAAKgY,M,EAKtB,UAAMI,GACJpY,KAAK+X,QAAU,KAEf,GAAI/X,KAAK8X,SAAW,EAAG,CACrB9X,KAAKgY,MAAQE,OAAOnJ,YAAW,KAC7B/O,KAAKqL,OAAO,GACXrL,KAAK8X,S,EAKZ,WAAMzM,GACJrL,KAAK+X,QAAU,MAGfhJ,YAAW,KACT,GAAI/O,KAAK+E,IAAM/E,KAAK+E,GAAGsT,WAAY,CACjCrY,KAAK+E,GAAGsT,WAAWC,YAAYtY,KAAK+E,G,IAErC,I,CAGL,MAAA5B,GACE,OACEW,EAAK,OAAA0D,IAAA,2CAAAzD,MAAO,CACV,cAAe,KACf,sBAAuB/D,KAAK+X,QAC5B,CAAC,eAAe/X,KAAKqE,QAAS,OAE9BP,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,uBACTD,EAAM,QAAA0D,IAAA,2CAAAzD,MAAM,oBACT/D,KAAKuY,cAERzU,EAAM,QAAA0D,IAAA,2CAAAzD,MAAM,oBAAoB/D,KAAK6X,U,CAMrC,UAAAU,GACN,OAAQvY,KAAKqE,MACX,IAAK,UACH,OAAOP,EAAK,OAAA6N,QAAQ,gBAAgBxK,MAAM,OAAOuF,OAAO,OAAOkF,KAAK,gBAAe9N,EAAA,QAAMgO,EAAE,uRAC7F,IAAK,QACH,OAAOhO,EAAK,OAAA6N,QAAQ,gBAAgBxK,MAAM,OAAOuF,OAAO,OAAOkF,KAAK,gBAAe9N,EAAA,QAAMgO,EAAE,6WAC7F,IAAK,UACH,OAAOhO,EAAK,OAAA6N,QAAQ,gBAAgBxK,MAAM,OAAOuF,OAAO,OAAOkF,KAAK,gBAAe9N,EAAA,QAAMgO,EAAE,sOAC7F,QACE,OAAOhO,EAAK,OAAA6N,QAAQ,gBAAgBxK,MAAM,OAAOuF,OAAO,OAAOkF,KAAK,gBAAe9N,EAAA,QAAMgO,EAAE,wQ,kBCrFnG,MAAM0G,GAAkB,GCAxB,MAAMjc,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBHgc,GAAS,M,oVAIV7b,WAAqB,SAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAUtBC,aAAuC,GAKvCC,qBAAgC,MAKfgb,eAAyB,EAKzBC,kBAA6B,KAK7C3a,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtC5S,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBO,eAAyB,GACzBC,aAAwB,MAEzBC,qBACAC,oBAGR,iBAAAE,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAK3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKkS,oBACLlS,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,E,KAEnB,CACH,GAAIY,KAAKvC,cAAgBuC,KAAKvC,aAAasF,SAAU,CACjD/C,KAAKZ,eAAiBY,KAAKvC,aAAasF,Q,OAGtC5C,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,gBAAmB4C,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcsF,SAAW,CACrF/C,KAAKnB,cAAgB,I,GAKjC,iBAAAuB,GAEI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAG5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAEzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAIL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnB4R,iBAAoBhR,IACxB,MAAMK,EAAQL,EAAME,OACpB,GAAIG,EAAM4Q,OAAS5Q,EAAM4Q,MAAMtM,OAAS,EAAG,CACvC9F,KAAKtB,aAAe8C,EAAM4Q,MAAM,E,GAIhCC,kBAAoB,KACxB,MAAMC,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D0G,GAAW3D,OAAO,EAGduD,kBAAoB,KACxBlS,KAAKtB,aAAe,KACpBsB,KAAKpB,iBAAmB,KACxB,MAAM0T,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D,GAAI0G,EAAW,CACXA,EAAUhR,MAAQ,E,GAIlB,gBAAMiR,GACV,IAAKvS,KAAKtB,aAAc,OAExBsB,KAAKrB,YAAc,KAEnB,IAEI,MAAMwD,QAAeqQ,EAAoBxS,KAAKtB,aAAc,GACzD,CACC2G,KAAQ,CAAC,YAGbrF,KAAKpB,iBAAmBuD,EACxBnC,KAAKhC,cAAcuC,KAAK4B,E,CAC1B,MAAOH,GACLiH,QAAQjH,MAAM,UAAWA,GACzBhC,KAAKkS,oBACLO,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,aACRC,UAAW,iBACX1J,MAAO,WAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,c,SAGbtC,KAAKrB,YAAc,K,EAInBuC,2BAA8BC,IAClC,MAAMC,EAAWD,EAAME,OACvBrB,KAAKZ,eAAiBgC,EAASE,KAAK,EAGhCsX,2BAA8BzX,IAClC,MAAMK,EAAQL,EAAME,OACpB,MAAMC,EAAQyP,SAASvP,EAAMF,OAC7BtB,KAAK0Y,eAAkBpX,GAAS,GAAKA,GAAS,GAAMA,EAAQ,CAAC,EAGzDuX,qBAAwB1X,IAC5B,MAAMK,EAAQL,EAAME,OACpBrB,KAAK2Y,kBAAoBnX,EAAMsX,OAAO,EAGlChW,qBAAuBjB,UAC3B,IAAK7B,KAAKtB,aAAc,CACpBoU,MAAM,SACN,M,CAIJ,IAAK9S,KAAKvC,cAAcsF,WAAa/C,KAAKZ,eAAe0C,OAAQ,CAC7DgR,MAAM,WACN,M,CAGJ9S,KAAKX,aAAe,KAEpB,IAEI,IAAKW,KAAKpB,iBAAkB,OAClBoB,KAAKuS,aACX,IAAKvS,KAAKpB,iBAAkB,CACxBoB,KAAKX,aAAe,MACpB,M,EAKRW,KAAKnB,cAAgB,I,CACvB,MAAOmD,GACLiH,QAAQjH,MAAM,WAAYA,GAC1ByQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,uBACRC,UAAW,iBACX1J,MAAO,YAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,e,SAGbtC,KAAKX,aAAe,K,GAI5B,MAAA8D,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM0Y,EAAc7T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAasF,UAGnE,MAAMyU,EAAmB9T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAamG,UAGxE,MAAM6T,EAAgB/T,QAAQ1D,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcsF,UAEhF,OACIe,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmBqa,GAC7C3T,EAAK,OAAAC,MAAM,oBAELwT,GACEzT,EAAK,OAAAC,MAAM,oBACPD,EAAO,SAAAM,QAAQ,mBAAsC,gBACrDN,EAAA,YACIW,GAAG,kBACHV,MAAM,2BACNW,YAAY,wBACZC,KAAM,EACNrD,MAAOtB,KAAKZ,eACZwF,QAAS5E,KAAKkB,+BAMxBsW,GACE1T,EAAK,OAAAC,MAAM,yBACPD,EAAmB,qBACnBA,EAAK,OAAAC,MAAM,cAAcI,QAASnE,KAAKqS,mBAClCrS,KAAKtB,aACFoF,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAC,MAAM,qBACPD,EAAM,QAAAC,MAAM,aAAqB,MACjCD,EAAM,QAAAC,MAAM,aAAa/D,KAAKtB,aAAa4F,OAE/CR,EAAQ,UAAAC,MAAM,cAAcI,QAAUK,IAClCA,EAAE0M,kBACFlR,KAAKkS,mBAAmB,GAC3B,MAGLpO,EAAA,OAAKC,MAAM,sBACPD,EAAK,OAAAG,IAAI,kEACTH,EAAG,KAAAC,MAAM,eAAwB,UACjCD,EAAG,KAAAC,MAAM,eAAa,yCAQ1CD,EAAK,OAAAC,MAAM,8BACPD,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,2BACPD,EAAO,SAAAC,MAAM,kBAA+B,UAC5CD,EAAK,OAAAC,MAAM,oBACPD,EACI,SAAAO,KAAK,QACL0U,IAAI,IACJC,IAAI,KACJ1X,MAAOtB,KAAK0Y,eACZ3U,MAAM,kBACNa,QAAS5E,KAAK4Y,6BAElB9U,EAAK,OAAAC,MAAM,gBAAgB/D,KAAK0Y,eAAsB,QAKlE5U,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,2BACPD,EAAO,SAAAC,MAAM,kBAAkC,aAC/CD,EAAK,OAAAC,MAAM,oBACPD,EAAO,SAAAC,MAAM,iBACTD,EAAA,SACIO,KAAK,WACLyU,QAAS9Y,KAAK2Y,kBACd7H,SAAU9Q,KAAK6Y,uBAEnB/U,EAAA,QAAMC,MAAM,mBAEhBD,EAAA,QAAMC,MAAM,eAAe/D,KAAK2Y,kBAAoB,KAAO,UAM3E7U,EAAA,UACIC,MAAM,gBACNc,UAAa2S,IAAqBxX,KAAKtB,eAC1B6Y,IAAgBvX,KAAKZ,eAAe0C,QACtC9B,KAAKrB,aAAeqB,KAAKX,aACpC8E,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,kCAIrFlC,EAAA,SACIO,KAAK,OACLN,MAAM,aACN+M,SAAU9Q,KAAKmS,oBAM1B3O,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACN7I,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C8G,gBAAiBlG,KAAK0Y,eACtBO,mBAAoBjZ,KAAK2Y,kBAAoB,OAAS,SAE1Dra,cAAc,W,+GC7f9C,MAAM4a,GAAoB,GCA1B,MAAM3c,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCsBH0c,GAAW,M,iYAIZvc,WAAqB,OAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,UAKvBC,iBAA2B,IAK3BC,YAAsB,GAKtBC,WAAsB,MAatBC,aAAuC,GAKvCC,qBAAgC,MAKhC2Z,kBAA6B,MAK7BnS,iBAA4B,MAQ5BtH,UAQAC,aAAuB,EAKvBC,mBAA8B,MAK9BC,uBAAkC,MAMjCC,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAMDC,cAAkC,OAKjCC,eAKDC,eAA0B,KAK1BC,oBAA+B,KAG9BC,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBO,eAAyB,GACzBC,aAAwB,MAEzBC,qBACAC,oBAGAC,oBAA6D,KAGrE,iBAAAC,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAM3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEX,GAAIC,KAAKR,oBAAqB,OACpBQ,KAAKR,oBAAoBS,mBAAmB,M,CAGrDD,KAAKE,Y,KAEH,CACH,GAAIF,KAAKvC,cAAgBuC,KAAKvC,aAAasF,SAAU,CACjD/C,KAAKZ,eAAiBY,KAAKvC,aAAasF,Q,OAGtC5C,EAAaH,KAAKnD,OAGxB,IAAMmD,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcoG,iBAAmB7D,KAAKvC,cAAcsF,UAAa/C,KAAK5C,eAAgB,CAC5H4C,KAAKnB,cAAgB,I,GAOjC,iBAAAuB,GAEI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAG7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAI5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAGzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAMJ,UAAAW,GACLF,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,GACtBY,KAAKX,aAAe,MACpBW,KAAKtB,aAAe,KACpBsB,KAAKrB,YAAc,MACnBqB,KAAKpB,iBAAmB,I,CAIpBqC,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnBW,2BAA8BC,IAClC,MAAMC,EAAWD,EAAME,OACvBrB,KAAKZ,eAAiBgC,EAASE,KAAK,EAGhCwB,qBAAuBjB,UAE3B,IAAK7B,KAAKvC,cAAcsF,WAAa/C,KAAKZ,eAAe0C,OAAQ,CAC7DgR,MAAM,WACN,M,CAGJ,SAAU9S,KAAKiD,cAAcC,oBAAoB,CAC7CnB,EAAQS,KAAK,aACb,M,CAEJxC,KAAKX,aAAe,KACpBW,KAAKnB,cAAgB,IAAI,EAGrBoE,aAER,MAAAE,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAIxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM0Y,EAAc7T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAasF,UAGnE,MAAMyU,EAAmB9T,QAAQ1D,KAAKvC,eAAiBuC,KAAKvC,aAAamG,UAAY5D,KAAKvC,aAAaoG,iBAGvG,MAAM4T,EAAgB/T,SAAS1D,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAcoG,iBAAmB7D,KAAKvC,cAAcsF,UAEvH,OACIe,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmBqa,GAC7C3T,EAAK,OAAAC,MAAM,oBAELwT,GACEzT,EAAK,OAAAC,MAAM,oBACPD,EAAO,SAAAM,QAAQ,mBAAsC,kBAE/CpE,KAAKqX,mBACHvT,EACI,wBAAAQ,KAAK,OACLC,KAAOC,IACHxE,KAAKZ,eAAiBoF,EAAE5B,MAAM,IAK9CkB,EAAA,YACIW,GAAG,kBACHV,MAAM,2BACNW,YAAY,wBACZC,KAAM,EACNrD,MAAOtB,KAAKZ,eACZwF,QAAS5E,KAAKkB,+BAOrBsW,GACG1T,EAAK,OAAAC,MAAM,oBACPD,EAAuB,yBACvBA,EACI,cAAAgB,IAAKC,GAAM/E,KAAKiD,aAAe8B,EAC/BC,YAAa,GAAK,KAAO,KACzBC,SAAU,MACVC,iBAAkBlF,KAAKkF,iBACvBC,qBAAsB,CAAC,OAAQ,MAAO,OAAQ,QAAS,QACvDC,aAAc,CACVC,KAAM,CAAC,WAEXO,eAAiBpB,IACb,MAAMrC,EAA+BqC,EAAE5B,QAAU,GACjD5C,KAAKpB,iBAAmBuD,EAAO,GAC/BnC,KAAKhC,cAAcuC,KAAKP,KAAKpB,iBAAiB,KAOlEkF,EACI,UAAAC,MAAM,gBACNc,UAAY0S,IAAgBvX,KAAKZ,eAAe0C,QAAW9B,KAAKrB,aAAeqB,KAAKX,aACpF8E,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO5FxC,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACK9D,KAAKlC,oBAAsBkC,KAAKpC,UAC7BkG,EAAA,0BACIgB,IAAKC,GAAM/E,KAAKR,oBAAsBuF,EACtCjI,OAAQ,KACRU,WAAYwC,KAAKxC,WACjByI,MAAM,mBACNrI,UAAWoC,KAAKpC,UAChBC,aAAcmC,KAAKnC,aACnBT,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBE,YAAayC,KAAKzC,YAClBQ,uBAAwBiC,KAAKjC,uBAC7BN,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C8G,gBAAiBlG,KAAKvC,cAAcyI,iBAAmB,EACvDC,eAAe,OAIvBrC,EACI,sBAAAhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACNrI,UAAWoC,KAAKpC,UAChBR,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBC,iBAAkB0C,KAAK1C,iBACvBC,YAAayC,KAAKzC,YAClBiB,eAAgBwB,KAAKxB,eACrBC,oBAAqBuB,KAAKvB,oBAC1BV,uBAAwBiC,KAAKjC,uBAC7BN,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,eAC9C8G,gBAAiBlG,KAAKvC,cAAcyI,iBAAmB,GAE3D5H,cAAe0B,KAAK1B,kB;;;;;;;;;GChexD,MAAM8a,GAAoB,IAAIC,IAQ9B,MAAMC,GACJC,GACAC,GAEAC,aAAe,IAAIH,GAAQ,QAAS,EAAG,GACvCG,kBAAoB,IAAIH,GAAQ,aAAc,EAAG,GACjDG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,GAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,IAC9CG,kBAAoB,IAAIH,GAAQ,aAAc,IAC9CG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,mBAAqB,IAAIH,GAAQ,cAAe,IAChDG,iBAAmB,IAAIH,GAAQ,YAAa,IAC5CG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,gBAAkB,IAAIH,GAAQ,WAAY,IAC1CG,aAAe,IAAIH,GAAQ,QAAS,IACpCG,aAAe,IAAIH,GAAQ,QAAS,IACpCG,YAAc,IAAIH,GAAQ,OAAQ,IAClCG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,cAAgB,IAAIH,GAAQ,SAAU,IACtCG,WAAa,IAAIH,GAAQ,MAAO,IAChCG,eAAiB,IAAIH,GAAQ,UAAW,IACxCG,gBAAkB,IAAIH,GAAQ,WAAY,IAC1CG,gBAAkB,IAAIH,GAAQ,WAAY,IAC1CG,gBAAkB,IAAIH,GAAQ,WAAY,IAC1CG,mBAAqB,IAAIH,GAAQ,cAAe,KAChDG,cAAgB,IAAIH,GAAQ,SAAU,KAMtC,WAAAI,CAAYH,KAAUC,GACpBxZ,MAAKuZ,EAASA,EACdvZ,MAAKwZ,EAAU/R,OAAOkS,OAAOH,GAC7B,IAAK,MAAMlY,KAASkY,EAAQ,CAC1B,GAAIlY,GAAS,GAAKA,GAAS,QAAUsY,OAAOC,UAAUvY,GAAQ,CAC5D8X,GAAkBU,IAAIxY,EAAOtB,KACrC,KAAa,CACL,MAAM,IAAI+I,MAAM,gDACxB,CACA,CACA,CAKE,SAAIwQ,GACF,OAAOvZ,MAAKuZ,CAChB,CAKE,UAAIC,GACF,OAAOxZ,MAAKwZ,CAChB;;;;;;;;;GC3EA,SAASO,GAAMzY,GACb,OAAOA,EAAQ,CACjB,CACA,SAAS0Y,GAAQ1Y,GACf,OAAOA,EAAQ,CACjB,CAIA,SAAS2Y,GAAW3Y,GAClB,OAAO,GAAK4Y,GAAa5Y,EAC3B,CACA,SAAS4Y,GAAa5Y,GACpB,OAAOA,EAAQ,EACjB,CAiBA,SAAS6Y,GAAW7Y,GAClB,OAAO,GAAKqP,KAAKyJ,MAAM9Y,EACzB,CA0BA,SAAS+Y,GAAiB/Y,EAAOgZ,GAG/B,MAAMC,EAAeJ,GAAWG,GAChChZ,IAAUiZ,EAAe,EAEzB,MAAOJ,GAAW7Y,IAAUiZ,EAAc,CACxCjZ,GAASgZ,GAASH,GAAW7Y,GAASiZ,CAC1C,CAEE,OAAOjZ,CACT;;;;;;;;;GCtEA,MAAMkZ,GAAiB,IAAInB,IAQ3B,MAAMoB,GACJC,GACAC,GACAlB,kBAAoB,IAAIgB,GAAK,CAAC,EAAG,EAAG,GAAI,GACxChB,eAAiB,IAAIgB,GAAK,CAAC,GAAI,GAAI,IAAK,GACxChB,oBAAsB,IAAIgB,GAAK,CAAC,EAAG,GAAI,IAAK,GAC5ChB,yBAA2B,IAAIgB,GAAK,CAAC,EAAG,EAAG,GAAI,GAC/ChB,YAAc,IAAIgB,GAAK,CAAC,EAAG,GAAI,IAAK,GACpChB,WAAa,IAAIgB,GAAK,CAAC,EAAG,EAAG,GAAI,GACjChB,aAAe,IAAIgB,GAAK,CAAC,EAAG,GAAI,IAAK,GACrChB,2BAA6B,IAAIgB,GAAK,CAAC,EAAG,EAAG,GAAI,GACjDhB,4BAA8B,IAAIgB,GAAK,CAAC,EAAG,EAAG,GAAI,GAClDhB,aAAe,IAAIgB,GAAK,CAAC,EAAG,GAAI,IAAK,IACrC,WAAAf,CAAYiB,EAAuBD,GACjC1a,MAAK0a,EAAQA,EACb1a,MAAK2a,EAAyB,IAAIC,WAAWD,GAC7CH,GAAeV,IAAIY,EAAM1a,KAC7B,CACE,QAAI0a,GACF,OAAO1a,MAAK0a,CAChB,CACE,qBAAAG,EAAsBC,QAAEA,IACtB,IAAIC,EACJ,GAAID,GAAW,EAAG,CAChBC,EAAS,CACf,MAAW,GAAID,GAAW,GAAI,CACxBC,EAAS,CACf,KAAW,CACLA,EAAS,CACf,CACI,OAAO/a,MAAK2a,EAAuBI,EACvC;;;;;;;;;GCpCA,MAAMC,GAAK,EACX,MAAMC,GAAK,EACX,MAAMC,GAAK,GACX,MAAMC,GAAK,GAEX,SAASC,GAAOC,EAAQC,EAAGC,GACzB,OAAOF,EAAOG,IAAIF,EAAGC,KAAO,CAC9B,CAGA,SAASE,GAA8BJ,EAAQK,GAC7C,IAAIC,EAAU,EACd,MAAM/U,KAAEA,GAASyU,EACjB,IAAK,IAAIE,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAIK,GAAU,EACd,IAAIC,EAAkB,EACtB,IAAK,IAAIP,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,MAAMQ,EAAMJ,EAAaL,EAAOG,IAAID,EAAGD,GAAKD,EAAOG,IAAIF,EAAGC,GAC1D,GAAIO,IAAQF,EAAS,CACnBC,GACR,KAAa,CACL,GAAIA,GAAmB,EAAG,CACxBF,GAAWX,IAAMa,EAAkB,EAC7C,CAEQD,EAAUE,EAEVD,EAAkB,CAC1B,CACA,CACI,GAAIA,GAAmB,EAAG,CACxBF,GAAWX,IAAMa,EAAkB,EACzC,CACA,CACE,OAAOF,CACT,CAGA,SAASI,GAAsBV,GAC7B,OAAOI,GAA8BJ,GAAUI,GAA8BJ,EAAQ,KACvF,CAIA,SAASW,GAAsBX,GAC7B,IAAIM,EAAU,EACd,MAAM/U,EAAOyU,EAAOzU,KAAO,EAC3B,IAAK,IAAI2U,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAK,IAAID,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,MAAMQ,EAAMT,EAAOG,IAAIF,EAAGC,GAC1B,GAEEO,IAAQT,EAAOG,IAAIF,EAAI,EAAGC,IAC1BO,IAAQT,EAAOG,IAAIF,EAAGC,EAAI,IAC1BO,IAAQT,EAAOG,IAAIF,EAAI,EAAGC,EAAI,GAC9B,CACAI,GAAWV,EACnB,CACA,CACA,CACE,OAAOU,CACT,CAEA,SAASM,GAAYZ,EAAQN,EAAQmB,EAAMC,EAAIT,GAC7C,GAAIQ,EAAO,GAAKC,EAAKd,EAAOzU,KAAM,CAChC,OAAO,KACX,CACE,IAAK,IAAIwO,EAAI8G,EAAM9G,EAAI+G,EAAI/G,IAAK,CAC9B,GAAIsG,EAAaN,GAAOC,EAAQN,EAAQ3F,GAAKgG,GAAOC,EAAQjG,EAAG2F,GAAS,CACtE,OAAO,KACb,CACA,CACE,OAAO,IACT,CAIA,SAASqB,GAAsBf,GAC7B,IAAIgB,EAAe,EACnB,MAAMzV,KAAEA,GAASyU,EACjB,IAAK,IAAIE,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAK,IAAID,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,GAEEA,EAAI,EAAI1U,GACRwU,GAAOC,EAAQC,EAAGC,KACjBH,GAAOC,EAAQC,EAAI,EAAGC,IACvBH,GAAOC,EAAQC,EAAI,EAAGC,IACtBH,GAAOC,EAAQC,EAAI,EAAGC,IACtBH,GAAOC,EAAQC,EAAI,EAAGC,KACrBH,GAAOC,EAAQC,EAAI,EAAGC,IACvBH,GAAOC,EAAQC,EAAI,EAAGC,KACrBU,GAAYZ,EAAQE,EAAGD,EAAI,EAAGA,IAAMW,GAAYZ,EAAQE,EAAGD,EAAI,EAAGA,EAAI,KACvE,CACAe,GACR,CACM,GAEEd,EAAI,EAAI3U,GACRwU,GAAOC,EAAQC,EAAGC,KACjBH,GAAOC,EAAQC,EAAGC,EAAI,IACvBH,GAAOC,EAAQC,EAAGC,EAAI,IACtBH,GAAOC,EAAQC,EAAGC,EAAI,IACtBH,GAAOC,EAAQC,EAAGC,EAAI,KACrBH,GAAOC,EAAQC,EAAGC,EAAI,IACvBH,GAAOC,EAAQC,EAAGC,EAAI,KACrBU,GAAYZ,EAAQC,EAAGC,EAAI,EAAGA,EAAG,OAASU,GAAYZ,EAAQC,EAAGC,EAAI,EAAGA,EAAI,GAAI,OACjF,CACAc,GACR,CACA,CACA,CACE,OAAOA,EAAenB,EACxB,CAGA,SAASoB,GAAsBjB,GAC7B,IAAIkB,EAAe,EACnB,MAAM3V,KAAEA,GAASyU,EACjB,IAAK,IAAIE,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAK,IAAID,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,GAAIF,GAAOC,EAAQC,EAAGC,GAAI,CACxBgB,GACR,CACA,CACA,CACE,MAAMC,EAAgB5V,EAAOA,EAC7B,MAAM6V,EAAuBzC,GAASrJ,KAAK+L,IAAIH,EAAe,EAAIC,GAAiB,GAAMA,GACzF,OAAOC,EAAuBtB,EAChC,CAGA,SAASwB,GAAqBtB,GAC5B,OACEU,GAAsBV,GACtBW,GAAsBX,GACtBe,GAAsBf,GACtBiB,GAAsBjB,EAE1B,CAEA,SAASuB,GAAYjS,EAAM2Q,EAAGC,GAC5B,IAAIsB,EACJ,IAAIC,EACJ,OAAQnS,GACN,KAAK,EACHmS,EAAgBvB,EAAID,EAAK,EACzB,MACF,KAAK,EACHwB,EAAevB,EAAI,EACnB,MACF,KAAK,EACHuB,EAAexB,EAAI,EACnB,MACF,KAAK,EACHwB,GAAgBvB,EAAID,GAAK,EACzB,MACF,KAAK,EACHwB,EAAgB9C,GAAQuB,EAAI,GAAKvB,GAAQsB,EAAI,GAAM,EACnD,MACF,KAAK,EACHuB,EAAYtB,EAAID,EAChBwB,GAAgBD,EAAY,GAASA,EAAY,EACjD,MACF,KAAK,EACHA,EAAYtB,EAAID,EAChBwB,GAAiBD,EAAY,GAASA,EAAY,EAAM,EACxD,MACF,KAAK,EACHC,EAAkBvB,EAAID,EAAK,GAAOC,EAAID,EAAK,GAAS,EACpD,MACF,QACE,MAAM,IAAIvS,MAAM,iBAAiB4B,KAErC,OAAOmS,IAAiB,CAC1B;;;;;;;;;GClLA,MAAMC,GAAoB,IAAI1D,IAQ9B,MAAM2D,GACJ1Y,GACAoW,GACAuC,GAEAxD,SAAW,IAAIuD,GAAQ,IAAK,EAAG,GAE/BvD,SAAW,IAAIuD,GAAQ,IAAK,EAAG,GAE/BvD,SAAW,IAAIuD,GAAQ,IAAK,EAAG,GAE/BvD,SAAW,IAAIuD,GAAQ,IAAK,EAAG,GAC/B,WAAAtD,CAAYpV,EAAM2Y,EAAOvC,GACvB1a,MAAK0a,EAAQA,EACb1a,MAAKsE,EAAQA,EACbtE,MAAKid,EAASA,EACdF,GAAkBjD,IAAIY,EAAM1a,KAChC,CACE,QAAI0a,GACF,OAAO1a,MAAK0a,CAChB,CACE,QAAIpW,GACF,OAAOtE,MAAKsE,CAChB,CACE,SAAI2Y,GACF,OAAOjd,MAAKid,CAChB;;;;;;;;;GClCA,MAAMC,GACJC,GACAC,GACA,WAAA1D,CAAYyD,EAAOC,GACjBpd,MAAKmd,EAASA,EACdnd,MAAKod,EAAoBA,CAC7B,CACE,SAAID,GACF,OAAOnd,MAAKmd,CAChB,CACE,oBAAIC,GACF,OAAOpd,MAAKod,CAChB;;;;;;;;;GCZA,MAAMC,GACJC,GACAC,GACAC,GACAC,GACAC,GACA,WAAAhE,CAAYgE,KAA2BJ,GACrC,IAAIK,EAAY,EAChB,IAAIF,EAAwB,EAC5B,IAAK,MAAMN,MAAEA,EAAKC,iBAAEA,KAAsBE,EAAU,CAClDK,GAAaR,EACbM,GAAyBL,EAAmBD,CAClD,CACI,MAAMK,EAAsBE,EAAyBC,EACrD3d,MAAKsd,EAAYA,EACjBtd,MAAKwd,EAAuBA,EAC5Bxd,MAAKyd,EAAyBA,EAC9Bzd,MAAK0d,EAA0BA,EAC/B1d,MAAKud,EAAqBE,EAAwBD,CACtD,CACE,YAAIF,GACF,OAAOtd,MAAKsd,CAChB,CACE,qBAAIC,GACF,OAAOvd,MAAKud,CAChB,CACE,uBAAIC,GACF,OAAOxd,MAAKwd,CAChB,CACE,yBAAIC,GACF,OAAOzd,MAAKyd,CAChB,CACE,0BAAIC,GACF,OAAO1d,MAAK0d,CAChB;;;;;;;;;GCTA,MAAME,GACJhX,GACAkU,GACAwC,GACAO,GACA,WAAAnE,CAAYoB,EAAS+C,KAAsBP,GACzCtd,MAAK8a,EAAWA,EAChB9a,MAAKsd,EAAYA,EACjBtd,MAAK4G,EAAQ,GAAK,EAAIkU,EACtB9a,MAAK6d,EAAqBA,CAC9B,CACE,QAAIjX,GACF,OAAO5G,MAAK4G,CAChB,CACE,WAAIkU,GACF,OAAO9a,MAAK8a,CAChB,CACE,qBAAI+C,GACF,OAAO7d,MAAK6d,CAChB,CACE,WAAAC,EAAYb,MAAEA,IACZ,OAAOjd,MAAKsd,EAAUL,EAC1B,EAEA,MAAMc,GAAW,CACf,IAAIH,GACF,EACA,GACA,IAAIP,GAAS,EAAG,IAAIH,GAAI,EAAG,KAC3B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAE9B,IAAIU,GACF,EACA,CAAC,EAAG,IACJ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,MAE9B,IAAIU,GACF,EACA,CAAC,EAAG,IACJ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,MAE9B,IAAIU,GACF,EACA,CAAC,EAAG,IACJ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAE9B,IAAIU,GACF,EACA,CAAC,EAAG,IACJ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,MAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,EACA,CAAC,EAAG,IACJ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,MAE9B,IAAIU,GACF,EACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,EACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,EACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,MAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,MAE9C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,IACR,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,MAC5B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,EAAG,KAC5C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,IACZ,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,KAC7B,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,KAC7B,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,MAE/B,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,KAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,KAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,KAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,KAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,KAChB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,GAAI,KACpB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,GAAI,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,EAAG,MAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,GAAI,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,MAC7B,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,KACrB,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,GAAI,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,EAAG,IAAK,IAAIA,GAAI,GAAI,MAE/C,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,EAAG,KAAM,IAAIA,GAAI,GAAI,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,EAAG,KAC7C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,MAEhD,IAAIU,GACF,GACA,CAAC,EAAG,GAAI,GAAI,GAAI,IAAK,IAAK,KAC1B,IAAIP,GAAS,GAAI,IAAIH,GAAI,GAAI,KAAM,IAAIA,GAAI,EAAG,MAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI,KAC9C,IAAIG,GAAS,GAAI,IAAIH,GAAI,GAAI,IAAK,IAAIA,GAAI,GAAI;;;;;;;;;GChXlD,MAAMc,GACJC,GACAC,GACA,WAAAxE,CAAYuE,EAAOC,GACjB,MAAMpY,OAAEA,GAAWoY,EACnB,GAAIpY,GAAU,EAAG,CACf,MAAM,IAAIiD,MAAM,uCACtB,CACI/I,MAAKie,EAASA,EACd,GAAInY,EAAS,GAAKoY,EAAa,KAAO,EAAG,CAEvC,IAAIC,EAAe,EACnB,MAAOA,EAAerY,GAAUoY,EAAaC,KAAkB,EAAG,CAChEA,GACR,CACM,GAAIA,IAAiBrY,EAAQ,CAC3B9F,MAAKke,EAAgB,IAAItD,WAAW,CAAC,GAC7C,KAAa,CACL,MAAMwD,EAAQ,IAAIxD,WAAW9U,EAASqY,GACtCC,EAAMtE,IAAIoE,EAAaG,SAASF,IAChCne,MAAKke,EAAgBE,CAC7B,CACA,KAAW,CACLpe,MAAKke,EAAgBA,CAC3B,CACA,CACE,gBAAIA,GACF,OAAOle,MAAKke,CAChB,CACE,MAAAI,GACE,OAAOte,MAAKke,EAAc,KAAO,CACrC,CACE,SAAAK,GACE,OAAOve,MAAKke,EAAcpY,OAAS,CACvC,CACE,cAAA0Y,CAAeC,GACb,MAAMP,EAAele,MAAKke,EAC1B,OAAOA,EAAaA,EAAapY,OAAS,EAAI2Y,EAClD,CACE,QAAAC,CAASC,GACP,GAAIA,IAAM,EAAG,CAEX,OAAO3e,KAAKwe,eAAe,EACjC,CACI,IAAIrc,EACJ,MAAM+b,EAAele,MAAKke,EAC1B,GAAIS,IAAM,EAAG,CAEXxc,EAAS,EACT,IAAK,MAAMyc,KAAeV,EAAc,CACtC/b,GAAUyc,CAClB,CACM,OAAOzc,CACb,EACKA,GAAU+b,EACX,MAAMD,EAAQje,MAAKie,EACnB,MAAMnY,OAAEA,GAAWoY,EACnB,IAAK,IAAI9I,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/BjT,EAAS8b,EAAMY,SAASF,EAAGxc,GAAU+b,EAAa9I,EACxD,CACI,OAAOjT,CACX,CACE,QAAA0c,CAASC,GACP,MAAMb,EAAQje,MAAKie,EACnB,MAAMC,EAAele,MAAKke,EAC1B,MAAMpY,OAAEA,GAAWoY,EACnB,GAAIY,aAAiBd,GAAY,CAC/B,GAAIhe,KAAKse,UAAYQ,EAAMR,SAAU,CACnC,OAAOL,EAAMc,IACrB,CACM,MAAMC,EAAoBF,GAAMZ,EAChC,MAAMe,EAAcD,EAAkBlZ,OACtC,MAAMoZ,EAAU,IAAItE,WAAW9U,EAASmZ,EAAc,GACtD,IAAK,IAAI7J,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B,MAAMwJ,EAAcV,EAAa9I,GACjC,IAAK,IAAIC,EAAI,EAAGA,EAAI4J,EAAa5J,IAAK,CACpC6J,EAAQ9J,EAAIC,IAAM4I,EAAMY,SAASD,EAAaI,EAAkB3J,GAC1E,CACA,CACM,OAAO,IAAI2I,GAAWC,EAAOiB,EACnC,CACI,GAAIJ,IAAU,EAAG,CACf,OAAOb,EAAMc,IACnB,CACI,GAAID,IAAU,EAAG,CACf,OAAO9e,IACb,CACI,MAAMkf,EAAU,IAAItE,WAAW9U,GAC/B,IAAK,IAAIsP,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B8J,EAAQ9J,GAAK6I,EAAMY,SAASX,EAAa9I,GAAI0J,EACnD,CACI,OAAO,IAAId,GAAWC,EAAOiB,EACjC,CACE,kBAAAC,CAAmBV,EAAQG,GACzB,MAAMX,EAAQje,MAAKie,EACnB,GAAIW,IAAgB,EAAG,CACrB,OAAOX,EAAMc,IACnB,CACI,MAAMb,EAAele,MAAKke,EAC1B,MAAMpY,OAAEA,GAAWoY,EACnB,MAAMgB,EAAU,IAAItE,WAAW9U,EAAS2Y,GACxC,IAAK,IAAIrJ,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B8J,EAAQ9J,GAAK6I,EAAMY,SAASX,EAAa9I,GAAIwJ,EACnD,CACI,OAAO,IAAIZ,GAAWC,EAAOiB,EACjC,CACE,aAAAE,CAAcN,GACZ,GAAI9e,KAAKse,SAAU,CACjB,OAAOQ,CACb,CACI,GAAIA,EAAMR,SAAU,CAClB,OAAOte,IACb,CACI,IAAIqf,EAAqBP,GAAMZ,EAC/B,IAAIoB,EAAeD,EAAmBvZ,OACtC,IAAIyZ,EAAsBvf,MAAKke,EAC/B,IAAIsB,EAAgBD,EAAoBzZ,OACxC,GAAIwZ,EAAeE,EAAe,EAC/BF,EAAcE,GAAiB,CAACA,EAAeF,IAC/CD,EAAoBE,GAAuB,CAACA,EAAqBF,EACxE,CAEI,MAAMtE,EAASuE,EAAeE,EAC9B,MAAMtB,EAAe,IAAItD,WAAW0E,GAEpCpB,EAAapE,IAAIuF,EAAmBhB,SAAS,EAAGtD,IAChD,IAAK,IAAI3F,EAAI2F,EAAQ3F,EAAIkK,EAAclK,IAAK,CAC1C8I,EAAa9I,GAAKmK,EAAoBnK,EAAI2F,GAAUsE,EAAmBjK,EAC7E,CACI,OAAO,IAAI4I,GAAWhe,MAAKie,EAAQC,EACvC,CACE,MAAAuB,CAAOX,GACL,MAAMb,EAAQje,MAAKie,EACnB,IAAIyB,EAAWzB,EAAMc,KACrB,IAAIY,EAAY3f,KAChB,MAAM4f,EAAyBd,EAAMN,eAAeM,EAAMP,aAC1D,MAAMsB,EAA+B5B,EAAM6B,OAAOF,GAClD,MAAOD,EAAUpB,aAAeO,EAAMP,cAAgBoB,EAAUrB,SAAU,CACxE,MAAMyB,EAAkBJ,EAAUpB,YAClC,MAAMyB,EAAaD,EAAkBjB,EAAMP,YAC3C,MAAM0B,EAAQhC,EAAMY,SAASc,EAAUnB,eAAeuB,GAAkBF,GACxE,MAAMK,EAAOpB,EAAMK,mBAAmBa,EAAYC,GAClD,MAAME,EAAoBlC,EAAMmC,gBAAgBJ,EAAYC,GAC5DP,EAAWA,EAASN,cAAce,GAClCR,EAAYA,EAAUP,cAAcc,EAC1C,CACI,MAAO,CAACR,EAAUC,EACtB;;;;;;;;;GCjJA,MAAMU,GACJzZ,GACA0Z,GACAvB,GACAwB,GACAC,GACAC,GACA,WAAA/G,CAAYgH,EAAW9Z,EAAM2Z,GAC3B,IAAIjF,EAAI,EACR,MAAMkF,EAAW,IAAI5F,WAAWhU,GAChC,IAAK,IAAIwO,EAAI,EAAGA,EAAIxO,EAAMwO,IAAK,CAC7BoL,EAASpL,GAAKkG,EAEdA,GAAK,EACL,GAAIA,GAAK1U,EAAM,CACb0U,GAAKoF,EACLpF,GAAK1U,EAAO,CACpB,CACA,CACI,MAAM6Z,EAAW,IAAI7F,WAAWhU,GAChC,IAAK,IAAIwO,EAAI,EAAGtP,EAASc,EAAO,EAAGwO,EAAItP,EAAQsP,IAAK,CAClDqL,EAASD,EAASpL,IAAMA,CAC9B,CACIpV,MAAK4G,EAAQA,EACb5G,MAAKwgB,EAAYA,EACjBxgB,MAAKygB,EAAYA,EACjBzgB,MAAKugB,EAAaA,EAClBvgB,MAAKsgB,EAAO,IAAItC,GAAWhe,KAAM,IAAI4a,WAAW,CAAC,KACjD5a,MAAK+e,EAAQ,IAAIf,GAAWhe,KAAM,IAAI4a,WAAW,CAAC,IACtD,CACE,QAAIhU,GACF,OAAO5G,MAAK4G,CAChB,CACE,OAAI0Z,GACF,OAAOtgB,MAAKsgB,CAChB,CACE,QAAIvB,GACF,OAAO/e,MAAK+e,CAChB,CACE,aAAIwB,GACF,OAAOvgB,MAAKugB,CAChB,CACE,GAAAI,CAAIhC,GACF,OAAO3e,MAAKwgB,EAAU7B,EAC1B,CACE,GAAAzU,CAAIyU,GACF,OAAO3e,MAAKygB,EAAU9B,EAC1B,CACE,MAAAmB,CAAOnB,GACL,OAAO3e,MAAKwgB,EAAUxgB,MAAK4G,EAAQ5G,MAAKygB,EAAU9B,GAAK,EAC3D,CACE,QAAAE,CAASF,EAAGiC,GACV,GAAIjC,IAAM,GAAKiC,IAAM,EAAG,CACtB,OAAO,CACb,CACI,MAAMH,EAAWzgB,MAAKygB,EACtB,OAAOzgB,MAAKwgB,GAAWC,EAAS9B,GAAK8B,EAASG,KAAO5gB,MAAK4G,EAAQ,GACtE,CACE,eAAAwZ,CAAgB3B,EAAQG,GACtB,GAAIA,IAAgB,EAAG,CACrB,OAAO5e,MAAK+e,CAClB,CACI,MAAMb,EAAe,IAAItD,WAAW6D,EAAS,GAC7CP,EAAa,GAAKU,EAClB,OAAO,IAAIZ,GAAWhe,KAAMke,EAChC,EAEA,MAAM2C,GAAoB,IAAIR,GAAY,IAAQ,IAAK;;;;;;;;;GCnEvD,SAASS,GAAgBjJ,EAASkJ,GAChC,MAAMC,EAAQ,GACd,IAAK,MAAMC,KAAapJ,EAAS,CAC/B,MAAMqJ,EAAOD,EAAUE,YAAY,GAEnCH,EAAMI,KAAKF,GAAQ,MAAQA,EAAOH,EAAU,GAAKG,EACrD,CACE,OAAO,IAAIG,WAAWL,EACxB,CACA,SAASM,GAAOzJ,EAAS0J,GACvB,OAAQA,GACN,KAAKjI,GAAQkI,MACX,OAAOV,GAAgBjJ,EAAS,KAClC,KAAKyB,GAAQmI,WACX,OAAOX,GAAgBjJ,EAAS,KAClC,KAAKyB,GAAQoI,MACX,OAAO,IAAIC,aAAcL,OAAOzJ,GAClC,QACE,MAAM9O,MAAM,wCAAwCwY,EAAQhI,SAElE;;;;;;;;;GCpBA,MAAMqI,GAAc,IACpB,SAAS7G,GAAO8G,GACd,OAAO7H,GAAQ6H,EAAQ,GACzB,CACA,SAASC,GAAUhc,GACjB,OAAO,IAAI8U,WAAWjK,KAAKC,KAAK9K,EAAS,IAC3C,CACA,MAAMic,GACJjc,GACA4U,GACA,WAAAhB,CAAY5T,EAAS,GACnB9F,MAAK8F,EAAUA,EACf9F,MAAK0a,EAAQoH,GAAUhc,EAC3B,CACE,EAAAkc,CAAOlc,GACL,MAAM4U,EAAO1a,MAAK0a,EAClB,GAAI5U,EAAS4U,EAAK5U,OAAS,GAAI,CAC7B,MAAMsY,EAAQ0D,GAAUnR,KAAKC,KAAK9K,EAAS8b,KAC3CxD,EAAMtE,IAAIY,GACV1a,MAAK0a,EAAQ0D,CACnB,CACIpe,MAAK8F,EAAUA,CACnB,CACE,UAAIA,GACF,OAAO9F,MAAK8F,CAChB,CACE,cAAImc,GACF,OAAOtR,KAAKC,KAAK5Q,MAAK8F,EAAU,EACpC,CACE,GAAAgU,CAAI+H,GACF7hB,MAAK0a,EAAMK,GAAO8G,KAAW5H,GAAW4H,EAC5C,CACE,GAAArG,CAAIqG,GACF,OAAO9H,GAAM/Z,MAAK0a,EAAMK,GAAO8G,MAAY3H,GAAa2H,GAC5D,CACE,GAAAK,CAAIvX,GACF,MAAM+P,EAAO1a,MAAK0a,EAClB,MAAMyH,EAAWxX,GAAK+P,EACtB,MAAM5U,EAAS6K,KAAKoI,IAAI/Y,MAAK8F,EAAS6E,GAAK7E,GAC3C,IAAK,IAAIsP,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAG/BsF,EAAKtF,IAAM+M,EAAS/M,EAC1B,CACA,CACE,MAAAgN,CAAO9gB,EAAOwE,EAAS,GACrB,IAAI+b,EAAQ7hB,MAAK8F,EACjB,GAAIxE,aAAiBygB,GAAU,CAC7Bjc,EAASxE,GAAMwE,EACf9F,MAAKgiB,EAAOH,EAAQ/b,GACpB,IAAK,IAAIsP,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B,GAAI9T,EAAMka,IAAIpG,KAAO,EAAG,CACtBpV,KAAK8Z,IAAI+H,EACnB,CACQA,GACR,CACA,KAAW,CACL7hB,MAAKgiB,EAAOH,EAAQ/b,GACpB,IAAK,IAAIsP,EAAItP,EAAS,EAAGsP,GAAK,EAAGA,IAAK,CACpC,GAAI2E,GAAMzY,IAAU8T,KAAO,EAAG,CAC5BpV,KAAK8Z,IAAI+H,EACnB,CACQA,GACR,CACA,CACA,CACE,iBAAAQ,CAAkBC,EAAWjhB,EAAQkhB,EAAYN,GAC/C,IAAK,IAAI7M,EAAI,EAAGA,EAAI6M,EAAY7M,IAAK,CACnC,IAAIoN,EAAO,EACX,IAAK,IAAInN,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,GAAIrV,KAAKwb,IAAI8G,OAAiB,EAAG,CAC/BE,GAAQ,GAAM,EAAInN,CAC5B,CACA,CACMhU,EAAOkhB,EAAanN,GAAKoN,CAC/B,CACA,CACE,KAAAC,GACEziB,MAAK0a,EAAM9I,KAAK,EACpB;;;;;;;;;GCjFA,MAAM8Q,GACJ9b,GACAoa,GACA,WAAAtH,CAAY9S,GACV5G,MAAK4G,EAAQA,EACb5G,MAAKghB,EAAS,IAAI2B,UAAU/b,EAAOA,EACvC,CACE,QAAIA,GACF,OAAO5G,MAAK4G,CAChB,CACE,GAAAkT,CAAIwB,EAAGC,EAAGja,GACRtB,MAAKghB,EAAOzF,EAAIvb,MAAK4G,EAAQ0U,GAAKha,CACtC,CACE,GAAAka,CAAIF,EAAGC,GACL,OAAOvb,MAAKghB,EAAOzF,EAAIvb,MAAK4G,EAAQ0U,EACxC,CACE,KAAAmH,CAAMnhB,GACJtB,MAAKghB,EAAOpP,KAAKtQ,EACrB;;;;;;;;;GCXA,MAAMshB,GAAmB,KAEzB,MAAMC,GAAmB,MAEzB,MAAMC,GAAoB,KAE1B,MAAMC,GAAuB,CAC3B,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GACnB,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAGrB,MAAMC,GAA0B,CAC9B,CAAC,EAAG,EAAG,EAAG,EAAG,GACb,CAAC,EAAG,EAAG,EAAG,EAAG,GACb,CAAC,EAAG,EAAG,EAAG,EAAG,GACb,CAAC,EAAG,EAAG,EAAG,EAAG,GACb,CAAC,EAAG,EAAG,EAAG,EAAG,IAGf,MAAMC,GAA0B,CAC9B,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,GACJ,CAAC,EAAG,IAGN,SAASC,GAAQ7H,EAAQC,EAAGC,GAC1B,OAAOF,EAAOG,IAAIF,EAAGC,MAAO,CAC9B,CACA,SAAS4H,GAAmB9H,EAAQC,EAAGC,GACrC,IAAK,IAAInG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MAAMgO,EAAUL,GAAqB3N,GACrC,IAAK,IAAIC,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1BgG,EAAOvB,IAAIwB,EAAIjG,EAAGkG,EAAInG,EAAGgO,EAAQ/N,GACvC,CACA,CACA,CACA,SAASgO,GAAyBhI,EAAQC,EAAGC,GAC3C,IAAK,IAAIlG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1BgG,EAAOvB,IAAIwB,EAAIjG,EAAGkG,EAAG,EACzB,CACA,CACA,SAAS+H,GAAuBjI,EAAQC,EAAGC,GACzC,IAAK,IAAInG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1BiG,EAAOvB,IAAIwB,EAAGC,EAAInG,EAAG,EACzB,CACA,CAEA,SAASmO,GAAiClI,GAExC,MAAMmI,EAAW,EAEjB,MAAMC,EAAW,EAEjB,MAAMC,EAAY,EAElB,MAAM9c,KAAEA,GAASyU,EAEjB8H,GAAmB9H,EAAQ,EAAG,GAE9B8H,GAAmB9H,EAAQzU,EAAO4c,EAAU,GAE5CL,GAAmB9H,EAAQ,EAAGzU,EAAO4c,GAErCH,GAAyBhI,EAAQ,EAAGoI,EAAW,GAE/CJ,GAAyBhI,EAAQzU,EAAO6c,EAAUA,EAAW,GAE7DJ,GAAyBhI,EAAQ,EAAGzU,EAAO6c,GAE3CH,GAAuBjI,EAAQqI,EAAW,GAE1CJ,GAAuBjI,EAAQzU,EAAO8c,EAAY,EAAG,GAErDJ,GAAuBjI,EAAQqI,EAAW9c,EAAO8c,EACnD,CACA,SAASC,GAAoBtI,GAC3B,MAAMzU,EAAOyU,EAAOzU,KAAO,EAG3B,IAAK,IAAI0U,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,MAAMQ,EAAOR,EAAI,EAAK,EAEtB,GAAI4H,GAAQ7H,EAAQC,EAAG,GAAI,CACzBD,EAAOvB,IAAIwB,EAAG,EAAGQ,EACvB,CACA,CAGE,IAAK,IAAIP,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,MAAMO,EAAOP,EAAI,EAAK,EAEtB,GAAI2H,GAAQ7H,EAAQ,EAAGE,GAAI,CACzBF,EAAOvB,IAAI,EAAGyB,EAAGO,EACvB,CACA,CACA,CACA,SAAS8H,GAAsBvI,EAAQC,EAAGC,GACxC,IAAK,IAAInG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MAAMgO,EAAUJ,GAAwB5N,GACxC,IAAK,IAAIC,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1BgG,EAAOvB,IAAIwB,EAAIjG,EAAGkG,EAAInG,EAAGgO,EAAQ/N,GACvC,CACA,CACA,CAEA,SAASwO,GAAuBxI,GAAQP,QAAEA,IACxC,GAAIA,GAAW,EAAG,CAChB,MAAM+C,kBAAEA,GAAsBE,GAASjD,EAAU,GACjD,MAAMhV,OAAEA,GAAW+X,EACnB,IAAK,IAAIzI,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B,MAAMmG,EAAIsC,EAAkBzI,GAC5B,IAAK,IAAIC,EAAI,EAAGA,EAAIvP,EAAQuP,IAAK,CAC/B,MAAMiG,EAAIuC,EAAkBxI,GAC5B,GAAI6N,GAAQ7H,EAAQC,EAAGC,GAAI,CAIzBqI,GAAsBvI,EAAQC,EAAI,EAAGC,EAAI,EACnD,CACA,CACA,CACA,CACA,CAEA,SAASuI,GAAgBzI,GACvBA,EAAOvB,IAAI,EAAGuB,EAAOzU,KAAO,EAAG,EACjC,CAIA,SAASmd,GAAmBrJ,EAAMsJ,EAASrZ,GACzC,MAAMsZ,EAAcD,EAAQtJ,MAAQ,EAAK/P,EACzC+P,EAAK0H,OAAO6B,EAAY,GACxB,MAAMC,EAAU7J,GAAiB4J,EAAYrB,IAC7ClI,EAAK0H,OAAO8B,EAAS,IACrB,MAAM/B,EAAW,IAAIJ,GACrBI,EAASC,OAAOS,GAAkB,IAClCnI,EAAKwH,IAAIC,EACX,CAEA,SAASgC,GAAgB9I,EAAQ2I,EAASrZ,GACxC,MAAMyZ,EAAiB,IAAIrC,GAC3BgC,GAAmBK,EAAgBJ,EAASrZ,GAC5C,MAAM/D,KAAEA,GAASyU,EACjB,MAAMvV,OAAEA,GAAWse,EACnB,IAAK,IAAIhP,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAE/B,MAAOkG,EAAGC,GAAK0H,GAAwB7N,GAEvC,MAAM0G,EAAMsI,EAAe5I,IAAI1V,EAAS,EAAIsP,GAC5CiG,EAAOvB,IAAIwB,EAAGC,EAAGO,GACjB,GAAI1G,EAAI,EAAG,CAETiG,EAAOvB,IAAIlT,EAAOwO,EAAI,EAAG,EAAG0G,EAClC,KAAW,CAELT,EAAOvB,IAAI,EAAGlT,EAAO,GAAKwO,EAAI,GAAI0G,EACxC,CACA,CAEEgI,GAAgBzI,EAClB,CAGA,SAASgJ,GAAoB3J,EAAMI,GACjCJ,EAAK0H,OAAOtH,EAAS,GACrB,MAAMoJ,EAAU7J,GAAiBS,EAASgI,IAC1CpI,EAAK0H,OAAO8B,EAAS,GACvB,CAGA,SAASI,GAAiBjJ,GAAQP,QAAEA,IAClC,GAAIA,GAAW,EAAG,CAChB,MAAMyJ,EAAkB,IAAIxC,GAC5BsC,GAAoBE,EAAiBzJ,GAErC,IAAI0J,EAAW,EAAI,EAAI,EACvB,MAAM5d,KAAEA,GAASyU,EACjB,IAAK,IAAIjG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,IAAK,IAAIC,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAE1B,MAAMyG,EAAMyI,EAAgB/I,IAAIgJ,KAEhCnJ,EAAOvB,IAAI1E,EAAGxO,EAAO,GAAKyO,EAAGyG,GAE7BT,EAAOvB,IAAIlT,EAAO,GAAKyO,EAAGD,EAAG0G,EACrC,CACA,CACA,CACA,CAGA,SAAS2I,GAAepJ,EAAQqJ,EAAW/Z,GACzC,IAAI6Z,EAAW,EACf,MAAM5d,KAAEA,GAASyU,EACjB,MAAMvV,OAAEA,GAAW4e,EAEnB,IAAK,IAAIpJ,EAAI1U,EAAO,EAAG0U,GAAK,EAAGA,GAAK,EAAG,CAErC,GAAIA,IAAM,EAAG,CACXA,EAAI,CACV,CACI,IAAK,IAAIC,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAK,IAAInG,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,MAAMuP,EAAUrJ,EAAIlG,EACpB,MAAMwP,GAAWtJ,EAAI,EAAK,KAAO,EACjC,MAAMuJ,EAAUD,EAAShe,EAAO,EAAI2U,EAAIA,EAExC,GAAI2H,GAAQ7H,EAAQsJ,EAASE,GAAU,CAErC,IAAI/I,EAAM,EACV,GAAI0I,EAAW1e,EAAQ,CACrBgW,EAAM4I,EAAUlJ,IAAIgJ,IAChC,CAEU,GAAI5H,GAAYjS,EAAMga,EAASE,GAAU,CACvC/I,GAAO,CACnB,CACUT,EAAOvB,IAAI6K,EAASE,EAAS/I,EACvC,CACA,CACA,CACA,CACA,CAMA,SAASgJ,GAAsBzJ,EAAQP,GAErCyI,GAAiClI,GAEjCwI,GAAuBxI,EAAQP,GAE/B6I,GAAoBtI,EACtB,CAMA,SAAS0J,GAAoB1J,EAAQqJ,EAAW5J,EAASkJ,EAASrZ,GAEhEwZ,GAAgB9I,EAAQ2I,EAASrZ,GAEjC2Z,GAAiBjJ,EAAQP,GAEzB2J,GAAepJ,EAAQqJ,EAAW/Z,EACpC,CAGA,SAASqa,GAAYN,EAAW5J,EAASkJ,EAASrZ,GAChD,MAAM0Q,EAAS,IAAIqH,GAAW5H,EAAQlU,MAEtCyU,EAAOoH,OAAM,GAEbqC,GAAsBzJ,EAAQP,GAE9BiK,GAAoB1J,EAAQqJ,EAAW5J,EAASkJ,EAASrZ,GACzD,OAAO0Q,CACT;;;;;;;;;GC7RA,MAAM4J,GACJC,GACAC,GACA,WAAAzL,CAAYyL,EAAeD,GACzBllB,MAAKklB,EAAeA,EACpBllB,MAAKmlB,EAAiBA,CAC1B,CACE,eAAID,GACF,OAAOllB,MAAKklB,CAChB,CACE,iBAAIC,GACF,OAAOnlB,MAAKmlB,CAChB;;;;;;;;;GCTA,SAASC,GAAenH,EAAOoH,EAAY5G,GACzC,MAAM3Y,OAAEA,GAAWuf,EACnB,GAAI5G,GAAU3Y,EAAQ,CACpB,MAAMya,UAAEA,GAActC,EACtB,IAAIqH,EAAgBD,EAAWvf,EAAS,GACxC,IAAK,IAAIsP,EAAItP,EAAQsP,GAAKqJ,EAAQrJ,IAAK,CACrC,MAAM8I,EAAe,IAAItD,WAAW,CAAC,EAAGqD,EAAM0C,IAAIvL,EAAI,EAAImL,KAC1D,MAAMgF,EAAgBD,EAAczG,SAAS,IAAIb,GAAWC,EAAOC,IACnEmH,EAAWjE,KAAKmE,GAChBD,EAAgBC,CACtB,CACA,CACE,OAAOF,EAAW5G,EACpB,C,OACA,MAAM+G,EACJvH,GACAoH,GACA,WAAA3L,CAAYuE,EAAQ4C,IAClB7gB,MAAKie,EAASA,EACdje,MAAKqlB,EAAc,CAAC,IAAIrH,GAAWC,EAAO,IAAIrD,WAAW,CAAC,KAC9D,CACE,MAAA0G,CAAOmE,EAAUC,GACf,MAAMC,EAAYF,EAAS3f,OAAS4f,EACpC,MAAME,EAAmB,IAAIhL,WAAW+K,GACxC,MAAMpF,EAAY6E,GAAeplB,MAAKie,EAAQje,MAAKqlB,EAAaK,GAChEE,EAAiB9L,IAAI2L,EAASpH,SAAS,EAAGsH,IAC1C,MAAME,EAAO,IAAI7H,GAAWhe,MAAKie,EAAQ2H,GACzC,MAAMpjB,EAAOqjB,EAAK1G,mBAAmBuG,EAAU,GAC/C,MAAM,CAAG/F,GAAand,EAAKid,OAAOc,GAClC,MAAMrC,aAAEA,GAAiByB,EACzB,MAAMmG,EAAsBJ,EAAWxH,EAAapY,OACpD,MAAMigB,EAAyBJ,EAAYG,EAC3CL,EAAS7T,KAAK,EAAG+T,EAAWI,GAC5BN,EAAS3L,IAAIoE,EAAc6H,EAC/B;;;;;;;;;GC7BA,SAASC,GAAoBtB,EAAWuB,GACtC,MAAM7I,EAAmBsH,EAAU5e,OACnC,MAAMogB,EAAS,IAAItL,WAAWwC,EAAmB6I,GAEjDC,EAAOpM,IAAI4K,IAEX,IAAIc,IAAUlE,OAAO4E,EAAQD,GAE7B,OAAO,IAAI5E,WAAW6E,EAAO7H,SAASjB,GACxC,CACA,SAAS+I,GAAkBzL,GAAM4C,SAAEA,EAAQI,uBAAEA,IAG3C,IAAI0I,EAAoB,EACxB,IAAIC,EAAsB,EAC1B,IAAIC,EAAsB,EAE1B,MAAMC,EAAS,GACf,IAAK,MAAMpJ,MAAEA,EAAKC,iBAAEA,KAAsBE,EAAU,CAClD,IAAK,IAAIlI,EAAI,EAAGA,EAAI+H,EAAO/H,IAAK,CAC9B,MAAM+P,EAAgB,IAAI9D,WAAWjE,GACrC1C,EAAK2H,kBAAkBiE,EAAsB,EAAGnB,EAAe,EAAG/H,GAClE,MAAM8H,EAAcc,GAAoBb,EAAezH,GACvD6I,EAAOnF,KAAK,IAAI6D,GAAUE,EAAeD,IACzCoB,GAAuBlJ,EACvBgJ,EAAoBzV,KAAKqI,IAAIoN,EAAmBlB,EAAYpf,QAC5DugB,EAAsB1V,KAAKqI,IAAIqN,EAAqBjJ,EAC1D,CACA,CACE,MAAMsH,EAAY,IAAI3C,GAEtB,IAAK,IAAI3M,EAAI,EAAGA,EAAIiR,EAAqBjR,IAAK,CAC5C,IAAK,MAAM+P,cAAEA,KAAmBoB,EAAQ,CACtC,GAAInR,EAAI+P,EAAcrf,OAAQ,CAC5B4e,EAAUtC,OAAO+C,EAAc/P,GAAI,EAC3C,CACA,CACA,CAEE,IAAK,IAAIA,EAAI,EAAGA,EAAIgR,EAAmBhR,IAAK,CAC1C,IAAK,MAAM8P,YAAEA,KAAiBqB,EAAQ,CACpC,GAAInR,EAAI8P,EAAYpf,OAAQ,CAC1B4e,EAAUtC,OAAO8C,EAAY9P,GAAI,EACzC,CACA,CACA,CACE,OAAOsP,CACT,CACA,SAAS8B,GAAiB9L,EAAM0C,GAC9B,MAAMqJ,EAAWrJ,EAAmB,EAEpC,IAAK,IAAIhI,EAAI,EAAGA,EAAI,GAAKsF,EAAK5U,OAAS2gB,EAAUrR,IAAK,CACpDsF,EAAK0H,OAAO,EAChB,CAGE,MAAMsE,EAAoBhM,EAAK5U,OAAS,EACxC,GAAI4gB,EAAoB,EAAG,CACzB,IAAK,IAAItR,EAAIsR,EAAmBtR,EAAI,EAAGA,IAAK,CAC1CsF,EAAK0H,OAAO,EAClB,CACA,CAEE,MAAMuE,EAAsBvJ,EAAmB1C,EAAKuH,WACpD,IAAK,IAAI7M,EAAI,EAAGA,EAAIuR,EAAqBvR,IAAK,CAC5CsF,EAAK0H,OAAOhN,EAAI,EAAO,GAAO,IAAM,EACxC,CACA,CACA,SAASwR,GAAWC,GAClB,OAAOA,EAAQC,OAASrM,GAAKsM,IAC/B,CACA,SAASC,GAAYH,GACnB,OAAOA,EAAQC,OAASrM,GAAKwM,KAC/B,CACA,SAASC,GAAexM,EAAMoM,GAC5BpM,EAAK0H,OAAO0E,EAAKpM,KAAM,EACzB,CACA,SAASyM,GAAUzM,EAAMmM,EAASO,GAChC,GAAIR,GAAWC,GAAU,CACvB,MAAOvlB,GAASulB,EAAQtF,QAAQ/H,OAChC,GAAIlY,IAAU8lB,EAAiB,CAC7B1M,EAAK0H,OAAO3H,GAAK4M,IAAI3M,KAAM,GAE3B,GAAIpZ,GAAS,IAAK,CAChBoZ,EAAK0H,OAAO9gB,EAAO,EAC3B,MAAa,GAAIA,GAAS,MAAO,CACzBoZ,EAAK0H,OAAO,MAAS9gB,EAAO,GACpC,KAAa,CACLoZ,EAAK0H,OAAO,SAAW9gB,EAAO,GACtC,CACM,OAAOA,CACb,CACA,CACE,OAAO8lB,CACT,CACA,SAASE,GAAe5M,EAAM6M,GAC5B,MAAOT,EAAMU,GAAaD,EAE1B,OAAQT,GACN,IAAK,MAEHI,GAAexM,EAAMD,GAAKgN,qBAC1B,MACF,IAAK,MAEHP,GAAexM,EAAMD,GAAKiN,sBAE1BhN,EAAK0H,OAAOoF,EAAW,GACvB,MAEN,CACA,SAASG,GAAiBd,EAASnM,GAEjC,GAAIkM,GAAWC,GAAU,CACvB,OAAOnM,EAAKuH,UAChB,CAGE,OAAO4E,EAAQhP,QAAQ/R,MACzB,CACA,SAAS8hB,GAAiBlN,EAAMoM,EAAMhM,EAAS+M,GAC7CnN,EAAK0H,OAAOyF,EAAYf,EAAKjM,sBAAsBC,GACrD,CACA,SAASgN,GAAQC,EAAcjN,EAASkJ,GAEtC,MAAM1G,EAAWxC,EAAQgD,YAAYkG,GACrC,MAAMgE,EAAoBrX,KAAKC,KAAKmX,EAAe,GACnD,OAAOzK,EAASG,uBAAyBuK,CAC3C,CACA,SAASC,GAAcF,EAAc/D,GACnC,IAAK,MAAMlJ,KAAWiD,GAAU,CAC9B,GAAI+J,GAAQC,EAAcjN,EAASkJ,GAAU,CAC3C,OAAOlJ,CACb,CACA,CACE,MAAM,IAAI/R,MAAM,gCAClB,CACA,SAASmf,GAAoBC,EAAerN,GAC1C,IAAIsN,EAAa,EACjB,IAAK,MAAMtB,KAAEA,EAAIuB,KAAEA,EAAI9c,KAAEA,KAAU4c,EAAe,CAChDC,GAAcC,EAAKviB,OAASghB,EAAKjM,sBAAsBC,GAAWvP,EAAKzF,MAC3E,CACE,OAAOsiB,CACT,CACA,SAASE,GAAuBH,EAAenE,GAI7C,MAAMuE,EAAwBL,GAAoBC,EAAepK,GAAS,IAC1E,MAAMyK,EAAqBP,GAAcM,EAAuBvE,GAEhE,MAAMoE,EAAaF,GAAoBC,EAAeK,GACtD,OAAOP,GAAcG,EAAYpE,EACnC,CACA,SAASyE,GAAwB/D,EAAW5J,EAASkJ,GACnD,IAAI0E,EAAW,EACf,IAAIC,EAAa3D,GAAYN,EAAW5J,EAASkJ,EAAS0E,GAC1D,IAAIE,EAAajM,GAAqBgM,GAEtC,IAAK,IAAIhe,EAAO,EAAGA,EAAO,EAAGA,IAAQ,CACnC,MAAM0Q,EAAS2J,GAAYN,EAAW5J,EAASkJ,EAASrZ,GACxD,MAAMgR,EAAUgB,GAAqBtB,GAErC,GAAIM,EAAUiN,EAAY,CACxBF,EAAW/d,EACXge,EAAatN,EACbuN,EAAajN,CACnB,CACA,CACE,MAAO,CAAC+M,EAAUC,EACpB;;;;;;;;;GChLA,MAAME,IAAY,GAAK,IAAM,EAQ7B,MAAMC,GACJC,GACAC,GACAtO,GACAuO,GACAriB,GACAsiB,GACAC,GACA,WAAAzP,CAAYuP,GACV,MAAMF,EAAM,GAAKE,EACjB,MAAMD,EAAMD,EAAM,EAClB/oB,MAAK+oB,EAAOA,EACZ/oB,MAAKgpB,EAAOA,EACZhpB,MAAKipB,EAASA,EACdjpB,KAAKopB,OACT,CACE,OAAIL,GACF,OAAO/oB,MAAK+oB,CAChB,CACE,OAAIC,GACF,OAAOhpB,MAAKgpB,CAChB,CACE,QAAItO,GACF,OAAO1a,MAAK0a,CAChB,CACE,SAAIuO,GACF,OAAOjpB,MAAKipB,CAChB,CACE,KAAAG,GACE,MAAM1O,EAAO1a,MAAKipB,EAAS,EAC3BjpB,MAAK0a,EAAQA,EACb1a,MAAK4G,EAAQ,GAAK8T,EAClB1a,MAAKmpB,EAAS,IAAI9P,IAClBrZ,MAAKkpB,EAAUlpB,MAAKgpB,EAAO,CAC/B,CACE,GAAAK,CAAInI,EAAMW,GACR,IAAIqH,EAASlpB,MAAKkpB,EAClB,GAAIA,EAASL,GAAU,CACrB,OAAO,KACb,CACI7oB,MAAKmpB,EAAOrP,IAAKoH,GAAQ,EAAKW,EAAOqH,KACrC,IAAIxO,EAAO1a,MAAK0a,EAChB,IAAI9T,EAAO5G,MAAK4G,EAChB,GAAIsiB,EAAStiB,EAAM,CACjBA,EAAO,KAAO8T,CACpB,CACI1a,MAAK0a,EAAQA,EACb1a,MAAK4G,EAAQA,EACb5G,MAAKkpB,EAAUA,EACf,OAAO,IACX,CACE,GAAA1N,CAAI0F,EAAMW,GACR,OAAO7hB,MAAKmpB,EAAO3N,IAAK0F,GAAQ,EAAKW,EACzC;;;;;;;;;GC9DA,MAAMyH,GACJ5O,GAAQ,EACR6O,GACArD,GAAU,EACVlF,GAAS,GACT,WAAAtH,CAAY6P,GACVvpB,MAAKupB,EAAQA,CACjB,CACE,KAAAC,CAAMtI,GACJ,IAAIxG,EAAO1a,MAAK0a,EAChB,IAAIwL,EAASlmB,MAAKkmB,EAAWhF,GAAQxG,EACrCA,GAAQ1a,MAAKupB,EAAM7O,KACnB,MAAMsG,EAAQhhB,MAAKghB,EACnB,MAAOtG,GAAQ,EAAG,CAChBsG,EAAMI,KAAK8E,EAAS,KACpBA,IAAW,EACXxL,GAAQ,CACd,CACI1a,MAAK0a,EAAQA,EACb1a,MAAKkmB,EAAUA,CACnB,CACE,IAAAuD,CAAKC,GACH,MAAM1I,EAAQhhB,MAAKghB,EAEnB,GAAIhhB,MAAK0a,EAAQ,EAAG,CAClBsG,EAAMI,KAAKphB,MAAKkmB,EACtB,CACIwD,EAAOC,UAAU3pB,MAAKupB,EAAMN,OAE5B,MAAMnjB,OAAEA,GAAWkb,EACnB,IAAK,IAAI5L,EAAI,EAAGA,EAAItP,GAAU,CAC5B,MAAM8jB,EAAS9jB,EAASsP,EACxB,GAAIwU,GAAU,IAAK,CACjBF,EAAOC,UAAU,KACjBD,EAAOG,WAAW7I,EAAO5L,EAAG,KAC5BA,GAAK,GACb,KAAa,CACLsU,EAAOC,UAAUC,GACjBF,EAAOG,WAAW7I,EAAO5L,EAAGwU,GAC5BxU,EAAItP,CACZ,CACA,CACI4jB,EAAOC,UAAU,EACrB;;;;;;;;;GCxCA,SAASG,GAASC,EAAQd,EAAOS,GAC/B,MAAMH,EAAO,IAAIT,GAAKG,GACtB,MAAM/C,EAAS,IAAIoD,GAAWC,GAC9BrD,EAAOsD,MAAMD,EAAKR,KAClB,GAAIgB,EAAOjkB,OAAS,EAAG,CACrB,IAAIob,EAAO6I,EAAO,GAClB,MAAMjkB,OAAEA,GAAWikB,EACnB,IAAK,IAAI3U,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B,MAAM4U,EAAaD,EAAO3U,GAC1B,MAAM6U,EAAWV,EAAK/N,IAAI0F,EAAM8I,GAChC,GAAIC,GAAY,KAAM,CACpB/I,EAAO+I,CACf,KAAa,CACL/D,EAAOsD,MAAMtI,GAEb,IAAKqI,EAAKF,IAAInI,EAAM8I,GAAa,CAC/B9D,EAAOsD,MAAMD,EAAKR,KAClBQ,EAAKH,OACf,CACQlI,EAAO8I,CACf,CACA,CACI9D,EAAOsD,MAAMtI,EACjB,CACEgF,EAAOsD,MAAMD,EAAKP,KAClB9C,EAAOuD,KAAKC,EACd;;;;;;;;;GC9BA,MAAMQ,GACJlJ,GAAS,GACT,SAAIA,GACF,OAAOhhB,MAAKghB,CAChB,CACE,SAAA2I,CAAUroB,GACRtB,MAAKghB,EAAOI,KAAK9f,EAAQ,IAC7B,CACE,UAAA6oB,CAAW7oB,GACTtB,MAAKghB,EAAOI,KAAK9f,EAAQ,IAAOA,GAAS,EAAK,IAClD,CACE,UAAAuoB,CAAW7I,EAAOjG,EAAS,EAAGjV,EAASkb,EAAMlb,QAC3C,MAAMogB,EAASlmB,MAAKghB,EACpB,IAAK,IAAI5L,EAAI,EAAGA,EAAItP,EAAQsP,IAAK,CAC/B8Q,EAAO9E,KAAKJ,EAAMjG,EAAS3F,GAAK,IACtC,CACA;;;;;;;;;GCdA,MAAMgV,aAAEA,IAAiB/mB,OACzB,SAASie,GAAOkB,GACdA,GAAQ,GACR,GAAIA,GAAQ,EAAG,CACb,GAAIA,EAAO,GAAI,CAEb,OAAO,GAAOA,CACpB,MAAW,GAAIA,EAAO,GAAI,CAEpB,OAAO,IAAQA,EAAO,GAC5B,MAAW,GAAIA,EAAO,GAAI,CAEpB,OAAO,IAAQA,EAAO,GAC5B,MAAW,GAAIA,IAAS,GAAI,CAEtB,OAAO,EACb,MAAW,GAAIA,IAAS,GAAI,CAEtB,OAAO,EACb,CACA,CACE,MAAM,IAAIzZ,MAAM,iBAAiBqhB,GAAa5H,KAChD,CACA,MAAM6H,GACJ3P,GAAQ,EACRwL,GAAU,EACVpgB,GAAU,EACV4jB,GAAU,IAAIQ,GACd,SAAIlJ,GACF,OAAOhhB,MAAK0pB,EAAQ1I,KACxB,CACE,KAAAwI,CAAMhH,GACJ,IAAI9H,EAAO1a,MAAK0a,EAAQ,EACxB,MAAMgP,EAAS1pB,MAAK0pB,EACpB,MAAMxD,EAAUlmB,MAAKkmB,GAAW,EAAM1D,EAAO,IAC7C,MAAO9H,GAAQ,EAAG,CAChBgP,EAAOC,UAAUrI,GAAO4E,IAAYxL,EAAO,IAC3CA,GAAQ,CACd,CACI1a,MAAK8F,IACL9F,MAAK0a,EAAQA,EACb1a,MAAKkmB,EAAUA,CACnB,CACE,KAAA7a,GACE,MAAMqP,EAAO1a,MAAK0a,EAClB,MAAMgP,EAAS1pB,MAAK0pB,EACpB,GAAIhP,EAAO,EAAG,CACZgP,EAAOC,UAAUrI,GAAOthB,MAAKkmB,GAAY,EAAIxL,IAC7C1a,MAAK0a,EAAQ,EACb1a,MAAKkmB,EAAU,CACrB,CACI,MAAMpgB,EAAS9F,MAAK8F,EACpB,GAAIA,EAAS,GAAK,EAAG,CAEnB,MAAMwkB,EAAM,EAAKxkB,EAAS,EAC1B,IAAK,IAAIsP,EAAI,EAAGA,EAAIkV,EAAKlV,IAAK,CAE5BsU,EAAOC,UAAU,GACzB,CACA,CACA;;;;;;;;;GC1DA,MAAMY,GACJpjB,GACAuF,GACA8d,GACAC,GACAV,GAAU,GACV,WAAArQ,CAAYvS,EAAOuF,GAAQ8d,WAAEA,EAAa,CAAC,EAAM,EAAM,GAAKC,WAAEA,EAAa,CAAC,IAAM,IAAM,MAAU,IAChGzqB,MAAKmH,EAASA,EACdnH,MAAK0M,EAAUA,EACf1M,MAAKwqB,EAAcA,EACnBxqB,MAAKyqB,EAAcA,CACvB,CACE,EAAAnJ,GACE,MAAMna,EAAQnH,MAAKmH,EACnB,MAAMuF,EAAS1M,MAAK0M,EACpB,MAAMgd,EAAS,IAAIQ,GACnB,MAAMO,EAAazqB,MAAKyqB,EACxB,MAAMD,EAAaxqB,MAAKwqB,EAExBd,EAAOG,WAAW,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,KAEjDH,EAAOS,WAAWhjB,GAClBuiB,EAAOS,WAAWzd,GAClBgd,EAAOG,WAAW,CAAC,IAAM,EAAG,IAE5BH,EAAOG,WAAW,CAACY,EAAW,GAAIA,EAAW,GAAIA,EAAW,KAE5Df,EAAOG,WAAW,CAACW,EAAW,GAAIA,EAAW,GAAIA,EAAW,KAE5Dd,EAAOC,UAAU,IACjBD,EAAOS,WAAW,GAClBT,EAAOS,WAAW,GAClBT,EAAOS,WAAWhjB,GAClBuiB,EAAOS,WAAWzd,GAClBgd,EAAOC,UAAU,GAEjBG,GAAS9pB,MAAK+pB,EAAS,EAAGL,GAE1BA,EAAOC,UAAU,IACjB,OAAOD,EAAO1I,KAClB,CACE,GAAAlH,CAAIwB,EAAGC,EAAGpO,GACRnN,MAAK+pB,EAAQxO,EAAIvb,MAAKmH,EAASmU,GAAKnO,CACxC,CACE,SAAAud,GACE,MAAM1J,EAAQhhB,MAAKshB,IACnB,MAAMoI,EAAS,IAAIW,GACnB,IAAK,MAAM7H,KAAQxB,EAAO,CACxB0I,EAAOF,MAAMhH,EACnB,CACIkH,EAAOre,QACP,MAAMsf,EAASjB,EAAO1I,MACtB,IAAIpY,EAAM,yBACV,IAAK,MAAM4Z,KAAQmI,EAAQ,CACzB/hB,GAAOwhB,GAAa5H,EAC1B,CACI,OAAO5Z,CACX;;;;;;;;;GC1DA,MAAMgiB,GACJjgB,GACAsS,GACAnC,GACAO,GACA,WAAA3B,CAAY2B,EAAQP,EAASmC,EAAOtS,GAClC3K,MAAK2K,EAAQA,EACb3K,MAAKid,EAASA,EACdjd,MAAKqb,EAAUA,EACfrb,MAAK8a,EAAWA,CACpB,CAKE,QAAIlU,GACF,OAAO5G,MAAKqb,EAAQzU,IACxB,CAKE,QAAI+D,GACF,OAAO3K,MAAK2K,CAChB,CAKE,SAAIsS,GACF,OAAOjd,MAAKid,EAAO3Y,IACvB,CAKE,WAAIwW,GACF,OAAO9a,MAAK8a,EAASA,OACzB,CAKE,GAAAU,CAAIF,EAAGC,GACL,MAAM3U,KAAEA,GAAS5G,MAAKqb,EACtB,GAAIC,EAAI,GAAKC,EAAI,GAAKD,GAAK1U,GAAQ2U,GAAK3U,EAAM,CAC5C,MAAM,IAAImC,MAAM,wBAAwBuS,MAAMC,KACpD,CACI,OAAOvb,MAAKqb,EAAQG,IAAIF,EAAGC,EAC/B,CAME,SAAAmP,CAAUG,EAAa,GAAGC,OAAEA,EAASD,EAAa,KAAME,GAAW,IACjEF,EAAala,KAAKqI,IAAI,EAAG6R,GAAc,GACvCC,EAASna,KAAKqI,IAAI,EAAG8R,GAAU,GAC/B,MAAMzP,EAASrb,MAAKqb,EACpB,MAAM2P,EAAa3P,EAAOzU,KAC1B,MAAMA,EAAOikB,EAAaG,EAAaF,EAAS,EAChD,MAAMG,EAAM,IAAIV,GAAS3jB,EAAMA,EAAMmkB,GACrC,MAAM/R,EAAMpS,EAAOkkB,EACnB,IAAK,IAAIvP,EAAI,EAAGA,EAAI3U,EAAM2U,IAAK,CAC7B,IAAK,IAAID,EAAI,EAAGA,EAAI1U,EAAM0U,IAAK,CAC7B,GAAIA,GAAKwP,GAAUxP,EAAItC,GAAOuC,GAAKuP,GAAUvP,EAAIvC,EAAK,CACpD,MAAM2L,EAAU3K,IAASsB,EAAIwP,GAAUD,GACvC,MAAMhG,EAAU7K,IAASuB,EAAIuP,GAAUD,GACvCI,EAAInR,IAAIwB,EAAGC,EAAGF,EAAOG,IAAImJ,EAASE,GAC5C,KAAe,CAELoG,EAAInR,IAAIwB,EAAGC,EAAG,EACxB,CACA,CACA,CACI,OAAO0P,EAAIP,WACf;;;;;;;;;GC7EA,SAASQ,GAAcrT,GACrB,GAAIA,IAAY,GAAI,CAClB,MAAM,IAAI9O,MAAM,iDACpB,CACA,CACA,SAASoiB,GAAc5J,GACrB,KAAMA,aAAmBjI,IAAU,CACjC,MAAM,IAAIvQ,MAAM,kBACpB,CACA,CACA,SAASqiB,GAAYC,GACnB,MAAM9D,KAAEA,GAAS8D,EAEjB,GAAI9D,GAAQ,KAAM,CAChB,MAAOT,GAAQS,EACf,GAAIT,IAAS,OAASA,IAAS,MAAO,CACpC,MAAM,IAAI/d,MAAM,mBACtB,CACI,GAAI+d,IAAS,MAAO,CAClB,MAAM,CAAGU,GAAaD,EACtB,GAAIC,EAAY,GAAKA,EAAY,MAAS5N,OAAOC,UAAU2N,GAAY,CACrE,MAAM,IAAIze,MAAM,oCACxB,CACA,CACA,CACA,CACA,SAASuiB,GAAYrO,GACnB,GAAI,CAAC,IAAK,IAAK,IAAK,KAAKsO,QAAQtO,GAAS,EAAG,CAC3C,MAAM,IAAIlU,MAAM,iCACpB,CACA,CACA,SAASyiB,GAAc1Q,GACrB,GAAIA,IAAY,OAAQ,CACtB,GAAIA,EAAU,GAAKA,EAAU,KAAOlB,OAAOC,UAAUiB,GAAU,CAC7D,MAAM,IAAI/R,MAAM,kBACtB,CACA,CACA;;;;;;;;;GCjBA,MAAMyc,GACJ6F,GACApO,GACAqE,GACAxG,GAKA,WAAApB,EAAY2R,MAAEA,EAAQ,GAAEpO,MAAEA,EAAQ,IAAGnC,QAAEA,EAAU,OAAQwG,OAAQmK,EAAWnK,IAAW,IACrF8J,GAAYC,GACZC,GAAYrO,GACZuO,GAAc1Q,GACd9a,MAAKqrB,EAASA,EACdrrB,MAAKshB,EAAUmK,EACfzrB,MAAK8a,EAAWA,EAChB9a,MAAKid,EAASD,GAAQC,EAC1B,CAME,MAAAqE,IAAUoK,GACR,MAAM1H,EAAUhkB,MAAKid,EACrB,MAAMqE,EAASthB,MAAKshB,EACpB,MAAMiG,KAAEA,GAASvnB,MAAKqrB,EACtB,MAAMM,EAAgB3rB,MAAK8a,EAC3B,MAAMqN,EAAgB,GAEtB,IAAIyD,EAAiB,MAErB,IAAKxE,GAAmB9N,GAAQmI,WAAWjI,OAE3C,IAAK,MAAMqN,KAAW6E,EAAU,CAC9B,MAAM5E,KAAEA,GAASD,EACjB,MAAMwB,EAAO,IAAItG,GACjB,MAAMxW,EAAOsb,EAAQvF,OAAOA,GAC5B,MAAMxb,EAAS6hB,GAAiBd,EAAStb,GAEzC6b,EAAkBD,GAAUkB,EAAMxB,EAASO,GAE3C,GAAIG,GAAQ,OAASqE,EAAgB,CACnCA,EAAiB,KACjBtE,GAAee,EAAMd,EAC7B,CAEML,GAAemB,EAAMvB,GAErB,GAAIE,GAAYH,GAAU,CACxBwB,EAAKjG,OAAO,EAAG,EACvB,CAEM+F,EAAc/G,KAAK,CAAE0F,OAAMuB,OAAM9c,OAAMzF,UAC7C,CACI,IAAIgV,EACJ,GAAI6Q,IAAkB,OAAQ,CAC5B7Q,EAAUwN,GAAuBH,EAAenE,EACtD,KAAW,CACLlJ,EAAUiD,GAAS4N,EAAgB,GACnC,MAAMvD,EAAaF,GAAoBC,EAAerN,GACtD,IAAKgN,GAAQM,EAAYtN,EAASkJ,GAAU,CAC1C,MAAM,IAAIjb,MAAM,qCACxB,CACA,CACI,MAAMmd,EAAS,IAAInE,GACnB,IAAK,MAAM+E,KAAEA,EAAIuB,KAAEA,EAAI9c,KAAEA,EAAIzF,OAAEA,KAAYqiB,EAAe,CACxDjC,EAAO9D,OAAOiG,GACdT,GAAiB1B,EAAQY,EAAMhM,EAAShV,GACxCogB,EAAO9D,OAAO7W,EACpB,CACI,MAAM+R,EAAWxC,EAAQgD,YAAYkG,GACrCwC,GAAiBN,EAAQ5I,EAASG,uBAClC,MAAMiH,EAAYyB,GAAkBD,EAAQ5I,GAC5C,MAAO3S,EAAM0Q,GAAUoN,GAAwB/D,EAAW5J,EAASkJ,GACnE,OAAO,IAAI4G,GAAQvP,EAAQP,EAASkJ,EAASrZ,EACjD;;;;;;;;;GC7FA,MAAMkhB,GACJhU,GACA0J,GAMA,WAAA7H,CAAY7B,EAAS0J,EAAUjI,GAAQmI,YACrCyJ,GAAcrT,GACdsT,GAAc5J,GACdvhB,MAAK6X,EAAWA,EAChB7X,MAAKuhB,EAAWA,CACpB,CAKE,QAAIuF,GACF,OAAOrM,GAAKsM,IAChB,CAKE,WAAIlP,GACF,OAAO7X,MAAK6X,CAChB,CAKE,WAAI0J,GACF,OAAOvhB,MAAKuhB,CAChB,CAME,MAAAD,CAAOA,GACL,MAAM5G,EAAO,IAAIqH,GACjB,MAAMf,EAAQM,EAAOthB,MAAK6X,EAAU7X,MAAKuhB,GACzC,IAAK,MAAMiB,KAAQxB,EAAO,CACxBtG,EAAK0H,OAAOI,EAAM,EACxB,CACI,OAAO9H,CACX,EC9DA,MAAMoR,GAAkB,CACpBC,OAAQ,GACRC,UAAW,MACX3gB,MAAOxJ,eAAgBgM,GAInB,MAAMtJ,KAAEA,EAAI0nB,QAAEA,GAAYpe,GAAU,GACpC,MAAMke,OAAEA,GAAW/rB,KACnB,GAAI+rB,EAAQ,CACR,MAAM5pB,QAAewG,EAAgB,CACjCC,IAAK,uBAAuBmjB,IAC5BljB,OAAQ,WAEZ,GAAI1G,EAAOE,QAAS,CAChBrC,KAAK+rB,OAAS,GACdxnB,K,KACG,CACH0nB,K,KCrBhB,MAAMC,GAAuB,qoDCA7B,MAAM3vB,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCWH0vB,GAAe,MAAAA,E,8CAEhB7nB,KAAe,GAIfK,KAAe,EAIfkB,UAAoBF,UAIpBymB,cAIAhnB,aAECinB,mBAA6B,EAC7BjhB,KAAgB,MAChBkhB,UAAoB,GACpBC,qBAAgC,MAChCC,yBAAoC,MACpCC,aAA6D,UAC7DnrB,MAAgB,GAChBorB,WAAqB,GAErB7hB,GAED8hB,4BAA+BnoB,IACnCsnB,GAAgBE,UAAYxnB,EAC5BxE,KAAKusB,qBAAuB/nB,CAAC,EAGxBooB,UAAoB,GACrBC,oBAAuBroB,IAC3BxE,KAAKssB,UAAY9nB,EACjB,GAAIA,EAAG,CACH,MAAMsoB,EAAU,IAAItH,GACpB,MAAMuH,EAASD,EAAQxL,OAAO,IAAIuK,GAAKrnB,IACvCxE,KAAK4sB,UAAYG,EAAOrC,W,KACrB,CACH1qB,KAAK4sB,UAAY,E,GAKjBI,uBAAyBnrB,MAAOorB,IACpC,MAAMC,QAAYvkB,EAAgB,CAC9BC,IAAK,qBAAqBqkB,WAC1BpkB,OAAQ,QAEZ,GAAIqkB,GAAK7qB,QAAS,CACd,MAAM8qB,EAUFD,EAAIpkB,MAAQ,GAChB,MAAMskB,YAAEA,GAAgBD,EACxBntB,KAAKsB,MAAQ8rB,GAAe,E,CAEhC,GAAItB,GAAgBE,UAAW,CAC3Bjd,YAAW,KACP/O,KAAKgtB,uBAAuBC,EAAI,GACjC,I,GAIHI,wBAA0BxrB,UAC9B,MAAMyrB,EAAOttB,KACbA,KAAKysB,aAAe,UACpBzsB,KAAKwsB,yBAA2B,KAChC,MAAM3e,EAAS7N,KAAKoF,cAAgB,GACpC,MAAMmoB,EAEF,CACAC,IAAK,CACDC,aAAc,GACdC,WAAY,GACZC,OAAQL,EAAKloB,aACbd,KAAMgpB,EAAKhpB,KACXK,KAAM2oB,EAAK3oB,KACXkB,UAAWynB,EAAKznB,UAChBgI,WAGR,MAAMqf,QAAYvkB,EAAgB,CAC9BC,IAAK,oBACLC,OAAQ,OACRC,KAAMykB,IAEV,GAAIL,GAAK7qB,QAAS,CACd,MAAM8qB,EAUFD,EAAIpkB,MAAQ,GAChBgjB,GAAgBC,OAASoB,EAAQS,UAEjC,MAAMC,EAAa,IAAIve,KAAKA,KAAKwe,MAAQ,KAAO,KAChD9tB,KAAK0sB,WAAa,GAAGmB,EAAWE,WAAW7d,WAAW8d,SAAS,EAAG,QAAQH,EAAWI,aAAa/d,WAAW8d,SAAS,EAAG,OACzH,MAAME,EAAe,GAAGC,4BAAqCrC,GAAgBC,SAC7E/rB,KAAK6sB,oBAAoBqB,GACzBluB,KAAK2sB,4BAA4B,MACjC3sB,KAAKysB,aAAe,SAEpBzsB,KAAKgtB,uBAAuBlB,GAAgBC,O,CAEhD/rB,KAAKwsB,yBAA2B,KAAK,EAIhC4B,cAAgB,MACjBC,mBAAqBxsB,UACzB7B,KAAKouB,cAAgB,WACftC,GAAgBzgB,MAAM,CACxB,OAAA4gB,GACIlqB,EAAQS,KAAK,O,IAGrBxC,KAAKouB,cAAgB,MACrBpuB,KAAKqsB,mBAAqB,EAC1BrsB,KAAK0sB,WAAa,GAClB1sB,KAAK2sB,4BAA4B,OACjC3sB,KAAK6sB,oBAAoB,IACzB7sB,KAAKysB,aAAe,UACpBzsB,KAAKsB,MAAQ,GACbtB,KAAKoL,KAAO,KAAK,EAIrB,MAAAjI,GACI,MAAMmrB,EAASC,IACf,GAAID,EAAQ,CACR,OAAO,I,KACJ,CACH,OACIxqB,EAAA,WACIA,EAAK,OAAAC,MAAM,iBACPD,EAAA,OACIC,MAAM,eACNI,QAAS,KACLnE,KAAKoL,KAAO,KACZpL,KAAKqtB,yBAAyB,GACjC,SAILrtB,KAAKoL,MAAQtH,EAAK,OAAAC,MAAM,QACpBD,EAAK,OAAAC,MAAM,kBAEH/D,KAAKusB,qBAAuBzoB,EAAK,OAAAC,MAAM,cACnCD,EAAK,OAAAC,MAAM,kBAEH/D,KAAKysB,eAAiB,UAAY3oB,EAAK,OAAAC,MAAM,SAASE,IAAKjE,KAAK4sB,YAGhE5sB,KAAKysB,eAAiB,WAAa3oB,EAAM,QAAAC,MAAM,WAAuB,UAGtE/D,KAAKysB,eAAiB,WAAa3oB,EAAA,OAC/BC,MAAM,eACNI,QAASnE,KAAKqtB,yBAAuB,SAIjDvpB,EAAK,OAAAC,MAAM,eAAa,WACX/D,KAAK0sB,YAElB5oB,EAAK,OAAAC,MAAM,aAEL,iBAEF/D,KAAKysB,eAAiB,UAAY3oB,EAAA,OAC9BE,MAAO,CAAEwqB,UAAW,OAAQC,SAAU,QACtC1qB,MAAM,eACNI,QAAS,KACLuqB,UAAUC,UACLC,UAAU5uB,KAAKssB,WACfuC,MAAK,KACF9sB,EAAQM,QAAQ,UAAU,IAE7BysB,OAAM,KACH/sB,EAAQC,MAAM,OAAO,GACvB,GAEA,YAEZhC,KAAKwsB,0BAA4B1oB,EAAM,QAAAC,MAAM,WAAS,UAGpED,EAAA,OAAKE,MAAO,CAAEwqB,UAAW,WAEfxuB,KAAKsB,OAAOwE,QAAUhC,EAAA,YACpBirB,SAAQ,KACRhrB,MAAM,kBACNzC,MAAOtB,KAAKsB,MACZwP,SAAWtM,IACPxE,KAAKsB,MAAQkD,EAAEnD,OAAOC,KAAK,KAK3CwC,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,kBAAkBI,QAASnE,KAAKquB,oBAA4B,MACvEvqB,EAAA,OAAKC,MAAM,kBAAkBI,QAAS,KAClC,IAAKnE,KAAKsB,MAAO,CACbS,EAAQS,KAAK,SACb,M,CAEJ,GAAIxC,KAAKsB,MAAMwE,OAAS9F,KAAK6F,UAAW,CACpC9D,EAAQS,KAAK,WAAWxC,KAAK6F,gBAC7B,M,CAEJ7F,KAAK6K,GAAGtK,KAAKP,KAAKsB,OAClBtB,KAAKquB,oBAAoB,GAC5B,S,wBC9OrC,MAAMvC,GAAkB,CACpBC,OAAQ,GACRC,UAAW,MACX3gB,MAAOxJ,eAAgBgM,GAInB,MAAMtJ,KAAEA,EAAI0nB,QAAEA,GAAYpe,GAAU,GACpC,MAAMke,OAAEA,GAAW/rB,KACnB,GAAI+rB,EAAQ,CACR,MAAM5pB,QAAewG,EAAgB,CACjCC,IAAK,uBAAuBmjB,IAC5BljB,OAAQ,WAEZ,GAAI1G,EAAOE,QAAS,CAChBrC,KAAK+rB,OAAS,GACdxnB,K,KACG,CACH0nB,K,KCrBhB,MAAM+C,GAAwB,u7CCA9B,MAAMzyB,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCWH0vB,GAAe,M,8CAIhBlnB,SAAoB,MAIpBE,qBAAiC,GAIjC8pB,aAAuBC,SAIvBlqB,YAAsBkqB,SAItB9C,cAIAhnB,aACCinB,mBAA6B,EAC7BjhB,KAAgB,MAChBkhB,UAAoB,GACpBC,qBAAgC,MAChCC,yBAAoC,MACpCC,aAA6D,UAC7DnrB,MAAe,GACforB,WAAqB,GAErB7hB,GAED8hB,4BAA+BnoB,IACnCsnB,GAAgBE,UAAYxnB,EAC5BxE,KAAKusB,qBAAuB/nB,CAAC,EAGxBooB,UAAoB,GACrBC,oBAAuBroB,IAC3BxE,KAAKssB,UAAY9nB,EACjB,GAAIA,EAAG,CACH,MAAMsoB,EAAU,IAAItH,GACpB,MAAMuH,EAASD,EAAQxL,OAAO,IAAIuK,GAAKrnB,IACvCxE,KAAK4sB,UAAYG,EAAOrC,W,KACrB,CACH1qB,KAAK4sB,UAAY,E,GAKjBI,uBAAyBnrB,MAAOorB,IACpC,MAAMC,QAAYvkB,EAAgB,CAC9BC,IAAK,qBAAqBqkB,WAC1BpkB,OAAQ,QAEZ,GAAIqkB,GAAK7qB,QAAS,CACd,MAAM8qB,EASFD,EAAIpkB,MAAQ,GAChB,MAAMqmB,UAAEA,GAAchC,EACtBntB,KAAKsB,MAAQ6tB,GAAa,E,CAE9B,GAAIrD,GAAgBE,UAAW,CAC3Bjd,YAAW,KACP/O,KAAKgtB,uBAAuBC,EAAI,GACjC,I,GAIHI,wBAA0BxrB,UAC9B,MAAMyrB,EAAOttB,KACbA,KAAKysB,aAAe,UACpBzsB,KAAKwsB,yBAA2B,KAChC,MAAM3e,EAAS7N,KAAKoF,cAAgB,GACpC,MAAMmoB,EAIF,CACA6B,iBAAkB,MAClB/pB,KAAMwI,EAAOxI,KACbmoB,IAAK,CACD6B,QAAS/B,EAAKtoB,YACdsqB,SAAUhC,EAAKroB,SAAWqoB,EAAK2B,aAAe,EAC9CxB,aAAc,GACdC,WAAY,GACZ6B,aAAcjC,EAAKnoB,qBAAqByC,KAAK,KAC7C+lB,OAAQL,EAAKloB,eAGrB,MAAM8nB,QAAYvkB,EAAgB,CAC9BC,IAAK,oBACLC,OAAQ,OACRC,KAAMykB,IAEV,GAAIL,GAAK7qB,QAAS,CACd,MAAM8qB,EAWFD,EAAIpkB,MAAQ,GAChBgjB,GAAgBC,OAASoB,EAAQS,UAEjC,MAAMC,EAAa,IAAIve,KAAKA,KAAKwe,MAAQ,KAAO,KAChD9tB,KAAK0sB,WAAa,GAAGmB,EAAWE,WAAW7d,WAAW8d,SAAS,EAAG,QAAQH,EAAWI,aAAa/d,WAAW8d,SAAS,EAAG,OACzH,MAAME,EAAe,GAAGC,iCAA0CrC,GAAgBC,SAClF/rB,KAAK6sB,oBAAoBqB,GACzBluB,KAAK2sB,4BAA4B,MACjC3sB,KAAKysB,aAAe,SAEpBzsB,KAAKgtB,uBAAuBlB,GAAgBC,O,CAEhD/rB,KAAKwsB,yBAA2B,KAAK,EAIhC4B,cAAgB,MACjBC,mBAAqBxsB,UACzB7B,KAAKouB,cAAgB,WACftC,GAAgBzgB,MAAM,CACxB,OAAA4gB,GACIlqB,EAAQS,KAAK,O,IAGrBxC,KAAKouB,cAAgB,MACrBpuB,KAAKqsB,mBAAqB,EAC1BrsB,KAAK0sB,WAAa,GAClB1sB,KAAK2sB,4BAA4B,OACjC3sB,KAAK6sB,oBAAoB,IACzB7sB,KAAKysB,aAAe,UACpBzsB,KAAKsB,MAAQ,GACbtB,KAAKoL,KAAO,KAAK,EAIb0D,aAAejN,MAAO0D,IAC1B,MAAM2nB,QAAYvkB,EAAgB,CAC9BC,IAAK,qBAAqBkjB,GAAgBC,cAC1CljB,OAAQ,SACRgF,OAAQ,CACJ+f,UAAW9B,GAAgBC,OAC3BxmB,aAGR,GAAI2nB,GAAK7qB,QAAS,CACdrC,KAAKsB,MAAQtB,KAAKsB,MAAMqG,QAAO6nB,GAAMA,EAAGjqB,UAAYA,G,GAK5D,MAAApC,GACI,MAAMmrB,EAASC,IACf,GAAID,EAAQ,CACR,OAAO,I,KACJ,CACH,OACIxqB,EAAA,WACIA,EAAK,OAAAC,MAAM,iBACPD,EAAA,OACIC,MAAM,eACNI,QAAS,KACL,GAAInE,KAAKivB,aAAe,EAAG,CACvBltB,EAAQS,KAAK,cACb,M,CAEJxC,KAAKoL,KAAO,KACZpL,KAAKqtB,yBAAyB,GACjC,SAILrtB,KAAKoL,MAAQtH,EAAK,OAAAC,MAAM,QACpBD,EAAK,OAAAC,MAAM,kBAEH/D,KAAKusB,qBAAuBzoB,EAAK,OAAAC,MAAM,cACnCD,EAAK,OAAAC,MAAM,kBAEH/D,KAAKysB,eAAiB,UAAY3oB,EAAK,OAAAC,MAAM,SAASE,IAAKjE,KAAK4sB,YAGhE5sB,KAAKysB,eAAiB,WAAa3oB,EAAM,QAAAC,MAAM,WAAuB,UAGtE/D,KAAKysB,eAAiB,WAAa3oB,EAAA,OAC/BC,MAAM,eACNI,QAASnE,KAAKqtB,yBAAuB,SAIjDvpB,EAAK,OAAAC,MAAM,eAAa,WACX/D,KAAK0sB,YAElB5oB,EAAK,OAAAC,MAAM,aAEL,iBAEF/D,KAAKysB,eAAiB,UAAY3oB,EAAA,OAC9BE,MAAO,CAAEwqB,UAAW,OAAQC,SAAU,QACtC1qB,MAAM,eACNI,QAAS,KACLuqB,UAAUC,UACLC,UAAU5uB,KAAKssB,WACfuC,MAAK,KACF9sB,EAAQM,QAAQ,UAAU,IAE7BysB,OAAM,KACH/sB,EAAQC,MAAM,OAAO,GACvB,GAEA,YAEZhC,KAAKwsB,0BAA4B1oB,EAAM,QAAAC,MAAM,WAAS,UAGpED,EAAK,OAAAE,MAAO,CAAEwqB,UAAW,SAEjBxuB,KAAKsB,OAAOiP,OAAM,CAACkf,EAAM5N,IACd/d,EAAA,OAAKC,MAAM,YAAYyD,IAAKqa,GAC/B/d,EAAK,OAAAC,MAAM,qBACPD,EAAM,QAAAC,MAAM,aAAqB,MACjCD,EAAM,QAAAC,MAAM,aAAa0rB,GAAMjqB,YAEnC1B,EAAQ,UAAAC,MAAM,cAAcI,QAAUK,IAClCA,EAAE0M,kBACFlR,KAAK8O,aAAa2gB,EAAKlqB,QAAQ,GAClC,SAKjBzB,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,kBAAkBI,QAASnE,KAAKquB,oBAA4B,MACvEvqB,EAAA,OAAKC,MAAM,kBAAkBI,QAAS,KAClC,GAAInE,KAAKsB,MAAMwE,OAAS9F,KAAKivB,aAAc,CACvCltB,EAAQS,KAAK,SAASxC,KAAKivB,4BAC3B,M,CAEJjvB,KAAK6K,GAAGtK,KAAKP,KAAKsB,OAClBtB,KAAKquB,oBAAoB,GAC5B,S,wBC5QrC,MAAMqB,GAAkB,GCAxB,MAAMnzB,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCiBHkzB,GAAS,M,oVAIV/yB,WAAqB,OAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAOtBC,aAAsC,GAKtCC,qBAAgC,MAK/BM,cAKAC,eAKAC,kBAKAC,kBAKAC,aAKAC,eAODiT,gBAAuC,SAEtC5S,aAA4B,KAC5BC,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,M,iCAKzBO,eAAyB,GACzBC,aAAwB,MAEzBC,qBACAC,oBAGR,iBAAAE,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAK3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKkS,oBACLlS,KAAKnB,cAAgB,MACrBmB,KAAKZ,eAAiB,E,KACnB,CACH,GAAIY,KAAKvC,cAAgBuC,KAAKvC,aAAasF,SAAU,CACjD/C,KAAKZ,eAAiBY,KAAKvC,aAAasF,Q,OAGtC5C,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,gBAAmB4C,KAAKvC,cAAcmyB,WAAa5vB,KAAKvC,cAAcsF,SAAW,CACtF/C,KAAKnB,cAAgB,I,GAMjC,iBAAAuB,GAII,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAElBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAG5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAEzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAKL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnB4R,iBAAoBhR,IACxB,MAAMK,EAAQL,EAAME,OACpB,GAAIG,EAAM4Q,OAAS5Q,EAAM4Q,MAAMtM,OAAS,EAAG,CACvC9F,KAAKtB,aAAe8C,EAAM4Q,MAAM,E,GAIhCC,kBAAoB,KACxB,MAAMC,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D0G,GAAW3D,OAAO,EAGduD,kBAAoB,KACxBlS,KAAKtB,aAAe,KACpBsB,KAAKpB,iBAAmB,KACxB,MAAM0T,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D,GAAI0G,EAAW,CACXA,EAAUhR,MAAQ,E,GAIlB,gBAAMiR,GACV,IAAKvS,KAAKtB,aAAc,OAExBsB,KAAKrB,YAAc,KAEnB,IAEI,MAAMwD,QAAeqQ,EAAoBxS,KAAKtB,aAAc,GACzD,CACC2G,KAAQ,CAAC,WAGbrF,KAAKpB,iBAAmBuD,EACxBnC,KAAKhC,cAAcuC,KAAK4B,E,CAC1B,MAAOH,GACLiH,QAAQjH,MAAM,UAAWA,GACzBhC,KAAKkS,oBACLO,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,aACRC,UAAW,iBACX1J,MAAO,WAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,c,SAGbtC,KAAKrB,YAAc,K,EAInBuC,2BAA8BC,IAClC,MAAMC,EAAWD,EAAME,OACvBrB,KAAKZ,eAAiBgC,EAASE,KAAK,EAGhCwB,qBAAuBjB,UAC3B,IAAK7B,KAAKtB,aAAc,CACpBoU,MAAM,WACN,M,CAIJ,IAAK9S,KAAKvC,cAAcsF,WAAa/C,KAAKZ,eAAe0C,OAAQ,CAC7DgR,MAAM,WACN,M,CAGJ9S,KAAKX,aAAe,KAEpB,IAEI,IAAKW,KAAKpB,iBAAkB,OAClBoB,KAAKuS,aACX,IAAKvS,KAAKpB,iBAAkB,CACxBoB,KAAKX,aAAe,MACpB,M,EAKRW,KAAKnB,cAAgB,I,CACvB,MAAOmD,GACLiH,QAAQjH,MAAM,WAAYA,GAC1ByQ,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,uBACRC,UAAW,iBACX1J,MAAO,YAEX1I,EAAcqS,UAAU,CACpB7Q,MAAOA,EACPM,QAAS,e,SAGbtC,KAAKX,aAAe,K,GAI5B,MAAA8D,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAIxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM0Y,EAAc7T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAasF,UAGnE,MAAMgQ,EAAiBrP,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAamyB,WAGtE,MAAMnY,EAAgB/T,QAAQ1D,KAAKvC,cAAcmyB,WAAa5vB,KAAKvC,cAAcsF,UAEjF,OACIe,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAO5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmBqa,GAC7C3T,EAAK,OAAAC,MAAM,oBAELwT,GACEzT,EAAK,OAAAC,MAAM,oBACPD,EAAO,SAAAM,QAAQ,mBAAsC,gBACrDN,EAAA,YACIW,GAAG,kBACHV,MAAM,2BACNW,YAAY,wBACZC,KAAM,EACNrD,MAAOtB,KAAKZ,eACZwF,QAAS5E,KAAKkB,+BAMxB6R,GACEjP,EAAK,OAAAC,MAAM,yBACPD,EAAqB,uBACrBA,EAAK,OAAAC,MAAM,cAAcI,QAASnE,KAAKqS,mBAClCrS,KAAKtB,aACFoF,EAAK,OAAAC,MAAM,aACPD,EAAK,OAAAC,MAAM,qBACPD,EAAM,QAAAC,MAAM,aAAqB,MACjCD,EAAM,QAAAC,MAAM,aAAa/D,KAAKtB,aAAa4F,OAE/CR,EAAQ,UAAAC,MAAM,cAAcI,QAAUK,IAClCA,EAAE0M,kBACFlR,KAAKkS,mBAAmB,GAC3B,MAGLpO,EAAA,OAAKC,MAAM,sBACPD,EAAK,OAAAG,IAAI,kEACTH,EAAG,KAAAC,MAAM,eAA0B,YACnCD,EAAG,KAAAC,MAAM,eAAa,yCAO1CD,EAAA,UACIC,MAAM,gBACNc,UAAYkO,IAAmB/S,KAAKtB,eAAmB6Y,IAAgBvX,KAAKZ,eAAe0C,QAAW9B,KAAKrB,aAAeqB,KAAKX,aAC/H8E,QAASnE,KAAK8C,sBAEb9C,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,kCAIrFlC,EAAA,SACIO,KAAK,OACLN,MAAM,aACN+M,SAAU9Q,KAAKmS,oBAMzB3O,GACEM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBM,WAAYwC,KAAKxC,WACjBE,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACN7I,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRmyB,UAAW5vB,KAAKvC,cAAcmyB,WAAa5vB,KAAKpB,kBAAkB2G,QAClEsqB,WAAY7vB,KAAKvC,cAAcoyB,YAAc7vB,KAAKpB,kBAAkB4G,UACpEzC,SAAU/C,KAAKvC,cAAcsF,UAAY/C,KAAKZ,gBAElDd,cAAc,W,+GC/b9C,MAAMwxB,GAAmB,4FCAzB,MAAMvzB,GAAY,g/MCAlB,MAAME,GAAU,4wB,y0NCAhB,MAAMszB,GAAe,kHCArB,MAAMxzB,GAAY,g/MCAlB,MAAME,GAAU,4wB,MCgBHuzB,GAAS,M,2GAIV/qB,SAAoB,MAIpBC,iBAA4B,MAK5BC,qBAAiC,GAIjC8pB,aAAuBC,SAIvBlqB,YAAsBkqB,SAItB9C,cAIAhnB,aAIA2M,WAAqB,SAIrBzM,gBAIAT,SAAoB,MAInBorB,aAIAC,a,iCAIAC,cAAsD,KAE/D,iBAAA/vB,GAEI,GAAIJ,KAAKsF,iBAAmBtF,KAAKsF,gBAAgBQ,OAAS,EAAG,CACzD9F,KAAKmwB,cAAgBnwB,KAAKsF,gBAAgBiL,KAAI6f,IAAI,IAC3CA,EACHC,MAAOC,EAAgBC,W,EAMnC,oBAAMrtB,GACF,QAASlD,KAAKmwB,eAAeK,MAAKf,GAAQA,EAAKY,QAAUC,EAAgBG,W,CAO7E,wBAAMC,GACF1wB,KAAKmwB,cAAgB,KACrBnwB,KAAKkS,mB,CAGDG,kBAAoB,KACxB,GAAIrS,KAAK6E,SAAU,OACnB,MAAMyN,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D0G,GAAW3D,OAAO,EAGduD,kBAAoB,KACxB,MAAMI,EAAYtS,KAAK0L,YAAYC,YAAYC,cAAc,eAC7D,GAAI0G,EAAW,CACXA,EAAUhR,MAAQ,E,GAIlB,gBAAMiR,CAAW6d,GACrB,IACI,MAAMjuB,QAAeqQ,EAAoB4d,EAAMpwB,KAAKosB,eAAiB,GAAIpsB,KAAKoF,cAAgB,IAC9F,MAAO,IACAjD,EACHiuB,OACA5qB,UAAW4qB,EAAK9rB,KAChBmB,UAAW2qB,EAAKxpB,KAChBypB,MAAOC,EAAgBC,Q,CAE7B,MAAOvuB,GACLhC,KAAKkS,oBACLO,EAAeC,aAAa1Q,EAAO,CAC/B2Q,OAAQ,aACRC,UAAW,iBACX1J,MAAO,WAEXlJ,KAAKiwB,aAAa1vB,KAAK,CACnByB,MAAOA,EACPM,QAAS,eAEb,MAAO,CACH8tB,OACApuB,QACAquB,MAAOC,EAAgBK,O,EAK3Bxe,iBAAmBtQ,MAAOV,IAC9B,MAAMK,EAAQL,EAAME,OAEpB,GAAIrB,KAAKiF,SAAU,CAEf,MAAMmN,EAAQwe,MAAM1U,KAAK1a,EAAM4Q,OAAS,IACxC,GAAIA,EAAMtM,SAAW,EAAG,OAGxB,MAAM+qB,EAAmB7wB,KAAKmwB,eAAerqB,QAAU,EACvD,MAAMgrB,EAAiB9wB,KAAKivB,aAAe4B,EAC3C,GAAIze,EAAMtM,OAASgrB,EAAgB,CAC/B/uB,EAAQS,KAAK,UAAUxC,KAAKivB,0BAA0B4B,OACtD,M,CAGJ,MAAME,EAAqB,GAC3B,MAAMC,EAAyB,GAG/B5e,EAAMsE,SAAQ0Z,IAEV,GAAIpwB,KAAKmF,sBAAsBW,OAAQ,CACnC,MAAMmrB,EAAS,IAAMb,EAAK9rB,KAAK4sB,MAAM,KAAKC,OAAOC,cACjD,IAAKpxB,KAAKmF,qBAAqB0Q,SAASob,GAAS,CAC7CD,EAAa5P,KAAK,GAAGgP,EAAK9rB,eAC1B,M,EAIR,GAAItE,KAAKgF,YAAcorB,EAAKxpB,KAAM,CAC9BoqB,EAAa5P,KAAK,GAAGgP,EAAK9rB,cAC1B,M,CAEJysB,EAAW3P,KAAKgP,EAAK,IAIzB,GAAIY,EAAalrB,OAAS,EAAG,CACzB,MAAMurB,EAAmBrxB,KAAKmF,sBAAsBW,OAAS9F,KAAKmF,qBAAqByC,KAAK,KAAO,GACnG,MAAM0pB,EAActxB,KAAKgF,cAAgBkqB,SAAWqC,EAAevxB,KAAKgF,aAAe,GACvFjD,EAAQS,KAAK,YAAYwuB,EAAappB,KAAK,QAAQypB,EAAmB,QAAQA,KAAsB,KAAKC,EAAc,UAAUA,KAAiB,K,CAGtJ,GAAIP,EAAWjrB,SAAW,EAAG,CACzB9F,KAAKkS,oBACL,M,CAIJ,MAAMsf,EAA8CT,EAAWxgB,KAAI6f,IAAI,CACnEA,OACA5qB,UAAW4qB,EAAK9rB,KAChBmB,UAAW2qB,EAAKxpB,KAChBypB,MAAOC,EAAgBG,UACvBlrB,QAAS,GACTvD,MAAO2D,cAIX3F,KAAKmwB,cAAgB,IACbnwB,KAAKmwB,eAAiB,MACvBqB,GAIP,IAAK,IAAIpc,EAAI,EAAGA,EAAI2b,EAAWjrB,OAAQsP,IAAK,CACxC,MAAMgb,EAAOW,EAAW3b,GACxB,MAAMqc,QAAqBzxB,KAAKuS,WAAW6d,GAG3C,GAAIpwB,KAAKmwB,cAAe,CACpB,MAAMU,EAAmB7wB,KAAKmwB,cAAcrqB,OAC5C,MAAM4rB,EAAcb,EAAmBE,EAAWjrB,OAASsP,EAC3D,GAAIsc,GAAe,GAAKA,EAAc1xB,KAAKmwB,cAAcrqB,OAAQ,CAC7D9F,KAAKmwB,cAAcuB,GAAeD,EAElCzxB,KAAKmwB,cAAgB,IAAInwB,KAAKmwB,c,GAK1CnwB,KAAKkS,oBACLlS,KAAK2xB,kB,KACF,CAEH,MAAMvB,EAAO5uB,EAAM4Q,QAAQ,GAC3B,IAAKge,EAAM,OAEX,GAAIpwB,KAAKmF,sBAAsBW,OAAQ,CACnC,MAAMmrB,EAAS,IAAMb,EAAK9rB,KAAK4sB,MAAM,KAAKC,OAAOC,cACjD,IAAKpxB,KAAKmF,qBAAqB0Q,SAASob,GAAS,CAC7ClvB,EAAQS,KAAK,OAAOxC,KAAKmF,qBAAqByC,KAAK,cACnD,M,EAIR,GAAI5H,KAAKgF,YAAcorB,EAAKxpB,KAAM,CAC9B7E,EAAQS,KAAK,YAAY+uB,EAAevxB,KAAKgF,cAAgB,OAC7D,M,CAEJhF,KAAKmwB,cAAgB,CAAC,CAClBC,OACA5qB,UAAW4qB,EAAK9rB,KAChBmB,UAAW2qB,EAAKxpB,KAChBypB,MAAOC,EAAgBG,UACvBlrB,QAAS,GACTvD,MAAO2D,YAEX,MAAM8rB,QAAqBzxB,KAAKuS,WAAW6d,GAC3CpwB,KAAKmwB,cAAgB,CAACsB,GACtBzxB,KAAKkS,oBACLlS,KAAK2xB,kB,GAILA,iBAAmB,KACvB3xB,KAAKkwB,aAAa3vB,KAAKP,KAAKmwB,eAAexoB,QAAO8nB,GAAQA,EAAKY,QAAUC,EAAgBC,UAAShgB,OAAMkf,IAAI,CACxGlqB,QAASkqB,EAAKlqB,QACdC,UAAWiqB,EAAKjqB,UAChBC,UAAWgqB,EAAKhqB,UAChBC,IAAK+pB,EAAK/pB,QACV,EAGA,SAAAksB,GACJ,OAAO9tB,EAAA,OAAKE,MAAO,CAAEmD,MAAO,WAElBnH,KAAKkF,kBAAoBpB,EACvB,yBAAAmB,SAAUjF,KAAKiF,SACfE,qBAAsBnF,KAAKmF,qBAC3B8pB,aAAcjvB,KAAKivB,aACnBjqB,YAAahF,KAAKgF,YAClBonB,cAAepsB,KAAKosB,cACpBhnB,aAAcpF,KAAKoF,aACnBb,KAAMC,IACFxE,KAAKmwB,cAAgB,IACbnwB,KAAKmwB,eAAiB,OACtB3rB,EAAE5B,QAAU,IAAI2N,KAAIkf,IAAI,IACrBA,EACHY,MAAOC,EAAgBC,aAG/BvwB,KAAK2xB,kBAAkB,IAInC7tB,EAAK,OAAAC,MAAM,qBAAqBI,QAASnE,KAAKqS,mBAC1CvO,EAAK,OAAAG,IAAI,kEACTH,EAAA,KAAGC,MAAM,eAAe/D,KAAK+R,cAEvB/R,KAAKmF,sBAAsBW,QAAUhC,EAAA,KAAGC,MAAM,eAAa,MAAK/D,KAAKmF,qBAAqByC,KAAK,KAAa,UAG5G5H,KAAKgF,aAAehF,KAAKgF,cAAgBkqB,UAAYprB,EAAG,KAAAC,MAAM,eAAa,YAAWwtB,EAAevxB,KAAKgF,cAAgB,GAAQ,OAGlIhF,KAAKivB,cAAgBjvB,KAAKivB,eAAiBC,UAAYprB,EAAG,KAAAC,MAAM,eAAa,QAAO/D,KAAKivB,aAAsB,U,CAMjI,MAAA9rB,GACI,OACIW,EAAA,OAAA0D,IAAA,4CACI1D,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,yBACPD,EAAK,OAAA0D,IAAA,2CAAAzD,MAAM,eACPD,EAAA,OAAA0D,IAAA,4CAEQxH,KAAKmwB,eAAe5f,OAAM,CAACkf,EAAM5N,IACtB/d,EAAA,OAAKC,MAAM,aACdD,EAAK,OAAAC,MAAM,qBACPD,EAAM,QAAAC,MAAM,aAAqB,MACjCD,EAAA,QAAMC,MAAM,YAAYC,MAAOyrB,EAAKY,QAAUC,EAAgBK,OAAS,CAAExjB,MAAO,MAAO0kB,eAAgB,gBAAmBlsB,WAAY8pB,GAAMjqB,WAExIiqB,EAAKY,QAAUC,EAAgBK,QAAU7sB,EAAM,QAAAE,MAAO,CAAEmJ,MAAO,MAAO2kB,WAAY,QAAO,IAAIrC,EAAKztB,OAAOM,SAAW,OAAM,OAGhItC,KAAK6E,UAAYf,EAAA,UAAQC,MAAM,cAAcI,QAAUK,IACrDA,EAAE0M,kBACFlR,KAAKmwB,cAAgBnwB,KAAKmwB,eAAexoB,QAAO,CAACoqB,EAAGC,IAAcnQ,IAAUmQ,IAC5EhyB,KAAK2xB,kBAAkB,GAC1B,WAQhB3xB,KAAK6E,WAAa7E,KAAKiF,SAAWnB,EAAK,OAAAC,MAAM,mBAErC/D,KAAKmwB,eAAerqB,QAAU,GAAK9F,KAAKivB,cAAgBjvB,KAAK4xB,aAE7D9tB,EAAA,OAAKC,MAAM,mBAEX/D,KAAKmwB,eAAerqB,QAAU9F,KAAK4xB,eAKpD9tB,EACI,SAAA0D,IAAA,2CAAAnD,KAAK,OACLN,MAAM,aACNkB,SAAUjF,KAAKiF,SACf6L,SAAU9Q,KAAKmS,mB,uBCvVnC,MAAM8f,GAAyB,srdCA/B,MAAMx1B,GAAU,4wB,064BCAhB,MAAMy1B,GAAqB,23XCA3B,MAAMz1B,GAAU,4wB,s0jBCAhB,MAAMF,GAAY,g/MCAlB,MAAM41B,GAAkB,2zBCAxB,MAAM11B,GAAU,4wB,MCmBH21B,GAAS,M,kVAIVx1B,WAAqB,SAKCC,MAKLC,OAAkB,MAKlCC,YAKDC,KAKAC,OAAkB,IAKlBC,aAAwB,KAKxBC,YAAuB,KAKNC,eAKjBC,aAAuB,QAKvBG,WAAsB,MAQtBC,aAAuC,GAKvCC,qBAAgC,MAKhCwH,iBAA4B,MAM3BlH,cAKAC,eAKAC,kBAKAm0B,iBAQAj0B,aAKAC,eAODiT,gBAAuC,SAEtC3S,YAAuB,MACvBC,iBAA8C,KAC9CC,cAAyB,MACzBQ,aAAwB,MACxBizB,iBAAmC,O,iCAKpChzB,qBACAC,oBACA0D,aAGR,iBAAAxD,CAAkBC,GAEd,GAAIA,GAAYA,IAAaC,EAAUC,WAAY,CAC/CD,EAAUE,SAASH,E,EAM3B,wBAAMI,CAAmBC,GACrB,IAAKA,EAAU,CAEXC,KAAKnB,cAAgB,K,KAElB,CACH,GAAImB,KAAKvC,cAAgBuC,KAAKvC,aAAa4G,KAAM,CAE7C,MAAMA,EAAOrE,KAAKvC,aAAa4G,KAC/B,GAAIA,IAAS,QAAUA,IAAS,QAAUA,IAAS,OAAQ,CACvDrE,KAAKsyB,iBAAmBjuB,C,QAI1BlE,EAAaH,KAAKnD,OAGxB,GAAImD,KAAK5C,gBAAmB4C,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAc4G,KAAO,CACjFrE,KAAKnB,cAAgB,I,GAOjC,iBAAAuB,GAGI,GAAIJ,KAAK/C,OAAQ,CACboD,EAAYC,QAAQ,eAAgBN,KAAK/C,O,CAE7C,GAAI+C,KAAKnD,MAAO,CACZ8C,EAAUE,SAASG,KAAKnD,M,CAE5BsD,EAAaH,KAAKnD,OAGlBmD,KAAKV,qBAAuB,KACxBU,KAAK5B,aAAamC,MAAM,EAG5BP,KAAKT,oBAAsBiB,EAAcC,kBAAkBC,IACvDV,KAAK3B,eAAekC,KAAKG,EAAY,IAEzCC,SAASC,iBAAiB,oBAAqBZ,KAAKV,qB,CAGxD,oBAAAuB,GAEIF,SAASG,oBAAoB,oBAAqBd,KAAKV,sBAEvD,GAAIU,KAAKT,oBAAqB,CAC1BS,KAAKT,qB,EAIL0B,YAAc,KAClBjB,KAAKjD,YAAYwD,MAAM,EAGnBgyB,qBAAwBluB,IAC5BrE,KAAKsyB,iBAAmBjuB,CAAI,EAGxBmuB,oBAAsB3wB,UAE1B,IAAK7B,KAAKvC,cAAcmG,WAAa5D,KAAKpB,iBAAkB,CACxDmD,EAAQS,KAAK,SACb,M,CAGJ,SAAUxC,KAAKiD,cAAcC,oBAAoB,CAC7CnB,EAAQS,KAAK,aACb,M,CAEJxC,KAAKX,aAAe,KACpBW,KAAKnB,cAAgB,KACrBmB,KAAKX,aAAe,KAAK,EAKrBozB,uBAA0BtxB,IAC9BnB,KAAKqyB,iBAAiB9xB,KAAK,IACpBY,EAAMyB,OACTyB,KAAMrE,KAAKsyB,kBACb,EAIN,MAAAnvB,GACI,IAAKnD,KAAKlD,OAAQ,OAAO,KAEzB,MAAMsG,EAAa,CACfnG,OAAQoG,OAAOrD,KAAK/C,SAGxB,MAAMqG,EAAiB,CACnB,kBAAmB,KACnB9F,WAAcwC,KAAKxC,WACnB,YAAa,MAGjB,MAAM+F,EAAe,CACjB,gBAAiB,KACjB,qBAAsBvD,KAAKxC,YAI/B,MAAMgG,EAAYxD,KAAK5C,iBAAmB4C,KAAKnB,cAG/C,MAAM2Y,EAAmB9T,QAAQ1D,KAAKvC,cAAgBuC,KAAKvC,aAAamG,UAGxE,MAAM8uB,EAAiBhvB,QAAQ1D,KAAKvC,cAAcmG,UAAY5D,KAAKvC,cAAc4G,MAEjF,OACIP,EAAA,OAAKC,MAAOR,EAAcS,MAAOZ,GAC7BU,EAAK,OAAAC,MAAOT,GACPtD,KAAK9C,cACF4G,EAAK,OAAAC,MAAM,gBACPD,EAAK,OAAAC,MAAM,eACN/D,KAAKhD,MAAQ8G,EAAK,OAAAG,IAAKjE,KAAKhD,KAAM+G,MAAM,cAAcG,IAAI,SAC3DJ,EAAA,WAAM9D,KAAKpD,aAEdoD,KAAK7C,aACF2G,EAAQ,UAAAC,MAAM,eAAeI,QAASnE,KAAKiB,aACvC6C,EAAc,oBAQ5B9D,KAAKnB,gBAAkBmB,KAAK5C,iBAAmBs1B,GAC7C5uB,EAAK,OAAAC,MAAM,mBAGPD,EAAK,OAAAC,MAAM,qBACPD,EAAqB,uBACrBA,EAAK,OAAAC,MAAM,qBACPD,EAAA,OACIC,MAAO,oBAAoB/D,KAAKsyB,mBAAqB,OAAS,WAAa,KAC3EnuB,QAAS,IAAMnE,KAAKuyB,qBAAqB,SAEzCzuB,EAAK,OAAAC,MAAM,eAAsB,MACjCD,EAAA,OAAKC,MAAM,gBAAc,SAE7BD,EAAA,OACIC,MAAO,oBAAoB/D,KAAKsyB,mBAAqB,OAAS,WAAa,KAC3EnuB,QAAS,IAAMnE,KAAKuyB,qBAAqB,SAEzCzuB,EAAK,OAAAC,MAAM,eAAsB,MACjCD,EAAA,OAAKC,MAAM,gBAAc,SAE7BD,EAAA,OACIC,MAAO,oBAAoB/D,KAAKsyB,mBAAqB,OAAS,WAAa,KAC3EnuB,QAAS,IAAMnE,KAAKuyB,qBAAqB,SAEzCzuB,EAAK,OAAAC,MAAM,eAAsB,MACjCD,EAAA,OAAKC,MAAM,gBAAyB,YAM9CyT,GACE1T,EAAK,OAAAC,MAAM,yBACPD,EAAmB,qBACnBA,EACI,cAAAgB,IAAKC,GAAM/E,KAAKiD,aAAe8B,EAC/BC,YAAa,GAAK,KAAO,KACzBC,SAAU,MACVC,iBAAkBlF,KAAKkF,iBACvBC,qBAAsB,CAAC,OAAQ,MAAO,OAAQ,QAAS,QACvDC,aAAc,CACVC,KAAM,CAAC,WAEXO,eAAiBpB,IACb,MAAMrC,EAA+BqC,EAAE5B,QAAU,GACjD5C,KAAKpB,iBAAmBuD,EAAO,GAC/BnC,KAAKhC,cAAcuC,KAAKP,KAAKpB,iBAAiB,KAM9DkF,EACI,UAAAC,MAAM,gBACNc,UAAY7E,KAAKvC,cAAcmG,WAAa5D,KAAKpB,kBAAqBoB,KAAKrB,aAAeqB,KAAKX,aAC/F8E,QAASnE,KAAKwyB,qBAEbxyB,KAAKrB,YAAc,SAAWqB,KAAKX,aAAe,SAAW,QAGlEyE,EAAK,OAAAC,MAAM,iBACPD,EAAqB,2BACrBA,EAAG,KAAAC,MAAM,cACLD,EAA8B,qCAC9BA,EAAA,KAAGiC,KAAK,4BAA4B1E,OAAO,SAAS2E,IAAI,uBAAqB,mCAO5FxC,GACGM,EAAK,OAAAC,MAAM,qBACPD,EAAK,OAAAC,MAAM,oBACXD,EAAA,KAAGC,MAAM,gBAAc,cAK9B/D,KAAKnB,eACFiF,EAAA,WACIA,EAAA,sBACIhH,OAAQ,KACRF,WAAYoD,KAAKpD,WACjBI,KAAMgD,KAAKhD,KACXE,aAAc8C,KAAK9C,aACnBC,YAAa6C,KAAK9C,aAClBQ,qBAAsBsC,KAAKtC,qBAC3BuI,MAAM,mBACNzI,WAAYwC,KAAKxC,WACjBJ,eAAgB4C,KAAK5C,eACrBC,aAAc2C,KAAK3C,aACnBiU,gBAAiBtR,KAAKsR,gBACtB7T,aAAc,IACPuC,KAAKvC,aACRmG,SAAU5D,KAAKvC,cAAcmG,UAAY5D,KAAKpB,kBAAkB2G,QAChEC,UAAWxF,KAAKvC,cAAc+H,WAAaxF,KAAKpB,kBAAkB4G,UAClEnB,KAAMrE,KAAKsyB,kBAEfh0B,cAAc,OACdq0B,oBAAqB3yB,KAAKyyB,2B","ignoreList":[]}