pcm-agents 0.6.76 → 0.6.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components-position-selector.cjs.entry.js +1 -1
- package/dist/cjs/index-C_qhED9Z.js +2 -6
- package/dist/cjs/{index-DJuHr4W9.js → index-DOCJeM7I.js} +3 -3
- package/dist/cjs/{index-DJuHr4W9.js.map → index-DOCJeM7I.js.map} +1 -1
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/oem-htws-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-jd-modal.cjs.entry.js +2 -2
- package/dist/cjs/oem-jlpp-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-jlsx-modal.cjs.entry.js +24 -2
- package/dist/cjs/oem-jlsx-modal.cjs.entry.js.map +1 -1
- package/dist/cjs/oem-jlsx-modal.entry.cjs.js.map +1 -1
- package/dist/cjs/oem-jlzz-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-mnct-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-mnms-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-qgqjl-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-zygh-modal.cjs.entry.js +1 -1
- package/dist/cjs/{pcm-1zhanshi-mnms-modal_28.cjs.entry.js → pcm-1zhanshi-mnms-modal_29.cjs.entry.js} +540 -108
- package/dist/cjs/pcm-1zhanshi-mnms-modal_29.cjs.entry.js.map +1 -0
- package/dist/cjs/pcm-agents.cjs.js +1 -1
- package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js +19 -2
- package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js.map +1 -1
- package/dist/cjs/pcm-hr-chat-modal.entry.cjs.js.map +1 -1
- package/dist/cjs/{sentry-reporter-COJ0pOg4.js → sentry-reporter-BY3e-WWj.js} +3 -3
- package/dist/cjs/{sentry-reporter-COJ0pOg4.js.map → sentry-reporter-BY3e-WWj.js.map} +1 -1
- package/dist/collection/components/oem-jlsx-modal/oem-jlsx-modal.js +22 -0
- package/dist/collection/components/oem-jlsx-modal/oem-jlsx-modal.js.map +1 -1
- package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js +19 -0
- package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js.map +1 -1
- package/dist/collection/components/pcm-hr-chat-modal/pcm-hr-chat-modal.js +17 -0
- package/dist/collection/components/pcm-hr-chat-modal/pcm-hr-chat-modal.js.map +1 -1
- package/dist/collection/components/pcm-jlpp-modal/pcm-jlpp-modal.js +12 -11
- package/dist/collection/components/pcm-jlpp-modal/pcm-jlpp-modal.js.map +1 -1
- package/dist/collection/components/pcm-jlsx-modal/pcm-jlsx-modal.js +12 -0
- package/dist/collection/components/pcm-jlsx-modal/pcm-jlsx-modal.js.map +1 -1
- package/dist/collection/components/pcm-jlzz-modal/pcm-jlzz-modal.js +88 -2
- package/dist/collection/components/pcm-jlzz-modal/pcm-jlzz-modal.js.map +1 -1
- package/dist/collection/components/pcm-qgqjl-modal/pcm-qgqjl-modal.js +20 -19
- package/dist/collection/components/pcm-qgqjl-modal/pcm-qgqjl-modal.js.map +1 -1
- package/dist/collection/components/pcm-virtual-chat-modal/pcm-virtual-chat-modal.js +108 -3
- package/dist/collection/components/pcm-virtual-chat-modal/pcm-virtual-chat-modal.js.map +1 -1
- package/dist/collection/components/pcm-zsk-chat-modal/pcm-zsk-chat-modal.js +17 -0
- package/dist/collection/components/pcm-zsk-chat-modal/pcm-zsk-chat-modal.js.map +1 -1
- package/dist/collection/components/pcm-zygh-v2-modal/pcm-zygh-v2-modal.js +14 -14
- package/dist/collection/components/pcm-zygh-v2-modal/pcm-zygh-v2-modal.js.map +1 -1
- package/dist/components/components-position-selector.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/oem-htws-modal.js +6 -6
- package/dist/components/oem-jd-modal.js +4 -4
- package/dist/components/oem-jlpp-modal.js +8 -8
- package/dist/components/oem-jlsx-modal.js +28 -6
- package/dist/components/oem-jlsx-modal.js.map +1 -1
- package/dist/components/oem-jlzz-modal.js +6 -6
- package/dist/components/oem-mnct-modal.js +8 -8
- package/dist/components/oem-mnms-modal.js +9 -9
- package/dist/components/oem-qgqjl-modal.js +8 -8
- package/dist/components/oem-zygh-modal.js +6 -6
- package/dist/components/{p-CGRQB-kz.js → p-9hnllPbt.js} +3 -3
- package/dist/components/{p-CGRQB-kz.js.map → p-9hnllPbt.js.map} +1 -1
- package/dist/components/{p-nFix5BDn.js → p-B7cdvqSY.js} +4 -4
- package/dist/components/{p-nFix5BDn.js.map → p-B7cdvqSY.js.map} +1 -1
- package/dist/components/{p-BZeNORff.js → p-BnkPmLIU.js} +111 -6
- package/dist/components/p-BnkPmLIU.js.map +1 -0
- package/dist/components/{p-DtCXILg5.js → p-C4KAf-6-.js} +3 -3
- package/dist/components/{p-DtCXILg5.js.map → p-C4KAf-6-.js.map} +1 -1
- package/dist/components/{p-pTzOe1-b.js → p-C6OdIxkm.js} +3 -3
- package/dist/components/{p-pTzOe1-b.js.map → p-C6OdIxkm.js.map} +1 -1
- package/dist/components/{p-BJnD41Qm.js → p-DHwXxizT.js} +3 -3
- package/dist/components/{p-BJnD41Qm.js.map → p-DHwXxizT.js.map} +1 -1
- package/dist/components/{p-Caxrsbp0.js → p-Da-8BxdM.js} +24 -5
- package/dist/components/p-Da-8BxdM.js.map +1 -0
- package/dist/components/{p--B9t4xVs.js → p-QwH3TimN.js} +3 -3
- package/dist/components/{p--B9t4xVs.js.map → p-QwH3TimN.js.map} +1 -1
- package/dist/components/{p-BjKpPzZZ.js → p-ikx6J73I.js} +3 -3
- package/dist/components/{p-BjKpPzZZ.js.map → p-ikx6J73I.js.map} +1 -1
- package/dist/components/{p-CvHWzHdd.js → p-qUBE1daM.js} +3 -3
- package/dist/components/{p-CvHWzHdd.js.map → p-qUBE1daM.js.map} +1 -1
- package/dist/components/pcm-1zhanshi-mnms-modal.js +5 -5
- package/dist/components/pcm-app-chat-modal.js +1 -1
- package/dist/components/pcm-ats-mnms-modal.js +5 -5
- package/dist/components/pcm-card.js +1 -1
- package/dist/components/pcm-chat-message.js +1 -1
- package/dist/components/pcm-digital-human.js +1 -1
- package/dist/components/pcm-export-records-modal.js +1 -1
- package/dist/components/pcm-hr-chat-modal.js +19 -2
- package/dist/components/pcm-hr-chat-modal.js.map +1 -1
- package/dist/components/pcm-htws-modal.js +7 -7
- package/dist/components/pcm-hyzj-modal.js +4 -4
- package/dist/components/pcm-jd-modal.js +4 -4
- package/dist/components/pcm-jlpp-modal.js +18 -17
- package/dist/components/pcm-jlpp-modal.js.map +1 -1
- package/dist/components/pcm-jlsx-modal.js +17 -5
- package/dist/components/pcm-jlsx-modal.js.map +1 -1
- package/dist/components/pcm-jlzz-modal.js +39 -8
- package/dist/components/pcm-jlzz-modal.js.map +1 -1
- package/dist/components/pcm-mnct-modal.js +4 -4
- package/dist/components/pcm-mnms-modal.js +8 -8
- package/dist/components/pcm-mnms-zp-modal.js +8 -8
- package/dist/components/pcm-mobile-input-btn.js +1 -1
- package/dist/components/pcm-mobile-upload-btn.js +1 -1
- package/dist/components/pcm-msbg-modal.js +4 -4
- package/dist/components/pcm-qgqjl-modal.js +26 -25
- package/dist/components/pcm-qgqjl-modal.js.map +1 -1
- package/dist/components/pcm-upload.js +1 -1
- package/dist/components/pcm-virtual-chat-modal.js +1 -1
- package/dist/components/pcm-zsk-chat-modal.js +19 -2
- package/dist/components/pcm-zsk-chat-modal.js.map +1 -1
- package/dist/components/pcm-zygh-modal.js +6 -6
- package/dist/components/pcm-zygh-v2-modal.js +18 -18
- package/dist/components/pcm-zygh-v2-modal.js.map +1 -1
- package/dist/esm/components-position-selector.entry.js +1 -1
- package/dist/esm/index-Bq0K-WqZ.js +2 -6
- package/dist/esm/{index-DBfBNGaa.js → index-CtBK1m67.js} +3 -3
- package/dist/esm/{index-DBfBNGaa.js.map → index-CtBK1m67.js.map} +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/oem-htws-modal.entry.js +1 -1
- package/dist/esm/oem-jd-modal.entry.js +2 -2
- package/dist/esm/oem-jlpp-modal.entry.js +1 -1
- package/dist/esm/oem-jlsx-modal.entry.js +24 -2
- package/dist/esm/oem-jlsx-modal.entry.js.map +1 -1
- package/dist/esm/oem-jlzz-modal.entry.js +1 -1
- package/dist/esm/oem-mnct-modal.entry.js +1 -1
- package/dist/esm/oem-mnms-modal.entry.js +1 -1
- package/dist/esm/oem-qgqjl-modal.entry.js +1 -1
- package/dist/esm/oem-zygh-modal.entry.js +1 -1
- package/dist/esm/{pcm-1zhanshi-mnms-modal_28.entry.js → pcm-1zhanshi-mnms-modal_29.entry.js} +540 -109
- package/dist/esm/pcm-1zhanshi-mnms-modal_29.entry.js.map +1 -0
- package/dist/esm/pcm-agents.js +1 -1
- package/dist/esm/pcm-hr-chat-modal.entry.js +19 -2
- package/dist/esm/pcm-hr-chat-modal.entry.js.map +1 -1
- package/dist/esm/{sentry-reporter-BcA0r0vQ.js → sentry-reporter-D8jwTnnH.js} +3 -3
- package/dist/esm/{sentry-reporter-BcA0r0vQ.js.map → sentry-reporter-D8jwTnnH.js.map} +1 -1
- package/dist/pcm-agents/index.esm.js +1 -1
- package/dist/pcm-agents/oem-jlsx-modal.entry.esm.js.map +1 -1
- package/dist/pcm-agents/p-0a831595.entry.js +2 -0
- package/dist/pcm-agents/{p-365a351b.entry.js.map → p-0a831595.entry.js.map} +1 -1
- package/dist/pcm-agents/{p-d9e464fd.entry.js → p-1cc1dbcc.entry.js} +2 -2
- package/dist/pcm-agents/{p-cc3c0220.entry.js → p-43cefa20.entry.js} +2 -2
- package/dist/pcm-agents/{p-4b363eb3.entry.js → p-5bf761de.entry.js} +2 -2
- package/dist/pcm-agents/{p-96c41b85.entry.js → p-680bf3a3.entry.js} +2 -2
- package/dist/pcm-agents/p-8452f80b.entry.js +251 -0
- package/dist/pcm-agents/p-8452f80b.entry.js.map +1 -0
- package/dist/pcm-agents/{p-86c2748a.entry.js → p-890fb793.entry.js} +2 -2
- package/dist/pcm-agents/{p-Dz4pPCio.js → p-B1X08zm_.js} +2 -2
- package/dist/pcm-agents/{p-Dz4pPCio.js.map → p-B1X08zm_.js.map} +1 -1
- package/dist/pcm-agents/{p-zJbvNgZt.js → p-BmPGiYO3.js} +2 -2
- package/dist/pcm-agents/{p-zJbvNgZt.js.map → p-BmPGiYO3.js.map} +1 -1
- package/dist/pcm-agents/{p-a54ca8e2.entry.js → p-a31fa268.entry.js} +2 -2
- package/dist/pcm-agents/{p-4b257381.entry.js → p-ad6ce0c9.entry.js} +2 -2
- package/dist/pcm-agents/{p-41b4b6bb.entry.js → p-b80f01e6.entry.js} +2 -2
- package/dist/pcm-agents/{p-e442dabc.entry.js → p-c3eb9590.entry.js} +2 -2
- package/dist/pcm-agents/{p-92eea906.entry.js → p-eb44bda0.entry.js} +2 -2
- package/dist/pcm-agents/pcm-agents.esm.js +1 -1
- package/dist/pcm-agents/pcm-hr-chat-modal.entry.esm.js.map +1 -1
- package/dist/types/components/pcm-jlpp-modal/pcm-jlpp-modal.d.ts +3 -2
- package/dist/types/components/pcm-jlzz-modal/pcm-jlzz-modal.d.ts +14 -0
- package/dist/types/components/pcm-qgqjl-modal/pcm-qgqjl-modal.d.ts +3 -2
- package/dist/types/components/pcm-virtual-chat-modal/pcm-virtual-chat-modal.d.ts +10 -0
- package/dist/types/components/pcm-zygh-v2-modal/pcm-zygh-v2-modal.d.ts +4 -4
- package/dist/types/components.d.ts +36 -12
- package/package.json +1 -1
- package/dist/cjs/pcm-1zhanshi-mnms-modal_28.cjs.entry.js.map +0 -1
- package/dist/cjs/pcm-zygh-v2-modal.cjs.entry.js +0 -260
- package/dist/cjs/pcm-zygh-v2-modal.cjs.entry.js.map +0 -1
- package/dist/cjs/pcm-zygh-v2-modal.entry.cjs.js.map +0 -1
- package/dist/components/p-BZeNORff.js.map +0 -1
- package/dist/components/p-Caxrsbp0.js.map +0 -1
- package/dist/esm/pcm-1zhanshi-mnms-modal_28.entry.js.map +0 -1
- package/dist/esm/pcm-zygh-v2-modal.entry.js +0 -258
- package/dist/esm/pcm-zygh-v2-modal.entry.js.map +0 -1
- package/dist/pcm-agents/p-210d610a.entry.js +0 -2
- package/dist/pcm-agents/p-210d610a.entry.js.map +0 -1
- package/dist/pcm-agents/p-365a351b.entry.js +0 -2
- package/dist/pcm-agents/p-6551d616.entry.js +0 -251
- package/dist/pcm-agents/p-6551d616.entry.js.map +0 -1
- package/dist/pcm-agents/pcm-zygh-v2-modal.entry.esm.js.map +0 -1
- /package/dist/pcm-agents/{p-d9e464fd.entry.js.map → p-1cc1dbcc.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-cc3c0220.entry.js.map → p-43cefa20.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-4b363eb3.entry.js.map → p-5bf761de.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-96c41b85.entry.js.map → p-680bf3a3.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-86c2748a.entry.js.map → p-890fb793.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-a54ca8e2.entry.js.map → p-a31fa268.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-4b257381.entry.js.map → p-ad6ce0c9.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-41b4b6bb.entry.js.map → p-b80f01e6.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-e442dabc.entry.js.map → p-c3eb9590.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-92eea906.entry.js.map → p-eb44bda0.entry.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["pcm1zhanshiMnmsModalCss","globalCss","hostCss","ZhanshiMnmsModal","modalTitle","token","isOpen","modalClosed","icon","zIndex","isShowHeader","isNeedClose","conversationId","defaultQuery","maxRecordingTime","waitingTime","fullscreen","customInputs","digitalId","openingIndex","enableVirtualHuman","showEndInterviewButton","playbackRate","uploadSuccess","streamComplete","conversationStart","interviewComplete","tokenInvalid","someErrorEvent","recordingError","selectedFile","isUploading","uploadedFileInfo","showChatModal","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","handleClose","render","modalStyle","String","containerClass","overlayClass","isLoading","h","class","style","src","alt","onClick","ref","el","botId","file_url","cos_key","file_name","job_info","ai_interview_type","interviewMode","pcmAppChatModalCss","markdownCss","pcmAtsMnmsModalCss","AtsMnmsModal","interview_type","pcmButtonCss","PcmButton","type","size","loading","disabled","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","error","watchBotIdHandler","fetchBotData","response","sendHttpRequest","url","method","success","data","Error","message","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","webpackUniversalModuleDefinition","root","factory","module","exports","__webpack_modules__","__unused_webpack_module","__webpack_exports__","__webpack_require__","d","default","clipboard","tiny_emitter","tiny_emitter_default","n","listen","listen_default","src_select","select_default","command","execCommand","ClipboardActionCut","target","selectedText","actions_cut","createFakeElement","value","isRTL","documentElement","getAttribute","fakeElement","createElement","fontSize","border","padding","margin","position","yPosition","window","pageYOffset","scrollTop","top","concat","setAttribute","fakeCopyAction","options","container","appendChild","remove","ClipboardActionCopy","arguments","length","undefined","body","HTMLInputElement","includes","actions_copy","_typeof","obj","Symbol","iterator","constructor","prototype","ClipboardActionDefault","_options$action","action","text","nodeType","hasAttribute","actions_default","clipboard_typeof","_classCallCheck","instance","Constructor","TypeError","_defineProperties","props","i","descriptor","enumerable","configurable","writable","defineProperty","_createClass","protoProps","staticProps","_inherits","subClass","superClass","create","_setPrototypeOf","o","p","setPrototypeOf","__proto__","_createSuper","Derived","hasNativeReflectConstruct","_isNativeReflectConstruct","_createSuperInternal","Super","_getPrototypeOf","result","NewTarget","Reflect","construct","apply","_possibleConstructorReturn","self","call","_assertThisInitialized","ReferenceError","sham","Proxy","Date","toString","e","getPrototypeOf","getAttributeValue","suffix","element","attribute","Clipboard","_Emitter","_super","trigger","_this","resolveOptions","listenClick","defaultAction","defaultTarget","defaultText","_this2","listener","delegateTarget","currentTarget","clearSelection","focus","getSelection","removeAllRanges","selector","querySelector","destroy","copy","cut","isSupported","actions","support","queryCommandSupported","forEach","DOCUMENT_NODE_TYPE","Element","matches","proto","matchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","webkitMatchesSelector","closest","parentNode","__unused_webpack_exports","_delegate","callback","useCapture","listenerFn","delegate","elements","bind","querySelectorAll","Array","map","node","HTMLElement","nodeList","string","fn","is","listenNode","listenNodeList","listenSelector","select","nodeName","isReadOnly","setSelectionRange","removeAttribute","selection","range","createRange","selectNodeContents","addRange","E","on","name","ctx","push","once","off","_","slice","evtArr","len","evts","liveEvents","TinyEmitter","__webpack_module_cache__","moduleId","getter","__esModule","a","definition","get","prop","hasOwnProperty","pcmChatMessageCss","pcmConfirmModalCss","PcmConfirmModal","okText","cancelText","okType","maskClosable","mask","centered","ok","cancel","closed","afterOpen","afterClose","bodyOverflowBeforeOpen","transitionEndHandler","open","close","visibleChanged","overflow","modal","hostElement","shadowRoot","cachedZIndex","getItem","handleMaskClick","handleCancel","handleOk","maskStyle","contentClass","okButtonClass","pcmDigitalHumanCss","pcmDrawerCss","PcmDrawer","drawerTitle","height","closable","drawer","drawerStyle","pcmExportRecordsModalCss","DEFAULT_PAGINATION","page","EXPORT_BATCH_STATUS_MAP","color","PcmExportRecordsModal","sourceId","pagination","showMessage","messageText","messageType","watchOpen","fetchData","params","bot_id","source_id","records","total","handleDownload","record","downloadUrl","getCosPresignedUrl","fileName","link","href","click","showMessageToast","handleDelete","id","setTimeout","handleRefresh","handlePageChange","newPagination","formatDate","dateString","date","toLocaleString","year","month","day","hour","minute","second","renderEmpty","renderTag","status","statusInfo","renderButton","variant","renderTable","textAlign","created_at","renderPagination","totalPages","Math","ceil","currentPage","onChange","parseInt","selected","renderMessage","stopPropagation","pcmHtwsModalCss","HtwsModal","showWorkspaceHistory","mobileUploadAble","mobileInputAble","filePreviewMode","inputMode","freeInputText","pcmUploadRef","handleToggleInput","handleFreeInputChange","event","textarea","handleStartInterview","async","Message","info","trim","getIsUploading","input","viewBox","fill","stroke","maxFileSize","multiple","uploadText","acceptFileSuffixList","uploadParams","tags","onUploadChange","detail","onOk","placeholder","rows","onInput","rel","pcmHyzjModalCss","HyzjModal","clearSelectedFile","handleFileChange","files","handleUploadClick","fileInput","uploadFile","uploadFileToBackend","SentryReporter","captureError","component","emitError","alert","hideFileUpload","Boolean","pcmJdModalCss","PcmJdModal","locale","showSaveJdButton","saveJdButtonText","strings","step","jobName","tagGroups","shuffledTagGroups","selectedAITags","selectedTags","salary","benefits","education","stringsEn","stringsZh","getSalaryRanges","salaryRanges","above_20k","getBenefits","benefitsList","insurance","bonus","paidLeave","overtimePay","mealAllowance","transportAllowance","holidayBenefits","teamBuilding","getEducationRequirements","educationList","college","bachelor","master","doctor","noLimit","handleJobNameChange","handleNextStep","alerts","enterJobName","handlePositionAnalysis","handlePrevStep","inputs","input_info","workflow_code","outputs","jsonText","markdownJsonMatch","match","parsedOutput","JSON","parse","tagGroup","initialSelectedTags","shuffled","group","allTags","defaultTags","optionalTags","j","floor","random","dimensionName","handleTagClick","category","currentTags","newTags","t","handleAITagClick","tag","handleSubmitStructured","salaryRange","find","r","selectedBenefits","edu","jobInfo","jobInfoFields","entries","dimension","handleSubmitFree","enterJobInfo","getBotId","currentLocale","lang","botIdMap","zh","en","renderTagGroup","option","isSelected","renderAITagGroups","renderLoadingState","aiAnalyzing","pleaseWait","jobRequirementInfo","toggleInput","htmlFor","required","jobNamePlaceholder","nextStep","aiRecommendedTags","prevStep","processing","generateJD","jdInfo","jdInfoPlaceholder","inputGuideTitle","inputGuide","jobTitle","responsibilities","qualifications","location","aiDisclaimer","beianLabel","beianNumber","loadingConversation","pcmJlppModalCss","JlppModal","mobileJdInputAble","handleJobDescriptionChange","handleStartAnalysis","hideJdInput","hideResumeUpload","hasFileAndJob","pcmJlsxModalCss","pcmJlzzModalCss","pcmMessageCss","PcmMessage","content","duration","visible","timer","componentDidLoad","clearTimeout","show","removeChild","renderIcon","pcmMnctModalCss","MnctModal","questionNumber","canOutputAnalysis","errors","uploadFailed","handleQuestionNumberChange","handleAnalysisToggle","checked","uploadResume","enterJobDescription","startInterviewFailed","jobDescriptionLabel","jobDescriptionPlaceholder","resumeUploadLabel","uploadPlaceholder","uploadHint","questionNumberLabel","min","max","questionUnit","analysisToggleLabel","toggleOn","toggleOff","uploading","startAnalysis","question_number","can_outputAnalysis","pcmMnmsModalCss","MnmsModal","showCopyButton","showFeedbackButtons","resume_content","pcmMnmsZpModalCss","MnmsZpModal","VALUES_TO_CHARSET","Map","Charset","label","values","static","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","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","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","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","colors","matrixSize","gif","assertContent","assertCharset","assertHints","hints","assertLevel","indexOf","assertVersion","encode$1","segments","versionNumber","isFNC1Appended","Byte","uploadNumberSDK","number","isWorking","onError","pcmMobileInputBtnCss","MobileUploadBtn","maxLength","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","navigator","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","defaultFileList","uploadChange","selectedFiles","file","state","FileUploadState","Success","some","Uploading","clearSelectedFiles","file_size","Failed","currentFileCount","remainingSlots","validFiles","invalidFiles","split","pop","toLowerCase","supportedFormats","maxSizeText","formatFileSize","newFileItems","uploadResult","targetIndex","emitUploadChange","ext","uploadBtn","textDecoration","marginLeft","itemIndex","pcmVirtualChatModalCss","pcmZskChatModalCss","pcmZyghModalCss","ZyghModal","planningComplete","selectedPlanType","handlePlanTypeChange","handleStartPlanning","handlePlanningComplete","hasFileAndType","onInterviewComplete"],"sources":["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-ats-mnms-modal/pcm-ats-mnms-modal.css?tag=pcm-ats-mnms-modal&encapsulation=shadow","src/global/global.css?tag=pcm-ats-mnms-modal&encapsulation=shadow","src/global/host.css?tag=pcm-ats-mnms-modal&encapsulation=shadow","src/components/pcm-ats-mnms-modal/pcm-ats-mnms-modal.tsx","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","node_modules/.pnpm/clipboard@2.0.11/node_modules/clipboard/dist/clipboard.js","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-jlzz-modal/pcm-jlzz-modal.css?tag=pcm-jlzz-modal&encapsulation=shadow","src/global/global.css?tag=pcm-jlzz-modal&encapsulation=shadow","src/global/host.css?tag=pcm-jlzz-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-modal/pcm-mnms-modal.css?tag=pcm-mnms-modal&encapsulation=shadow","src/global/global.css?tag=pcm-mnms-modal&encapsulation=shadow","src/global/host.css?tag=pcm-mnms-modal&encapsulation=shadow","src/components/pcm-mnms-modal/pcm-mnms-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":[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: auto;\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 * 数字人视频播放速率(0.5-2.0之间),默认1.0\r\n */\r\n @Prop() playbackRate: number = 1.0;\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 maxRecordingTime={this.maxRecordingTime}\r\n waitingTime={this.waitingTime}\r\n playbackRate={this.playbackRate}\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 ai_interview_type: this.digitalId\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 playbackRate={this.playbackRate}\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/** 结束对话按钮 */\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\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.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}",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: auto;\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-ats-mnms-modal',\r\n styleUrls: ['pcm-ats-mnms-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class AtsMnmsModal {\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=\"137635156700770304\"\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.isNeedClose}\r\n fullscreen={this.fullscreen}\r\n botId=\"137635156700770304\"\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: 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} ","/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT © Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\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: auto;\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.isNeedClose}\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: auto;\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.isNeedClose}\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: auto;\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\nimport stringsZh from './pcm-jd-modal.i18n.zh.json';\r\nimport stringsEn from './pcm-jd-modal.i18n.en.json';\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 * 语言设置\r\n */\r\n @Prop() locale: string = 'zh';\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 // 国际化字符串\r\n @State() strings: any;\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 async componentWillLoad() {\r\n // 加载国际化字符串\r\n this.strings = this.locale === 'en' ? stringsEn : stringsZh;\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 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 getSalaryRanges() {\r\n return [\r\n { text: this.strings.salaryRanges['3k_5k'], value: '3k_5k' },\r\n { text: this.strings.salaryRanges['5k_8k'], value: '5k_8k' },\r\n { text: this.strings.salaryRanges['8k_12k'], value: '8k_12k' },\r\n { text: this.strings.salaryRanges['12k_15k'], value: '12k_15k' },\r\n { text: this.strings.salaryRanges['15k_20k'], value: '15k_20k' },\r\n { text: this.strings.salaryRanges.above_20k, value: 'above_20k' },\r\n ];\r\n }\r\n\r\n // 福利待遇选项\r\n private getBenefits() {\r\n return [\r\n { text: this.strings.benefitsList.insurance, value: '五险一金' },\r\n { text: this.strings.benefitsList.bonus, value: '年终奖' },\r\n { text: this.strings.benefitsList.paidLeave, value: '带薪年假' },\r\n { text: this.strings.benefitsList.overtimePay, value: '加班补贴' },\r\n { text: this.strings.benefitsList.mealAllowance, value: '餐补' },\r\n { text: this.strings.benefitsList.transportAllowance, value: '交通补贴' },\r\n { text: this.strings.benefitsList.holidayBenefits, value: '节日福利' },\r\n { text: this.strings.benefitsList.teamBuilding, value: '团队建设' },\r\n ];\r\n }\r\n\r\n // 学历要求选项\r\n private getEducationRequirements() {\r\n return [\r\n { text: this.strings.educationList.college, value: '大专' },\r\n { text: this.strings.educationList.bachelor, value: '本科' },\r\n { text: this.strings.educationList.master, value: '硕士' },\r\n { text: this.strings.educationList.doctor, value: '博士' },\r\n { text: this.strings.educationList.noLimit, value: '学历不限' },\r\n ];\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(this.strings.alerts.enterJobName);\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 locale: this.locale\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.getSalaryRanges().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.getEducationRequirements().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.strings.jobInfoFields.jobName}:${this.jobName}\\n`;\r\n\r\n if (salaryRange) {\r\n jobInfo += `${this.strings.jobInfoFields.salaryRange}:${salaryRange}\\n`;\r\n }\r\n\r\n if (selectedBenefits) {\r\n jobInfo += `${this.strings.jobInfoFields.benefits}:${selectedBenefits}\\n`;\r\n }\r\n\r\n if (education) {\r\n jobInfo += `${this.strings.jobInfoFields.education}:${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(this.strings.alerts.enterJobInfo);\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 // 根据语言获取对应的botId\r\n private getBotId(): string {\r\n const currentLocale = this.locale || this.hostElement?.lang || 'zh';\r\n const botIdMap: Record<string, string> = {\r\n 'zh': '3022316191018873',\r\n 'en': '8164748078835713'\r\n };\r\n return botIdMap[currentLocale] || botIdMap['zh'];\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 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>{this.strings.aiAnalyzing}</div>\r\n <div class=\"loading-subtext\">{this.strings.pleaseWait}</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>{this.strings.jobRequirementInfo}</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 {this.strings.toggleInput}\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 {this.strings.jobName} <span class=\"required\">{this.strings.required}</span>\r\n </label>\r\n <input\r\n id=\"job-name\"\r\n type=\"text\"\r\n placeholder={this.strings.jobNamePlaceholder}\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 {this.strings.nextStep}\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\">{this.strings.aiRecommendedTags}</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.strings.salaryRange, this.getSalaryRanges(), 'salary')}\r\n {this.renderTagGroup(this.strings.benefits, this.getBenefits(), 'benefits')}\r\n {this.renderTagGroup(this.strings.education, this.getEducationRequirements(), '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 {this.strings.prevStep}\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 ? this.strings.processing : this.strings.generateJD}\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 {this.strings.jdInfo} <span class=\"required\">{this.strings.required}</span>\r\n </label>\r\n <textarea\r\n id=\"free-input-text\"\r\n placeholder={this.strings.jdInfoPlaceholder}\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\">{this.strings.inputGuideTitle}</div>\r\n <div class=\"guide-content\">\r\n <div>{this.strings.inputGuide.jobTitle}</div>\r\n <div>{this.strings.inputGuide.salary}</div>\r\n <div>{this.strings.inputGuide.benefits}</div>\r\n <div>{this.strings.inputGuide.responsibilities}</div>\r\n <div>{this.strings.inputGuide.qualifications}</div>\r\n <div>{this.strings.inputGuide.location}</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 ? this.strings.processing : this.strings.generateJD}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>{this.strings.aiDisclaimer}</p>\r\n <p class=\"beian-info\">\r\n <span>{this.strings.beianLabel}</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">{this.strings.beianNumber}</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\">{this.strings.loadingConversation}</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 locale={this.locale}\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isNeedClose}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId={this.getBotId()}\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: auto;\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.isNeedClose}\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: auto;\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}",".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: auto;\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}",".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: auto;\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\nimport stringsZh from './pcm-mnct-modal.i18n.zh.json';\r\nimport stringsEn from './pcm-mnct-modal.i18n.en.json';\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 * 语言设置\r\n */\r\n @Prop() locale: string = 'zh';\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 // 国际化字符串\r\n @State() strings: any;\r\n\r\n @State() jobDescription: string = '';\r\n @State() isSubmitting: boolean = false;\r\n\r\n // 根据语言获取对应的botId\r\n private getBotId(): string {\r\n const currentLocale = this.locale || this.hostElement?.lang || 'zh';\r\n const botIdMap: Record<string, string> = {\r\n 'zh': '3022316191018876',\r\n 'en': '8164755731671041'\r\n };\r\n return botIdMap[currentLocale] || botIdMap['zh'];\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 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 async componentWillLoad() {\r\n // 加载国际化字符串\r\n this.strings = this.locale === 'en' ? stringsEn : stringsZh;\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 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: this.strings.errors.uploadFailed\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(this.strings.alerts.uploadResume);\r\n return;\r\n }\r\n\r\n // 如果没有预设的job_info,则需要检查用户输入\r\n if (!this.customInputs?.job_info && !this.jobDescription.trim()) {\r\n alert(this.strings.alerts.enterJobDescription);\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: this.strings.errors.startInterviewFailed\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\">{this.strings.jobDescriptionLabel}</label>\r\n <textarea\r\n id=\"job-description\"\r\n class=\"job-description-textarea\"\r\n placeholder={this.strings.jobDescriptionPlaceholder}\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>{this.strings.resumeUploadLabel}</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'>{this.strings.uploadPlaceholder}</p>\r\n <p class=\"upload-hint\">{this.strings.uploadHint}</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\">{this.strings.questionNumberLabel}</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}{this.strings.questionUnit}</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\">{this.strings.analysisToggleLabel}</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 ? this.strings.toggleOn : this.strings.toggleOff}</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.strings.uploading : this.isSubmitting ? this.strings.processing : this.strings.startAnalysis}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>{this.strings.aiDisclaimer}</p>\r\n <p class=\"beian-info\">\r\n <span>{this.strings.beianLabel}</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">{this.strings.beianNumber}</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\">{this.strings.loadingConversation}</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 locale={this.locale}\r\n isOpen={true}\r\n modalTitle={this.modalTitle}\r\n icon={this.icon}\r\n isShowHeader={this.isShowHeader}\r\n isNeedClose={this.isNeedClose}\r\n fullscreen={this.fullscreen}\r\n showWorkspaceHistory={this.showWorkspaceHistory}\r\n botId={this.getBotId()}\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: auto;\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-modal',\r\n styleUrls: ['pcm-mnms-modal.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class MnmsModal {\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.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 * 数字人视频播放速率(0.5-2.0之间),默认1.0\r\n */\r\n @Prop() playbackRate: number = 1.0;\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 } 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\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 */\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 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=\"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 playbackRate={this.playbackRate}\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 ai_interview_type: this.digitalId\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 playbackRate={this.playbackRate}\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} ",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: auto;\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.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 * 数字人视频播放速率(0.5-2.0之间),默认1.0\r\n */\r\n @Prop() playbackRate: number = 1.0;\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 playbackRate={this.playbackRate}\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 ai_interview_type: this.digitalId\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 playbackRate={this.playbackRate}\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: auto;\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: auto;\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: auto;\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.isNeedClose}\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: auto;\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: auto;\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: auto;\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.isNeedClose}\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":"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","ignoreList":[]}
|